Commit Graph
100 Commits
Author SHA1 Message Date
Jannis Braun edb050fd39 feat: add category settings context menu, lock icon, empty category hiding 2026-03-21 18:38:47 +01:00
Jannis Braun 892164f3a5 refactor: use extracted PermissionsEditor in ChannelSettingsModal 2026-03-21 18:35:38 +01:00
Jannis Braun c43afc23a8 feat: extract TriStateToggle, OverrideEntry, PermissionsEditor shared components 2026-03-21 18:35:35 +01:00
Jannis Braun 637e083e9a feat: add category override API endpoints, fix channel categoryId reassignment, include isPrivate on categories
- Add GET/PUT/DELETE /api/categories/:id/overrides endpoints with
  privilege escalation guard matching existing channel override pattern
- Add isCategoryPrivate() and broadcastCategoryOverrideChange() helpers
  that cascade visibility changes to all channels in a category
- Fix PATCH /api/channels/:id to recompute permissions via
  broadcastOverrideChange when categoryId changes (different category
  overrides may apply)
- Include isPrivate flag on categories in GET /api/spaces/:id payload
  using batch-fetched @everyone overrides
- Include isPrivate on categories in broadcastChannelLayout and
  PATCH /api/categories/:id broadcasts
2026-03-21 18:29:25 +01:00
Jannis Braun b5ac7d3ee4 feat: add category override API client methods 2026-03-21 18:29:16 +01:00
Jannis Braun 17289445bd feat: add categorySettings modal type to uiStore 2026-03-21 18:25:56 +01:00
Jannis Braun bfe317f465 feat: interleaved category override resolution in permission engine 2026-03-21 18:22:22 +01:00
Jannis Braun 1473f4f88c fix: emoji reaction picker no longer overflows viewport on bottom messages 2026-03-21 18:21:30 +01:00
Jannis Braun eb04c4ad30 feat: add category_overrides table schema and migration 2026-03-21 18:20:21 +01:00
Jannis Braun 90d702338d feat: add slideDown animation for upward-flipping popovers 2026-03-21 18:20:02 +01:00
Jannis Braun 3300ce8d5c feat: add CategoryOverride type and isPrivate to ChannelCategory 2026-03-21 18:19:45 +01:00
Jannis Braun 448ff9a59c fix: exclude desktop, installers, and other non-Docker files from deploy rsync 2026-03-21 17:42:13 +01:00
Jannis Braun fe6de6456a feat: add ffmpeg to Docker runtime for video thumbnail generation 2026-03-21 17:23:19 +01:00
Jannis Braun 80d97d72c9 feat: add backfill migration for media dimensions and video thumbnails 2026-03-21 17:22:44 +01:00
Jannis Braun 7ec61c16fd feat: use aspect-ratio and preload=none for video/image attachments 2026-03-21 17:20:54 +01:00
Jannis Braun 561c9bc4f3 feat: include width, height, duration in all attachment serialization 2026-03-21 17:20:04 +01:00
Jannis Braun 7c767b580a feat: extract media dimensions and video thumbnails on upload 2026-03-21 17:18:59 +01:00
Jannis Braun d0f33446de feat: add video thumbnail generation and media metadata extraction 2026-03-21 17:16:40 +01:00
Jannis Braun b74e33b349 feat: add width, height, duration columns to attachments schema 2026-03-21 17:15:09 +01:00
Jannis Braun 948fa6de5c feat(desktop): add remote dictionary sync engine to activity detector
Refactor loadDictionary to accept a file path and support both legacy
bare-array (version 0) and versioned object formats. Add background
sync that fetches the latest games.json from GitHub, uses ETag-based
conditional requests (304 support), atomic cache writes, and hot-swaps
processMap/gameEntries without resetting current detection state.
On startup, the best local source (cache vs bundled seed) is loaded
immediately for instant detection, then sync runs fire-and-forget.
2026-03-21 04:12:21 +01:00
Jannis Braun 228ffe4894 feat(desktop): expand game dictionary to 249 entries with versioned schema
Rewrite games.json from bare array (28 entries) to versioned format
{ version: 1, games: [...] } with 249 entries covering top Steam games,
competitive titles, AAA, indie, survival/craft, simulation, horror,
fighting, racing, MMOs, and media apps (Spotify, VLC, OBS, mpv).
Every process name is specific enough to avoid false-positive detection.
2026-03-21 04:12:15 +01:00
Jannis Braun 156189dfa2 fix: redesign activity cards with glass-pill material and accent borders
Replace bg-surface-elevated cards and inline text badges with glass-pill
rows featuring colored left borders (mint=playing, sky=listening,
lavender=watching, rose=streaming). Identical treatment in both
ActivityPanel and MemberSidebar — no more compact/full distinction.
Members with rich activities get the frosted glass row; others stay plain.
2026-03-21 03:50:09 +01:00
Jannis Braun 2c122d066e fix: add console warnings for invalid games.json entries 2026-03-21 03:00:14 +01:00
Jannis Braun 0f4f129337 feat(desktop): add automatic game/app activity detection
Add cross-platform process scanning that detects running games and apps,
then broadcasts them as Rich Presence activities via the existing Phase 1
pipeline (activityStore -> WS -> other users).

- games.json dictionary with 26 entries (games, Spotify, VLC, OBS)
- activityDetector module: polls OS process list every 15s via execFile,
  matches against dictionary, emits IPC on state change only
- IPC bridge in main.ts/preload.ts with cleanup on quit
- Frontend activityBridge subscribes to IPC and feeds activityStore
- Supports Windows (tasklist CSV), macOS (ps -c), Linux (ps)
2026-03-21 02:57:30 +01:00
Jannis Braun 568b049b22 ci: add GitHub Actions workflow for desktop release builds
Triggers on v* tag push, builds for Windows, macOS (arm64), and Linux.
Uses electron-builder --publish to upload artifacts to GitHub Releases.
2026-03-21 02:32:43 +01:00
Jannis Braun 2593f7075c feat(desktop): add version display and check-for-updates to account settings 2026-03-21 02:32:19 +01:00
Jannis Braun a9fcdb72a8 feat(desktop): add manual download fallback to UpdateToast
Extends UpdateToast to handle update-error events from the preload bridge,
showing a "Download" link to the GitHub release URL when auto-update fails.
2026-03-21 02:31:20 +01:00
Jannis Braun 6ebb124d25 feat(desktop): update preload bridge types for enhanced update-error and getVersion 2026-03-21 02:30:06 +01:00
Jannis Braun a7d5abfca9 feat(desktop): enhance update-error payload with release URL, add get-app-version IPC 2026-03-21 02:29:42 +01:00
Jannis Braun a234041210 feat(desktop): switch auto-update provider from generic to github 2026-03-21 02:29:28 +01:00
Jannis Braun 9e4878c48f fix: move showActivity toggle from Account to Privacy settings panel 2026-03-21 02:13:32 +01:00
Jannis Braun 1f4e149ee1 feat: add frontend Rich Presence — activityStore, ActivityCard, sidebar upgrades, settings toggle
- Task 7: Create activityStore (Zustand) with Map<userId, Activity[]>, showActivity toggle,
  debounced pushActivities, and reset on logout
- Task 8: Wire WS integration — presence_update propagates activities to store,
  ready payload initializes userActivities and showActivity (via setState to avoid side effects)
- Task 9: Create ActivityCard component with compact/full modes, type-colored labels,
  elapsed time display, asset images, and fallback to customStatus
- Task 10: Upgrade ActivityPanel to three groups — active friends (full cards, no header),
  online friends (compact), offline friends — using getPrimaryActivity for grouping
- Task 11: Upgrade MemberSidebar to show compact ActivityCards instead of raw customStatus
- Task 12: Add showActivity toggle in AccountPanel settings (Activity Status section)
  with API persistence and store sync
2026-03-21 01:55:17 +01:00
Jannis Braun 9403ded8da feat: add showActivity toggle to PATCH @me with activity broadcast clear
- Accept showActivity boolean in PATCH /api/users/@me body
- Validate and persist as integer in DB
- Update ConnectionManager cache on toggle
- Broadcast empty activities via presence_update when toggled off
2026-03-21 01:49:41 +01:00
Jannis Braun ceb8894d58 feat: add WS activity_update handler and enhanced presence_update with activities
- Add validateActivities() with full field validation against ACTIVITY_LIMITS
- Add handleActivityUpdate() with showActivity gate and rate limiting
- Enhance handlePresenceUpdate() to include activities in broadcast payload
- Update status cache via connectionManager.setUserStatus() on presence change
- Wire activity_update case into event router switch statement
2026-03-21 01:48:57 +01:00
Jannis Braun d4366a2207 feat: add ConnectionManager in-memory activity state and ready payload
Add Rich Presence infrastructure to ConnectionManager:
- Four new Maps: userActivities, userShowActivity, userStatuses, lastActivityUpdate
- Public accessors: set/get/clear activities, showActivity, status, rate limit check
- Cleanup in finalizeDisconnect() and forceDisconnectUser()
- Cache showActivity and status from DB at auth time in buildReadyPayload()
- Assemble userActivities snapshot in ready payload with customStatus fallback
- Include activities: [] in offline presence_update broadcast
2026-03-21 01:44:36 +01:00
Jannis Braun bc408235c9 feat: add Activity type system, DB migration, and self-only showActivity in sanitizeUser
- Add Activity, ActivityType, ActivityTimestamps, ActivityAssets types to shared types
- Add activity_update client event and activities field on presence_update server event
- Add userActivities to ready payload and showActivity to User/UpdateUserRequest
- Create shared activities.ts with ACTIVITY_LIMITS, ACTIVITY_PRIORITY, getPrimaryActivity
- Add show_activity column to users table (schema + migration)
- Update sanitizeUser with isSelf parameter; only include showActivity for self
- Fix .map(sanitizeUser) calls to use arrow wrapper to prevent index-as-boolean bug
- Mark auth routes (register/login) as isSelf=true since they return own user data
2026-03-21 01:38:36 +01:00
Jannis Braun ce981ee5fc fix: prevent metadata fetch from overwriting fallback thumbnail with null
Use logical OR when merging fetched metadata so null values from
failed og: extraction don't destroy valid defaults (e.g. YouTube
thumbnail set before the fetch).
2026-03-21 00:35:44 +01:00
Jannis Braun 1c7d8557c6 fix: use predictable YouTube thumbnail URL as fallback for embed poster
YouTube may block og:image extraction via BackspaceBot user-agent.
Use img.youtube.com/vi/{ID}/hqdefault.jpg as a guaranteed thumbnail
that doesn't require metadata fetching. If og:image is successfully
fetched, it overwrites the fallback.
2026-03-21 00:31:59 +01:00
Jannis Braun a3db74c7f7 fix: resolve YouTube Error 153 by adding origin param and removing no-referrer
YouTube's embed API requires knowing the embedding origin to authorize
playback. The referrerPolicy="no-referrer" was stripping the Referer
header, and the missing origin param meant youtube-nocookie.com couldn't
verify the embed source, causing Error 153 (video player configuration
error). Fix: pass origin param explicitly and let the browser send the
default referrer.
2026-03-21 00:26:32 +01:00
Jannis Braun c0133397e3 fix: resolve 4 media embed bugs from testing
1. Video aspect ratio: remove container border/overflow-hidden, use
   preload="metadata" so browser knows dimensions before play
2. YouTube Error 153: remove sandbox attr (too restrictive), add full
   allow permissions (encrypted-media, accelerometer, gyroscope, etc.)
3. Google Images not displaying: detect image Content-Type from HTTP
   response in metadataFetcher, override classifier to create image
   embed for URLs that serve image/* content
4. Audio seeking broken: add HTTP Range request support in uploads
   route (Accept-Ranges, Content-Range, 206 Partial Content)
2026-03-21 00:19:04 +01:00
Jannis Braun ff2decded5 fix: address code review issues for embeds implementation
- Fix ?? to || in metadataFetcher.ts to handle empty strings from Cheerio
- Fix stale embeds on message edit: delete old embeds synchronously before
  broadcast, then resolve new ones async (all 4 edit paths: REST+WS, msg+DM)
- Revert unrelated MessageList.tsx scroll threshold change (5000 not 150)
- Remove duplicate embed indexes from migrateAddIndexes (kept standalone ones)
2026-03-20 23:58:06 +01:00
Jannis Braun dcdf10c5de docs: update CLAUDE.md with embeds schema, WS events, and feature status 2026-03-20 23:50:48 +01:00
Jannis Braun 4486341007 feat: add embeds_resolved WS handlers and optimistic embeds:[] default
- chatStore: normalize embeds to [] in addMessage, addRealtimeMessage, and updateMessage to guard against missing field from older servers/federation
- useWebSocket: add embeds_resolved and dm_embeds_resolved cases that patch the in-memory message cache when the server broadcasts resolved embed data
- useWebSocket: normalize embed image URLs for remote origins in message_created, message_updated, dm_message_created, dm_message_updated, and the new embeds_resolved handlers
2026-03-20 23:49:15 +01:00
Jannis Braun 95762a1974 feat: replace Embed.tsx with AttachmentRenderer + EmbedRenderer in Message
Switches Message.tsx from client-side URL metadata fetching (old Embed.tsx)
to server-driven embed objects via message.embeds[]. Delegates attachment
rendering to AttachmentRenderer. Removes firstUrl extraction and urlRegex.
2026-03-20 23:47:16 +01:00
Jannis Braun 5a670bc6ad feat: add embed sub-components (Generic, Video, Image, Rich) and dispatcher 2026-03-20 23:45:32 +01:00
Jannis Braun a800d9ff25 feat: add AttachmentRenderer with video/audio inline playback 2026-03-20 23:43:31 +01:00
Jannis Braun 01ee7ab67a feat: wire embeds into all message query and creation paths
Integrate embed infrastructure into the complete message flow:
- messages.ts: batch-fetch embeds in GET, resolve on POST, re-resolve on PATCH
- dm.ts: same pattern for DM messages with isDm=true
- search.ts: include embeds in all 4 search/around endpoints
- events.ts: embed resolution in WS message create/edit for both space and DM
- Fix embedClassifier.ts type errors (regex match undefined → null)
- Add embeds: [] to all inline MessageWithUser/DmMessageWithUser constructions
- Add embeds: [] to chatStore optimistic message
2026-03-20 23:41:53 +01:00
Jannis Braun 5fe25fb077 feat: add embed resolver with async resolution and batch fetching 2026-03-20 23:33:21 +01:00
Jannis Braun 29cfd88a15 feat: add URL classifier for embed type detection 2026-03-20 23:30:13 +01:00
Jannis Braun de1c0b4ed8 refactor: extract metadata fetcher into reusable utility 2026-03-20 23:30:01 +01:00
Jannis Braun ebc1868dd1 feat: add embeds database table with schema and migration 2026-03-20 23:28:57 +01:00
Jannis Braun 009923a12f feat: add Embed types and extend MessageWithUser with embeds[] 2026-03-20 23:25:58 +01:00
Jannis Braun f7d388c9a8 fix: clean up redundant regex guard and differentiate copy icons 2026-03-20 22:23:15 +01:00
Jannis Braun 720a3c4553 feat: wire up enhanced message context menu with all actions 2026-03-20 22:19:12 +01:00
Jannis Braun 3aa7e93a4d feat: pass previousMessageId prop from MessageList to Message 2026-03-20 22:16:55 +01:00
Jannis Braun 8da412c0d4 feat: create message context menu builder function 2026-03-20 22:15:31 +01:00
Jannis Braun 896cb77b5c feat: add markUnread store action and WS handler 2026-03-20 22:13:47 +01:00
Jannis Braun 2e26f98246 feat: add mark_unread WebSocket event handler 2026-03-20 22:11:42 +01:00
Jannis Braun 3c23893549 feat: add mark_unread to WebSocket event types 2026-03-20 22:09:40 +01:00
Jannis Braun c90ba431e8 fix: resolve mentions in reply previews to display usernames
Reply preview was rendering raw <@userId> tokens as plain text instead
of resolving them to MentionBadge components with proper usernames.
2026-03-20 21:25:45 +01:00
Jannis Braun 9fe46ad19b fix: voice drop zone was swallowing channel reorder drops
handleVoiceDropZoneDrop called stopPropagation and clearState
unconditionally, preventing container's handleContainerDrop from
firing when dropping a channel onto a voice channel. Add early
return for non-voiceUser drags so channel/category drops bubble
through to the container handler correctly.
2026-03-20 21:15:13 +01:00
Jannis Braun 99e6f2f249 fix: normalize drop indicator to single line between channels
Port the SpaceSidebar normalization pattern: convert 'before B'
to 'after A' so only one drop indicator renders at any gap.
Fixes double-line visual glitch and unreliable drops when cursor
is between two channels. Also adjust indicator offsets from
top-0/bottom-0 to -top-[1px]/-bottom-[1px] to center in the gap.
2026-03-20 21:07:20 +01:00
Jannis Braun ebe34a710b refactor: update VoiceChannel to use useDragManager hook-provided handlers 2026-03-20 20:46:49 +01:00
Jannis Braun 439a71dc13 refactor: wire useDragManager handlers into ChannelSidebar JSX and ChannelItem 2026-03-20 20:45:30 +01:00
Jannis Braun 999c13cdab refactor: replace old drag state with useDragManager hook in ChannelSidebar 2026-03-20 20:43:41 +01:00
Jannis Braun eb6f4bf94e fix: stabilize useDragManager callback refs and containerHandlers memo
Remove activeDrag from drag-start dependency arrays to prevent
unnecessary re-renders during drag. Wrap containerHandlers in
useMemo for consistent reference stability.
2026-03-20 20:39:52 +01:00
Jannis Braun 2952799d00 feat: add auto-scroll during drag near sidebar edges 2026-03-20 20:35:47 +01:00
Jannis Braun a8befcc701 feat: add voice user and voice channel drop zone handler factories 2026-03-20 20:35:13 +01:00
Jannis Braun 23c102a3cb feat: add channel/category handler factories and container handlers 2026-03-20 20:34:37 +01:00
Jannis Braun 9670450eec feat: scaffold useDragManager hook with types and state 2026-03-20 20:34:05 +01:00
Jannis Braun eb835f7e22 docs: add system prompt and design system reference files 2026-03-20 19:06:10 +01:00
Jannis Braun 0dc3eb1884 fix: notify displaced tab when user joins voice from another session
When a user joins a voice channel while already connected from another
tab, the server now sends a 'displaced' reason on voice_disconnected.
The client tears down LiveKit and shows an informational toast.
2026-03-20 19:03:35 +01:00
Jannis Braun 68378c7d83 fix: deduplicate VolumeSliderItem and add missing stopPropagation
- Extract VolumeSliderItem to voiceMenuItems.tsx (was duplicated in
  VoiceUser.tsx and VoiceChannel.tsx)
- Add e.stopPropagation() to all imperative context menu handlers
  for consistency with useContextMenu hook behavior
2026-03-20 18:55:58 +01:00
Jannis Braun 443259a527 chore: delete old context menu components replaced by centralized system 2026-03-20 18:48:40 +01:00
Jannis Braun 8eb3fc84a5 refactor: migrate voice context menus to centralized store 2026-03-20 18:47:45 +01:00
Jannis Braun cba19e8b20 refactor: migrate SpaceSidebar context menus to centralized store 2026-03-20 18:41:17 +01:00
Jannis Braun 15af93b979 refactor: migrate ChannelSidebar context menus to centralized store 2026-03-20 18:35:55 +01:00
Jannis Braun 3ead68b3e7 refactor: migrate Message context menu to centralized store 2026-03-20 18:32:18 +01:00
Jannis Braun ba0243d88c feat: mount ContextMenuRenderer in AppLayout 2026-03-20 18:30:58 +01:00
Jannis Braun 9e93734719 feat: add centralized ContextMenuRenderer with submenu and mobile support 2026-03-20 18:28:10 +01:00
Jannis Braun 6fb8801960 feat: add useContextMenu consumer hook 2026-03-20 18:24:44 +01:00
Jannis Braun 9a1b266760 feat: add context menu Zustand store and types 2026-03-20 18:24:25 +01:00
Jannis Braun e3e3eb82ff fix: restore missing logo and fix mobile space icon URLs
Restore logo.png lost during fast-forward merge and replace broken
resolveAssetUrl pattern in MobileSpacesScreen with proven desktop logic.
2026-03-17 16:16:09 +01:00
Jannis Braun f505f6578b fix(mobile): add viewport-fit=cover for safe area insets on notched devices 2026-03-17 15:55:06 +01:00
Jannis Braun ed70099963 fix(mobile): resolve all TypeScript errors from integration
- Fix voiceStore method names (toggleMic, leaveVoice, setCurrentVoiceChannel)
- Fix MemberWithUser nested user property access
- Pass required channelId props to MessageList, TypingIndicator, MessageInput
- Fix ConfirmDialog props (isOpen, description, variant, onClose)
- Add mobileStyle prop to Modal component (fullscreen + sheet modes)
- Fix fromId/isAdmin camelCase property names
- Guard possibly undefined touch events and array accesses
- Fix notification channelId resolution
2026-03-17 15:54:39 +01:00
Jannis Braun 7619b091da feat(mobile): route user profile to pushed screen instead of popout 2026-03-17 15:49:36 +01:00
Jannis Braun 1e0e957824 feat(mobile): route notification taps through mobile screen stack 2026-03-17 15:48:23 +01:00
Jannis Braun 206a0491ea feat(mobile): add full-screen voice view with controls 2026-03-17 15:47:41 +01:00
Jannis Braun 913b4c7365 feat(mobile): add mobileStyle to all modals (sheet for forms, fullscreen for settings) 2026-03-17 15:46:28 +01:00
Jannis Braun a073613b43 feat(mobile): disable tooltips, render context menus as bottom sheets 2026-03-17 15:44:46 +01:00
Jannis Braun 183290ef07 fix(mobile): stacked Add Friend input, responsive tab bar, mobile header 2026-03-17 15:43:43 +01:00
Jannis Braun 2790e9e088 feat(mobile): add voice mini-bar with quick controls 2026-03-17 15:42:16 +01:00
Jannis Braun af84674963 feat(mobile): add MobileSettingsScreen with drill-down navigation 2026-03-17 15:41:19 +01:00
Jannis Braun 934a1b85a7 feat(mobile): add MobileYouScreen with profile card and action links 2026-03-17 15:40:23 +01:00
Jannis Braun 49e4402802 feat(mobile): add MobileDmsScreen with activity row and DM list 2026-03-17 15:39:19 +01:00
Jannis Braun 0222946f04 feat(mobile): add swipe-from-left-edge back gesture 2026-03-17 15:37:27 +01:00
Jannis Braun e45bf1927e feat(mobile): add MobileChatScreen with back nav and member list access 2026-03-17 15:36:50 +01:00
Jannis Braun eac4e5f5eb feat(mobile): add MobileSpacesScreen with space strip and channel list 2026-03-17 15:35:53 +01:00
Jannis Braun 8463ca9ba8 feat(mobile): add MobileShell and split AppLayout for mobile/desktop 2026-03-17 15:32:52 +01:00
Jannis Braun 2386f497aa feat(mobile): add 3-tab bottom nav with unread badges 2026-03-17 15:31:06 +01:00