From 3fa8def57bd9cf0185e77a666e8983dcac1977ca Mon Sep 17 00:00:00 2001 From: "Rosy.iso" Date: Fri, 6 Mar 2026 00:19:14 +0100 Subject: [PATCH 01/10] very very very initial placeholder stuff for tomorrow --- .../common-settings/cosmetics/Cosmetics.tsx | 62 ++++++++++++++++++- 1 file changed, 60 insertions(+), 2 deletions(-) diff --git a/src/app/features/common-settings/cosmetics/Cosmetics.tsx b/src/app/features/common-settings/cosmetics/Cosmetics.tsx index 70c4cacd01..f4196f73bc 100644 --- a/src/app/features/common-settings/cosmetics/Cosmetics.tsx +++ b/src/app/features/common-settings/cosmetics/Cosmetics.tsx @@ -147,8 +147,65 @@ export function Cosmetics({ requestClose }: CosmeticsProps) { /> - - {/* --- COMMAND REFERENCE SECTION --- */} + + Profile + + + + + + + + + + + + + + + + + {/* } Commands + { */} From 579f439e2da6f972e773835f83573b616a18b577 Mon Sep 17 00:00:00 2001 From: "Rosy.iso" Date: Fri, 6 Mar 2026 10:01:42 +0100 Subject: [PATCH 02/10] update description of cosmetic settings and move the to-be cosmetics above them --- .../common-settings/cosmetics/Cosmetics.tsx | 132 +++++------------- 1 file changed, 34 insertions(+), 98 deletions(-) diff --git a/src/app/features/common-settings/cosmetics/Cosmetics.tsx b/src/app/features/common-settings/cosmetics/Cosmetics.tsx index f4196f73bc..71f074310f 100644 --- a/src/app/features/common-settings/cosmetics/Cosmetics.tsx +++ b/src/app/features/common-settings/cosmetics/Cosmetics.tsx @@ -70,83 +70,6 @@ export function Cosmetics({ requestClose }: CosmeticsProps) { - - Settings - - - handleToggle(StateEvent.RoomCosmeticsColor, enabled)} - disabled={!canEditPermissions} - /> - } - /> - - - - handleToggle(StateEvent.RoomCosmeticsFont, enabled)} - disabled={!canEditPermissions} - /> - } - /> - - - - - handleToggle(StateEvent.RoomCosmeticsPronouns, enabled) - } - disabled={!canEditPermissions} - /> - } - /> - - Profile - {/* } - Commands - - - + Settings handleToggle(StateEvent.RoomCosmeticsColor, enabled)} + disabled={!canEditPermissions} + /> + } /> handleToggle(StateEvent.RoomCosmeticsFont, enabled)} + disabled={!canEditPermissions} + /> + } /> + handleToggle(StateEvent.RoomCosmeticsPronouns, enabled) + } + disabled={!canEditPermissions} + /> + } /> - { */} From b6ed01cee15533ecd529f5aaea854b283bb2a96d Mon Sep 17 00:00:00 2001 From: "Rosy.iso" Date: Fri, 6 Mar 2026 10:20:10 +0100 Subject: [PATCH 03/10] underlike Cosmetics icon in rooms and spaces' settings --- .../features/room-settings/RoomSettings.tsx | 51 +++++++++++-------- .../features/space-settings/SpaceSettings.tsx | 48 ++++++++++------- 2 files changed, 58 insertions(+), 41 deletions(-) diff --git a/src/app/features/room-settings/RoomSettings.tsx b/src/app/features/room-settings/RoomSettings.tsx index d79cfd77ab..a2abde704a 100644 --- a/src/app/features/room-settings/RoomSettings.tsx +++ b/src/app/features/room-settings/RoomSettings.tsx @@ -24,6 +24,7 @@ type RoomSettingsMenuItem = { page: RoomSettingsPage; name: string; icon: IconSrc; + activeIcon?: IconSrc; }; const useRoomSettingsMenuItems = (): RoomSettingsMenuItem[] => @@ -48,6 +49,7 @@ const useRoomSettingsMenuItems = (): RoomSettingsMenuItem[] => page: RoomSettingsPage.CosmeticsPage, name: 'Cosmetics', icon: Icons.Alphabet, + activeIcon: Icons.AlphabetUnderline, }, { page: RoomSettingsPage.EmojisStickersPage, @@ -139,29 +141,34 @@ export function RoomSettings({ initialPage, requestClose }: RoomSettingsProps) {
- {menuItems.map((item) => ( - - } - onClick={() => setActivePage(item.page)} - > - { + const currentIcon = + activePage === item.page && item.activeIcon ? item.activeIcon : item.icon; + + return ( + + } + onClick={() => setActivePage(item.page)} > - {item.name} - - - ))} + + {item.name} + + + ); + })}
diff --git a/src/app/features/space-settings/SpaceSettings.tsx b/src/app/features/space-settings/SpaceSettings.tsx index 79ab84429d..ddd1d5c74e 100644 --- a/src/app/features/space-settings/SpaceSettings.tsx +++ b/src/app/features/space-settings/SpaceSettings.tsx @@ -23,6 +23,7 @@ type SpaceSettingsMenuItem = { page: SpaceSettingsPage; name: string; icon: IconSrc; + activeIcon?: IconSrc; }; const useSpaceSettingsMenuItems = (): SpaceSettingsMenuItem[] => @@ -47,6 +48,7 @@ const useSpaceSettingsMenuItems = (): SpaceSettingsMenuItem[] => page: SpaceSettingsPage.CosmeticsPage, name: 'Cosmetics', icon: Icons.Alphabet, + activeIcon: Icons.AlphabetUnderline, }, { page: SpaceSettingsPage.EmojisStickersPage, @@ -132,26 +134,34 @@ export function SpaceSettings({ initialPage, requestClose }: SpaceSettingsProps)
- {menuItems.map((item) => ( - } - onClick={() => setActivePage(item.page)} - > - { + const currentIcon = + activePage === item.page && item.activeIcon ? item.activeIcon : item.icon; + + return ( + + } + onClick={() => setActivePage(item.page)} > - {item.name} - - - ))} + + {item.name} + + + ); + })}
From 29ee1922519b25bd9556e20b7a6692c00d675fed Mon Sep 17 00:00:00 2001 From: "Rosy.iso" Date: Fri, 6 Mar 2026 10:42:18 +0100 Subject: [PATCH 04/10] placeholder avatar --- .../common-settings/cosmetics/Cosmetics.tsx | 29 +++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/src/app/features/common-settings/cosmetics/Cosmetics.tsx b/src/app/features/common-settings/cosmetics/Cosmetics.tsx index 71f074310f..d34f41e633 100644 --- a/src/app/features/common-settings/cosmetics/Cosmetics.tsx +++ b/src/app/features/common-settings/cosmetics/Cosmetics.tsx @@ -1,5 +1,5 @@ import { useCallback } from 'react'; -import { Box, Text, IconButton, Icon, Icons, Scroll, Switch } from 'folds'; +import { Box, Text, IconButton, Icon, Icons, Scroll, Switch, Avatar } from 'folds'; import { Page, PageContent, PageHeader } from '$components/page'; import { SequenceCard } from '$components/sequence-card'; import { SettingTile } from '$components/setting-tile'; @@ -11,6 +11,11 @@ import { useRoomCreators } from '$hooks/useRoomCreators'; import { useRoomPermissions } from '$hooks/useRoomPermissions'; import { createLogger } from '$utils/debug'; import { SequenceCardStyle } from '$features/common-settings/styles.css'; +import { UserAvatar } from '$components/user-avatar'; +import { nameInitials } from '$utils/common'; +import { useMediaAuthentication } from '$hooks/useMediaAuthentication'; +import { useUserProfile } from '$hooks/useUserProfile'; +import { getMxIdLocalPart, mxcUrlToHttp } from '$utils/matrix'; type CosmeticsProps = { requestClose: () => void; @@ -20,6 +25,8 @@ const log = createLogger('Cosmetics'); export function Cosmetics({ requestClose }: CosmeticsProps) { const mx = useMatrixClient(); + const userId = mx.getUserId()!; + const profile = useUserProfile(userId); const room = useRoom(); const creators = useRoomCreators(room); const powerLevels = usePowerLevels(room); @@ -28,6 +35,13 @@ export function Cosmetics({ requestClose }: CosmeticsProps) { const permissions = useRoomPermissions(creators, powerLevels); const canEditPermissions = permissions.stateEvent(StateEvent.RoomPowerLevels, mx.getSafeUserId()); + const useAuthentication = useMediaAuthentication(); + const avatarUrl = profile.avatarUrl + ? (mxcUrlToHttp(mx, profile.avatarUrl, useAuthentication, 96, 96, 'crop') ?? undefined) + : undefined; + + const defaultDisplayName = profile.displayName ?? getMxIdLocalPart(userId) ?? userId; + const getLevel = (eventType: string) => (powerLevels as any).events?.[eventType] ?? 50; const handleToggle = useCallback( @@ -80,7 +94,18 @@ export function Cosmetics({ requestClose }: CosmeticsProps) { > + ( + {nameInitials(defaultDisplayName)} + )} + /> + + } /> Date: Sat, 7 Mar 2026 19:05:16 +0100 Subject: [PATCH 05/10] add room display name --- .../common-settings/cosmetics/Cosmetics.tsx | 105 ++++++++++++++++-- 1 file changed, 96 insertions(+), 9 deletions(-) diff --git a/src/app/features/common-settings/cosmetics/Cosmetics.tsx b/src/app/features/common-settings/cosmetics/Cosmetics.tsx index d34f41e633..61f266153b 100644 --- a/src/app/features/common-settings/cosmetics/Cosmetics.tsx +++ b/src/app/features/common-settings/cosmetics/Cosmetics.tsx @@ -1,5 +1,5 @@ -import { useCallback } from 'react'; -import { Box, Text, IconButton, Icon, Icons, Scroll, Switch, Avatar } from 'folds'; +import { ChangeEventHandler, FormEventHandler, useCallback, useEffect, useState } from 'react'; +import { Box, Text, IconButton, Icon, Icons, Scroll, Switch, Avatar, Input, config, Button, Spinner } from 'folds'; import { Page, PageContent, PageHeader } from '$components/page'; import { SequenceCard } from '$components/sequence-card'; import { SettingTile } from '$components/setting-tile'; @@ -16,13 +16,103 @@ import { nameInitials } from '$utils/common'; import { useMediaAuthentication } from '$hooks/useMediaAuthentication'; import { useUserProfile } from '$hooks/useUserProfile'; import { getMxIdLocalPart, mxcUrlToHttp } from '$utils/matrix'; +import { AsyncStatus, useAsyncCallback } from '$hooks/useAsyncCallback'; +import { Room } from '$types/matrix-sdk'; +import { Command, useCommands } from '$hooks/useCommands'; -type CosmeticsProps = { - requestClose: () => void; +const log = createLogger('Cosmetics'); + +type CosmeticsSettingProps = { + userId: string; + room: Room; }; +export function CosmeticsNickname({ userId, room }: CosmeticsSettingProps) { + const mx = useMatrixClient(); -const log = createLogger('Cosmetics'); + const defaultDisplayName = room.getMember(userId)!.rawDisplayName; + const [displayName, setDisplayName] = useState(defaultDisplayName); + + const myRoomNick = useCommands(mx, room)[Command.MyRoomNick]; + const [changeState, changeDisplayName] = useAsyncCallback((name: string) => myRoomNick.exe(name)); + const changingDisplayName = changeState.status === AsyncStatus.Loading; + + useEffect(() => { + setDisplayName(defaultDisplayName); + }, [defaultDisplayName]); + + const handleChange: ChangeEventHandler = (evt) => { + const name = evt.currentTarget.value; + setDisplayName(name); + }; + + const handleReset = () => { + setDisplayName(defaultDisplayName); + }; + + const handleSubmit: FormEventHandler = (evt) => { + evt.preventDefault(); + if (changingDisplayName) return; + + const target = evt.target as HTMLFormElement | undefined; + const displayNameInput = target?.displayNameInput as HTMLInputElement | undefined; + const name = displayNameInput?.value; + if (!name) return; + + changeDisplayName(name); + }; + const hasChanges = displayName !== defaultDisplayName; + return ( + + + + + + + + ) + } + /> + + + + + + ); +} + +type CosmeticsProps = { + requestClose: () => void; +}; export function Cosmetics({ requestClose }: CosmeticsProps) { const mx = useMatrixClient(); const userId = mx.getUserId()!; @@ -114,10 +204,7 @@ export function Cosmetics({ requestClose }: CosmeticsProps) { direction="Column" gap="400" > - + Date: Sat, 7 Mar 2026 21:27:23 +0100 Subject: [PATCH 06/10] hide away room profile and display name in spaces (they're room only) --- .../common-settings/cosmetics/Cosmetics.tsx | 79 +++++++++++-------- 1 file changed, 48 insertions(+), 31 deletions(-) diff --git a/src/app/features/common-settings/cosmetics/Cosmetics.tsx b/src/app/features/common-settings/cosmetics/Cosmetics.tsx index 61f266153b..e4bc861301 100644 --- a/src/app/features/common-settings/cosmetics/Cosmetics.tsx +++ b/src/app/features/common-settings/cosmetics/Cosmetics.tsx @@ -1,5 +1,18 @@ import { ChangeEventHandler, FormEventHandler, useCallback, useEffect, useState } from 'react'; -import { Box, Text, IconButton, Icon, Icons, Scroll, Switch, Avatar, Input, config, Button, Spinner } from 'folds'; +import { + Box, + Text, + IconButton, + Icon, + Icons, + Scroll, + Switch, + Avatar, + Input, + config, + Button, + Spinner, +} from 'folds'; import { Page, PageContent, PageHeader } from '$components/page'; import { SequenceCard } from '$components/sequence-card'; import { SettingTile } from '$components/setting-tile'; @@ -176,36 +189,40 @@ export function Cosmetics({ requestClose }: CosmeticsProps) { Profile - - - ( - {nameInitials(defaultDisplayName)} - )} - /> - - } - /> - - - - + {!isSpace && ( + + + ( + {nameInitials(defaultDisplayName)} + )} + /> + + } + /> + + )} + {!isSpace && ( + + + + )} Date: Sat, 7 Mar 2026 21:40:44 +0100 Subject: [PATCH 07/10] allow being able to reset a room display name into the global display name --- .../common-settings/cosmetics/Cosmetics.tsx | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/app/features/common-settings/cosmetics/Cosmetics.tsx b/src/app/features/common-settings/cosmetics/Cosmetics.tsx index e4bc861301..8204b2a014 100644 --- a/src/app/features/common-settings/cosmetics/Cosmetics.tsx +++ b/src/app/features/common-settings/cosmetics/Cosmetics.tsx @@ -27,7 +27,7 @@ import { SequenceCardStyle } from '$features/common-settings/styles.css'; import { UserAvatar } from '$components/user-avatar'; import { nameInitials } from '$utils/common'; import { useMediaAuthentication } from '$hooks/useMediaAuthentication'; -import { useUserProfile } from '$hooks/useUserProfile'; +import { UserProfile, useUserProfile } from '$hooks/useUserProfile'; import { getMxIdLocalPart, mxcUrlToHttp } from '$utils/matrix'; import { AsyncStatus, useAsyncCallback } from '$hooks/useAsyncCallback'; import { Room } from '$types/matrix-sdk'; @@ -36,14 +36,16 @@ import { Command, useCommands } from '$hooks/useCommands'; const log = createLogger('Cosmetics'); type CosmeticsSettingProps = { + profile: UserProfile; userId: string; room: Room; }; -export function CosmeticsNickname({ userId, room }: CosmeticsSettingProps) { +export function CosmeticsNickname({ profile, userId, room }: CosmeticsSettingProps) { const mx = useMatrixClient(); const defaultDisplayName = room.getMember(userId)!.rawDisplayName; const [displayName, setDisplayName] = useState(defaultDisplayName); + const hasChanges = displayName !== defaultDisplayName; const myRoomNick = useCommands(mx, room)[Command.MyRoomNick]; const [changeState, changeDisplayName] = useAsyncCallback((name: string) => myRoomNick.exe(name)); @@ -59,7 +61,11 @@ export function CosmeticsNickname({ userId, room }: CosmeticsSettingProps) { }; const handleReset = () => { - setDisplayName(defaultDisplayName); + if (hasChanges) { + setDisplayName(defaultDisplayName); + } else { + setDisplayName(profile.displayName ?? getMxIdLocalPart(userId) ?? userId); + } }; const handleSubmit: FormEventHandler = (evt) => { @@ -74,7 +80,6 @@ export function CosmeticsNickname({ userId, room }: CosmeticsSettingProps) { changeDisplayName(name); }; - const hasChanges = displayName !== defaultDisplayName; return ( @@ -90,7 +95,7 @@ export function CosmeticsNickname({ userId, room }: CosmeticsSettingProps) { style={{ paddingRight: config.space.S200 }} readOnly={changingDisplayName} after={ - hasChanges && + displayName !== (profile.displayName ?? getMxIdLocalPart(userId) ?? userId) && !changingDisplayName && ( - + )} Date: Sun, 8 Mar 2026 09:33:42 +0100 Subject: [PATCH 08/10] allow inputting an empty name to reset the room display name --- src/app/features/common-settings/cosmetics/Cosmetics.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/app/features/common-settings/cosmetics/Cosmetics.tsx b/src/app/features/common-settings/cosmetics/Cosmetics.tsx index 8204b2a014..24d81fdff6 100644 --- a/src/app/features/common-settings/cosmetics/Cosmetics.tsx +++ b/src/app/features/common-settings/cosmetics/Cosmetics.tsx @@ -75,9 +75,8 @@ export function CosmeticsNickname({ profile, userId, room }: CosmeticsSettingPro const target = evt.target as HTMLFormElement | undefined; const displayNameInput = target?.displayNameInput as HTMLInputElement | undefined; const name = displayNameInput?.value; - if (!name) return; - changeDisplayName(name); + changeDisplayName(name ?? ''); }; return ( @@ -86,7 +85,6 @@ export function CosmeticsNickname({ profile, userId, room }: CosmeticsSettingPro Date: Mon, 9 Mar 2026 00:21:22 +0100 Subject: [PATCH 09/10] show room profile in cosmetics --- .../common-settings/cosmetics/Cosmetics.tsx | 71 ++++++++++++------- 1 file changed, 46 insertions(+), 25 deletions(-) diff --git a/src/app/features/common-settings/cosmetics/Cosmetics.tsx b/src/app/features/common-settings/cosmetics/Cosmetics.tsx index 24d81fdff6..14abaca5fa 100644 --- a/src/app/features/common-settings/cosmetics/Cosmetics.tsx +++ b/src/app/features/common-settings/cosmetics/Cosmetics.tsx @@ -30,20 +30,51 @@ import { useMediaAuthentication } from '$hooks/useMediaAuthentication'; import { UserProfile, useUserProfile } from '$hooks/useUserProfile'; import { getMxIdLocalPart, mxcUrlToHttp } from '$utils/matrix'; import { AsyncStatus, useAsyncCallback } from '$hooks/useAsyncCallback'; -import { Room } from '$types/matrix-sdk'; +import { Room, RoomMember } from '$types/matrix-sdk'; import { Command, useCommands } from '$hooks/useCommands'; const log = createLogger('Cosmetics'); type CosmeticsSettingProps = { profile: UserProfile; + member: RoomMember; userId: string; room: Room; }; -export function CosmeticsNickname({ profile, userId, room }: CosmeticsSettingProps) { +export function CosmeticsAvatar({ profile, member, userId, room }: CosmeticsSettingProps) { const mx = useMatrixClient(); - const defaultDisplayName = room.getMember(userId)!.rawDisplayName; + const useAuthentication = useMediaAuthentication(); + /* const avatarUrl = profile.avatarUrl + ? (mxcUrlToHttp(mx, profile.avatarUrl, useAuthentication, 96, 96, 'crop') ?? undefined) + : undefined; */ + const avatarMxc = member.getMxcAvatarUrl(); + const avatarUrl = + avatarMxc && (mxcUrlToHttp(mx, avatarMxc, useAuthentication, 96, 96, 'crop') ?? undefined); + + return ( + + ( + {nameInitials(room.getMember(userId)!.rawDisplayName)} + )} + /> + + } + /> + ); +} + +export function CosmeticsNickname({ profile, member, userId, room }: CosmeticsSettingProps) { + const mx = useMatrixClient(); + + const defaultDisplayName = member.rawDisplayName; const [displayName, setDisplayName] = useState(defaultDisplayName); const hasChanges = displayName !== defaultDisplayName; @@ -135,19 +166,13 @@ export function Cosmetics({ requestClose }: CosmeticsProps) { const profile = useUserProfile(userId); const room = useRoom(); const creators = useRoomCreators(room); + const member = room.getMember(userId)!; const powerLevels = usePowerLevels(room); const isSpace = room.isSpaceRoom(); const permissions = useRoomPermissions(creators, powerLevels); const canEditPermissions = permissions.stateEvent(StateEvent.RoomPowerLevels, mx.getSafeUserId()); - const useAuthentication = useMediaAuthentication(); - const avatarUrl = profile.avatarUrl - ? (mxcUrlToHttp(mx, profile.avatarUrl, useAuthentication, 96, 96, 'crop') ?? undefined) - : undefined; - - const defaultDisplayName = profile.displayName ?? getMxIdLocalPart(userId) ?? userId; - const getLevel = (eventType: string) => (powerLevels as any).events?.[eventType] ?? 50; const handleToggle = useCallback( @@ -199,20 +224,11 @@ export function Cosmetics({ requestClose }: CosmeticsProps) { direction="Column" gap="400" > - - ( - {nameInitials(defaultDisplayName)} - )} - /> - - } + )} @@ -223,7 +239,12 @@ export function Cosmetics({ requestClose }: CosmeticsProps) { direction="Column" gap="400" > - + )} Date: Mon, 9 Mar 2026 13:56:36 +0100 Subject: [PATCH 10/10] add room specific avatar interface --- .../common-settings/cosmetics/Cosmetics.tsx | 165 +++++++++++++++++- 1 file changed, 157 insertions(+), 8 deletions(-) diff --git a/src/app/features/common-settings/cosmetics/Cosmetics.tsx b/src/app/features/common-settings/cosmetics/Cosmetics.tsx index 14abaca5fa..a286f6ab1c 100644 --- a/src/app/features/common-settings/cosmetics/Cosmetics.tsx +++ b/src/app/features/common-settings/cosmetics/Cosmetics.tsx @@ -1,4 +1,11 @@ -import { ChangeEventHandler, FormEventHandler, useCallback, useEffect, useState } from 'react'; +import { + ChangeEventHandler, + FormEventHandler, + useCallback, + useEffect, + useMemo, + useState, +} from 'react'; import { Box, Text, @@ -12,6 +19,12 @@ import { config, Button, Spinner, + OverlayBackdrop, + Overlay, + OverlayCenter, + Modal, + Dialog, + Header, } from 'folds'; import { Page, PageContent, PageHeader } from '$components/page'; import { SequenceCard } from '$components/sequence-card'; @@ -32,6 +45,15 @@ import { getMxIdLocalPart, mxcUrlToHttp } from '$utils/matrix'; import { AsyncStatus, useAsyncCallback } from '$hooks/useAsyncCallback'; import { Room, RoomMember } from '$types/matrix-sdk'; import { Command, useCommands } from '$hooks/useCommands'; +import { useCapabilities } from '$hooks/useCapabilities'; +import { useObjectURL } from '$hooks/useObjectURL'; +import { createUploadAtom, UploadSuccess } from '$state/upload'; +import { useFilePicker } from '$hooks/useFilePicker'; +import { CompactUploadCardRenderer } from '$components/upload-card'; +import FocusTrap from 'focus-trap-react'; +import { ImageEditor } from '$components/image-editor'; +import { stopPropagation } from '$utils/keyboard'; +import { ModalWide } from '$styles/Modal.css'; const log = createLogger('Cosmetics'); @@ -43,19 +65,46 @@ type CosmeticsSettingProps = { }; export function CosmeticsAvatar({ profile, member, userId, room }: CosmeticsSettingProps) { const mx = useMatrixClient(); - const useAuthentication = useMediaAuthentication(); - /* const avatarUrl = profile.avatarUrl - ? (mxcUrlToHttp(mx, profile.avatarUrl, useAuthentication, 96, 96, 'crop') ?? undefined) - : undefined; */ + const capabilities = useCapabilities(); + const [alertRemove, setAlertRemove] = useState(false); + const disableSetAvatar = capabilities['m.set_avatar_url']?.enabled === false; + const avatarMxc = member.getMxcAvatarUrl(); const avatarUrl = avatarMxc && (mxcUrlToHttp(mx, avatarMxc, useAuthentication, 96, 96, 'crop') ?? undefined); + const [imageFile, setImageFile] = useState(); + const imageFileURL = useObjectURL(imageFile); + const uploadAtom = useMemo(() => { + if (imageFile) return createUploadAtom(imageFile); + return undefined; + }, [imageFile]); + + const pickFile = useFilePicker(setImageFile, false); + + const handleRemoveUpload = useCallback(() => { + setImageFile(undefined); + }, []); + + const myRoomAvatar = useCommands(mx, room)[Command.MyRoomAvatar]; + const handleUploaded = useCallback( + (upload: UploadSuccess) => { + const { mxc } = upload; + myRoomAvatar.exe(mxc); + handleRemoveUpload(); + }, + [myRoomAvatar, handleRemoveUpload] + ); + + const handleRemoveAvatar = () => { + myRoomAvatar.exe(''); + setAlertRemove(false); + }; + return ( } - /> + > + {uploadAtom ? ( + + + + ) : ( + + + {avatarUrl && + avatarUrl !== + mxcUrlToHttp(mx, profile.avatarUrl ?? '', useAuthentication, 96, 96, 'crop') && ( + + )} + + )} + + {imageFileURL && ( + }> + + + + + + + + + )} + + }> + + setAlertRemove(false), + clickOutsideDeactivates: true, + escapeDeactivates: stopPropagation, + }} + > + +
+ + Remove Room Avatar + + setAlertRemove(false)} radii="300"> + + +
+ + + Are you sure you want to remove room avatar? + + + +
+
+
+
+
); }