Commit Graph

183 Commits

Author SHA1 Message Date
Sravan a33ed27ffe feat(chat): per-chat drafts + fix emoji picker closing on tab switch
- Unsent text is saved per conversation (survives switching chats and reloads) and restored
  when you reopen the chat; cleared on send. (#1)
- Emoji picker: stopPropagation on tab/grid clicks so switching category no longer closes it
  (the re-render was detaching the clicked node -> outside-click handler fired). (#6)
build batch23.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 11:55:14 +05:30
Sravan 3f209bf619 feat(desktop): real Windows inline reply via SnoreToast -tb + sender/group avatar
- node-notifier's WindowsToaster forwards raw opts to SnoreToast, so inject -tb (reply box)
  + -p (image). Reuses its named-pipe + result parsing (exit 5 = TextEntered). No pwsh needed.
  Logs the raw toast result to userData/toast-debug.log to confirm the reply field on real HW.
- home.html: notifAvatarDataUrl draws the DM sender's pic / group's DP (else colored initials)
  to a round PNG and passes it as the toast image. Reply -> sendReplyTo; click -> open chat.
- dropped powertoast (ESM + needs pwsh 7, absent here). build batch22.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 23:26:24 +05:30
Sravan 21ae3e1aa5 feat(desktop): Phase D — inline-reply notifications (Windows toast reply box)
Reply to a chat straight from the OS notification, no app switch:
- node-notifier (bundles SnoreToast) renders a native Windows toast with a reply box —
  Electron's own Notification can't do Windows inline reply.
- main.js reply-notification handler resolves {text}|{open}|null; preload exposes replyNotify.
- home.html notify() routes chat toasts through it on desktop: a typed reply -> sendReplyTo()
  POSTs to /api/messages without opening the app; a click opens the chat. Web/PWA path unchanged.
- Works only in the installed app (needs the installer's AppUserModelID). desktop 0.1.2, build batch21.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 22:36:02 +05:30
Sravan 160a66f934 fix(landing): Windows logo on the Download button (signals it's the Windows app)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 22:27:31 +05:30
Sravan 9ff2ef5d48 feat(dashboard): "App installs" view + compact top-right Download button
- dashboard.html: admin "App installs" card — table of user · platform · version · OS ·
  first/last seen, from GET /api/v1/admin/installs (loadInstalls).
- index.html: replaced the long inline link with a compact white "Download app" button in
  the blue top header (top-right); hidden when already inside the desktop app.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 22:16:38 +05:30
Sravan 899770ed02 feat: Windows download link + self-served update feed + install tracking
Downloads/updates:
- config: DOWNLOADS_DIR (override to a mounted volume in prod).
- static.js: serves /downloads/* (installer, latest.yml, .blockmap) with range support for
  resumable + differential auto-updates; /download/windows redirects to the current .exe
  (stable link). Landing page gets a "Download the Windows desktop app" button (hidden in-app).

Install tracking (who installed the app):
- db app_installs + repos.appInstalls (upsert by install_id, fills in the user on sign-in).
- POST /api/v1/telemetry/install (records install + user once authenticated);
  GET /api/v1/admin/installs (admin: list installs with user/version/os/last-seen).
- desktop main.js: stable per-install id in userData, exposed via preload
  (bizConnectNative.installId/version/os); home.html reportInstall() posts it after login.
- e2e: +2 checks (telemetry recorded, admin sees it). 119/119. build batch20.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 21:28:53 +05:30
Sravan e5c94ebf6d fix: login submits on Enter (real <form>) + desktop notifications show "Biz Connect"
- home.html: login is now a real <form> with a submit button, so Enter (or click) both
  submit natively — replaces the ad-hoc keydown handler. (build batch19; header stays removed)
- desktop/main.js: app.setAppUserModelId('com.bizgaze.connect.desktop') so Windows resolves
  the installed shortcut and toasts read "Biz Connect" instead of "electron.app.BizConnect".
- desktop version → 0.1.1; installer rebuilt.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 18:19:01 +05:30
Sravan 2404538270 fix(ui): modern thin scrollbars app-wide (remove classic up/down arrows)
Only the chat LIST had styled scrollbars; the chat message area and every other scroll
region fell back to the OS scrollbar, which in the Electron/Windows shell shows classic
up/down stepper arrows. Added a global ::-webkit-scrollbar style (thin, rounded thumb,
scrollbar-button hidden) + scrollbar-width:thin to home.html, share.html, connect.html,
dashboard.html. (home build batch18)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 16:46:40 +05:30
Sravan 1ca0b836e1 feat(desktop): unread-chat count badge on the taskbar icon
Mirrors the rail's unread-chat count onto the Windows taskbar icon (overlay) and the
macOS/Linux dock badge. updateRailUnread() draws a small red count badge on a canvas
and hands it to the shell via bizConnectNative.setUnread(count, dataUrl); main sets it
with win.setOverlayIcon + app.setBadgeCount. Clears at 0, shows 99+ past 99. No-op in a
browser/mobile. (home.html build batch17)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 16:28:15 +05:30
Sravan 5a98ae4d34 feat(desktop): media/notification permissions + notification raises the app
- desktop/main.js: grant media (camera/mic), display-capture, notifications, clipboard,
  fullscreen, pointerLock for the app origin (Electron denies these by default, which
  silently broke meetings' camera/mic). Adds setPermissionRequestHandler +
  setPermissionCheckHandler on the app session.
- Clicking a notification now raises + focuses the window: preload exposes
  bizConnectNative.focusApp(), main handles 'focus-window' IPC, and the web notify()
  onclick calls it when running in the desktop shell. (home.html build batch16)
- CLIENTS.md: Phase D — inline-reply notifications (Windows Toast RemoteInput /
  Android RemoteInput / iOS UNTextInputNotificationAction) queued right after packaging.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 16:16:40 +05:30
Sravan 7a2ab3fc8d fix(agent): remote-control input now works (data channel + nut-js API)
Two latent bugs that broke input control on any setup:
- Data channel was created by the viewer (the answerer), so the agent's offer had
  no SCTP m-line and the channel never opened -> no input reached the agent. The
  agent (offerer) now creates the 'input' channel; the viewer receives it.
- inject.js used nut.screen.getResolution() which doesn't exist in this nut-js;
  switched to screen.width()/height() with per-session caching.

Verified end-to-end locally: screen streams + mouse injection moves the remote cursor.
Also commits desktop/ + mobile/ package-lock.json from client installs.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 15:47:09 +05:30
Sravan 7ae0cacf74 feat(push): wire Capacitor native push into the web UI
home.html: in a Capacitor app shell, setupPush() now uses the native FCM/APNs path
instead of Web Push — requests permission, registers, POSTs the OS device token to
/api/v1/devices, deep-links on notification tap (selectChat), and unregisters the
token on logout. Web Notification prompts are suppressed on native. Fully inert in a
normal browser (Web Push unchanged). build batch15.

CLIENTS.md Phase B push items checked off.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 19:56:59 +05:30
Sravan 06f0b08a18 feat(chat): rich shared-media view, status selector, drag-drop upload + fixes
Chat / shared media:
- Media/Docs/Links: clean underline tabs (green active), audio & video now
  classified as Media and rendered as tiles (download + headphone/play +
  duration) instead of broken-image glyphs; image thumbnails -> lightbox
- Drag-and-drop a file/video/image onto a conversation to send it
- Fix: removed #chatPanel{position:relative} override that collapsed the
  conversation pane (messages spilled into a clipped right-edge strip)
- "Media, links & docs" row cleaned up (no folder/placeholder icon); media
  popup keeps the back arrow, drops the redundant close button

Presence / status:
- Single current-status row with an arrow that expands Available/Away/On leave
- On leave = circle with minus, In a call = solid red indicators
- Fix: selected-status tick now follows the chosen option

Icons: added headphones + play; bumped icons.js cache-bust to v4

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 17:01:15 +05:30
Sravan e9e5c7f406 fix(pwa): white icon tile for contrast + cache-bust icon URLs (v2)
Logo was dark-on-blue (low contrast); now centered on a white tile like the
header treatment. Icon URLs versioned (?v=2) so browsers/installs fetch the new
ones. Build marker -> pwa2.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 15:02:11 +05:30
Sravan b576ed372a feat(pwa): installable app (Add to Home Screen) for Android + iOS
- manifest.json (standalone display, theme color, maskable icons 192/512).
- generated square icons + apple-touch-icon (180) from the logo.
- apple-mobile-web-app + theme-color meta in home.html.
- sw.js gets a no-op fetch handler so it meets installability criteria (still
  no caching). static.js serves .json/.webmanifest with correct MIME.
- Installing as a PWA also unlocks Web Push on iOS (Apple requires Add to Home Screen).
Build marker -> pwa1.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 17:13:01 +05:30
Sravan f4a23ae805 fix(cache): serve HTML with no-store so deploys reach browsers without a hard refresh
Browsers were serving a cached old home.html on normal reloads (only incognito/
hard-refresh got the new one). HTML now sends Cache-Control: no-store; versioned
assets keep ETag revalidation. Bumps build marker to push4.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 16:30:17 +05:30
Sravan f7ddb2e7ae fix(push): wait for active SW before subscribe + log every step (subscribe was failing silently)
subscribePush() swallowed all errors, so if pushManager.subscribe() failed
(e.g. called before the service worker was active) nobody ever subscribed and
there was no trace. Now: await serviceWorker.ready before subscribing, and
console.log/warn each step so the real failure is visible. Server send path
verified independently (web-push builds valid VAPID requests).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 13:57:03 +05:30
Sravan 5edb3fa241 fix(chat): dedup sent message in sendMessage too (WS echo can beat the POST response)
The server echoes the sender's own message over WS before returning the HTTP
response, so onChatMessage could append it before sendMessage's await resolved,
then sendMessage appended again -> double. Both append paths now dedup by id.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 13:39:42 +05:30
Sravan 88d7657364 chore: add build marker (window.__BUILD) to home.html for deploy verification
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 12:38:35 +05:30
Sravan 1272b81cee feat(push): Web Push notifications for backgrounded/closed/mobile tabs
Page-level Notifications can't fire when a tab is frozen/closed (and never on
mobile), which is why recipients on another tab/app got nothing. Adds a
notification-only service worker (sw.js, no caching) + Web Push:

- push.js: optional web-push wrapper (no-op unless web-push installed AND
  VAPID_PUBLIC_KEY/VAPID_PRIVATE_KEY set -> app unaffected if unconfigured).
- push_subscriptions table + R.pushSubs repo (upsert by endpoint, prune dead).
- /api/push/vapid|subscribe|unsubscribe; DM + group message routes also send a
  Web Push to recipients.
- Client registers /sw.js, subscribes when permission granted; hidden-tab popups
  are left to push to avoid double-notifying (pushActive flag); SW suppresses the
  OS popup when a tab is visible. Removes the old code that unregistered SWs.

Requires (prod, once): npm install + VAPID_PUBLIC_KEY/VAPID_PRIVATE_KEY/VAPID_SUBJECT env.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 21:58:49 +05:30
Sravan d50d4bde47 fix(icons): proper end-call (hang-up) glyph + cache-bust icons.js (v3)
- callEnd is now a rotated-handset hang-up icon (was a phone-off placeholder).
- All pages reference /icons.js?v=3 so browsers/proxies fetch the corrected
  file instead of a stale cached copy (fixes 'old end icon' + icons not
  appearing until a re-render when an old/404 icons.js was cached).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 18:47:24 +05:30
Sravan 1f4516d69b fix(chat): dedup own echoed message so sent messages don't show twice
Server echoes your own message back over WS (multi-tab/device sync) and
sendMessage already appended it optimistically; onChatMessage now skips the
append if the id is already in the thread.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 18:06:00 +05:30
Sravan fcd6a60baa fix(prod): add missing public/icons.js (was untracked -> 404 in prod)
icons.js was never committed (untracked, lost from disk), so every page
404'd /icons.js and stalled at Loading. Restored from commit e05a788 and
added 16 icons referenced by current code but absent in that snapshot
(bell, bold, italic, strikethrough, code, list, listOrdered, type, crown,
checkCheck, calendarX, calendarClock, fileText, record, callEnd, settings).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 17:41:44 +05:30
Sravan bda63b6f0a Merge origin/master (TURN/coturn + BizGaze-only login) into feature tree
Resolved conflicts in routes.js and share.html: kept the dev tree's superset
(ALLOW_LOCAL_LOGIN dev escape, avatar sync, richer login errors) which already
includes the incoming production BizGaze-only behavior; took the more descriptive
incoming comments. Restored 5 untracked modules (chat, calls, directory,
reminders, webhooks) that were missing from disk — required by routes/signaling.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 16:27:59 +05:30
Sravan 27355cec76 BizGaze Connect: chat, meetings, recordings, mobile, directory + UI fixes
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 16:15:29 +05:30
Sravan 54b74d5db1 feat(turn): self-hosted coturn support + time-limited creds + failure UX
- /api/ice: when TURN_SECRET is set, mint short-lived HMAC credentials
  (coturn use-auth-secret) so no permanent password is exposed and the relay
  can't be abused. Static TURN_USERNAME/CREDENTIAL still supported.
- share.html: connection watchdog + clear "couldn't connect on this network"
  message instead of a blank screen when no path can be established.
- deploy/coturn: ready-to-run turnserver.conf + docker-compose + README for
  hosting our own TURN on a VM we own (flat cost, no per-GB billing).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 14:36:05 +05:30
Sravan 6ac280f178 fix(webrtc): use TURN on desktop too (screen share blank/disconnect)
TURN relay candidates were applied only when IS_MOBILE, leaving desktop
clients STUN-only. Customers behind symmetric NAT / corporate firewalls /
VPNs then couldn't establish the peer connection -> connectionState 'failed'
-> "connection lost" -> blank screen right after granting permissions. This
hit only some users (those needing a relay).

Apply the /api/ice config (STUN + managed TURN) regardless of device, in both
the customer (share.html) and agent (connect.html) flows. Requires TURN_URLS /
TURN_USERNAME / TURN_CREDENTIAL to be set in the production environment.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 13:15:06 +05:30
Sravan ba8bfc3f46 feat: BizGaze Connect home, BizGaze login, modular backend, /api/v1
User-facing
- New post-login home (/home): chat rail + Share/Connect (embedded) + Meeting; login lives here when logged out
- Landing: "Log in with BizGaze" + no-login screen share
- Console replaced by a role-scoped Dashboard (/dashboard): admins see all team sessions, others see only their own; stats + CSV/PDF export
- Recordings saved as MP4 (H.264/AAC) with WebM fallback; old .webm still downloadable
- Fix: duplicate "Sign in" on the login card

Auth / integration
- BizGaze as identity provider: /api/login validates against BIZGAZE_LOGIN_URL (env-gated) and provisions a local user
- Phase 2 start: /api/v1 alias for all /api routes; Authorization: Bearer accepted across HTTP + WS; login returns a token (for native desktop/mobile clients)

Backend refactor (Phase 1, behavior-preserving)
- Split server.js into config/lib/session/presence/routes/static/signaling + repos (data-access) + bizgaze (service)
- All SQL behind repos.js, tenant-scoped (tenantId == team_id for now)
- e2e updated to current flow (21/21 pass before and after)

Docs: ARCHITECTURE.md (target architecture + phased plan), CLAUDE.md repo layout, .env.example BIZGAZE_LOGIN_URL

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-12 00:40:07 +05:30
Sravan 1d9ffcc3d4 Mobile screen share bug fix 2026-06-10 16:47:14 +05:30
Sravan 28f616d829 Added Record screen, transcribe, mobile screen share bug fix. 2026-06-10 16:46:03 +05:30
Sravan 3e24cacc39 Mobile Browser connection fix. 2026-06-10 15:47:02 +05:30
Sravan 3560e1756e managed TURN (mobile/cellular fix) + UI bug fixes
- server: /api/ice endpoint reads TURN creds from env (TURN_URLS/USERNAME/CREDENTIAL)
- share/connect: load ICE config at page open
- fixes: stop icon, bright chat notification, beep audio-unlock,
  customer screen cleanup on session end, Home link, Remember-me on agent login, Time spent fixed from 90 seconds to actual time spent
2026-06-09 16:47:43 +05:30
sriram b984b55bc0 first commit 2026-06-05 17:29:09 +05:30