Commit Graph

215 Commits

Author SHA1 Message Date
Robin
3a754479dc Add simple global controls to put the call in picture-in-picture mode (#2573)
* Stop sharing state observables when the view model is destroyed

By default, observables running with shareReplay will continue running forever even if there are no subscribers. We need to stop them when the view model is destroyed to avoid memory leaks and other unintuitive behavior.

* Hydrate the call view model in a less hacky way

This ensures that only a single view model is created per call, unlike the previous solution which would create extra view models in strict mode which it was unable to dispose of. The other way was invalid because React gives us no way to reliably dispose of a resource created in the render phase. This is essentially a memory leak fix.

* Add simple global controls to put the call in picture-in-picture mode

Our web and mobile apps (will) all support putting calls into a picture-in-picture mode. However, it'd be nice to have a way of doing this that's more explicit than a breakpoint, because PiP views could in theory get fairly large. Specifically, on mobile, we want a way to do this that can tell you whether the call is ongoing, and that works even without the widget API (because we support SPA calls in the Element X apps…)

To this end, I've created a simple global "controls" API on the window. Right now it only has methods for controlling the picture-in-picture state, but in theory we can expand it to also control mute states, which is current possible via the widget API only.

* Fix footer appearing in large PiP views

* Add a method for whether you can enter picture-in-picture mode

* Have the controls emit booleans directly
2024-08-27 13:47:20 +02:00
Robin
29df87d22c Merge pull request #2548 from robintown/hide-controls
Show controls on tap/hover on small screens
2024-08-09 11:52:01 -04:00
Robin
aa6b7056ae Show controls on tap/hover on small screens
This changes the mobile landscape view to automatically hide the controls, giving more visibility to the video underneath, and show them on tap/hover.
2024-08-09 11:09:45 -04:00
Robin
5069b008e2 Avoid duplicating the video of someone in the spotlight
We've gotten feedback that it's distracting whenever the same video is shown in two places on screen. This fixes the spotlight case by showing only the avatar of anyone who is already visible in the spotlight. It also makes sense to hide the speaking indicators in spotlight layouts, I think, because this information is redundant to the spotlight tile.
2024-08-08 12:16:32 -04:00
Robin
ab42fe97cb Merge pull request #2514 from robintown/mobile-layouts
Improve the layouts on small mobile calls
2024-08-06 10:10:29 -04:00
Robin
7abb56e406 Add back some margins to the interface
There were a couple of cases where the lack of margins after the new layout changes just looked odd. Specifically, when the header is hidden (as in embedded mode), there would be no margin at the top of the window. Also the floating tile would run directly up against the sides of the window.
2024-08-01 16:33:10 -04:00
Robin
eb051ab318 Replace the mobile one-on-one layout with an edge-to-edge spotlight 2024-08-01 13:49:49 -04:00
Robin
a3ce333352 Only show the expand button in spotlight layout (#2510)
It has no effect in any layout other than spotlight, and we've decided to hide it rather than spending effort to make it do something.
2024-07-26 12:57:49 +02:00
Timo
b05c4234b7 Remove hide header condition (#2493) 2024-07-25 11:32:05 +02:00
Robin
4955535374 Use more consistent names for layout types 2024-07-18 11:24:18 -04:00
Robin
2440037639 Implement most of the remaining layout changes
Includes the mobile UX optimizations and the tweaks we've made to cut down on wasted space, but does not yet include the change to embed the spotlight tile within the grid.
2024-07-12 15:50:17 -04:00
Robin
45c89a2298 Delete the legacy grid system 2024-07-12 15:49:43 -04:00
Robin
7979493371 Implement the new one-on-one layout 2024-07-12 15:47:56 -04:00
Robin
e0b10d89b5 Add model for one-on-one layout 2024-07-12 15:47:56 -04:00
Robin
ec1b020d4e Add indicators to spotlight tile and make spotlight layout responsive 2024-07-12 15:47:00 -04:00
Robin
ffbbc74a96 Implement the new spotlight layout 2024-07-12 15:47:00 -04:00
Robin
af0bd795b5 Replace react-rxjs with observable-hooks
react-rxjs is the library we've been using to connect our React components to view models and consume observables. However, after spending some time with react-rxjs, I feel that it's a very heavy-handed solution. It requires us to sprinkle <Subscribe /> and <RemoveSubscribe /> components all throughout the code, and makes React go through an extra render cycle whenever we mount a component that binds to a view model. What I really want is a lightweight React hook that just gets the current value out of a plain observable, without any extra setup. Luckily the observable-hooks library with its useObservableEagerState hook seems to do just that—and it's more actively maintained, too!
2024-07-12 15:46:33 -04:00
Robin
e33fbd77d1 Split local and remote user media into different classes 2024-07-12 15:43:24 -04:00
Robin
14fc1481f3 Address some review feedback 2024-07-12 14:01:32 -04:00
Robin
20602c122b Implement the new unified grid layout
Here I've implemented an MVP for the new unified grid layout, which scales smoothly up to arbitrarily many participants. It doesn't yet have a special 1:1 layout, so in spotlight mode and 1:1s, we will still fall back to the legacy grid systems.

Things that happened along the way:
- The part of VideoTile that is common to both spotlight and grid tiles, I refactored into MediaView
- VideoTile renamed to GridTile
- Added SpotlightTile for the new, glassy spotlight designs
- NewVideoGrid renamed to Grid, and refactored to be even more generic
- I extracted the media name logic into a custom React hook
- Deleted the BigGrid experiment
2024-07-03 15:29:08 -04:00
Robin
70fdc68b13 Fix lints 2024-06-04 11:20:25 -04:00
Timo
5284479ece Knocking support (#2281)
* Add joining with knock room creation flow.

Also add `WaitForInviteView` after knocking.
And appropriate error views when knock failed or gets rejected.

Signed-off-by: Timo K <toger5@hotmail.de>

* Refactor encryption information.

We had lots of enums and booleans to describe the encryption situation.
Now we only use the `EncryptionSystem` "enum" which contains the
additional information like sharedKey. (and we don't use the isRoomE2EE
function that is somewhat confusing since it checks `return widget ===
null && !room.getCanonicalAlias();` which is only indirectly related to
e2ee)

Signed-off-by: Timo K <toger5@hotmail.de>

* Update recent list.

- Don't use deprecated `groupCallEventHander` anymore (it used the old
  `m.call` state event.)
- make the recent list reactive (getting removed from a call removes the
  item from the list)
- support having rooms without shared secret but actual matrix
  encryption in the recent list
- change the share link creation button so that we create a link with
  pwd for sharedKey rooms and with `perParticipantE2EE=true` for matrix
  encrypted rooms.

Signed-off-by: Timo K <toger5@hotmail.de>

* fix types

Signed-off-by: Timo K <toger5@hotmail.de>

* patch js-sdk for linter

Signed-off-by: Timo K <toger5@hotmail.de>

* ignore ts expect error

Signed-off-by: Timo K <toger5@hotmail.de>

* Fix error in widget mode.

We cannot call client.getRoomSummary in widget mode. The code path needs
to throw before reaching this call. (In general we should never call
getRoomSummary if getRoom returns a room)

Signed-off-by: Timo K <toger5@hotmail.de>

* tempDemo

Signed-off-by: Timo K <toger5@hotmail.de>

* remove wait for invite view

Signed-off-by: Timo K <toger5@hotmail.de>

* yarn i18n

Signed-off-by: Timo K <toger5@hotmail.de>

* reset back mute participant count

* add logic to show error view when getting removed

* include reason whenever someone gets removed from a call.

* fix activeRoom not beeing early enough

* fix lints

* add comment about encryption situation

Signed-off-by: Timo K <toger5@hotmail.de>

* Fix lockfile

* Use (unmerged!) RoomSummary type from the js-sdk

Temporarily change the js-sdk dependency to the PR branch that provides
that type

* review

Signed-off-by: Timo K <toger5@hotmail.de>

* review (remove participant count unknown)

Signed-off-by: Timo K <toger5@hotmail.de>

* remove error for unencrypted calls (allow intentional unencrypted calls)

Signed-off-by: Timo K <toger5@hotmail.de>

* update js-sdk

Signed-off-by: Timo K <toger5@hotmail.de>

---------

Signed-off-by: Timo K <toger5@hotmail.de>
Co-authored-by: Andrew Ferrazzutti <andrewf@element.io>
2024-04-23 22:15:13 +09:00
Robin
b2bc8edcc1 Refactor/redesign video tiles 2023-12-18 16:59:48 -05:00
Robin
169ccd9de5 Start refactoring some business logic into view models
As Element Call grows in complexity, it has become a pain point that our business logic remains so tightly coupled to the UI code. In particular, this has made testing difficult, and the complex semantics of React hooks are not a great match for arbitrary business logic. Here, I show the beginnings of what it would look like for us to adopt the MVVM pattern. I've created a CallViewModel and TileViewModel that expose their state to the UI as rxjs Observables, as well as a couple of helper functions for consuming view models in React code.

This should contain no user-visible changes, but we need to watch out for regressions particularly around focus switching and promotion of speakers, because this was the logic I chose to refactor first.
2023-12-01 17:09:21 -05:00
Robin
c433069f90 Format code 2023-11-30 23:40:33 -05:00
Timo
db859d43e9 Refactor livekit disconnect to use an effect hook. (#1925)
---------

Signed-off-by: Timo K <toger5@hotmail.de>
2023-11-28 19:07:08 +01:00
Timo
005b0bfa5e Fix not disconnecting from livekit session. (#1920)
Signed-off-by: Timo K <toger5@hotmail.de>
2023-11-24 17:53:15 +01:00
Robin
49a50514fd Show a warning on unencrypted media 2023-11-20 19:04:53 -05:00
Robin
aa8ef57ee0 Merge pull request #1908 from vector-im/t3chguy/localazy/2
Switch from Weblate to Localazy
2023-11-20 16:55:58 -05:00
Robin
0144aafee5 Count people as speakers even if there is a presenter 2023-11-20 13:33:45 -05:00
Michael Telatynski
cdbf4cac01 ```
move "{{count, number}}_one" "participant_count_one"
move "{{count, number}}_other" "participant_count_other"
move "{{count}} stars_one" "star_rating_input_label_one"
move "{{count}} stars_other" "star_rating_input_label_other"
move "{{displayName}} is presenting" "video_tile.presenter_label"
move "{{displayName}}, your call has ended." "call_ended_view.headline"
move "<0></0><1></1>You may withdraw consent by unchecking this box. If you are currently in a call, this setting will take effect at the end of the call." "settings.opt_in_description"
move "<0>Already have an account?</0><1><0>Log in</0> Or <2>Access as a guest</2></1>" "register_auth_links"
move "<0>Create an account</0> Or <2>Access as a guest</2>" "login_auth_links"
move "<0>Oops, something's gone wrong.</0>" "full_screen_view_h1"
move "<0>Submitting debug logs will help us track down the problem.</0>" "full_screen_view_description"
move "<0>Thanks for your feedback!</0>" "call_ended_view.feedback_done"
move "<0>We'd love to hear your feedback so we can improve your experience.</0>" "call_ended_view.feedback_prompt"
move "<0>Why not finish by setting up a password to keep your account?</0><1>You'll be able to keep your name and set an avatar for use on future calls</1>" "call_ended_view.create_account_prompt"
move "Another user on this call is having an issue. In order to better diagnose these issues we'd like to collect a debug log." "rageshake_request_modal.body"
move "Back to recents" "lobby.leave_button"
move "By participating in this beta, you consent to the collection of anonymous data, which we use to improve the product. You can find more information about which data we track in our <2>Privacy Policy</2> and our <5>Cookie Policy</5>." "analytics_notice"
move "Call not found" "group_call_loader_failed_heading"
move "Calls are now end-to-end encrypted and need to be created from the home page. This helps make sure everyone's using the same encryption key." "group_call_loader_failed_text"
move "Confirm password" "register_confirm_password_label"
move "Connectivity to the server has been lost." "disconnected_banner"
move "Continue in browser" "app_selection_modal.continue_in_browser"
move "Create account" "call_ended_view.create_account_button"
move "Debug log request" "rageshake_request_modal.title"
move "Developer" "settings.developer_tab_title"
move "Developer Settings" "settings.developer_settings_label"
move "Element Call Home" "header_label"
move "End call" "hangup_button_label"
move "Full screen" "fullscreen_button_label"
move "Exit full screen" "exit_fullscreen_button_label"
move "Expose developer settings in the settings window." "settings.developer_settings_label_description"
move "Feedback" "settings.feedback_tab_title"
move "Grid" "layout_grid_label"
move "Spotlight" "layout_spotlight_label"
move "How did it go?" "call_ended_view.survey_prompt"
move "If you are experiencing issues or simply would like to provide some feedback, please send us a short description below." "settings.feedback_tab_body"
move "Include debug logs" "settings.feedback_tab_send_logs_label"
move "Invite to this call" "invite_modal.title"
move "Join call" "lobby.join_button"
move "Join call now" "room_auth_view_join_button"
move "Join existing call?" "join_existing_call_modal.title"
move "Link copied to clipboard" "invite_modal.link_copied_toast"
move "Local volume" "local_volume_label"
move "Logging in…" "logging_in"
move "Login" "login_title"
move "Login to your account" "unauthenticated_view_login_button"
move "Microphone off" "microphone_off"
move "Microphone on" "microphone_on"
move "More" "settings.more_tab_title"
move "Mute microphone" "mute_microphone_button_label"
move "Name of call" "call_name"
move "Not now, return to home screen" "call_ended_view.not_now_button"
move "Open in the app" "app_selection_modal.open_in_app"
move "Not registered yet? <2>Create an account</2>" "unauthenticated_view_body"
move "Participants" "header_participants_label"
move "Passwords must match" "register.passwords_must_match"
move "Ready to join?" "app_selection_modal.text"
move "Recaptcha dismissed" "recaptcha_dismissed"
move "Recaptcha not loaded" "recaptcha_not_loaded"
move "Reconnect" "call_ended_view.reconnect_button"
move "Registering…" "register.registering"
move "Retry sending logs" "rageshake_button_error_caption"
move "Return to home screen" "return_home_button"
move "Select an option" "select_input_unset_button"
move "Select app" "app_selection_modal.title"
move "Send debug logs" "rageshake_send_logs"
move "Sending debug logs…" "rageshake_sending_logs"
move "Sending…" "rageshake_sending"
move "Share screen" "screenshare_button_label"
move "Sharing screen" "stop_screenshare_button_label"
move "Show connection stats" "settings.show_connection_stats_label"
move "Speaker" "settings.speaker_device_selection_label"
move "Start new call" "start_new_call"
move "Start video" "start_video_button_label"
move "Stop video" "stop_video_button_label"
move "Submit feedback" "settings.feedback_tab_h4"
move "Submitting…" "submitting"
move "Thanks, we received your feedback!" "settings.feedback_tab_thank_you"
move "Thanks!" "rageshake_sent"
move "This application has been opened in another tab." "application_opened_another_tab"
move "This call already exists, would you like to join?" "join_existing_call_modal.text"
move "Unmute microphone" "unmute_microphone_button_label"
move "Version: {{version}}" "version"
move "Waiting for other participants…" "waiting_for_participants"
move "Yes, join call" "join_existing_call_modal.join_button"
move "You" "video_tile.sfu_participant_local"
move "You were disconnected from the call" "call_ended_view.body"
move "Your feedback" "settings.feedback_tab_description_label"
move "Your web browser does not support media end-to-end encryption. Supported Browsers are Chrome, Safari, Firefox >=117" "browser_media_e2ee_unsupported"
move "By clicking \"Go\", you agree to our <2>End User Licensing Agreement (EULA)</2>" "unauthenticated_view_eula_caption"
move "By clicking \"Join call now\", you agree to our <2>End User Licensing Agreement (EULA)</2>" "room_auth_view_eula_caption"
move "This site is protected by ReCAPTCHA and the Google <2>Privacy Policy</2> and <6>Terms of Service</6> apply.<9></9>By clicking \"Register\", you agree to our <12>End User Licensing Agreement (EULA)</12>" "register.recaptcha_caption"
```
2023-11-20 13:20:19 +00:00
David Baker
be5cd619bb Add comment 2023-11-15 16:20:28 +00:00
David Baker
c146e83c15 Keep screenshares when switching focus
This also removes the use of the useLivekitRoom hook: we had reached
the point where the only thing it was actually doing was disconnecting,
so we now do that in the onClick handler for the leave button (I don't
think we need to disconnect on unmount?). It was otherwise just getting in
the way and causing tracks to be enabled/disabled when we didn't want them
to be. This also removes the need for the blockAudio code.

Fixes https://github.com/vector-im/element-call/issues/1413
2023-11-10 15:24:43 +00:00
David Baker
5ab6d18712 Make E2EEConfig required
Previously it could be either undefined or type None which meant the
same thing: no need to have both, just make it required.

This also means we can move the line to set e2ee enabled into a more
sensible place rather than in the ActiveCall de-nulling wrapper.
2023-11-10 11:54:59 +00:00
David Baker
731f1e4008 Merge pull request #1772 from vector-im/dbkr/ppe2ee
Support key-per-participant e2ee
2023-10-31 20:08:05 +00:00
Timo
5008c33dfa missing showControls condition (#1854)
Signed-off-by: Timo K <toger5@hotmail.de>
2023-10-31 16:04:22 +01:00
Timo
70f32feb5f invert show/hide controls (#1850)
Signed-off-by: Timo K <toger5@hotmail.de>
2023-10-31 13:47:24 +01:00
David Baker
70c042aeee Merge remote-tracking branch 'origin/livekit' into dbkr/ppe2ee 2023-10-27 20:48:51 +01:00
Timo
58ee31d383 Add hideControls url param for screen recordings. (#1808)
---------

Signed-off-by: Timo K <toger5@hotmail.de>
2023-10-26 19:33:59 +02:00
David Baker
15d3e7574d Re-apply Simon's emebdded e2ee work on latest livekit branch
Replaces https://github.com/vector-im/element-call/pull/1350
2023-10-16 17:45:06 +01:00
David Baker
aac92c18b3 Re-enable screen sharing on Safari
Appears to work fine now, and no reason to think it shouldn't on
Livekit.
2023-10-13 11:02:20 +01:00
Robin
614bc82402 Format code 2023-10-11 10:42:04 -04:00
Robin
cc6f1f8631 Merge branch 'livekit' into eslint-upgrade 2023-10-11 10:30:57 -04:00
Robin
44dbe77757 Merge branch 'livekit' into remove-inspector 2023-09-28 09:54:37 -04:00
Robin
3245ae9f60 Merge pull request #1641 from robintown/invite-modal
Implement the new invite modal designs
2023-09-28 09:45:03 -04:00
Robin
17836113ac Merge pull request #1642 from robintown/participants-icon
Replace the avatar stack in the header with an icon
2023-09-28 09:42:46 -04:00
Robin
7df093a23c Merge branch 'livekit' into invite-modal 2023-09-28 09:42:06 -04:00
Robin
2730cea181 Fix imports 2023-09-27 19:06:10 -04:00
Robin
1dc4ef67f3 Remove the group call inspector
It's unused ever since we switched to LiveKit, and we intend to use other telemetry mechanisms going forward to fill this debugging use case, so it can be removed as discussed in today's team meeting.
2023-09-27 18:27:42 -04:00
Robin
916a88712a Replace the avatar stack in the header with an icon
This is a design update.
2023-09-27 18:12:04 -04:00