feat: stateless federated identity resolver + federation UX improvements

Add identity.ts with isSelf() and resolveDisplayIdentity() — pure
stateless functions that detect replicated-self using the immutable
(username, homeInstance) composite key. No store lookups, no data
mutation. Fixes wrong avatar gradient and missing edit/delete on
own messages in remote channels.

Also includes: optimistic message dedup fix for cross-instance
messages (content-only matching), federation toast notifications,
Username component with @domain display, invite parser, and
deploy script simplification.
This commit is contained in:
Jannis Braun
2026-03-04 03:37:49 +01:00
parent 64fd8edfc9
commit dca9c4dc83
19 changed files with 713 additions and 110 deletions
@@ -2,6 +2,7 @@ import React from 'react';
import { useNavigate } from 'react-router-dom';
import type { User } from '@backspace/shared';
import { Avatar } from '../ui/Avatar';
import { Username } from '../ui/Username';
import { api } from '../../api/client';
import { useServerStore } from '../../stores/serverStore';
import { useUIStore } from '../../stores/uiStore';
@@ -77,12 +78,15 @@ export function UserProfilePopout({ user, onClose, position }: UserProfilePopout
{/* Name & info — flows naturally after avatar */}
<div>
<div className="text-[16px] font-semibold text-txt-primary leading-tight">
{displayName}
</div>
<div className="text-[13px] text-txt-tertiary">
@{user.username}
</div>
<Username
username={displayName}
className="text-[16px] font-semibold text-txt-primary leading-tight"
/>
{user.username.includes('@') ? (
<Username username={user.username} className="text-[13px] text-txt-tertiary" />
) : (
<div className="text-[13px] text-txt-tertiary">@{user.username}</div>
)}
{user.customStatus && (
<div className="text-[13px] text-txt-secondary italic mt-1">
{user.customStatus}