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.
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"
```
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
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.
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.
This upgrade came with a number of new lints that needed to be fixed across the code base. Primarily: explicit return types on functions, and explicit visibility modifiers on class members.
This attempts to converge all our modals on the new modal component while changing their designs as little as possible. This should reduce the bundle size a bit and make the app generally feel like it's converging on the new designs, even though individual modals still remain to be revamped.
We were manipulating the participant's mute state directly for some
reason, just for setting the mute state directly, which bypased the
mutestates hook.
Rather than the matrixRTC memberships. We're essentially trusting
LiveKit's view of weho is connected here, so we may as well include
the real names of anyone we don't think is a matrixRTC participant,
for whatever reason.