From 33ddd2a345dd9ef41f4851b62a0d215ac763fc60 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Sun, 28 Apr 2024 21:45:42 +0200 Subject: [PATCH] GH-93: Fix build issues on Android AArch64 builds --- package.json | 3 ++ src-tauri/.cargo/config.toml | 2 +- src-tauri/Cargo.toml | 16 ++++++--- src-tauri/build.rs | 12 +++++-- src-tauri/capabilities/migrated.json | 9 ++++- src-tauri/src/commands/mod.rs | 16 ++++++--- src-tauri/src/commands/settings_cmd.rs | 12 +++++-- src-tauri/src/connection/mod.rs | 7 +++- src-tauri/src/lib.rs | 18 ++++++++++ src-tauri/src/main.rs | 1 + src-tauri/src/mobile.rs | 30 ++++++++--------- src-tauri/src/utils/certificate_store.rs | 21 +++++++----- src-tauri/tauri.conf.json | 2 +- src/App.tsx | 16 +++++++-- src/components/EventLog.tsx | 5 +-- src/components/Sidebar.tsx | 14 ++++++-- src/helper/PlatformHelper.ts | 10 ++++++ src/routes/Chat.tsx | 43 ++++++++++++++++++++++-- src/routes/Login.tsx | 4 +-- vite.config.ts | 6 +--- yarn.lock | 30 +++++++++++++++-- 21 files changed, 213 insertions(+), 64 deletions(-) create mode 100644 src/helper/PlatformHelper.ts diff --git a/package.json b/package.json index 6ebb938..26174ec 100644 --- a/package.json +++ b/package.json @@ -17,14 +17,17 @@ "@mui/material": "^5.12.0", "@mui/styles": "^5.12.0", "@reduxjs/toolkit": "^1.9.5", + "@rollup/rollup-linux-x64-gnu": "^4.17.0", "@tauri-apps/api": "^2.0.0", "@tauri-apps/plugin-dialog": "^2.0.0-beta.2", + "@tauri-apps/plugin-os": "^2.0.0-beta.2", "@types/dompurify": "^3.0.1", "@types/lodash": "^4.14.202", "@types/marked": "^5.0.0", "@types/quill": "^2.0.10", "@types/react-color": "^3.0.6", "@types/tinycolor2": "^1.4.3", + "@use-gesture/react": "^10.3.1", "dayjs": "^1.11.7", "dompurify": "^3.0.2", "fuse.js": "^6.6.2", diff --git a/src-tauri/.cargo/config.toml b/src-tauri/.cargo/config.toml index 58fa028..c383b48 100644 --- a/src-tauri/.cargo/config.toml +++ b/src-tauri/.cargo/config.toml @@ -1,4 +1,4 @@ [build] -target = "x86_64-pc-windows-msvc" +target = "x86_64-unknown-linux-gnu" [target] diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index c5c2392..d424410 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -32,7 +32,6 @@ async-trait = "0.1.68" tracing = "0.1" tracing-subscriber = {version = "0.3", features = ["env-filter"] } base64 = "0.22.0" -openssl = "0.10.52" os_info = "3" rodio = "0.17.1" directories = "5.0.1" @@ -47,10 +46,9 @@ symphonia = "0.5.3" mime_guess = "2.0.4" uuid = "1.7.0" tauri-plugin-dialog = "2.0.0-beta.4" -image = {version = "0.25.1", features = ["gif", "png"], default-features = false } # zune jpeg is broken in android builds -audiopus_sys = { git = "F:/Dokumente/projekte/rust/audiopus_sys", branch = "0.0.6" } +audiopus_sys = { git = "file:///mnt/f/Dokumente/projekte/rust/audiopus_sys", branch = "0.0.9" } opus = "0.3.0" -oboe = { version = "0.6.1", features = [ "java-interface", "shared-stdcxx" ] } # Android +tauri-plugin-os = "2.0.0-beta.3" [dev-dependencies] tempfile = "3.5.0" @@ -58,6 +56,15 @@ mockall = "0.12.1" tokio-test = "0.4.2" xshell = "0.2.3" +[target.'cfg(all(target_os = "windows", target_os = "linux", target_os = "macos"))'.dependencies] +image = "0.25.1" +openssl = "0.10.52" + +[target.'cfg(target_os = "android")'.dependencies] +oboe = { version = "0.6.1", features = [ "java-interface", "shared-stdcxx" ] } # Android +image = {version = "0.25.1", features = ["gif", "png"], default-features = false} # zune jpeg is broken in android builds +openssl = { version = "0.10", features = ["vendored"] } + [features] # by default Tauri runs in production mode # when `tauri dev` runs it is executed with `cargo run --no-default-features` if `devPath` is an URL @@ -66,7 +73,6 @@ default = ["custom-protocol"] # DO NOT remove this custom-protocol = ["tauri/custom-protocol"] - [profile.release] debug = 1 diff --git a/src-tauri/build.rs b/src-tauri/build.rs index c949819..1743f14 100644 --- a/src-tauri/build.rs +++ b/src-tauri/build.rs @@ -117,9 +117,15 @@ fn main() -> io::Result<()> { }); } - let mumble_proto_str = mumble_proto.to_str().expect("Failed to convert path to string"); - let mumble_udp_proto_str = mumble_udp_proto.to_str().expect("Failed to convert path to string"); - let fancy_proto_str = fancy_proto.to_str().expect("Failed to convert path to string"); + let mumble_proto_str = mumble_proto + .to_str() + .expect("Failed to convert path to string"); + let mumble_udp_proto_str = mumble_udp_proto + .to_str() + .expect("Failed to convert path to string"); + let fancy_proto_str = fancy_proto + .to_str() + .expect("Failed to convert path to string"); prost_build::compile_protos(&[mumble_proto_str], &["../out"])?; prost_build::compile_protos(&[mumble_udp_proto_str], &["../out"])?; diff --git a/src-tauri/capabilities/migrated.json b/src-tauri/capabilities/migrated.json index 03fd357..6eda160 100644 --- a/src-tauri/capabilities/migrated.json +++ b/src-tauri/capabilities/migrated.json @@ -12,6 +12,13 @@ "app:default", "resources:default", "menu:default", - "tray:default" + "tray:default", + "os:default", + "os:default", + "os:allow-arch", + "os:allow-hostname", + "os:allow-os-type", + "os:allow-platform", + "store:allow-set" ] } \ No newline at end of file diff --git a/src-tauri/src/commands/mod.rs b/src-tauri/src/commands/mod.rs index 32dbfed..a30df70 100644 --- a/src-tauri/src/commands/mod.rs +++ b/src-tauri/src/commands/mod.rs @@ -68,6 +68,7 @@ pub async fn connect_to_server( username: String, identity: Option, state: State<'_, ConnectionState>, + app_handle: tauri::AppHandle, ) -> Result<(), String> { info!("Connecting to server: {server_host}:{server_port}, username: {username}, identity: {identity:?}"); @@ -89,6 +90,7 @@ pub async fn connect_to_server( identity, app_info, settings_channel, + app_handle )); if let Err(e) = connection.connect().await { return Err(format!("{e:?}")); @@ -207,9 +209,12 @@ pub async fn crop_and_store_image( zoom: f32, crop: Coordinates, rotation: i32, - app_handle: tauri::AppHandle + app_handle: tauri::AppHandle, ) -> Result { - let data_dir = app_handle.path().app_data_dir().map_err(|e| format!("{e:?}"))?; + let data_dir = app_handle + .path() + .app_data_dir() + .map_err(|e| format!("{e:?}"))?; let path = Path::new(path); let img = image::open(path).map_err(|e| e.to_string())?; @@ -368,7 +373,10 @@ pub fn close_app(app: AppHandle) { #[cfg(desktop)] #[tauri::command] pub fn dev_tools(app: AppHandle) { - if let Err(e) = app.get_webview_window("main").map_or_else(|| Err(()), |w| Ok(w.open_devtools())) { + if let Err(e) = app + .get_webview_window("main") + .map_or_else(|| Err(()), |w| Ok(w.open_devtools())) + { error!("Failed to toggle dev tools: {:?}", e); } -} \ No newline at end of file +} diff --git a/src-tauri/src/commands/settings_cmd.rs b/src-tauri/src/commands/settings_cmd.rs index 46c8652..e04f521 100644 --- a/src-tauri/src/commands/settings_cmd.rs +++ b/src-tauri/src/commands/settings_cmd.rs @@ -32,7 +32,7 @@ pub fn save_server( server_port: u16, username: &str, identity: Option, - app_handle: tauri::AppHandle + app_handle: tauri::AppHandle, ) -> Result<(), String> { info!("Saving server: {server_host}:{server_port}"); let mut server_file = get_settings_file(SERVER_SETTINS_FILE, &app_handle)?; @@ -77,7 +77,10 @@ pub fn save_server( pub fn get_server_list(app_handle: tauri::AppHandle) -> Result, String> { info!("Getting server list"); - let data_dir = app_handle.path().app_config_dir().map_err(|e| format!("{e:?}"))?; + let data_dir = app_handle + .path() + .app_config_dir() + .map_err(|e| format!("{e:?}"))?; // create config dir if it doesn't exist std::fs::create_dir_all(&data_dir).map_err(|e| format!("{e:?}"))?; @@ -101,7 +104,10 @@ pub fn get_server_list(app_handle: tauri::AppHandle) -> Result, Stri #[tauri::command] pub fn get_identity_certs(app_handle: tauri::AppHandle) -> Result, String> { - let data_dir = app_handle.path().app_data_dir().map_err(|e| format!("{e:?}"))?; + let data_dir = app_handle + .path() + .app_data_dir() + .map_err(|e| format!("{e:?}"))?; if !data_dir.exists() { std::fs::create_dir_all(&data_dir).map_err(|e| format!("{e:?}"))?; diff --git a/src-tauri/src/connection/mod.rs b/src-tauri/src/connection/mod.rs index d1797cc..90cab65 100644 --- a/src-tauri/src/connection/mod.rs +++ b/src-tauri/src/connection/mod.rs @@ -16,7 +16,7 @@ use base64::Engine; use std::collections::HashMap; use std::sync::atomic::AtomicBool; use std::sync::Arc; -use tauri::PackageInfo; +use tauri::{Manager, PackageInfo}; use threads::{InputThread, MainThread, OutputThread, PingThread}; use tokio::net::TcpStream; use tokio::sync::broadcast::{self, Receiver, Sender}; @@ -63,6 +63,8 @@ pub struct Connection { package_info: PackageInfo, stream_reader: Arc>>, settings_channel: Receiver, + + app_handle: tauri::AppHandle, } impl Connection { @@ -73,6 +75,7 @@ impl Connection { identity: Option, package_info: PackageInfo, settings_channel: Receiver, + app_handle: tauri::AppHandle, ) -> Self { let (tx_in, _): (Sender>, Receiver>) = broadcast::channel(QUEUE_SIZE); let (tx_out, _): (Sender>, Receiver>) = broadcast::channel(QUEUE_SIZE); @@ -97,6 +100,7 @@ impl Connection { message_channels: MessageChannels { message_channel }, stream_reader: Arc::new(Mutex::new(None)), settings_channel, + app_handle, } } @@ -109,6 +113,7 @@ impl Connection { ); let mut certificate_store = CertificateBuilder::try_from(&self.server_data.identity) + .cert_path(self.app_handle.path().data_dir()?) .load_or_generate_new(true) .store_to_project_dir(true) .build()?; diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 793c9ca..4806939 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -19,6 +19,10 @@ use crate::commands::{ }, zip_cmd::{convert_to_base64, unzip_data_from_utf8, zip_data_to_utf8}, }; +use commands::{web_cmd::CrawlerState, ConnectionState}; +use std::{collections::HashMap, sync::Arc}; +use tauri::Manager; +use tokio::sync::Mutex; #[cfg(mobile)] mod mobile; @@ -50,7 +54,21 @@ impl AppBuilder { let setup = self.setup; tauri::Builder::default() .plugin(tauri_plugin_store::Builder::default().build()) + .plugin(tauri_plugin_os::init()) .setup(move |app| { + app.manage(ConnectionState { + connection: Mutex::new(None), + window: Arc::new(Mutex::new( + app.get_webview_window("main").expect("window not found"), + )), + package_info: Mutex::new(app.package_info().clone()), + message_handler: Mutex::new(HashMap::new()), + device_manager: Mutex::new(None), + settings_channel: Mutex::new(None), + }); + app.manage(CrawlerState { + crawler: Mutex::new(None), + }); if let Some(setup) = setup { (setup)(app)?; } diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index fdf3bcc..b8d3605 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -60,6 +60,7 @@ async fn main() { init_logging(); tauri::Builder::default() + .plugin(tauri_plugin_os::init()) .plugin(tauri_plugin_window_state::Builder::default().build()) .plugin(tauri_plugin_store::Builder::default().build()) .setup(|app| { diff --git a/src-tauri/src/mobile.rs b/src-tauri/src/mobile.rs index e78670a..e4d4fec 100644 --- a/src-tauri/src/mobile.rs +++ b/src-tauri/src/mobile.rs @@ -5,23 +5,23 @@ use tracing_subscriber::{ }; fn init_logging() { - let format = fmt::format() - .with_level(true) - .with_target(false) - .with_thread_ids(false) - .with_thread_names(false) - .compact(); // use the `Compact` formatting style. + let format = fmt::format() + .with_level(true) + .with_target(false) + .with_thread_ids(false) + .with_thread_names(false) + .compact(); // use the `Compact` formatting style. - tracing_subscriber::fmt() - .with_max_level(Level::TRACE) - .event_format(format) - .with_env_filter(EnvFilter::from_default_env().add_directive(Level::INFO.into())) - .with_span_events(FmtSpan::CLOSE) - .init(); + tracing_subscriber::fmt() + .with_max_level(Level::TRACE) + .event_format(format) + .with_env_filter(EnvFilter::from_default_env().add_directive(Level::INFO.into())) + .with_span_events(FmtSpan::CLOSE) + .init(); } #[tauri::mobile_entry_point] fn main() { - init_logging(); - super::AppBuilder::new().run(); -} \ No newline at end of file + init_logging(); + super::AppBuilder::new().run(); +} diff --git a/src-tauri/src/utils/certificate_store.rs b/src-tauri/src/utils/certificate_store.rs index 5d2fdf4..753f3d6 100644 --- a/src-tauri/src/utils/certificate_store.rs +++ b/src-tauri/src/utils/certificate_store.rs @@ -21,6 +21,7 @@ pub struct CertificateBuilder { load_or_generate_new: bool, store_to_project_dir: bool, identity: Option, + data_dir: PathBuf, } impl CertificateBuilder { @@ -29,9 +30,15 @@ impl CertificateBuilder { load_or_generate_new: false, store_to_project_dir: false, identity: identity.clone(), + data_dir: PathBuf::new(), } } + pub fn cert_path(mut self, path: PathBuf) -> Self { + self.data_dir = path; + self + } + pub const fn load_or_generate_new(mut self, load_or_generate_new: bool) -> Self { self.load_or_generate_new = load_or_generate_new; self @@ -43,20 +50,16 @@ impl CertificateBuilder { } pub fn build(self) -> AnyError { - let project_dirs = get_project_dirs() - .ok_or_else(|| CertificateError::new("Unable to load project dir"))?; - let data_dir = project_dirs.data_dir(); - - if !data_dir.exists() { - std::fs::create_dir_all(data_dir)?; + if !self.data_dir.exists() { + std::fs::create_dir_all(&self.data_dir)?; } - let certificate_path = data_dir.join( + let certificate_path = self.data_dir.join( self.identity .as_ref() .map_or("certificate.pem".to_string(), |v| format!("cert_{v}.pem")), ); - let private_key_path = data_dir.join( + let private_key_path = self.data_dir.join( self.identity .as_ref() .map_or("private_key.pem".to_string(), |v| { @@ -70,7 +73,7 @@ impl CertificateBuilder { if let Some(certificate_store) = Self::read_certificates(&certificate_path, &private_key_path) { - trace!("Certificate loaded from project dir: {data_dir:?}"); + trace!("Certificate loaded from project dir: {:?}", self.data_dir); return Ok(certificate_store); } diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 71c2b3f..d74753b 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -2,7 +2,7 @@ "build": { "beforeBuildCommand": "yarn run build", "beforeDevCommand": "yarn run dev", - "devUrl": "http://localhost:5173", + "devUrl": "http://192.168.178.120:5173", "frontendDist": "../dist" }, "productName": "Fancy Mumble", diff --git a/src/App.tsx b/src/App.tsx index 9741c21..fa599a7 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,7 +1,7 @@ import './App.css' import { RouterProvider, useNavigate } from 'react-router-dom'; import { router } from './routes/router'; -import { useEffect, useRef, useState } from 'react'; +import { useCallback, useEffect, useRef, useState } from 'react'; import { listen } from '@tauri-apps/api/event'; import { handleBackendMessage } from './helper/BackendMessageHandler'; import { useDispatch } from 'react-redux'; @@ -9,13 +9,21 @@ import Titlebar from './components/Titlebar'; import { Box } from '@mui/material'; import ContextMenu from './components/contextMenus/ContextMenu'; import { copy, paste, showDeveloperTools } from './components/contextMenus/ContextMenuOptions'; +import { getPlatform, isMobile } from './helper/PlatformHelper'; function App() { const dispatch = useDispatch(); const mainElementRef = useRef(null); + const [mobile, setMobile] = useState(false); + const [platform, setPlatform] = useState("" as string); - useEffect(() => { + const getOs = useCallback(async () => { + setMobile(await isMobile()); + setPlatform(await getPlatform()); + }, []); + useEffect(() => { + getOs(); //listen to a event const unlisten = listen("backend_update", e => handleBackendMessage(e, dispatch)); @@ -24,9 +32,11 @@ function App() { } }); + const titlebar = mobile ? () : ; + return (
- + {titlebar} diff --git a/src/components/EventLog.tsx b/src/components/EventLog.tsx index 53c9eff..0f60ff6 100644 --- a/src/components/EventLog.tsx +++ b/src/components/EventLog.tsx @@ -9,9 +9,10 @@ import { useTranslation } from 'react-i18next'; interface EventLogProps { showLog: boolean; + mobile: boolean; } -const EventLog: React.FC = React.memo(({ showLog }) => { +const EventLog: React.FC = React.memo(({ showLog, mobile }) => { const { t, i18n } = useTranslation(); const eventLog = useSelector((state: RootState) => state.eventLog); const eventLogRef = useRef(null); @@ -28,7 +29,7 @@ const EventLog: React.FC = React.memo(({ showLog }) => { return ( { - if(!screenCasted) { + if (!screenCasted) { return; } const viewer = new WebRTCViewer(signalingServerUrl, currentUserId ?? 0, currentChannelId ?? 0); @@ -78,7 +83,7 @@ function Sidebar() { }; return ( - + @@ -95,6 +100,9 @@ function Sidebar() { + diff --git a/src/helper/PlatformHelper.ts b/src/helper/PlatformHelper.ts new file mode 100644 index 0000000..62ed0c1 --- /dev/null +++ b/src/helper/PlatformHelper.ts @@ -0,0 +1,10 @@ +import { platform } from '@tauri-apps/plugin-os'; + +export async function isMobile(): Promise { + const os = await platform(); + return os == "android" || os == "ios"; +} + +export async function getPlatform(): Promise { + return await platform(); +} \ No newline at end of file diff --git a/src/routes/Chat.tsx b/src/routes/Chat.tsx index c0a726b..f1d0cd3 100644 --- a/src/routes/Chat.tsx +++ b/src/routes/Chat.tsx @@ -1,4 +1,4 @@ -import { Box } from '@mui/material'; +import { Box, SwipeableDrawer } from '@mui/material'; import ChatMessageContainer from '../components/ChatMessageContainer'; @@ -17,11 +17,14 @@ import { updateAudioSettings } from '../store/features/users/audioSettings'; import { invoke } from "@tauri-apps/api/core"; import i18n from '../i18n/i18n'; import { updateCurrentUserListeningInfo } from '../store/features/users/userSlice'; +import { isMobile } from '../helper/PlatformHelper'; function Chat() { const [showLog, setShowLog] = useState(false); const [loading, setLoading] = useState(false); + const [mobile, setMobile] = useState(false); + const [showSidebar, setShowSidebar] = useState(false); const messageLog = useSelector((state: RootState) => state.reducer.chatMessage); const useWYSIWYG = useSelector((state: RootState) => state.reducer.frontendSettings?.advancedSettings?.useWYSIWYG); @@ -50,7 +53,12 @@ function Chat() { console.log("Settings fetched"); }, []) + const getOs = useCallback(async () => { + setMobile(await isMobile()); + }, []); + useEffect(() => { + getOs(); fetchSettings().then(() => setLoading(false)); }, [fetchSettings]); @@ -62,9 +70,38 @@ function Chat() { } }, [useWYSIWYG]); + let sidebar = useMemo(() => { + if (mobile) { + return ( setShowSidebar(false)} + onOpen={() => setShowSidebar(true)} + > + + ) + } else { + return () + } + }, [mobile]); + + let eventLog = useMemo(() => { + if (mobile) { + return ( setShowLog(false)} + onOpen={() => setShowLog(true)} + anchor='bottom' + > + + ) + } else { + return () + } + }, [mobile, showLog]); + return ( - + {sidebar} - + {eventLog} ) } diff --git a/src/routes/Login.tsx b/src/routes/Login.tsx index add8e0e..5992f9d 100644 --- a/src/routes/Login.tsx +++ b/src/routes/Login.tsx @@ -1,7 +1,7 @@ import React, { useEffect, useState } from 'react' import '../App.css'; import './styles/Login.css'; -import { Accordion, AccordionDetails, AccordionSummary, Alert, Avatar, Box, IconButton, LinearProgress, List, ListItem, ListItemAvatar, ListItemButton, ListItemText, MenuItem, Typography, Menu } from '@mui/material' +import { Accordion, AccordionDetails, AccordionSummary, Alert, Avatar, Box, IconButton, LinearProgress, List, ListItem, ListItemAvatar, ListItemButton, ListItemText, MenuItem, Typography, Menu } from '@mui/material'; import { invoke } from '@tauri-apps/api/core' import { useLocation, useNavigate } from 'react-router-dom'; import { useDispatch, useSelector } from 'react-redux'; @@ -116,7 +116,7 @@ function Login() { return ( - +