Add configurable sidebar nameplate background.
All checks were successful
Trigger cinny-mobile / dispatch (push) Successful in 2s

Render the equipped nameplate behind the larger settings avatar with blur-aware sidebar controls, adjustable opacity, and immediate collectible cache invalidation.
This commit is contained in:
2026-08-24 18:48:48 +10:00
parent 0cbc5d9a1c
commit d59945eb4c
6 changed files with 169 additions and 3 deletions

View File

@@ -12,8 +12,11 @@ import { useMediaAuthentication } from '../../../hooks/useMediaAuthentication';
import { Settings } from '../../../features/settings';
import { useUserProfile } from '../../../hooks/useUserProfile';
import { useOtherUserCollectibles } from '../../../hooks/useUserCollectibles';
import { pickAvatarDecorationUrl } from '../../../utils/collectibleAssets';
import { useSetting } from '../../../state/hooks/settings';
import { settingsAtom } from '../../../state/settings';
import { pickAvatarDecorationUrl, pickNameplateUrl } from '../../../utils/collectibleAssets';
import * as avatarDecorationCss from '../../../styles/AvatarDecoration.css';
import * as sidebarCss from '../../../components/sidebar/Sidebar.css';
import { Modal500 } from '../../../components/Modal500';
import { AccountSwitcher } from '../../../components/account-switcher';
import { stopPropagation } from '../../../utils/keyboard';
@@ -39,6 +42,11 @@ export function SettingsTab() {
: undefined;
const { assetUrls } = useOtherUserCollectibles(userId ?? '');
const avatarDecorationUrl = pickAvatarDecorationUrl(assetUrls);
const nameplateUrl = pickNameplateUrl(assetUrls);
const [sidebarNameplateOpacity] = useSetting(settingsAtom, 'sidebarNameplateOpacity');
const nameplateIsVideo = Boolean(
assetUrls['nameplate:animated'] || assetUrls['nameplate:asset.webm']
);
const openSettings = () => setSettings(true);
const closeSettings = () => setSettings(false);
@@ -53,12 +61,36 @@ export function SettingsTab() {
<SidebarItem active={settings}>
<SidebarAvatar
as="button"
className={sidebarCss.SidebarAvatarLarge}
onClick={openSettings}
onContextMenu={handleContextMenu}
style={{ overflow: 'visible' }}
>
<div className={avatarDecorationCss.SidebarAvatarStack}>
{sidebarNameplateOpacity > 0 &&
nameplateUrl &&
(nameplateIsVideo ? (
<video
className={sidebarCss.SidebarAvatarNameplate}
src={nameplateUrl}
style={{ opacity: sidebarNameplateOpacity / 100 }}
autoPlay
loop
muted
playsInline
aria-hidden="true"
/>
) : (
<img
className={sidebarCss.SidebarAvatarNameplate}
src={nameplateUrl}
style={{ opacity: sidebarNameplateOpacity / 100 }}
alt=""
draggable={false}
/>
))}
<UserAvatar
className={sidebarCss.SidebarAvatarForeground}
userId={userId ?? ''}
src={avatarUrl}
renderFallback={() => <Text size="H4">{nameInitials(displayName)}</Text>}