From ca2fe8e25884538c72080b2d0f181f72174d433d Mon Sep 17 00:00:00 2001 From: neoapps-dev Date: Tue, 11 Aug 2026 14:43:28 +0300 Subject: [PATCH] feat(android): LCEOnline auth --- .../android/app/src/main/AndroidManifest.xml | 5 + .../com/emerald/legacy/LceAuthActivity.kt | 123 ++++++++++++++++++ .../java/com/emerald/legacy/LceAuthPlugin.kt | 37 ++++++ src-tauri/src/android_runtime.rs | 2 +- src-tauri/src/lce_auth.rs | 35 +++++ src-tauri/src/lib.rs | 3 + src/components/views/LceOnlineView.tsx | 36 +++-- src/services/TauriService.ts | 4 + 8 files changed, 235 insertions(+), 10 deletions(-) create mode 100644 src-tauri/gen/android/app/src/main/java/com/emerald/legacy/LceAuthActivity.kt create mode 100644 src-tauri/gen/android/app/src/main/java/com/emerald/legacy/LceAuthPlugin.kt create mode 100644 src-tauri/src/lce_auth.rs diff --git a/src-tauri/gen/android/app/src/main/AndroidManifest.xml b/src-tauri/gen/android/app/src/main/AndroidManifest.xml index 90b8a8c..04986a1 100644 --- a/src-tauri/gen/android/app/src/main/AndroidManifest.xml +++ b/src-tauri/gen/android/app/src/main/AndroidManifest.xml @@ -31,6 +31,11 @@ + + Result<(), &intent, "addFlags", "(I)Landroid/content/Intent;", - &[JValue::Int(0x10000000 as jint)], + &[JValue::Int(0x10000000 as jint)], //neo: FLAG_ACTIVITY_NEW_TASK )?; env.call_method( diff --git a/src-tauri/src/lce_auth.rs b/src-tauri/src/lce_auth.rs new file mode 100644 index 0000000..b2f7639 --- /dev/null +++ b/src-tauri/src/lce_auth.rs @@ -0,0 +1,35 @@ +use tauri::plugin::{Builder, PluginHandle, TauriPlugin}; +use tauri::Wry; +pub struct LceAuthState(pub PluginHandle); +pub fn init() -> TauriPlugin { + Builder::new("emerald-lce-auth") + .setup(|app, api| { + #[cfg(target_os = "android")] + { + use tauri::Manager; + let handle = api.register_android_plugin("com.emerald.legacy", "LceAuthPlugin")?; + app.manage(LceAuthState(handle)); + } + Ok(()) + }) + .build() +} + +#[tauri::command] +pub async fn start_lce_auth(app: tauri::AppHandle) -> Result { + #[cfg(target_os = "android")] + { + use tauri::Manager; + let state = app.state::(); + state + .0 + .run_mobile_plugin_async("startAuth", ()) + .await + .map_err(|e| e.to_string()) + } + #[cfg(not(target_os = "android"))] + { + let _ = app; + Err("LCE Online auth is only supported on Android".into()) + } +} diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index e742f25..61d4219 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -7,6 +7,7 @@ mod playtime; mod platform; mod networking; mod workshop_server; +mod lce_auth; #[cfg(target_os = "android")] mod android_runtime; mod commands; @@ -36,6 +37,7 @@ pub fn run() { let mut builder = tauri::Builder::default() .plugin(tauri_plugin_deep_link::init()) .plugin(webview_deep_link_interceptor()) + .plugin(lce_auth::init()) .plugin(tauri_plugin_process::init()) .plugin(tauri_plugin_gamepad::init()) .plugin(tauri_plugin_opener::init()); @@ -136,6 +138,7 @@ pub fn run() { relay::stop_proxy, relay::stop_all_proxies, relay::join_game, + lce_auth::start_lce_auth, plugins::get_plugins_dir, plugins::list_directory, plugins::create_plugin_dir, diff --git a/src/components/views/LceOnlineView.tsx b/src/components/views/LceOnlineView.tsx index 3df6ab0..4c25415 100644 --- a/src/components/views/LceOnlineView.tsx +++ b/src/components/views/LceOnlineView.tsx @@ -7,6 +7,7 @@ import { useGame, } from "../../context/LauncherContext"; import ChooseInstanceModal from "../modals/ChooseInstanceModal"; +import { usePlatform } from "../../hooks/usePlatform"; import { lceOnlineService, SocialEntry } from "../../services/LceOnlineService"; import { TauriService } from "../../services/TauriService"; import { WebviewWindow } from '@tauri-apps/api/webviewWindow'; @@ -28,6 +29,7 @@ const LceOnlineView = memo(function LceOnlineView({ const { setActiveView, setIsUiHidden } = useUI(); const { animationsEnabled } = useConfig(); const { playPressSound, playBackSound } = useAudio(); + const { isAndroid } = usePlatform(); const game = useGame(); const [isSignedIn, setIsSignedIn] = useState(lceOnlineService.signedIn); const opened = useRef(false); @@ -80,25 +82,41 @@ const LceOnlineView = memo(function LceOnlineView({ if (!opened.current) { opened.current = true; - new WebviewWindow('LCEOnline', { - url: "https://mclegacyedition.xyz/internal/auth?appId=emerald_launcher", - width: 400, - height: 570, - resizable: false, - title: 'Emerald Legacy Launcher - LCEOnline', - }); + if (isAndroid) { + TauriService.startLceOnlineAuth() + .then((token) => { + lceOnlineService + .loginWithTokenAndFetchAccount(token) + .catch((e) => console.error(e)); + setIsSignedIn(true); + }) + .catch((e) => console.error("LCE Online auth failed", e)); + } else { + new WebviewWindow('LCEOnline', { + url: "https://mclegacyedition.xyz/internal/auth?appId=emerald_launcher", + width: 400, + height: 570, + resizable: false, + title: 'Emerald Legacy Launcher - LCEOnline', + }); + } }; const unlisten = listen('deep-link', async (event) => { const authUrl = event.payload.find(u => u.startsWith('emerald://')); if (!authUrl) return; const token = new URL(authUrl).searchParams.get('token'); - if (token) setIsSignedIn(true); + if (token) { + lceOnlineService + .loginWithTokenAndFetchAccount(token) + .catch((e) => console.error(e)); + setIsSignedIn(true); + } (await WebviewWindow.getByLabel('LCEOnline'))?.close(); }); return () => { unlisten.then(f => f()); }; - }, [isSignedIn]); + }, [isSignedIn, isAndroid]); useEffect(() => { if (!addFriendTarget) return; diff --git a/src/services/TauriService.ts b/src/services/TauriService.ts index c13ad33..aec4f01 100644 --- a/src/services/TauriService.ts +++ b/src/services/TauriService.ts @@ -238,6 +238,10 @@ export class TauriService { return invoke("plugin:opener|open_url", { url }); } + static async startLceOnlineAuth(): Promise { + return invoke("start_lce_auth"); + } + static async restartLauncher(): Promise { return invoke("restart_launcher"); }