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:
@@ -0,0 +1,47 @@
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { useInstanceStore, type ConnectedInstance } from '../stores/instanceStore';
|
||||
import { useUIStore } from '../stores/uiStore';
|
||||
|
||||
/**
|
||||
* Watches instanceStore for status changes on remote instances and fires
|
||||
* toast notifications when connections are lost or restored.
|
||||
*/
|
||||
export function useFederationToasts() {
|
||||
const instances = useInstanceStore((s) => s.instances);
|
||||
const addToast = useUIStore((s) => s.addToast);
|
||||
const prevStatuses = useRef<Map<string, ConnectedInstance['status']>>(new Map());
|
||||
|
||||
useEffect(() => {
|
||||
const prev = prevStatuses.current;
|
||||
|
||||
for (const inst of instances) {
|
||||
const prevStatus = prev.get(inst.origin);
|
||||
if (prevStatus === undefined) {
|
||||
// First time seeing this instance — record but don't toast
|
||||
continue;
|
||||
}
|
||||
if (prevStatus === inst.status) continue;
|
||||
|
||||
const label = inst.label || (() => { try { return new URL(inst.origin).host; } catch { return inst.origin; } })();
|
||||
|
||||
if (
|
||||
prevStatus === 'connected' &&
|
||||
(inst.status === 'disconnected' || inst.status === 'error')
|
||||
) {
|
||||
addToast(`Lost connection to ${label} — reconnecting...`, 'warning');
|
||||
} else if (
|
||||
(prevStatus === 'disconnected' || prevStatus === 'error' || prevStatus === 'connecting') &&
|
||||
inst.status === 'connected'
|
||||
) {
|
||||
addToast(`Reconnected to ${label}`, 'success');
|
||||
}
|
||||
}
|
||||
|
||||
// Update prev statuses
|
||||
const next = new Map<string, ConnectedInstance['status']>();
|
||||
for (const inst of instances) {
|
||||
next.set(inst.origin, inst.status);
|
||||
}
|
||||
prevStatuses.current = next;
|
||||
}, [instances, addToast]);
|
||||
}
|
||||
Reference in New Issue
Block a user