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
@@ -0,0 +1,29 @@
import React from 'react';
import { useUIStore } from '../../stores/uiStore';
const borderColors = {
info: 'border-l-accent-sky',
warning: 'border-l-accent-amber',
success: 'border-l-accent-mint',
} as const;
export function ToastContainer() {
const toasts = useUIStore((s) => s.toasts);
const removeToast = useUIStore((s) => s.removeToast);
if (toasts.length === 0) return null;
return (
<div className="fixed bottom-6 right-6 z-[300] flex flex-col gap-2 pointer-events-none">
{toasts.map((toast) => (
<div
key={toast.id}
className={`glass-pill border-l-2 ${borderColors[toast.type]} rounded-[10px] px-4 py-2.5 max-w-[320px] animate-slide-up pointer-events-auto cursor-pointer`}
onClick={() => removeToast(toast.id)}
>
<span className="text-sm text-txt-primary leading-snug">{toast.message}</span>
</div>
))}
</div>
);
}