mirror of
https://github.com/LCE-Hub/LCE-Emerald-Launcher.git
synced 2026-07-17 15:57:13 +00:00
feat: deeplinks
This commit is contained in:
parent
6312fb4540
commit
38fca607fd
|
|
@ -1,7 +1,9 @@
|
|||
[Desktop Entry]
|
||||
Name=Emerald Legacy Launcher
|
||||
Comment=FOSS cross-platform launcher for Minecraft Legacy Console Edition
|
||||
Exec=emerald-legacy-launcher
|
||||
Exec=emerald-legacy-launcher %u
|
||||
Icon=io.github.Emerald_Legacy_Launcher.Emerald_Legacy_Launcher
|
||||
Type=Application
|
||||
Categories=Game;
|
||||
Categories=Game;
|
||||
MimeType=x-scheme-handler/emerald;x-scheme-handler/emeraldlauncher;x-scheme-handler/discord-1482504445152460871;
|
||||
StartupNotify=true
|
||||
|
|
@ -16,6 +16,9 @@ finish-args:
|
|||
- --filesystem=xdg-data
|
||||
- --socket=pulseaudio
|
||||
- --filesystem=xdg-run/pipewire-0
|
||||
- --socket=session-bus
|
||||
- --talk-name=org.freedesktop.portal.Desktop
|
||||
- --talk-name=org.freedesktop.portal.OpenURI
|
||||
|
||||
modules:
|
||||
- shared-modules/libayatana-appindicator/libayatana-appindicator-gtk3.json
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@tauri-apps/api": "^2",
|
||||
"@tauri-apps/plugin-deep-link": "~2.4.9",
|
||||
"@tauri-apps/plugin-opener": "^2",
|
||||
"@tauri-apps/plugin-process": "~2.3.1",
|
||||
"@tauri-apps/plugin-updater": "~2.10.1",
|
||||
|
|
|
|||
|
|
@ -11,6 +11,9 @@ importers:
|
|||
'@tauri-apps/api':
|
||||
specifier: ^2
|
||||
version: 2.10.1
|
||||
'@tauri-apps/plugin-deep-link':
|
||||
specifier: ~2.4.9
|
||||
version: 2.4.9
|
||||
'@tauri-apps/plugin-opener':
|
||||
specifier: ^2
|
||||
version: 2.5.3
|
||||
|
|
@ -585,6 +588,9 @@ packages:
|
|||
'@tauri-apps/api@2.10.1':
|
||||
resolution: {integrity: sha512-hKL/jWf293UDSUN09rR69hrToyIXBb8CjGaWC7gfinvnQrBVvnLr08FeFi38gxtugAVyVcTa5/FD/Xnkb1siBw==}
|
||||
|
||||
'@tauri-apps/api@2.11.0':
|
||||
resolution: {integrity: sha512-7CinYODhky9lmO23xHnUFv0Xt43fbtWMyxZcLcRBlFkcgXKuEirBvHpmtJ89YMhyeGcq20Wuc47Fa4XjyniywA==}
|
||||
|
||||
'@tauri-apps/cli-darwin-arm64@2.10.1':
|
||||
resolution: {integrity: sha512-Z2OjCXiZ+fbYZy7PmP3WRnOpM9+Fy+oonKDEmUE6MwN4IGaYqgceTjwHucc/kEEYZos5GICve35f7ZiizgqEnQ==}
|
||||
engines: {node: '>= 10'}
|
||||
|
|
@ -656,6 +662,9 @@ packages:
|
|||
engines: {node: '>= 10'}
|
||||
hasBin: true
|
||||
|
||||
'@tauri-apps/plugin-deep-link@2.4.9':
|
||||
resolution: {integrity: sha512-u0SKOUHnJ1wqeqXsDFq2+kASCBj9xxbG0g9XZWPy9SOmU4wXtp6b/wiYpm6oH6/5fBTQsLqnLhIvqLBRpgHJlA==}
|
||||
|
||||
'@tauri-apps/plugin-opener@2.5.3':
|
||||
resolution: {integrity: sha512-CCcUltXMOfUEArbf3db3kCE7Ggy1ExBEBl51Ko2ODJ6GDYHRp1nSNlQm5uNCFY5k7/ufaK5Ib3Du/Zir19IYQQ==}
|
||||
|
||||
|
|
@ -1833,6 +1842,8 @@ snapshots:
|
|||
|
||||
'@tauri-apps/api@2.10.1': {}
|
||||
|
||||
'@tauri-apps/api@2.11.0': {}
|
||||
|
||||
'@tauri-apps/cli-darwin-arm64@2.10.1':
|
||||
optional: true
|
||||
|
||||
|
|
@ -1880,6 +1891,10 @@ snapshots:
|
|||
'@tauri-apps/cli-win32-ia32-msvc': 2.10.1
|
||||
'@tauri-apps/cli-win32-x64-msvc': 2.10.1
|
||||
|
||||
'@tauri-apps/plugin-deep-link@2.4.9':
|
||||
dependencies:
|
||||
'@tauri-apps/api': 2.11.0
|
||||
|
||||
'@tauri-apps/plugin-opener@2.5.3':
|
||||
dependencies:
|
||||
'@tauri-apps/api': 2.10.1
|
||||
|
|
|
|||
113
src-tauri/Cargo.lock
generated
113
src-tauri/Cargo.lock
generated
|
|
@ -564,6 +564,26 @@ dependencies = [
|
|||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "const-random"
|
||||
version = "0.1.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "87e00182fe74b066627d63b85fd550ac2998d4b0bd86bfed477a0ae4c7c71359"
|
||||
dependencies = [
|
||||
"const-random-macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "const-random-macro"
|
||||
version = "0.1.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e"
|
||||
dependencies = [
|
||||
"getrandom 0.2.17",
|
||||
"once_cell",
|
||||
"tiny-keccak",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "convert_case"
|
||||
version = "0.4.0"
|
||||
|
|
@ -929,6 +949,15 @@ dependencies = [
|
|||
"syn 2.0.117",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dlv-list"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "442039f5147480ba31067cb00ada1adae6892028e40e45fc5de7b7df6dcc1b5f"
|
||||
dependencies = [
|
||||
"const-random",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dom_query"
|
||||
version = "0.27.0"
|
||||
|
|
@ -1033,10 +1062,12 @@ dependencies = [
|
|||
"steam_shortcuts_util",
|
||||
"tauri",
|
||||
"tauri-build",
|
||||
"tauri-plugin-deep-link",
|
||||
"tauri-plugin-drpc",
|
||||
"tauri-plugin-gamepad",
|
||||
"tauri-plugin-opener",
|
||||
"tauri-plugin-process",
|
||||
"tauri-plugin-single-instance",
|
||||
"tauri-plugin-updater",
|
||||
"tokio",
|
||||
"tokio-tungstenite",
|
||||
|
|
@ -1773,6 +1804,12 @@ version = "0.12.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.14.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.15.5"
|
||||
|
|
@ -2993,6 +3030,16 @@ version = "0.2.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
|
||||
|
||||
[[package]]
|
||||
name = "ordered-multimap"
|
||||
version = "0.7.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49203cdcae0030493bad186b28da2fa25645fa276a51b6fec8010d281e02ef79"
|
||||
dependencies = [
|
||||
"dlv-list",
|
||||
"hashbrown 0.14.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ordered-stream"
|
||||
version = "0.2.0"
|
||||
|
|
@ -3851,6 +3898,16 @@ dependencies = [
|
|||
"uuid 0.8.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rust-ini"
|
||||
version = "0.21.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "796e8d2b6696392a43bea58116b667fb4c29727dc5abd27d6acf338bb4f688c7"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"ordered-multimap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-hash"
|
||||
version = "2.1.2"
|
||||
|
|
@ -4809,6 +4866,27 @@ dependencies = [
|
|||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tauri-plugin-deep-link"
|
||||
version = "2.4.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "70ee75bc5627f77bfdf40c913255ebc258117b10ebe2b2239a1a1cf40b0b58aa"
|
||||
dependencies = [
|
||||
"dunce",
|
||||
"plist",
|
||||
"rust-ini",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tauri",
|
||||
"tauri-plugin",
|
||||
"tauri-utils",
|
||||
"thiserror 2.0.18",
|
||||
"tracing",
|
||||
"url",
|
||||
"windows-registry",
|
||||
"windows-result 0.3.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tauri-plugin-drpc"
|
||||
version = "0.1.6"
|
||||
|
|
@ -4873,6 +4951,21 @@ dependencies = [
|
|||
"tauri-plugin",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tauri-plugin-single-instance"
|
||||
version = "2.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c8f29386f5e9fdc699182388a33ee80a56de436d91b67459e86afef426282af"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tauri",
|
||||
"thiserror 2.0.18",
|
||||
"tracing",
|
||||
"windows-sys 0.60.2",
|
||||
"zbus",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tauri-plugin-updater"
|
||||
version = "2.10.1"
|
||||
|
|
@ -5122,6 +5215,15 @@ dependencies = [
|
|||
"time-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tiny-keccak"
|
||||
version = "2.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237"
|
||||
dependencies = [
|
||||
"crunchy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tinystr"
|
||||
version = "0.8.3"
|
||||
|
|
@ -6165,6 +6267,17 @@ dependencies = [
|
|||
"windows-link 0.2.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-registry"
|
||||
version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b8a9ed28765efc97bbc954883f4e6796c33a06546ebafacbabee9696967499e"
|
||||
dependencies = [
|
||||
"windows-link 0.1.3",
|
||||
"windows-result 0.3.4",
|
||||
"windows-strings 0.4.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-result"
|
||||
version = "0.3.4"
|
||||
|
|
|
|||
|
|
@ -38,6 +38,8 @@ flate2 = "1"
|
|||
once_cell = "1"
|
||||
lzxd = "0.2.6"
|
||||
uuid = { version = "1", features = ["v4"] }
|
||||
tauri-plugin-deep-link = "2"
|
||||
tauri-plugin-single-instance = "2"
|
||||
|
||||
[target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies]
|
||||
tauri-plugin-updater = "2"
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"process:default"
|
||||
"process:default",
|
||||
"deep-link:default"
|
||||
]
|
||||
}
|
||||
|
|
@ -10,6 +10,7 @@
|
|||
],
|
||||
"permissions": [
|
||||
"updater:default",
|
||||
"process:default"
|
||||
"process:default",
|
||||
"deep-link:default"
|
||||
]
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -1 +1 @@
|
|||
{"default":{"identifier":"default","description":"Default permissions","local":true,"windows":["main"],"permissions":["core:default","core:app:default","core:event:default","core:image:default","core:menu:default","core:path:default","core:resources:default","core:tray:default","core:webview:default","core:window:default","opener:default","gamepad:default","drpc:default","updater:default",{"identifier":"opener:allow-open-path","allow":[{"path":"**"}]},{"identifier":"opener:allow-reveal-item-in-dir","allow":[{"path":"**"}]},"process:default"]},"desktop-capability":{"identifier":"desktop-capability","description":"","local":true,"windows":["main"],"permissions":["updater:default","process:default"],"platforms":["macOS","windows","linux"]}}
|
||||
{"default":{"identifier":"default","description":"Default permissions","local":true,"windows":["main"],"permissions":["core:default","core:app:default","core:event:default","core:image:default","core:menu:default","core:path:default","core:resources:default","core:tray:default","core:webview:default","core:window:default","opener:default","gamepad:default","drpc:default","updater:default",{"identifier":"opener:allow-open-path","allow":[{"path":"**"}]},{"identifier":"opener:allow-reveal-item-in-dir","allow":[{"path":"**"}]},"process:default","deep-link:default"]},"desktop-capability":{"identifier":"desktop-capability","description":"","local":true,"windows":["main"],"permissions":["updater:default","process:default","deep-link:default"],"platforms":["macOS","windows","linux"]}}
|
||||
|
|
@ -2312,6 +2312,60 @@
|
|||
"const": "core:window:deny-unminimize",
|
||||
"markdownDescription": "Denies the unminimize command without any pre-configured scope."
|
||||
},
|
||||
{
|
||||
"description": "Allows reading the opened deep link via the get_current command\n#### This default permission set includes:\n\n- `allow-get-current`",
|
||||
"type": "string",
|
||||
"const": "deep-link:default",
|
||||
"markdownDescription": "Allows reading the opened deep link via the get_current command\n#### This default permission set includes:\n\n- `allow-get-current`"
|
||||
},
|
||||
{
|
||||
"description": "Enables the get_current command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "deep-link:allow-get-current",
|
||||
"markdownDescription": "Enables the get_current command without any pre-configured scope."
|
||||
},
|
||||
{
|
||||
"description": "Enables the is_registered command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "deep-link:allow-is-registered",
|
||||
"markdownDescription": "Enables the is_registered command without any pre-configured scope."
|
||||
},
|
||||
{
|
||||
"description": "Enables the register command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "deep-link:allow-register",
|
||||
"markdownDescription": "Enables the register command without any pre-configured scope."
|
||||
},
|
||||
{
|
||||
"description": "Enables the unregister command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "deep-link:allow-unregister",
|
||||
"markdownDescription": "Enables the unregister command without any pre-configured scope."
|
||||
},
|
||||
{
|
||||
"description": "Denies the get_current command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "deep-link:deny-get-current",
|
||||
"markdownDescription": "Denies the get_current command without any pre-configured scope."
|
||||
},
|
||||
{
|
||||
"description": "Denies the is_registered command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "deep-link:deny-is-registered",
|
||||
"markdownDescription": "Denies the is_registered command without any pre-configured scope."
|
||||
},
|
||||
{
|
||||
"description": "Denies the register command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "deep-link:deny-register",
|
||||
"markdownDescription": "Denies the register command without any pre-configured scope."
|
||||
},
|
||||
{
|
||||
"description": "Denies the unregister command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "deep-link:deny-unregister",
|
||||
"markdownDescription": "Denies the unregister command without any pre-configured scope."
|
||||
},
|
||||
{
|
||||
"description": "Default permissions for the plugin\n#### This default permission set includes:\n\n- `allow-spawn-thread`\n- `allow-destroy-thread`\n- `allow-set-activity`\n- `allow-is-running`",
|
||||
"type": "string",
|
||||
|
|
|
|||
|
|
@ -2312,6 +2312,60 @@
|
|||
"const": "core:window:deny-unminimize",
|
||||
"markdownDescription": "Denies the unminimize command without any pre-configured scope."
|
||||
},
|
||||
{
|
||||
"description": "Allows reading the opened deep link via the get_current command\n#### This default permission set includes:\n\n- `allow-get-current`",
|
||||
"type": "string",
|
||||
"const": "deep-link:default",
|
||||
"markdownDescription": "Allows reading the opened deep link via the get_current command\n#### This default permission set includes:\n\n- `allow-get-current`"
|
||||
},
|
||||
{
|
||||
"description": "Enables the get_current command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "deep-link:allow-get-current",
|
||||
"markdownDescription": "Enables the get_current command without any pre-configured scope."
|
||||
},
|
||||
{
|
||||
"description": "Enables the is_registered command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "deep-link:allow-is-registered",
|
||||
"markdownDescription": "Enables the is_registered command without any pre-configured scope."
|
||||
},
|
||||
{
|
||||
"description": "Enables the register command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "deep-link:allow-register",
|
||||
"markdownDescription": "Enables the register command without any pre-configured scope."
|
||||
},
|
||||
{
|
||||
"description": "Enables the unregister command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "deep-link:allow-unregister",
|
||||
"markdownDescription": "Enables the unregister command without any pre-configured scope."
|
||||
},
|
||||
{
|
||||
"description": "Denies the get_current command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "deep-link:deny-get-current",
|
||||
"markdownDescription": "Denies the get_current command without any pre-configured scope."
|
||||
},
|
||||
{
|
||||
"description": "Denies the is_registered command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "deep-link:deny-is-registered",
|
||||
"markdownDescription": "Denies the is_registered command without any pre-configured scope."
|
||||
},
|
||||
{
|
||||
"description": "Denies the register command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "deep-link:deny-register",
|
||||
"markdownDescription": "Denies the register command without any pre-configured scope."
|
||||
},
|
||||
{
|
||||
"description": "Denies the unregister command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "deep-link:deny-unregister",
|
||||
"markdownDescription": "Denies the unregister command without any pre-configured scope."
|
||||
},
|
||||
{
|
||||
"description": "Default permissions for the plugin\n#### This default permission set includes:\n\n- `allow-spawn-thread`\n- `allow-destroy-thread`\n- `allow-set-activity`\n- `allow-is-running`",
|
||||
"type": "string",
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ mod commands;
|
|||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::Mutex;
|
||||
use tauri::Manager;
|
||||
use tauri::{Emitter, Manager};
|
||||
use commands::config as config_cmds;
|
||||
use commands::download;
|
||||
use commands::file_dialogs;
|
||||
|
|
@ -29,6 +29,21 @@ use state::{DownloadState, GameState, ProxyGuard};
|
|||
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
||||
pub fn run() {
|
||||
tauri::Builder::default()
|
||||
.plugin(tauri_plugin_deep_link::init())
|
||||
.plugin(tauri_plugin_single_instance::init(|app, args, _cwd| {
|
||||
let urls: Vec<String> = args
|
||||
.iter()
|
||||
.filter(|a| {
|
||||
a.starts_with("emerald://")
|
||||
|| a.starts_with("emeraldlauncher://")
|
||||
|| a.starts_with("discord-1482504445152460871://")
|
||||
})
|
||||
.cloned()
|
||||
.collect();
|
||||
if !urls.is_empty() {
|
||||
let _ = app.emit("deep-link", urls);
|
||||
}
|
||||
}))
|
||||
.plugin(tauri_plugin_process::init())
|
||||
.plugin(tauri_plugin_updater::Builder::new().build())
|
||||
.manage(DownloadState {
|
||||
|
|
@ -112,21 +127,27 @@ pub fn run() {
|
|||
|
||||
let args: Vec<String> = std::env::args().collect();
|
||||
if args.len() > 1 && !args[1].starts_with('-') {
|
||||
let instance_id = args[1].clone();
|
||||
let app_handle = app.handle().clone();
|
||||
tauri::async_runtime::spawn(async move {
|
||||
if let Some(window) = app_handle.get_webview_window("main") {
|
||||
let _ = window.hide();
|
||||
}
|
||||
let state = app_handle.state::<GameState>();
|
||||
match game::launch_game(app_handle.clone(), state, instance_id, Vec::new(), vec![]).await {
|
||||
Ok(_) => app_handle.exit(0),
|
||||
Err(e) => {
|
||||
eprintln!("Auto-launch error: {}", e);
|
||||
app_handle.exit(1);
|
||||
let first = &args[1];
|
||||
let is_deep_link = first.starts_with("emerald://")
|
||||
|| first.starts_with("emeraldlauncher://")
|
||||
|| first.starts_with("discord-1482504445152460871://");
|
||||
if !is_deep_link {
|
||||
let instance_id = first.clone();
|
||||
let app_handle_clone = app.handle().clone();
|
||||
tauri::async_runtime::spawn(async move {
|
||||
if let Some(window) = app_handle_clone.get_webview_window("main") {
|
||||
let _ = window.hide();
|
||||
}
|
||||
}
|
||||
});
|
||||
let state = app_handle_clone.state::<GameState>();
|
||||
match game::launch_game(app_handle_clone.clone(), state, instance_id, Vec::new(), vec![]).await {
|
||||
Ok(_) => app_handle_clone.exit(0),
|
||||
Err(e) => {
|
||||
eprintln!("Auto-launch error: {}", e);
|
||||
app_handle_clone.exit(1);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
|
|
|
|||
|
|
@ -27,6 +27,11 @@
|
|||
]
|
||||
},
|
||||
"plugins": {
|
||||
"deep-link": {
|
||||
"desktop": {
|
||||
"schemes": ["emerald", "discord-1482504445152460871", "emeraldlauncher"]
|
||||
}
|
||||
},
|
||||
"updater": {
|
||||
"pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IDM1NTk5MjQ4QjMxQjFCQgpSV1M3c1RHTEpKbFZBMEtxMnNUZ3F5V2FmQmQrREY5Z0pkbnJuUlBYL2d1cUtzRkJIeDFkUkR4RQo=",
|
||||
"endpoints": [
|
||||
|
|
|
|||
|
|
@ -27,6 +27,11 @@
|
|||
]
|
||||
},
|
||||
"plugins": {
|
||||
"deep-link": {
|
||||
"desktop": {
|
||||
"schemes": ["emerald", "discord-1482504445152460871", "emeraldlauncher"]
|
||||
}
|
||||
},
|
||||
"updater": {
|
||||
"pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IDM1NTk5MjQ4QjMxQjFCQgpSV1M3c1RHTEpKbFZBMEtxMnNUZ3F5V2FmQmQrREY5Z0pkbnJuUlBYL2d1cUtzRkJIeDFkUkR4RQo=",
|
||||
"endpoints": [
|
||||
|
|
|
|||
|
|
@ -17,7 +17,14 @@ import { TauriService } from "../../services/TauriService";
|
|||
import ChooseInstanceModal from "../modals/ChooseInstanceModal";
|
||||
import QRCode from "qrcode";
|
||||
|
||||
const LceLiveView = memo(function LceLiveView() {
|
||||
interface LceLiveViewProps {
|
||||
addFriendTarget?: string | null;
|
||||
onClearAddFriendTarget?: () => void;
|
||||
}
|
||||
const LceLiveView = memo(function LceLiveView({
|
||||
addFriendTarget,
|
||||
onClearAddFriendTarget,
|
||||
}: LceLiveViewProps) {
|
||||
const { setActiveView } = useUI();
|
||||
const { animationsEnabled } = useConfig();
|
||||
const { playPressSound, playBackSound } = useAudio();
|
||||
|
|
@ -37,7 +44,7 @@ const LceLiveView = memo(function LceLiveView() {
|
|||
);
|
||||
const [linkError, setLinkError] = useState<string | null>(null);
|
||||
const [isHosting, setIsHosting] = useState(false);
|
||||
const [hostStatus, setHostStatus] = useState("");
|
||||
const [_hostStatus, setHostStatus] = useState("");
|
||||
const [hostIp, setHostIp] = useState("");
|
||||
const [hostPort, setHostPort] = useState(19132);
|
||||
const [isDiscovering, setIsDiscovering] = useState(false);
|
||||
|
|
@ -392,6 +399,15 @@ const LceLiveView = memo(function LceLiveView() {
|
|||
showHostMethodPicker,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!addFriendTarget) return;
|
||||
setCurrentTab("friends");
|
||||
handleAction(() =>
|
||||
lceLiveService.sendFriendRequest(addFriendTarget),
|
||||
);
|
||||
onClearAddFriendTarget?.();
|
||||
}, [addFriendTarget, onClearAddFriendTarget]);
|
||||
|
||||
const tabs: ("friends" | "requests" | "invites")[] = [
|
||||
"friends",
|
||||
"requests",
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,4 +1,4 @@
|
|||
import { useEffect, useState, useMemo, useCallback } from "react";
|
||||
import { useEffect, useState, useMemo, useCallback, useRef } from "react";
|
||||
import { motion, AnimatePresence, MotionConfig } from "framer-motion";
|
||||
import "../css/App.css";
|
||||
import HomeView from "../components/views/HomeView";
|
||||
|
|
@ -39,6 +39,8 @@ import { PluginViewContainer } from "../components/plugins/PluginViewContainer";
|
|||
import type { Edition } from "../types/edition";
|
||||
import type { ToastOptions } from "../plugins/types";
|
||||
import pkg from "../../package.json";
|
||||
import { getCurrent, onOpenUrl } from "@tauri-apps/plugin-deep-link";
|
||||
import { listen } from "@tauri-apps/api/event";
|
||||
export default function App() {
|
||||
const ui = useUI();
|
||||
const {
|
||||
|
|
@ -69,8 +71,14 @@ export default function App() {
|
|||
} = notifications;
|
||||
const [showSetup, setShowSetup] = useState(false);
|
||||
const [isSetupChecked, setIsSetupChecked] = useState(false);
|
||||
const pendingDeepLinks = useRef<string[]>([]);
|
||||
const appReadyRef = useRef(false);
|
||||
const [workshopTarget, setWorkshopTarget] = useState<{
|
||||
id: string;
|
||||
type?: string;
|
||||
} | null>(null);
|
||||
const [addFriendTarget, setAddFriendTarget] = useState<string | null>(null);
|
||||
const displayIsDay = config.isDayTime;
|
||||
|
||||
const clearError = useCallback(() => game.setError(null), [game]);
|
||||
const clearGameUpdate = useCallback(
|
||||
() => game.setGameUpdateMessage(null),
|
||||
|
|
@ -124,6 +132,117 @@ export default function App() {
|
|||
}
|
||||
}, [showIntro, config.skipIntro, setShowIntro]);
|
||||
|
||||
const processDeepLink = useCallback(
|
||||
(url: string) => {
|
||||
try {
|
||||
const parsed = new URL(url);
|
||||
const path = parsed.hostname + parsed.pathname;
|
||||
const parts = path.replace(/^\/+/, "").split("/").filter(Boolean);
|
||||
if (parts.length === 0) return;
|
||||
const action = parts[0];
|
||||
if (action === "launch") {
|
||||
if (parts.length >= 2) {
|
||||
let instanceId = decodeURIComponent(parts[1]);
|
||||
if (instanceId === "neolegacy") instanceId = "legacy_evolved"; //neo: piebot said so
|
||||
TauriService.launchGame(instanceId, []).catch(console.error);
|
||||
} else {
|
||||
setActiveView("main");
|
||||
game.handleLaunch().catch(console.error);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (action === "lcelive" && parts.length >= 2 && parts[1] === "addfriend") {
|
||||
const username = parsed.searchParams.get("username");
|
||||
if (username) {
|
||||
setActiveView("lcelive");
|
||||
setAddFriendTarget(username);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (action === "workshop" && parts.length >= 2) {
|
||||
const workshopId = decodeURIComponent(parts[1]);
|
||||
const knownTypes = ["normal", "bytebukkit", "plugin", "version"];
|
||||
let workshopType: string | undefined;
|
||||
if (parts.length >= 3) {
|
||||
workshopType = parts[2];
|
||||
} else if (parsed.searchParams.get("type")) {
|
||||
workshopType = parsed.searchParams.get("type")!;
|
||||
} else {
|
||||
workshopType = knownTypes.find((t) => parsed.searchParams.has(t));
|
||||
}
|
||||
setActiveView("workshop");
|
||||
setWorkshopTarget({ id: workshopId, type: workshopType });
|
||||
return;
|
||||
}
|
||||
|
||||
setActiveView(action); //neo: yeah no im not checking if its valid or not.
|
||||
} catch (e) {
|
||||
console.error("failed to parse deep link:", e);
|
||||
}
|
||||
},
|
||||
[setActiveView, game.handleLaunch, setWorkshopTarget],
|
||||
);
|
||||
|
||||
const appReady =
|
||||
config.isLoaded && isSetupChecked && !showSetup && !showIntro;
|
||||
|
||||
useEffect(() => {
|
||||
if (appReady) {
|
||||
appReadyRef.current = true;
|
||||
if (pendingDeepLinks.current.length > 0) {
|
||||
for (const url of pendingDeepLinks.current) {
|
||||
processDeepLink(url);
|
||||
}
|
||||
pendingDeepLinks.current = [];
|
||||
}
|
||||
}
|
||||
}, [appReady, processDeepLink]);
|
||||
|
||||
const queueDeepLink = useCallback(
|
||||
(url: string) => {
|
||||
if (appReadyRef.current) {
|
||||
processDeepLink(url);
|
||||
} else {
|
||||
pendingDeepLinks.current.push(url);
|
||||
}
|
||||
},
|
||||
[processDeepLink],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
getCurrent()
|
||||
.then((urls) => {
|
||||
if (urls && urls.length > 0) {
|
||||
queueDeepLink(urls[0]);
|
||||
}
|
||||
})
|
||||
.catch(() => {});
|
||||
|
||||
let unlistenOpenUrl: Function;
|
||||
onOpenUrl((payload) => {
|
||||
for (const url of payload) {
|
||||
queueDeepLink(url);
|
||||
}
|
||||
}).then((unlistenFn) => {
|
||||
unlistenOpenUrl = unlistenFn;
|
||||
});
|
||||
|
||||
let unlistenEvent: Function;
|
||||
listen<string[]>("deep-link", (event) => {
|
||||
for (const url of event.payload) {
|
||||
queueDeepLink(url);
|
||||
}
|
||||
}).then((unlistenFn) => {
|
||||
unlistenEvent = unlistenFn;
|
||||
});
|
||||
|
||||
return () => {
|
||||
if (unlistenOpenUrl) unlistenOpenUrl();
|
||||
if (unlistenEvent) unlistenEvent();
|
||||
};
|
||||
}, [queueDeepLink]);
|
||||
useEffect(() => {
|
||||
if (config.isLoaded) {
|
||||
const setupCompleted =
|
||||
|
|
@ -433,7 +552,11 @@ export default function App() {
|
|||
<VersionsView key="versions-view" />
|
||||
)}
|
||||
{activeView === "workshop" && (
|
||||
<WorkshopView key="workshop-view" />
|
||||
<WorkshopView
|
||||
key="workshop-view"
|
||||
workshopTarget={workshopTarget}
|
||||
onClearWorkshopTarget={() => setWorkshopTarget(null)}
|
||||
/>
|
||||
)}
|
||||
{activeView === "devtools" && (
|
||||
<DevtoolsView key="devtools-view" />
|
||||
|
|
@ -460,7 +583,11 @@ export default function App() {
|
|||
<SwfView key="swf-editor-view" />
|
||||
)}
|
||||
{activeView === "lcelive" && (
|
||||
<LceLiveView key="lcelive-view" />
|
||||
<LceLiveView
|
||||
key="lcelive-view"
|
||||
addFriendTarget={addFriendTarget}
|
||||
onClearAddFriendTarget={() => setAddFriendTarget(null)}
|
||||
/>
|
||||
)}
|
||||
{activeView === "skins" && <SkinsView key="skins-view" />}
|
||||
{activeView === "screenshots" && (
|
||||
|
|
|
|||
Loading…
Reference in a new issue