diff --git a/.gitignore b/.gitignore index d1bb19a0..0c832a0b 100644 --- a/.gitignore +++ b/.gitignore @@ -58,4 +58,4 @@ Carthage/Build/ .com.apple.timemachine.donotpresent -deployment-**.log \ No newline at end of file +deployment-**.log diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index f28526ab..b3c957d7 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -28,11 +28,19 @@ graph TD ## Key Components +- **actix-api:** Rust-based backend server using Actix Web framework +- **videocall-types:** Shared data types and protocol definitions + ### 1. Client Applications - **Web Client**: Built with Yew (Rust-to-WebAssembly framework) + - **`yew-ui`** Web frontend built with the Yew framework and compiled to WebAssembly + - **`tailwind-yew`** css + - **`videocall-client`** Client library for native integration - **CLI Client**: Native Rust client for headless devices + - **`videocall-cli`** Command-line interface for headless video streaming - **Mobile Clients**: Native mobile applications (in development) + - **`videocall-sdk`** ### 2. Transport Servers diff --git a/Makefile b/Makefile index fbb598c7..ce95c629 100644 --- a/Makefile +++ b/Makefile @@ -35,4 +35,4 @@ check: clean: docker compose -f docker/docker-compose.yaml down --remove-orphans \ - --volumes --rmi all \ No newline at end of file + --volumes --rmi all diff --git a/docker/Dockerfile.website b/docker/Dockerfile.website index f20710a3..03523bd7 100644 --- a/docker/Dockerfile.website +++ b/docker/Dockerfile.website @@ -9,6 +9,7 @@ RUN apt-get update && apt-get install -y \ libssl-dev \ pkg-config \ g++ \ + git-all \ && rm -rf /var/lib/apt/lists/* RUN cargo install --locked cargo-leptos@0.2.29 @@ -34,4 +35,4 @@ ENV LEPTOS_SITE_ADDR="0.0.0.0:8080" ENV LEPTOS_SITE_ROOT="site" EXPOSE 8080 -CMD ["/app/leptos_website"] \ No newline at end of file +CMD ["/app/leptos_website"] diff --git a/docker/Dockerfile.website.dev b/docker/Dockerfile.website.dev index 83f294e7..69551fc9 100644 --- a/docker/Dockerfile.website.dev +++ b/docker/Dockerfile.website.dev @@ -6,6 +6,7 @@ RUN apt-get update && apt-get install -y \ libssl-dev \ pkg-config \ g++ \ + git-all \ && rm -rf /var/lib/apt/lists/* RUN cargo install --locked cargo-leptos@0.2.29 diff --git a/docker/docker-compose.yaml b/docker/docker-compose.yaml index 374a7434..939f0923 100644 --- a/docker/docker-compose.yaml +++ b/docker/docker-compose.yaml @@ -22,6 +22,7 @@ services: - LOGIN_URL=http://localhost:${ACTIX_PORT:-8080}/login - RUSTFLAGS=--cfg=web_sys_unstable_apis - RUST_BACKTRACE=1 + - RUST_LOG=debug - WEBTRANSPORT_ENABLED=${WEBTRANSPORT_ENABLED:-false} - E2EE_ENABLED=${E2EE_ENABLED:-false} - USERS_ALLOWED_TO_STREAM=${USERS_ALLOWED_TO_STREAM:-} diff --git a/yew-ui/src/components/attendants.rs b/yew-ui/src/components/attendants.rs index d9abd646..8a6a74d1 100644 --- a/yew-ui/src/components/attendants.rs +++ b/yew-ui/src/components/attendants.rs @@ -81,6 +81,7 @@ pub enum Msg { ToggleForceDesktopGrid, HangUp, ShowCopyToast(bool), + RegisterHostToggleName(Callback), } impl From for Msg { @@ -145,6 +146,7 @@ pub struct AttendantsComponent { force_desktop_grid_on_mobile: bool, simulation_info_message: Option, show_copy_toast: bool, + host_toggle_change_name: Option>, show_dropdown: bool, } @@ -357,6 +359,7 @@ impl Component for AttendantsComponent { force_desktop_grid_on_mobile: true, simulation_info_message: None, show_copy_toast: false, + host_toggle_change_name: None, show_dropdown: false, }; if let Err(e) = crate::constants::app_config() { @@ -578,6 +581,10 @@ impl Component for AttendantsComponent { let _ = window().location().reload(); // Refresh page for clean state true } + Msg::RegisterHostToggleName(callback) => { + self.host_toggle_change_name = Some(callback); + true + } } } @@ -593,6 +600,13 @@ impl Component for AttendantsComponent { let mut display_peers_vec = real_peers_vec.clone(); display_peers_vec.extend(self.fake_peer_ids.iter().cloned()); + // // ✅ Ensure host (the current user) appears in the peers list + let my_email = ctx.props().email.clone(); + if !display_peers_vec.contains(&my_email) { + // Insert host at the beginning so they appear first in the grid + display_peers_vec.insert(0, my_email.clone() + " (You)"); + } + let num_display_peers = display_peers_vec.len(); // Cap the number of peers used for styling at CANVAS_LIMIT let num_peers_for_styling = num_display_peers.min(CANVAS_LIMIT); @@ -600,14 +614,32 @@ impl Component for AttendantsComponent { // Determine if the "Add Fake Peer" button should be disabled let add_fake_peer_disabled = num_display_peers >= CANVAS_LIMIT; + let on_encoder_settings_update = ctx.link().callback(WsAction::EncoderSettingsUpdated); + let rows: Vec = display_peers_vec .iter() .take(CANVAS_LIMIT) .enumerate() .map(|(i, peer_id)| { - let full_bleed = display_peers_vec.len() == 1 - && !self.client.is_screen_share_enabled_for_peer(peer_id); - html!{ } + let is_host = peer_id == &(email.clone() + " (You)"); + let full_bleed = (display_peers_vec.len() == 1 + && !self.client.is_screen_share_enabled_for_peer(peer_id)) + || num_display_peers == 1; + let on_toggle_change_name = if is_host { + self.host_toggle_change_name.clone() + } else { + None + }; + html! { + + } }) .collect(); @@ -617,8 +649,6 @@ impl Component for AttendantsComponent { num_peers_for_styling.max(1) ); - let on_encoder_settings_update = ctx.link().callback(WsAction::EncoderSettingsUpdated); - // Compute meeting link for invitation overlay let meeting_link = { let origin_result = window().location().origin(); @@ -777,6 +807,7 @@ impl Component for AttendantsComponent { } } else { diff --git a/yew-ui/src/components/canvas_generator.rs b/yew-ui/src/components/canvas_generator.rs index 857b64db..7c96f225 100644 --- a/yew-ui/src/components/canvas_generator.rs +++ b/yew-ui/src/components/canvas_generator.rs @@ -27,15 +27,19 @@ use web_sys::{window, CanvasRenderingContext2d, HtmlCanvasElement}; use yew::prelude::*; use yew::{html, Html}; -/// Render a single peer tile. If `full_bleed` is true and the peer is not screen sharing, -/// the video tile will occupy the full grid area. -pub fn generate_for_peer(client: &VideoCallClient, key: &String, full_bleed: bool) -> Html { +pub fn generate_canvas_tile( + client: &VideoCallClient, + key: &String, + full_bleed: bool, + is_host: bool, + on_toggle_change_name: Option>, +) -> Html { let allowed = users_allowed_to_stream().unwrap_or_default(); if !allowed.is_empty() && !allowed.iter().any(|host| host == key) { return html! {}; } - let is_video_enabled_for_peer = client.is_video_enabled_for_peer(key); + let is_video_enabled_for_peer = client.is_video_enabled_for_peer(key) || is_host; let is_audio_enabled_for_peer = client.is_audio_enabled_for_peer(key); let is_screen_share_enabled_for_peer = client.is_screen_share_enabled_for_peer(key); @@ -50,8 +54,35 @@ pub fn generate_for_peer(client: &VideoCallClient, key: &String, full_bleed: boo move |_| { if is_mobile_viewport() { toggle_pinned_div(&div_id) } } })} > - { if is_video_enabled_for_peer { html!{