From a88882894185616d8d27527a850ab044123cb0f8 Mon Sep 17 00:00:00 2001 From: Jannis Braun <151788261+TheZwiss@users.noreply.github.com> Date: Mon, 23 Mar 2026 00:25:31 +0100 Subject: [PATCH] chore: gitignore installers and include pending web changes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add installers/ to .gitignore and remove from tracking — binaries should not be in git. Also includes: - Re-push Electron activities after WebSocket reconnect (sleep/wake) - Merge activity map instead of replacing to preserve local state - Nori mascot design plan --- .gitignore | 1 + packages/web/src/hooks/useWebSocket.ts | 13 ++++++++++++- packages/web/src/stores/activityStore.ts | 16 ++++++++++------ 3 files changed, 23 insertions(+), 7 deletions(-) diff --git a/.gitignore b/.gitignore index 811fa9c4..b4b3f518 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ node_modules/ # Build output dist/ dist-electron/ +installers/ packages/web/dist/ packages/server/dist/ packages/shared/dist/ diff --git a/packages/web/src/hooks/useWebSocket.ts b/packages/web/src/hooks/useWebSocket.ts index 584a15a1..cf152b2b 100644 --- a/packages/web/src/hooks/useWebSocket.ts +++ b/packages/web/src/hooks/useWebSocket.ts @@ -5,7 +5,7 @@ import { useChatStore } from '../stores/chatStore'; import { useVoiceStore } from '../stores/voiceStore'; import { useSocialStore } from '../stores/socialStore'; import { useSettingsStore } from '../stores/settingsStore'; -import type { ServerEvent, ClientEvent, ActiveCallInfo } from '@backspace/shared'; +import type { ServerEvent, ClientEvent, ActiveCallInfo, Activity } from '@backspace/shared'; import { resolveAssetUrl, normalizeUserAssets, normalizeMessageAssets } from '../utils/assetUrls'; import { broadcastVoiceStatus, broadcastDeafenViaLiveKit } from '../utils/voice'; import { registerSelfId } from '../utils/identity'; @@ -214,6 +214,17 @@ function handleEvent(origin: string, event: ServerEvent): void { useActivityStore.setState({ showActivity: event.user.showActivity }); } + // Re-push local Electron activities after reconnect (sleep/wake, network blip, etc.) + // The process scanner keeps running but onActivityDetected only fires on change, + // so if the same app was active before and after sleep, nothing would re-push. + if (isHome && window.backspace?.getCurrentActivity) { + window.backspace.getCurrentActivity().then((activity: unknown) => { + if (activity) { + useActivityStore.getState().pushActivities([activity as Activity]); + } + }).catch(() => {}); + } + // Populate voice user statuses (mute/deafen/camera/screenshare) from server if (event.voiceUserStates) { for (const [uid, status] of Object.entries(event.voiceUserStates)) { diff --git a/packages/web/src/stores/activityStore.ts b/packages/web/src/stores/activityStore.ts index 6c20226c..d4f927ce 100644 --- a/packages/web/src/stores/activityStore.ts +++ b/packages/web/src/stores/activityStore.ts @@ -41,13 +41,17 @@ export const useActivityStore = create((set, get) => ({ }, initActivities: (activityMap) => { - const next = new Map(); - for (const [userId, activities] of Object.entries(activityMap)) { - if (activities.length > 0) { - next.set(userId, activities); + set((state) => { + const next = new Map(state.userActivities); + for (const [userId, activities] of Object.entries(activityMap)) { + if (activities.length > 0) { + next.set(userId, activities); + } else { + next.delete(userId); + } } - } - set({ userActivities: next }); + return { userActivities: next }; + }); }, setShowActivity: (show) => {