feat: autoupdate toggle
This commit is contained in:
@ -3,6 +3,7 @@ use std::collections::HashMap;
|
|||||||
use tokio::sync::Mutex;
|
use tokio::sync::Mutex;
|
||||||
use tokio::fs;
|
use tokio::fs;
|
||||||
use tauri::{AppHandle, Manager, State};
|
use tauri::{AppHandle, Manager, State};
|
||||||
|
use crate::model::config::GlobalConfigField;
|
||||||
use crate::model::misc::Game;
|
use crate::model::misc::Game;
|
||||||
use crate::pkg::{Package, PkgKey};
|
use crate::pkg::{Package, PkgKey};
|
||||||
use crate::pkg_store::{InstallResult, PackageStore};
|
use crate::pkg_store::{InstallResult, PackageStore};
|
||||||
@ -356,19 +357,25 @@ pub async fn list_platform_capabilities() -> Result<Vec<String>, ()> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub async fn is_offline(state: State<'_, Mutex<AppData>>) -> Result<bool, ()> {
|
pub async fn get_global_config(state: State<'_, Mutex<AppData>>, field: GlobalConfigField) -> Result<bool, ()> {
|
||||||
log::debug!("invoke: is_offline");
|
log::debug!("invoke: get_global_config({field:?})");
|
||||||
|
|
||||||
let appd = state.lock().await;
|
let appd = state.lock().await;
|
||||||
Ok(appd.cfg.offline_mode)
|
match field {
|
||||||
|
GlobalConfigField::OfflineMode => Ok(appd.cfg.offline_mode),
|
||||||
|
GlobalConfigField::EnableAutoupdates => Ok(appd.cfg.enable_autoupdates)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub async fn set_offline(state: State<'_, Mutex<AppData>>, value: bool) -> Result<(), String> {
|
pub async fn set_global_config(state: State<'_, Mutex<AppData>>, field: GlobalConfigField, value: bool) -> Result<(), String> {
|
||||||
log::debug!("invoke: set_offline({value})");
|
log::debug!("invoke: set_global_config({field:?}, {value})");
|
||||||
|
|
||||||
let mut appd = state.lock().await;
|
let mut appd = state.lock().await;
|
||||||
appd.cfg.offline_mode = value;
|
match field {
|
||||||
|
GlobalConfigField::OfflineMode => appd.cfg.offline_mode = value,
|
||||||
|
GlobalConfigField::EnableAutoupdates => appd.cfg.enable_autoupdates = value
|
||||||
|
};
|
||||||
appd.write().map_err(|e| e.to_string())
|
appd.write().map_err(|e| e.to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -200,8 +200,8 @@ pub async fn run(_args: Vec<String>) {
|
|||||||
cmd::sync_current_profile,
|
cmd::sync_current_profile,
|
||||||
cmd::save_current_profile,
|
cmd::save_current_profile,
|
||||||
|
|
||||||
cmd::is_offline,
|
cmd::get_global_config,
|
||||||
cmd::set_offline,
|
cmd::set_global_config,
|
||||||
|
|
||||||
cmd::list_displays,
|
cmd::list_displays,
|
||||||
cmd::list_platform_capabilities,
|
cmd::list_platform_capabilities,
|
||||||
@ -265,10 +265,16 @@ fn deep_link(app: AppHandle, args: Vec<String>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn update(app: tauri::AppHandle) -> tauri_plugin_updater::Result<()> {
|
async fn update(app: tauri::AppHandle) -> tauri_plugin_updater::Result<()> {
|
||||||
|
let mutex = app.state::<Mutex<AppData>>();
|
||||||
|
let appd = mutex.lock().await;
|
||||||
|
if !appd.cfg.enable_autoupdates {
|
||||||
|
log::info!("skipping autoupdate");
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(update) = app.updater()?.check().await? {
|
if let Some(update) = app.updater()?.check().await? {
|
||||||
let mut downloaded = 0;
|
let mut downloaded = 0;
|
||||||
update
|
update.download_and_install(
|
||||||
.download_and_install(
|
|
||||||
|chunk_length, content_length| {
|
|chunk_length, content_length| {
|
||||||
downloaded += chunk_length;
|
downloaded += chunk_length;
|
||||||
log::debug!("downloaded {downloaded} from {content_length:?}");
|
log::debug!("downloaded {downloaded} from {content_length:?}");
|
||||||
|
@ -1,10 +1,25 @@
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use super::misc::Game;
|
use super::misc::Game;
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone, Default)]
|
#[derive(Serialize, Deserialize, Clone)]
|
||||||
pub struct GlobalConfig {
|
pub struct GlobalConfig {
|
||||||
pub recent_profile: Option<(Game, String)>,
|
pub recent_profile: Option<(Game, String)>,
|
||||||
|
|
||||||
#[serde(default)]
|
|
||||||
pub offline_mode: bool,
|
pub offline_mode: bool,
|
||||||
|
pub enable_autoupdates: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for GlobalConfig {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
recent_profile: Default::default(),
|
||||||
|
offline_mode: false,
|
||||||
|
enable_autoupdates: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
|
pub enum GlobalConfigField {
|
||||||
|
OfflineMode,
|
||||||
|
EnableAutoupdates
|
||||||
}
|
}
|
@ -48,7 +48,10 @@ const aimeCodePaste = (ev: ClipboardEvent) => {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<OptionCategory title="Aime">
|
<OptionCategory title="Aime">
|
||||||
<OptionRow title="Aime emulation">
|
<OptionRow
|
||||||
|
title="Aime emulation"
|
||||||
|
tooltip="Aime plugins can be downloaded from the package store."
|
||||||
|
>
|
||||||
<Select
|
<Select
|
||||||
v-model="prf.current!.data.sgt.aime"
|
v-model="prf.current!.data.sgt.aime"
|
||||||
:options="[
|
:options="[
|
||||||
|
@ -13,7 +13,10 @@ const prf = usePrfStore();
|
|||||||
<OptionRow title="OpenSSL bug workaround for Intel ≥10th gen">
|
<OptionRow title="OpenSSL bug workaround for Intel ≥10th gen">
|
||||||
<ToggleSwitch v-model="prf.current!.data.sgt.intel" />
|
<ToggleSwitch v-model="prf.current!.data.sgt.intel" />
|
||||||
</OptionRow>
|
</OptionRow>
|
||||||
<OptionRow title="More segatools options">
|
<OptionRow
|
||||||
|
title="More segatools options"
|
||||||
|
tooltip="Advanced options not covered by STARTLINER"
|
||||||
|
>
|
||||||
<FileEditor filename="segatools-base.ini" />
|
<FileEditor filename="segatools-base.ini" />
|
||||||
</OptionRow>
|
</OptionRow>
|
||||||
</OptionCategory>
|
</OptionCategory>
|
||||||
|
@ -79,7 +79,10 @@ const names = computed(() => {
|
|||||||
"
|
"
|
||||||
></FilePicker>
|
></FilePicker>
|
||||||
</OptionRow>
|
</OptionRow>
|
||||||
<OptionRow :title="names.hook">
|
<OptionRow
|
||||||
|
:title="names.hook"
|
||||||
|
tooltip="Hooks can be downloaded from the package store."
|
||||||
|
>
|
||||||
<Select
|
<Select
|
||||||
v-model="prf.current!.data.sgt.hook"
|
v-model="prf.current!.data.sgt.hook"
|
||||||
:options="
|
:options="
|
||||||
@ -97,7 +100,11 @@ const names = computed(() => {
|
|||||||
option-value="value"
|
option-value="value"
|
||||||
></Select>
|
></Select>
|
||||||
</OptionRow>
|
</OptionRow>
|
||||||
<OptionRow :title="names.io" v-if="prf.current?.meta.game === 'ongeki'">
|
<OptionRow
|
||||||
|
:title="names.io"
|
||||||
|
v-if="prf.current?.meta.game === 'ongeki'"
|
||||||
|
tooltip="IO plugins can be downloaded from the package store."
|
||||||
|
>
|
||||||
<Select
|
<Select
|
||||||
v-model="prf.current!.data.sgt.io"
|
v-model="prf.current!.data.sgt.io"
|
||||||
placeholder="segatools built-in"
|
placeholder="segatools built-in"
|
||||||
|
@ -16,10 +16,19 @@ const offlineModel = computed({
|
|||||||
await client.setOfflineMode(value);
|
await client.setOfflineMode(value);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const updatesModel = computed({
|
||||||
|
get() {
|
||||||
|
return client.enableAutoupdates;
|
||||||
|
},
|
||||||
|
async set(value: boolean) {
|
||||||
|
await client.setAutoupdates(value);
|
||||||
|
},
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<OptionCategory title="Startliner">
|
<OptionCategory title="STARTLINER">
|
||||||
<OptionRow title="UI scaling">
|
<OptionRow title="UI scaling">
|
||||||
<SelectButton
|
<SelectButton
|
||||||
v-model="client.scaleModel"
|
v-model="client.scaleModel"
|
||||||
@ -34,8 +43,14 @@ const offlineModel = computed({
|
|||||||
option-value="value"
|
option-value="value"
|
||||||
/>
|
/>
|
||||||
</OptionRow>
|
</OptionRow>
|
||||||
<OptionRow title="Offline mode" tooltip="Applies after a restart">
|
<OptionRow
|
||||||
|
title="Offline mode"
|
||||||
|
tooltip="Disables the package store. Applies after a restart"
|
||||||
|
>
|
||||||
<ToggleSwitch v-model="offlineModel" />
|
<ToggleSwitch v-model="offlineModel" />
|
||||||
</OptionRow>
|
</OptionRow>
|
||||||
|
<OptionRow title="Enable automatic updates">
|
||||||
|
<ToggleSwitch v-model="updatesModel" />
|
||||||
|
</OptionRow>
|
||||||
</OptionCategory>
|
</OptionCategory>
|
||||||
</template>
|
</template>
|
||||||
|
@ -336,7 +336,9 @@ export const useClientStore = defineStore('client', () => {
|
|||||||
type ScaleType = 's' | 'm' | 'l' | 'xl';
|
type ScaleType = 's' | 'm' | 'l' | 'xl';
|
||||||
const scaleFactor: Ref<ScaleType> = ref('s');
|
const scaleFactor: Ref<ScaleType> = ref('s');
|
||||||
const timeout: Ref<NodeJS.Timeout | null> = ref(null);
|
const timeout: Ref<NodeJS.Timeout | null> = ref(null);
|
||||||
const offlineMode = ref(true);
|
|
||||||
|
const offlineMode = ref(false);
|
||||||
|
const enableAutoupdates = ref(true);
|
||||||
|
|
||||||
const scaleValue = (value: ScaleType) =>
|
const scaleValue = (value: ScaleType) =>
|
||||||
value === 's' ? 1 : value === 'm' ? 1.25 : value === 'l' ? 1.5 : 2;
|
value === 's' ? 1 : value === 'm' ? 1.25 : value === 'l' ? 1.5 : 2;
|
||||||
@ -387,11 +389,17 @@ export const useClientStore = defineStore('client', () => {
|
|||||||
if (input.scaleFactor) {
|
if (input.scaleFactor) {
|
||||||
await setScaleFactor(input.scaleFactor);
|
await setScaleFactor(input.scaleFactor);
|
||||||
}
|
}
|
||||||
|
|
||||||
offlineMode.value = await invoke('is_offline');
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(`Error reading client options: ${e}`);
|
console.error(`Error reading client options: ${e}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
offlineMode.value = await invoke('get_global_config', {
|
||||||
|
field: 'OfflineMode',
|
||||||
|
});
|
||||||
|
|
||||||
|
enableAutoupdates.value = await invoke('get_global_config', {
|
||||||
|
field: 'EnableAutoupdates',
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const save = async () => {
|
const save = async () => {
|
||||||
@ -423,7 +431,15 @@ export const useClientStore = defineStore('client', () => {
|
|||||||
|
|
||||||
const setOfflineMode = async (value: boolean) => {
|
const setOfflineMode = async (value: boolean) => {
|
||||||
offlineMode.value = value;
|
offlineMode.value = value;
|
||||||
await invoke('set_offline', { value });
|
await invoke('set_global_config', { field: 'OfflineMode', value });
|
||||||
|
};
|
||||||
|
|
||||||
|
const setAutoupdates = async (value: boolean) => {
|
||||||
|
enableAutoupdates.value = value;
|
||||||
|
await invoke('set_global_config', {
|
||||||
|
field: 'EnableAutoupdates',
|
||||||
|
value,
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
getCurrentWindow().onResized(async ({ payload }) => {
|
getCurrentWindow().onResized(async ({ payload }) => {
|
||||||
@ -436,11 +452,13 @@ export const useClientStore = defineStore('client', () => {
|
|||||||
return {
|
return {
|
||||||
scaleFactor,
|
scaleFactor,
|
||||||
offlineMode,
|
offlineMode,
|
||||||
|
enableAutoupdates,
|
||||||
timeout,
|
timeout,
|
||||||
scaleModel,
|
scaleModel,
|
||||||
load,
|
load,
|
||||||
save,
|
save,
|
||||||
queueSave,
|
queueSave,
|
||||||
setOfflineMode,
|
setOfflineMode,
|
||||||
|
setAutoupdates,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
Reference in New Issue
Block a user