mirror of
https://github.com/LCE-Hub/LCE-Emerald-Launcher.git
synced 2026-08-20 04:27:29 +00:00
feat: android settings
This commit is contained in:
parent
29bcfd8121
commit
d5aaad83a8
|
|
@ -1 +1 @@
|
|||
Subproject commit bfe5ee43aa406049c7645dbe8891a445621bc02f
|
||||
Subproject commit a7631bab90e8c2fe4322ffb96a50e38f15ef4f0e
|
||||
|
|
@ -2,6 +2,9 @@ pub enum BridgeAction {
|
|||
Play,
|
||||
OpenContainer,
|
||||
OpenSettings,
|
||||
SwitchProton,
|
||||
InstallDriver,
|
||||
SetAudioBackend,
|
||||
}
|
||||
|
||||
pub fn launch_bridge(
|
||||
|
|
@ -80,6 +83,9 @@ pub fn launch_bridge(
|
|||
BridgeAction::Play => "play",
|
||||
BridgeAction::OpenContainer => "open",
|
||||
BridgeAction::OpenSettings => "settings",
|
||||
BridgeAction::SwitchProton => "switch_proton",
|
||||
BridgeAction::InstallDriver => "install_driver",
|
||||
BridgeAction::SetAudioBackend => "set_audio_backend",
|
||||
}
|
||||
.to_string();
|
||||
dispatch(move |env, activity, _webview| {
|
||||
|
|
|
|||
|
|
@ -783,3 +783,63 @@ async fn perform_instance_sync(app: &AppHandle, instance_id: &str) -> Result<(),
|
|||
perform_dlc_sync(app, &target_dir)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
#[cfg(target_os = "android")]
|
||||
pub fn switch_proton(app: AppHandle, version: String) -> Result<(), String> {
|
||||
let instance_id = {
|
||||
let config_val = config::load_config_raw(app.clone());
|
||||
config_val.profile.unwrap_or_else(|| "legacy_evolved".into())
|
||||
};
|
||||
crate::android_runtime::launch_bridge(
|
||||
instance_id,
|
||||
crate::android_runtime::BridgeAction::SwitchProton,
|
||||
vec![version],
|
||||
)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
#[cfg(not(target_os = "android"))]
|
||||
pub fn switch_proton(_app: AppHandle, _version: String) -> Result<(), String> {
|
||||
Err("Only supported on Android".into())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
#[cfg(target_os = "android")]
|
||||
pub fn install_latest_driver(app: AppHandle) -> Result<(), String> {
|
||||
let instance_id = {
|
||||
let config_val = config::load_config_raw(app.clone());
|
||||
config_val.profile.unwrap_or_else(|| "legacy_evolved".into())
|
||||
};
|
||||
crate::android_runtime::launch_bridge(
|
||||
instance_id,
|
||||
crate::android_runtime::BridgeAction::InstallDriver,
|
||||
Vec::new(),
|
||||
)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
#[cfg(not(target_os = "android"))]
|
||||
pub fn install_latest_driver(_app: AppHandle) -> Result<(), String> {
|
||||
Err("Only supported on Android".into())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
#[cfg(target_os = "android")]
|
||||
pub fn set_audio_backend(app: AppHandle, backend: String) -> Result<(), String> {
|
||||
let instance_id = {
|
||||
let config_val = config::load_config_raw(app.clone());
|
||||
config_val.profile.unwrap_or_else(|| "legacy_evolved".into())
|
||||
};
|
||||
crate::android_runtime::launch_bridge(
|
||||
instance_id,
|
||||
crate::android_runtime::BridgeAction::SetAudioBackend,
|
||||
vec![backend],
|
||||
)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
#[cfg(not(target_os = "android"))]
|
||||
pub fn set_audio_backend(_app: AppHandle, _backend: String) -> Result<(), String> {
|
||||
Err("Only supported on Android".into())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,6 +38,8 @@ pub fn load_config_raw(app: AppHandle) -> AppConfig {
|
|||
launch_prefix: None,
|
||||
launch_env_vars: None,
|
||||
instance_launch_args: None,
|
||||
android_runner: None,
|
||||
android_audio_backend: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -144,6 +144,9 @@ pub fn run() {
|
|||
plugins::list_directory,
|
||||
plugins::create_plugin_dir,
|
||||
plugins::remove_plugin_dir,
|
||||
game::switch_proton,
|
||||
game::install_latest_driver,
|
||||
game::set_audio_backend,
|
||||
])
|
||||
.setup(|app| {
|
||||
let app_handle = app.handle().clone();
|
||||
|
|
|
|||
|
|
@ -67,6 +67,8 @@ pub struct AppConfig {
|
|||
pub launch_prefix: Option<String>,
|
||||
pub launch_env_vars: Option<std::collections::HashMap<String, String>>,
|
||||
pub instance_launch_args: Option<std::collections::HashMap<String, InstanceLaunchArgs>>,
|
||||
pub android_runner: Option<String>,
|
||||
pub android_audio_backend: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
|
|
|
|||
|
|
@ -44,6 +44,10 @@ const SettingsView = memo(function SettingsView() {
|
|||
skipIntro,
|
||||
setSkipIntro,
|
||||
profile,
|
||||
androidRunner,
|
||||
setAndroidRunner,
|
||||
androidAudioBackend,
|
||||
setAndroidAudioBackend,
|
||||
} = useConfig();
|
||||
const { currentTrack, skipTrack, tracks, playPressSound, playBackSound } =
|
||||
useAudio();
|
||||
|
|
@ -57,7 +61,7 @@ const SettingsView = memo(function SettingsView() {
|
|||
const { isLinux, isMac, isAndroid } = usePlatform();
|
||||
const [focusIndex, setFocusIndex] = useState<number | null>(null);
|
||||
const [currentSubMenu, setCurrentSubMenu] = useState<
|
||||
"main" | "audio" | "video" | "launcher" | "game" | "plugins"
|
||||
"main" | "audio" | "video" | "launcher" | "game" | "plugins" | "android"
|
||||
>("main");
|
||||
const [runners, setRunners] = useState<Runner[]>([]);
|
||||
const [pluginsInfo, setPluginsInfo] = useState<PluginInfo[]>([]);
|
||||
|
|
@ -324,23 +328,15 @@ const SettingsView = memo(function SettingsView() {
|
|||
setFocusIndex(0);
|
||||
},
|
||||
});
|
||||
if (isAndroid && profile) {
|
||||
if (isAndroid) {
|
||||
items.push({
|
||||
id: "container_settings",
|
||||
label: "Container Settings",
|
||||
id: "android_menu",
|
||||
label: "Android",
|
||||
type: "button",
|
||||
onClick: () => {
|
||||
playPressSound();
|
||||
TauriService.openContainerSettings(profile).catch(console.error);
|
||||
},
|
||||
});
|
||||
items.push({
|
||||
id: "open_container",
|
||||
label: "Open Container",
|
||||
type: "button",
|
||||
onClick: () => {
|
||||
playPressSound();
|
||||
TauriService.openInstanceFolder(profile).catch(console.error);
|
||||
setCurrentSubMenu("android");
|
||||
setFocusIndex(0);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
|
@ -544,6 +540,58 @@ const SettingsView = memo(function SettingsView() {
|
|||
onClick: handleResetSetup,
|
||||
color: "orange",
|
||||
});
|
||||
} else if (currentSubMenu === "android") {
|
||||
if (profile) {
|
||||
items.push({
|
||||
id: "android_container_settings",
|
||||
label: "Container Settings",
|
||||
type: "button",
|
||||
onClick: () => {
|
||||
playPressSound();
|
||||
TauriService.openContainerSettings(profile).catch(console.error);
|
||||
},
|
||||
});
|
||||
items.push({
|
||||
id: "android_open_container",
|
||||
label: "Open Container",
|
||||
type: "button",
|
||||
onClick: () => {
|
||||
playPressSound();
|
||||
TauriService.openInstanceFolder(profile).catch(console.error);
|
||||
},
|
||||
});
|
||||
}
|
||||
items.push({
|
||||
id: "android_proton",
|
||||
label: `Proton: ${androidRunner === "proton10" ? "Proton 10" : "Proton 11 (Default)"}`,
|
||||
type: "button",
|
||||
onClick: () => {
|
||||
playPressSound();
|
||||
const next = androidRunner === "proton10" ? "proton11" : "proton10";
|
||||
setAndroidRunner(next);
|
||||
TauriService.switchProton(next).catch(console.error);
|
||||
},
|
||||
});
|
||||
items.push({
|
||||
id: "android_install_driver",
|
||||
label: "Install Latest Driver",
|
||||
type: "button",
|
||||
onClick: () => {
|
||||
playPressSound();
|
||||
TauriService.installLatestDriver().catch(console.error);
|
||||
},
|
||||
});
|
||||
items.push({
|
||||
id: "android_audio",
|
||||
label: `Audio: ${androidAudioBackend === "alsa" ? "ALSA" : "PulseAudio (Default)"}`,
|
||||
type: "button",
|
||||
onClick: () => {
|
||||
playPressSound();
|
||||
const next = androidAudioBackend === "alsa" ? "pulseaudio" : "alsa";
|
||||
setAndroidAudioBackend(next);
|
||||
TauriService.setAudioBackend(next).catch(console.error);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if (isGameRunning) {
|
||||
|
|
@ -613,6 +661,8 @@ const SettingsView = memo(function SettingsView() {
|
|||
launchEnvVars,
|
||||
skipIntro,
|
||||
profile,
|
||||
androidRunner,
|
||||
androidAudioBackend,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
|
|
|
|||
|
|
@ -109,6 +109,8 @@ export function LauncherProvider({ children }: { children: React.ReactNode }) {
|
|||
configRaw.startFullscreen,
|
||||
configRaw.skipIntro,
|
||||
configRaw.instanceLaunchArgs,
|
||||
configRaw.androidRunner,
|
||||
configRaw.androidAudioBackend,
|
||||
],
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -29,6 +29,8 @@ export function useAppConfig() {
|
|||
const [instanceLaunchArgs, setInstanceLaunchArgs] = useState<
|
||||
Record<string, { values: Record<string, unknown>; args: string[] }>
|
||||
>({});
|
||||
const [androidRunner, setAndroidRunner] = useLocalStorage<string | undefined>("lce-android-runner", undefined);
|
||||
const [androidAudioBackend, setAndroidAudioBackend] = useLocalStorage<"alsa" | "pulseaudio">("lce-android-audio", "pulseaudio");
|
||||
useEffect(() => {
|
||||
TauriService.loadConfig().then((config) => {
|
||||
if (config.username) setUsername(config.username);
|
||||
|
|
@ -53,6 +55,8 @@ export function useAppConfig() {
|
|||
if (config.launchEnvVars) setLaunchEnvVars(config.launchEnvVars);
|
||||
if (config.skipIntro !== undefined) setSkipIntro(config.skipIntro);
|
||||
if (config.instanceLaunchArgs) setInstanceLaunchArgs(config.instanceLaunchArgs);
|
||||
if (config.androidRunner) setAndroidRunner(config.androidRunner);
|
||||
if (config.androidAudioBackend) setAndroidAudioBackend(config.androidAudioBackend);
|
||||
setIsLoaded(true);
|
||||
});
|
||||
}, []);
|
||||
|
|
@ -81,9 +85,11 @@ export function useAppConfig() {
|
|||
launchEnvVars,
|
||||
skipIntro,
|
||||
instanceLaunchArgs,
|
||||
androidRunner,
|
||||
androidAudioBackend,
|
||||
}).catch(console.error);
|
||||
}
|
||||
}, [username, theme, linuxRunner, perfBoost, profile, customEditions, customPaths, customizations, animationsEnabled, vfxEnabled, rpcEnabled, startFullscreen, musicVol, sfxVol, legacyMode, mangohudEnabled, extraLaunchArgs, launchPrefix, launchEnvVars, skipIntro, isLoaded, instanceLaunchArgs]);
|
||||
}, [username, theme, linuxRunner, perfBoost, profile, customEditions, customPaths, customizations, animationsEnabled, vfxEnabled, rpcEnabled, startFullscreen, musicVol, sfxVol, legacyMode, mangohudEnabled, extraLaunchArgs, launchPrefix, launchEnvVars, skipIntro, isLoaded, instanceLaunchArgs, androidRunner, androidAudioBackend]);
|
||||
|
||||
return {
|
||||
username,
|
||||
|
|
@ -135,5 +141,9 @@ export function useAppConfig() {
|
|||
setSkipIntro,
|
||||
instanceLaunchArgs,
|
||||
setInstanceLaunchArgs,
|
||||
androidRunner,
|
||||
setAndroidRunner,
|
||||
androidAudioBackend,
|
||||
setAndroidAudioBackend,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,6 +52,8 @@ export interface AppConfig {
|
|||
string,
|
||||
{ values: Record<string, unknown>; args: string[] }
|
||||
>;
|
||||
androidRunner?: string;
|
||||
androidAudioBackend?: "alsa" | "pulseaudio";
|
||||
}
|
||||
|
||||
export interface ThemePalette {
|
||||
|
|
@ -480,4 +482,16 @@ export class TauriService {
|
|||
): Promise<string> {
|
||||
return invoke("lce_to_java", { inputMsPath, javaWorldOutput });
|
||||
}
|
||||
|
||||
static async installLatestDriver(): Promise<void> {
|
||||
return invoke("install_latest_driver");
|
||||
}
|
||||
|
||||
static async switchProton(version: string): Promise<void> {
|
||||
return invoke("switch_proton", { version });
|
||||
}
|
||||
|
||||
static async setAudioBackend(backend: string): Promise<void> {
|
||||
return invoke("set_audio_backend", { backend });
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue