Refactor the imp/gui bondary to use real traits (#18)
Build Mumble Web 2 / linux_build (push) Successful in 1m24s
Build Mumble Web 2 / windows_build (push) Successful in 2m36s
Build Mumble Web 2 / android_build (push) Successful in 5m57s
Build android container / android-release-builder-container-build (push) Successful in -4s
Build Mumble Web 2 release builder containers / windows-release-builder-container-build (push) Successful in 16s
Build Mumble Web 2 / linux_build (push) Successful in 1m24s
Build Mumble Web 2 / windows_build (push) Successful in 2m36s
Build Mumble Web 2 / android_build (push) Successful in 5m57s
Build android container / android-release-builder-container-build (push) Successful in -4s
Build Mumble Web 2 release builder containers / windows-release-builder-container-build (push) Successful in 16s
# Summary Introduces a trait-based platform abstraction layer that makes the boundary between platform-specific and shared code explicit and compile-time verified. The TLDR version of this new trait stuff works: 1. Define a `PlatformInterface` trait. 2. Each platform defines a zero-sized struct implementing the trait (ex `WebPlatform`). 3. Create an ifdef'd type alias on those structs: ```rust #[cfg(feature = "web")] pub type Platform = web::WebPlatform; #[cfg(all(feature = "desktop"))] pub type Platform = desktop::DesktopPlatform; #[cfg(all(feature = "mobile", not(feature = "web")))] pub type Platform = mobile::MobilePlatform; ``` 5. Add a compile time assertion that `Platform` implements `PlatformInterface`. # Motivation Previously, platform code used a mix of pub use re-exports and #[cfg] blocks that made it difficult to understand what each platform must implement. The new trait-based approach provides: - Clear documentation of the platform contract - Compile-time verification that all platforms implement required functionality - Ability to cargo check without feature flags (via stub platform) # Changes New traits in imp/mod.rs: - PlatformInterface - logging, permissions, network, config, storage. Overall this the trait that platforms must satify to compile. - AudioSystemInterface - audio system initialization and recording - AudioPlayerInterface - opus audio playback Type aliases: - Platform, AudioSystem, AudioPlayer resolve to the correct types based on feature flags Call site updates: - Changed from imp::function() to Platform::function() syntax - Removed ImpRead/ImpWrite helper traits in favor of direct bounds # Testing Manual testing reveals that Web and Desktop still work, I (Liam) have not tested the mobile version beyond compilation. Co-authored-by: Liam Warfield <liam.warfield@gmail.com> Reviewed-on: #18 Co-authored-by: Sam Sartor <me@samsartor.com> Co-committed-by: Sam Sartor <me@samsartor.com>
This commit was merged in pull request #18.
This commit is contained in:
+9
-9
@@ -6,7 +6,7 @@ use mumble_web2_common::{ClientConfig, ServerStatus};
|
||||
use ordermap::OrderSet;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
use crate::imp;
|
||||
use crate::imp::{Platform, PlatformInterface as _};
|
||||
|
||||
pub type ChannelId = u32;
|
||||
pub type UserId = u32;
|
||||
@@ -690,12 +690,12 @@ pub fn LoginView(config: Resource<ClientConfig>) -> Element {
|
||||
use_resource(move || async move {
|
||||
let client = reqwest::Client::new();
|
||||
loop {
|
||||
*last_status.write_unchecked() = Some(imp::get_status(&client).await);
|
||||
imp::sleep(std::time::Duration::from_secs_f32(1.0)).await;
|
||||
*last_status.write_unchecked() = Some(Platform::get_status(&client).await);
|
||||
Platform::sleep(std::time::Duration::from_secs_f32(1.0)).await;
|
||||
}
|
||||
});
|
||||
|
||||
let mut address_input = use_signal(|| imp::load_server_url());
|
||||
let mut address_input = use_signal(|| Platform::load_server_url());
|
||||
let address = use_memo(move || {
|
||||
if let Some(addr) = address_input() {
|
||||
addr.clone()
|
||||
@@ -706,14 +706,14 @@ pub fn LoginView(config: Resource<ClientConfig>) -> Element {
|
||||
}
|
||||
});
|
||||
|
||||
let previous_username = imp::load_username();
|
||||
let previous_username = Platform::load_username();
|
||||
let mut username = use_signal(|| previous_username.unwrap_or(String::new()));
|
||||
|
||||
let do_connect = move |_| {
|
||||
//let _ = set_default_username(&username.read());
|
||||
let _ = imp::set_default_username(&username.read());
|
||||
let _ = Platform::set_default_username(&username.read());
|
||||
if config.read().as_ref().is_some_and(|cfg| cfg.any_server) {
|
||||
imp::set_default_server(&address.read());
|
||||
Platform::set_default_server(&address.read());
|
||||
}
|
||||
net.send(Connect {
|
||||
address: address.read().clone(),
|
||||
@@ -860,13 +860,13 @@ pub fn app() -> Element {
|
||||
|
||||
use_coroutine(|rx: UnboundedReceiver<Command>| super::network_entrypoint(rx));
|
||||
let config = use_resource(|| async move {
|
||||
match imp::load_config().await {
|
||||
match Platform::load_config().await {
|
||||
Ok(config) => config,
|
||||
Err(_) => ClientConfig::default(),
|
||||
}
|
||||
});
|
||||
|
||||
imp::request_permissions();
|
||||
Platform::request_permissions();
|
||||
|
||||
rsx!(
|
||||
document::Link{ rel: "stylesheet", href: "https://fonts.googleapis.com/css2?family=Nunito:ital,wght@0,200..1000;1,200..1000&display=swap" }
|
||||
|
||||
Reference in New Issue
Block a user