fix: federated space icon display/upload in settings, restyle settings panels

Fix three federation bugs in Space Settings: icon URL was double-wrapped
through home API, upload targeted home instance instead of remote, and
updateSpace used home API client. Also restyle settings panels (User,
Space, Members, Roles, Connected Instances) with consistent section
headers, grouped cards, and improved layout.
This commit is contained in:
Jannis Braun
2026-03-09 03:30:15 +01:00
parent d75788febd
commit 096251e5b0
8 changed files with 599 additions and 485 deletions
@@ -57,7 +57,7 @@ export function UserSettingsModal() {
return (
<Modal isOpen={isOpen} onClose={closeModal} title="User Settings" maxWidth="max-w-lg">
<div className="space-y-6">
<div className="space-y-5">
{/* Profile preview */}
<div className="flex items-center gap-4 p-4 bg-surface-channel rounded-lg">
<Avatar
@@ -83,89 +83,96 @@ export function UserSettingsModal() {
<div className="p-2 bg-status-online/10 border border-status-online/30 rounded text-status-online text-sm">{success}</div>
)}
{/* Profile section card */}
<div>
<label className="block text-xs font-bold text-txt-secondary uppercase mb-2">
Status
</label>
<select
value={status}
onChange={(e) => setStatus(e.target.value as any)}
className="w-full px-3 py-2 bg-surface-input rounded text-txt-primary outline-none focus:ring-2 focus:ring-accent-primary appearance-none"
>
<option value="online">Online</option>
<option value="idle">Idle</option>
<option value="dnd">Do Not Disturb</option>
</select>
<div className="text-[11px] font-semibold text-txt-tertiary uppercase tracking-wider mb-1.5">Profile</div>
<div className="rounded-lg bg-white/[0.02] p-3.5 space-y-4">
<div>
<label className="block text-xs text-txt-secondary mb-1.5">
Status
</label>
<select
value={status}
onChange={(e) => setStatus(e.target.value as any)}
className="w-full px-3 py-2 bg-surface-input rounded text-txt-primary outline-none focus:ring-2 focus:ring-accent-primary appearance-none"
>
<option value="online">Online</option>
<option value="idle">Idle</option>
<option value="dnd">Do Not Disturb</option>
</select>
</div>
<div>
<label className="block text-xs text-txt-secondary mb-1.5">
Display Name
</label>
<input
type="text"
value={displayName}
onChange={(e) => setDisplayName(e.target.value)}
className="w-full px-3 py-2 bg-surface-input rounded text-txt-primary outline-none focus:ring-2 focus:ring-accent-primary"
/>
</div>
<div>
<label className="block text-xs text-txt-secondary mb-1.5">
Custom Status
</label>
<input
type="text"
value={customStatus}
onChange={(e) => setCustomStatus(e.target.value)}
className="w-full px-3 py-2 bg-surface-input rounded text-txt-primary outline-none focus:ring-2 focus:ring-accent-primary"
placeholder="What are you up to?"
/>
</div>
</div>
</div>
{/* Voice Processing section card */}
<div>
<label className="block text-xs font-bold text-txt-secondary uppercase mb-2">
Display Name
</label>
<input
type="text"
value={displayName}
onChange={(e) => setDisplayName(e.target.value)}
className="w-full px-3 py-2 bg-surface-input rounded text-txt-primary outline-none focus:ring-2 focus:ring-accent-primary"
/>
</div>
<div>
<label className="block text-xs font-bold text-txt-secondary uppercase mb-2">
Custom Status
</label>
<input
type="text"
value={customStatus}
onChange={(e) => setCustomStatus(e.target.value)}
className="w-full px-3 py-2 bg-surface-input rounded text-txt-primary outline-none focus:ring-2 focus:ring-accent-primary"
placeholder="What are you up to?"
/>
</div>
{/* Voice Processing */}
<div className="border-t border-white/[0.06] pt-4">
<h3 className="text-xs font-bold text-txt-secondary uppercase mb-3">
<div className="text-[11px] font-semibold text-txt-tertiary uppercase tracking-wider mb-1.5">
Voice Processing
</h3>
<div className="flex items-center justify-between py-2">
<div>
<div className="text-sm text-txt-primary">AI Noise Suppression</div>
<div className="text-xs text-txt-tertiary">ML-based noise removal (RNNoise) filters keyboard, fans, and background noise</div>
</div>
<button
onClick={() => setRnnoiseEnabled(!rnnoiseEnabled)}
className={`relative w-10 h-5 rounded-full transition-colors ${rnnoiseEnabled ? 'bg-status-online' : 'bg-surface-input'}`}
>
<div className={`absolute top-0.5 left-0.5 w-4 h-4 rounded-full bg-white transition-transform ${rnnoiseEnabled ? 'translate-x-5' : 'translate-x-0'}`} />
</button>
</div>
<div className="flex items-center justify-between py-2">
<div>
<div className="text-sm text-txt-primary">Echo Cancellation</div>
<div className="text-xs text-txt-tertiary">Removes echo when using speakers</div>
<div className="rounded-lg bg-white/[0.02] p-3.5">
<div className="flex items-center justify-between py-2">
<div>
<div className="text-sm text-txt-primary">AI Noise Suppression</div>
<div className="text-xs text-txt-tertiary">ML-based noise removal (RNNoise) filters keyboard, fans, and background noise</div>
</div>
<button
onClick={() => setRnnoiseEnabled(!rnnoiseEnabled)}
className={`relative w-10 h-5 rounded-full transition-colors ${rnnoiseEnabled ? 'bg-status-online' : 'bg-surface-input'}`}
>
<div className={`absolute top-0.5 left-0.5 w-4 h-4 rounded-full bg-white transition-transform ${rnnoiseEnabled ? 'translate-x-5' : 'translate-x-0'}`} />
</button>
</div>
<button
onClick={() => setEchoCancellation(!echoCancellation)}
className={`relative w-10 h-5 rounded-full transition-colors ${echoCancellation ? 'bg-status-online' : 'bg-surface-input'}`}
>
<div className={`absolute top-0.5 left-0.5 w-4 h-4 rounded-full bg-white transition-transform ${echoCancellation ? 'translate-x-5' : 'translate-x-0'}`} />
</button>
</div>
<div className="flex items-center justify-between py-2">
<div>
<div className="text-sm text-txt-primary">Auto Gain Control</div>
<div className="text-xs text-txt-tertiary">Auto-adjusts mic volume can cause voice ducking during streams</div>
<div className="flex items-center justify-between py-2">
<div>
<div className="text-sm text-txt-primary">Echo Cancellation</div>
<div className="text-xs text-txt-tertiary">Removes echo when using speakers</div>
</div>
<button
onClick={() => setEchoCancellation(!echoCancellation)}
className={`relative w-10 h-5 rounded-full transition-colors ${echoCancellation ? 'bg-status-online' : 'bg-surface-input'}`}
>
<div className={`absolute top-0.5 left-0.5 w-4 h-4 rounded-full bg-white transition-transform ${echoCancellation ? 'translate-x-5' : 'translate-x-0'}`} />
</button>
</div>
<div className="flex items-center justify-between py-2">
<div>
<div className="text-sm text-txt-primary">Auto Gain Control</div>
<div className="text-xs text-txt-tertiary">Auto-adjusts mic volume can cause voice ducking during streams</div>
</div>
<button
onClick={() => setAutoGainControl(!autoGainControl)}
className={`relative w-10 h-5 rounded-full transition-colors ${autoGainControl ? 'bg-status-online' : 'bg-surface-input'}`}
>
<div className={`absolute top-0.5 left-0.5 w-4 h-4 rounded-full bg-white transition-transform ${autoGainControl ? 'translate-x-5' : 'translate-x-0'}`} />
</button>
</div>
<button
onClick={() => setAutoGainControl(!autoGainControl)}
className={`relative w-10 h-5 rounded-full transition-colors ${autoGainControl ? 'bg-status-online' : 'bg-surface-input'}`}
>
<div className={`absolute top-0.5 left-0.5 w-4 h-4 rounded-full bg-white transition-transform ${autoGainControl ? 'translate-x-5' : 'translate-x-0'}`} />
</button>
</div>
</div>