feat: make analytics real-time via WebSocket-triggered refresh
- Analytics panel now refreshes immediately when messages are created, updated, deleted, or analyzed - WebSocket events (message_created, message_updated, message_deleted, message_analyzed) trigger custom event 'analytics_refresh' - Analytics hook listens to 'analytics_refresh' event for instant updates - Auto-refresh interval lowered from 60s to 5s as fallback - Two-tier refresh: real-time push + 5s polling safety net Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
fed9f39bd9
commit
9a7b8f569d
+20
-4
@@ -65,13 +65,29 @@ export default function App() {
|
||||
userTimelinesRef.current.set(userIdHash, nextStart + audioBuffer.duration);
|
||||
}, [isListening]);
|
||||
|
||||
const triggerAnalyticsRefresh = useCallback(() => {
|
||||
window.dispatchEvent(new CustomEvent("analytics_refresh"));
|
||||
}, []);
|
||||
|
||||
const socket = useDashboardSocket({
|
||||
onUIState: (state) => setUIState((prev) => ({ ...prev, ...state })),
|
||||
onUserState: setActiveSpeakers,
|
||||
onMessageCreated: (message) => messages.setMessages((prev) => mergeMessages(prev, [message])),
|
||||
onMessageUpdated: (message) => messages.setMessages((prev) => prev.map((item) => (item.id === message.id ? { ...item, ...message } as MessageRecord : item))),
|
||||
onMessageDeleted: (message) => messages.setMessages((prev) => prev.map((item) => (item.id === message.id ? { ...item, type: "deleted" } : item))),
|
||||
onMessageAnalyzed: (message) => messages.setMessages((prev) => mergeMessages(prev, [message])),
|
||||
onMessageCreated: (message) => {
|
||||
messages.setMessages((prev) => mergeMessages(prev, [message]));
|
||||
triggerAnalyticsRefresh();
|
||||
},
|
||||
onMessageUpdated: (message) => {
|
||||
messages.setMessages((prev) => prev.map((item) => (item.id === message.id ? { ...item, ...message } as MessageRecord : item)));
|
||||
triggerAnalyticsRefresh();
|
||||
},
|
||||
onMessageDeleted: (message) => {
|
||||
messages.setMessages((prev) => prev.map((item) => (item.id === message.id ? { ...item, type: "deleted" } : item)));
|
||||
triggerAnalyticsRefresh();
|
||||
},
|
||||
onMessageAnalyzed: (message) => {
|
||||
messages.setMessages((prev) => mergeMessages(prev, [message]));
|
||||
triggerAnalyticsRefresh();
|
||||
},
|
||||
onAttachmentUploaded: () => messages.fetchMessages(selectedTextChannel).catch(() => undefined),
|
||||
onMediaState: media.setMediaState,
|
||||
onVoiceRecordingUploaded: (recording) => {
|
||||
|
||||
@@ -9,7 +9,7 @@ interface UseAnalyticsOptions {
|
||||
refreshIntervalMs?: number;
|
||||
}
|
||||
|
||||
export function useAnalytics({ guildId, channelId, hours = 24, autoRefresh = true, refreshIntervalMs = 60_000 }: UseAnalyticsOptions) {
|
||||
export function useAnalytics({ guildId, channelId, hours = 24, autoRefresh = true, refreshIntervalMs = 5_000 }: UseAnalyticsOptions) {
|
||||
const [overview, setOverview] = useState<AnalyticsOverview | null>(null);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
@@ -33,7 +33,7 @@ export function useAnalytics({ guildId, channelId, hours = 24, autoRefresh = tru
|
||||
load();
|
||||
}, [load]);
|
||||
|
||||
// Auto-refresh
|
||||
// Auto-refresh on interval
|
||||
useEffect(() => {
|
||||
if (!autoRefresh || !guildId) return;
|
||||
intervalRef.current = setInterval(load, refreshIntervalMs);
|
||||
@@ -42,6 +42,13 @@ export function useAnalytics({ guildId, channelId, hours = 24, autoRefresh = tru
|
||||
};
|
||||
}, [load, autoRefresh, refreshIntervalMs, guildId]);
|
||||
|
||||
// Real-time refresh via WebSocket-triggered custom event
|
||||
useEffect(() => {
|
||||
const handler = () => load();
|
||||
window.addEventListener("analytics_refresh", handler);
|
||||
return () => window.removeEventListener("analytics_refresh", handler);
|
||||
}, [load]);
|
||||
|
||||
return {
|
||||
overview,
|
||||
loading,
|
||||
|
||||
@@ -17,6 +17,7 @@ export interface DashboardSocketHandlers {
|
||||
onMediaState?: (state: MediaState) => void;
|
||||
onVoiceRecordingUploaded?: (recording: any) => void;
|
||||
onPcm?: (data: ArrayBuffer) => void;
|
||||
onAnalyticsRefresh?: () => void;
|
||||
}
|
||||
|
||||
export function useDashboardSocket(handlers: DashboardSocketHandlers) {
|
||||
|
||||
Reference in New Issue
Block a user