Commit Graph
623 Commits
Author SHA1 Message Date
Jannis Braun 995c71367e fix(web): add aspect-ratio fallback for bare GIF URL messages 2026-03-25 01:56:08 +01:00
Jannis Braun 234ee9cd23 fix(web): add 16:9 aspect-ratio reservation to direct video embeds 2026-03-25 01:55:41 +01:00
Jannis Braun b96c16b622 fix(web): add dimension reservation to ImageEmbed component 2026-03-25 01:55:12 +01:00
Jannis Braun 4e170f0b69 feat(social): add TaggedUser type and origin-tag searchUsers results 2026-03-25 01:54:36 +01:00
Jannis Braun 123e40bb9a feat(server): populate embed width/height from OG tags and image probing 2026-03-25 01:53:39 +01:00
Jannis Braun bbb2c8bd19 feat(server): extract og:image:width/height from HTML metadata 2026-03-25 01:51:31 +01:00
Jannis Braun 2f883c6f63 refactor(server): extract SSRF validation into shared ssrf.ts utility 2026-03-25 01:48:18 +01:00
Jannis Braun d9094fabe1 feat(ws): re-push activities on new instance connections
When a WS connection receives its ready event, push cached myActivities
to that instance so federated users see activities immediately without
waiting for the next debounce cycle.
2026-03-24 22:00:28 +01:00
Jannis Braun 9705304be9 feat(activity): fan out activity updates to all connected instances
Switch pushActivities and setShowActivity from wsSend (home-only) to
wsSendAll (all instances). Add myActivities cache for re-push on late
connections.
2026-03-24 21:55:45 +01:00
Jannis Braun 38ffc214f0 test(context-menu): add tests for reactive checkbox behavior 2026-03-24 21:53:46 +01:00
Jannis Braun 7f4f40a1e5 feat(ws): add wsSendAll utility for multi-instance broadcast 2026-03-24 21:52:51 +01:00
Jannis Braun 0d91df166a fix(context-menu): update all checkbox call sites to reactive subscribe+getChecked 2026-03-24 21:48:26 +01:00
Jannis Braun 7a25a2df7b feat(context-menu): add ReactiveCheckboxItem with useSyncExternalStore 2026-03-24 21:47:52 +01:00
Jannis Braun 2513ba10e7 refactor(context-menu): replace static checked with reactive subscribe+getChecked 2026-03-24 21:47:16 +01:00
Jannis Braun f21a1f75ce feat(voice): add cachedUser fallback tier to useVoiceParticipantMeta
Inserts a new tier 3 between DM member lookup and identity-only fallback.
When the current space's member list doesn't contain the voice participant
(user navigated to a different space/instance), the hook now falls back
to the cached User object from ParticipantInfo. This preserves avatar,
avatarColor, displayName, and homeUserId for federated users in PiP.
2026-03-24 21:03:46 +01:00
Jannis Braun 1ca5ca3132 fix(voice): align local user homeUserId fallback with null contract
The isLocal branch was falling through to cachedUser.id when
homeUserId was null, diverging from the null-for-home-instance
contract used by the memberMatch and carry-forward branches.
Avatar.tsx already falls back to user.id internally.
2026-03-24 21:01:37 +01:00
Jannis Braun 8910de3053 feat(voice): add cachedUser carry-forward to ParticipantInfo
Extends ParticipantInfo with cachedUser: User | null. In updateParticipants,
snapshots the previous participant list and carries forward the cached User
object when spaceStore member lookup fails (user navigated to a different
space). Local user falls back to authStore. homeUserId is now derived from
cachedUser when the direct member lookup misses. Updates EMPTY_PARTICIPANT
in PictureInPicture.tsx.
2026-03-24 19:01:34 +01:00
Jannis Braun 52c93ae0c5 chore: clean up review feedback — consolidate imports, fix reconnect verb, DRY username 2026-03-24 18:42:45 +01:00
Jannis Braun a97dc95877 feat: wire ConnectInstanceModal into discover people cards 2026-03-24 18:38:36 +01:00
Jannis Braun 0dc5e8f8f4 feat: wire ConnectInstanceModal into FriendsPage add-friend input 2026-03-24 18:37:17 +01:00
Jannis Braun 13485bc20a feat: wire ConnectInstanceModal into UserProfileModal friend actions
InstanceNotConnectedError and InstanceDisconnectedError now open the
ConnectInstanceModal instead of being swallowed silently. After the user
connects/reconnects, the friend request is retried automatically and a
success toast confirms both the connection and the sent request. All
other friend action errors (remove, cancel, accept, decline) now surface
as warning toasts instead of being silently discarded.
2026-03-24 18:35:29 +01:00
Jannis Braun 19bae17730 feat: add ConnectInstanceModal for federation friend connect flow 2026-03-24 18:33:51 +01:00
Jannis Braun 947fb30901 feat: add useInstanceConnect hook for federation connect flow 2026-03-24 18:32:20 +01:00
Jannis Braun 70f9700e43 feat: add typed errors for federation friend request failures 2026-03-24 18:31:11 +01:00
Jannis Braun 8c2e20165a feat: rename codec buttons to Standard/NVIDIA · Apple with codec subtitles 2026-03-24 16:41:23 +01:00
Jannis Braun b6e8aee24b fix: cap markdown images to 400x300 2026-03-24 05:16:56 +01:00
Jannis Braun 7e9020f5a6 fix: cap all embed types to 400px max-width 2026-03-24 05:16:31 +01:00
Jannis Braun e64658bdd5 fix: cap image and video attachments to 400x300 2026-03-24 05:15:51 +01:00
Jannis Braun acb79c9de7 fix: cap GIF-only messages to 250x250 2026-03-24 05:15:10 +01:00
Jannis Braun 69a16ccdd5 fix: preserve hwOverdrive across mid-stream codec restart
stopScreenShare() resets hwOverdrive: false, which clobbers the
user's intent when switching VP9 → H.264 HW mid-stream. Save
and restore the flag around the restart.
2026-03-24 04:35:33 +01:00
Jannis Braun cc30080ba8 chore: sync repo with deployed state — clean up old specs/plans, desktop tweaks 2026-03-24 04:33:23 +01:00
Jannis Braun 46c3838193 fix: reset hwOverdrive in all voice cleanup paths
Add hwOverdrive: false to resetSession(), leaveVoice(), and
handleForceDisconnect() store resets. Add deactivateHwOverdrive()
to disconnect callback and cleanup effect in useLiveKit.
Ensures "resets when stream ends" contract holds for edge cases
like server shutdown, identity collision, and logout.
2026-03-24 04:00:37 +01:00
Jannis Braun 66a0793297 feat: add hwOverdrive to updateActiveTracks effect deps for mid-stream switching 2026-03-24 03:52:20 +01:00
Jannis Braun c6c44d1bdd feat: replace codec pills with VP9/H.264 HW, wire to hwOverdrive 2026-03-24 03:51:22 +01:00
Jannis Braun 23249be956 feat: integrate hwOverdrive into screen share start/stop/detect
- buildScreenShareOptions reads hwOverdrive from voiceStore instead of config.codec; both VP9 and H.264 paths now always get a VP8 SIMULCAST backup
- startScreenShare activates SDP override before WebRTC negotiation and deactivates on failure
- stopScreenShare and handleScreenShareUnpublished both deactivate the override and reset hwOverdrive: false
- scheduleEncoderDetection checks encoderImplementation in WebRTC stats after 4s and shows a warning toast if OpenH264 (software) is detected
2026-03-24 03:49:57 +01:00
Jannis Braun 94e955989a feat: remove codec from ScreenShareConfig, add transient hwOverdrive
VP9 is now always the default codec, so the persisted codec field is
removed. hwOverdrive is a transient boolean (excluded from partialize)
that drives hardware H.264 on demand without surviving page reload.
Persist version bumped 12→13 with migration to strip stale codec field.
2026-03-24 03:45:10 +01:00
Jannis Braun 0b49300d86 feat: add hwOverdrive SDP profile override module 2026-03-24 03:39:43 +01:00
Jannis Braun 1bdd9a387a revert: remove ineffective GPU encoding flags from Electron
Hardware H.264 encoding in Electron's WebRTC requires SDP profile
negotiation changes (NVENC rejects Constrained Baseline), not
command-line flags. VP9 via libvpx is the correct default — proven
by empirical benchmarks (CS2: VP9 60fps vs H.264 30fps).
2026-03-24 02:00:43 +01:00
Jannis Braun 6844f8d8fd fix: clean up GPU flags — hardware H.264 encoding not available on Win/Mac
AcceleratedVideoEncoder only enables VA-API encoding on Linux.
Windows/macOS hardware H.264 encoding in Chromium's WebRTC is not
reliably controllable — VP9 via libvpx remains the recommended codec.
2026-03-24 01:55:18 +01:00
Jannis Braun 07ac9cf505 fix: pass screenShareEncoding to override LiveKit's 15fps default
LiveKit uses screenShareEncoding (not videoEncoding) for screen share
tracks. Without it, both primary and backup fall back to the default
ScreenSharePresets.h1080fps15 (15fps). Primary was masked by our
overdrive mechanism, but backup had no overdrive and was stuck at 15fps.
2026-03-24 01:21:16 +01:00
Jannis Braun e53d3bcb98 fix: switch backup codec to VP8@30fps, dim H.264 pill with warning
- Backup codec changed from H.264 (OpenH264, slow) to VP8 (libvpx,
  fast) — same encoder family as VP9, lower dual-encode overhead
- Backup capped at 30fps with proportional bitrate to keep CPU
  overhead low during SIMULCAST dual-encoding
- H.264 pill visually dimmed with amber warning when selected
2026-03-24 01:14:47 +01:00
Jannis Braun a54dd9084a feat: show encoder implementation in Connection Info, VP9 recommended hint
- Connection Info now shows encoder impl (e.g. libvpx, OpenH264,
  ExternalEncoder) on send-side video tracks alongside quality
  limitation reason
- Amber warning "VP9 is recommended" when H.264 is selected
2026-03-24 01:06:19 +01:00
Jannis Braun 65a1fc1402 fix: VP9 default for both modes, clean up codec pill UI
VP9 empirically outperforms H.264 in gaming (Chrome may not use
NVENC for screen share H.264). Codec pills now match other pill
styles — simple labels, no description text. Mode change no longer
auto-switches codec; user's codec choice is independent.
2026-03-24 00:59:04 +01:00
Jannis Braun 2b2e1c7386 fix: remove preventDefault on touchstart that killed all mobile taps
Calling e.preventDefault() on touchstart inside [data-context-menu]
elements prevented the browser from synthesizing click events
(touchstart → touchend → click chain). This broke tapping on spaces,
channels, DMs, and every other surface with data-context-menu.

Text selection prevention is already handled by CSS user-select: none
on [data-context-menu] elements — the JS preventDefault was redundant
and destructive. Reverted touchstart listener back to passive.
2026-03-24 00:14:09 +01:00
Jannis Braun 8897a5894c feat: smart codec defaults + mid-stream codec switching
- Gaming mode defaults to H.264 (NVENC hardware encoding, zero CPU)
- Text mode defaults to VP9 (better compression, CPU is free)
- Changing mode auto-updates codec to smart default
- User can manually override codec via UI pills
- Changing codec mid-stream auto-restarts the stream (~1s interruption)
2026-03-23 23:35:33 +01:00
Jannis Braun 894ce68194 feat: add manual codec selection (VP9/H.264) to stream settings
VP9 is default — better quality per bit with H.264 SIMULCAST backup
for Safari. H.264 option available for zero-CPU hardware encoding.
Codec choice is independent of gaming/text mode, which still controls
contentHint and degradationPreference.
2026-03-23 22:44:31 +01:00
Jannis Braun e7a18bd28c fix: screenshare codec fallback, native FPS, and connection info
- Gaming mode uses H.264 primary (hardware NVENC encoding, zero CPU
  impact on games). Text mode uses VP9 primary with H.264 backup
  and SIMULCAST policy for Safari compatibility.
- Fix native mode starting at 30fps by decoupling frameRate constraint
  from resolution constraint in both screenShare.ts overdrive and
  useLiveKit.ts updateActiveTracks.
- Filter paused backup codec tracks in Connection Info stats so dead
  0kbps entries don't show alongside active codec tracks.
2026-03-23 22:10:16 +01:00
Jannis Braun 7693cc737e fix: send voice_leave WS message from mobile disconnect handlers
MobileVoiceFullScreen and MobileVoiceMiniBar were missing voice_leave
(and dm_call_end) WS messages in their disconnect handlers, leaving
the server showing stale voice state. Now matches VoiceControls pattern.
2026-03-23 21:18:34 +01:00
Jannis Braun 0b7206487e chore: delete dead useLongPress.ts hook
Zero imports — useGlobalLongPress in ContextMenuRenderer handles
all long-press detection at the document level.
2026-03-23 21:12:32 +01:00
Jannis Braun 9f8a4ffa90 fix: prevent native text selection on mobile long-press
iOS triggered both the app context menu and native text selection overlay
on long-press. Three-layer fix: CSS user-select:none on buttons/[role=button]/
[data-context-menu] elements; non-passive touchstart listener with conditional
preventDefault on context-menu targets; removeAllRanges() at timer fire to
clear any residual selection. Added data-context-menu to all mobile surfaces
that use onContextMenu handlers.
2026-03-23 21:12:06 +01:00