Update visible node settings immediately after admin saves

Hop-State: A_06FP8ATA10D8VTQA9QBS6KR
Hop-Proposal: R_06FP8ASAVWCYV52CHF5AE1G
Hop-Task: T_06FP8AC8PWCNKR7C8686AXG
Hop-Attempt: AT_06FP8AC8PXWTNRRHT6JBPMG
This commit is contained in:
2026-07-14 22:06:26 -07:00
committed by Hop
parent 67b96d6725
commit e8a2dd2979
3 changed files with 52 additions and 3 deletions
+4
View File
@@ -91,6 +91,10 @@ export default function AdminPage() {
body: JSON.stringify(payload), body: JSON.stringify(payload),
}); });
if (res.ok) { if (res.ok) {
const data = await res.json().catch(() => ({}));
if (data.node) {
window.dispatchEvent(new CustomEvent('synapsis:node-updated', { detail: data.node }));
}
showToast('Settings saved!', 'success'); showToast('Settings saved!', 'success');
refreshAccentColor(); refreshAccentColor();
} else { } else {
+34 -2
View File
@@ -10,9 +10,18 @@ interface Admin {
avatarUrl: string | null; avatarUrl: string | null;
} }
interface NodeInfo {
name: string;
description: string;
longDescription: string;
rules: string;
bannerUrl: string;
admins: Admin[];
}
export function RightSidebar() { export function RightSidebar() {
const fallbackDescription = process.env.NEXT_PUBLIC_NODE_DESCRIPTION || 'A swarm social network node.'; const fallbackDescription = process.env.NEXT_PUBLIC_NODE_DESCRIPTION || 'A swarm social network node.';
const [nodeInfo, setNodeInfo] = useState({ const [nodeInfo, setNodeInfo] = useState<NodeInfo>({
name: process.env.NEXT_PUBLIC_NODE_NAME || 'Synapsis Node', name: process.env.NEXT_PUBLIC_NODE_NAME || 'Synapsis Node',
description: fallbackDescription, description: fallbackDescription,
longDescription: '', longDescription: '',
@@ -28,7 +37,7 @@ export function RightSidebar() {
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);
useEffect(() => { useEffect(() => {
fetch('/api/node', { cache: 'no-store' }) const loadNodeInfo = () => fetch('/api/node', { cache: 'no-store' })
.then(res => res.json()) .then(res => res.json())
.then(data => { .then(data => {
setNodeInfo(prev => ({ setNodeInfo(prev => ({
@@ -45,11 +54,34 @@ export function RightSidebar() {
.catch(() => { }) .catch(() => { })
.finally(() => setLoading(false)); .finally(() => setLoading(false));
const handleNodeUpdated = (event: Event) => {
const updatedNode = (event as CustomEvent<Partial<NodeInfo>>).detail;
if (!updatedNode) {
void loadNodeInfo();
return;
}
setNodeInfo(prev => ({
...prev,
...updatedNode,
name: updatedNode.name ?? prev.name,
description: updatedNode.description ?? prev.description,
longDescription: updatedNode.longDescription ?? prev.longDescription,
rules: updatedNode.rules ?? prev.rules,
bannerUrl: updatedNode.bannerUrl ?? prev.bannerUrl,
admins: updatedNode.admins ?? prev.admins,
}));
};
void loadNodeInfo();
window.addEventListener('synapsis:node-updated', handleNodeUpdated);
// Fetch version info // Fetch version info
fetch('/api/version') fetch('/api/version')
.then(res => res.json()) .then(res => res.json())
.then(data => setVersion(data)) .then(data => setVersion(data))
.catch(() => setVersion({ version: 'unknown', buildDate: null })); .catch(() => setVersion({ version: 'unknown', buildDate: null }));
return () => window.removeEventListener('synapsis:node-updated', handleNodeUpdated);
}, []); }, []);
if (loading) { if (loading) {
+14 -1
View File
@@ -36,7 +36,7 @@ export function Sidebar() {
const formattedHandle = user ? shortHandle(user.handle) : ''; const formattedHandle = user ? shortHandle(user.handle) : '';
useEffect(() => { useEffect(() => {
fetch('/api/node') const loadLogo = () => fetch('/api/node', { cache: 'no-store' })
.then(res => res.json()) .then(res => res.json())
.then(data => { .then(data => {
setCustomLogoUrl(data.logoUrl || null); setCustomLogoUrl(data.logoUrl || null);
@@ -44,6 +44,19 @@ export function Sidebar() {
.catch(() => { .catch(() => {
setCustomLogoUrl(null); setCustomLogoUrl(null);
}); });
const handleNodeUpdated = (event: Event) => {
const updatedNode = (event as CustomEvent<{ logoUrl?: string | null }>).detail;
if (updatedNode && 'logoUrl' in updatedNode) {
setCustomLogoUrl(updatedNode.logoUrl || null);
return;
}
void loadLogo();
};
void loadLogo();
window.addEventListener('synapsis:node-updated', handleNodeUpdated);
return () => window.removeEventListener('synapsis:node-updated', handleNodeUpdated);
}, []); }, []);
const fetchUnreadNotifications = useCallback(() => { const fetchUnreadNotifications = useCallback(() => {