feat: Implement settings
This commit is contained in:
parent
bf4511e4e3
commit
af177152f0
9 changed files with 66 additions and 27 deletions
|
|
@ -15,6 +15,12 @@ const CURRENT_FORMAT_VERSION: u32 = 1;
|
|||
pub struct Settings {
|
||||
/// A OneLauncher [`Theme`] managed by the core GUI.
|
||||
pub theme: Theme,
|
||||
/// Does not ask for confirmation when closing the OneLauncher GUI
|
||||
#[serde(default)]
|
||||
pub hide_close_prompt: bool,
|
||||
/// Disables animations in the OneLauncher GUI
|
||||
#[serde(default)]
|
||||
pub disable_animations: bool,
|
||||
/// A global fullscreen Minecraft state.
|
||||
#[serde(default)]
|
||||
pub force_fullscreen: bool,
|
||||
|
|
@ -89,6 +95,8 @@ impl Settings {
|
|||
} else {
|
||||
let settings = Self {
|
||||
theme: Theme::Dark,
|
||||
hide_close_prompt: false,
|
||||
disable_animations: false,
|
||||
force_fullscreen: false,
|
||||
resolution: Resolution::default(),
|
||||
java_versions: JavaVersions::new(),
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ fn main() {
|
|||
"get_cluster",
|
||||
"get_manifest",
|
||||
"get_settings",
|
||||
"change_settings"
|
||||
"set_settings"
|
||||
]),
|
||||
),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -9,5 +9,5 @@ permissions = [
|
|||
"allow-get-manifest",
|
||||
"allow-login-msa",
|
||||
"allow-get-settings",
|
||||
"allow-change-settings"
|
||||
"allow-set-settings"
|
||||
]
|
||||
|
|
|
|||
|
|
@ -5,10 +5,9 @@ use std::str::FromStr;
|
|||
use chrono::DateTime;
|
||||
use onelauncher::data::{ClusterMeta, Loader, PackageData, Settings};
|
||||
use onelauncher::store::{Cluster, ClusterPath};
|
||||
use onelauncher::{cluster, State};
|
||||
use onelauncher::{cluster, settings};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use specta::Type;
|
||||
use tokio::sync::RwLock;
|
||||
use uuid::Uuid;
|
||||
|
||||
#[macro_export]
|
||||
|
|
@ -24,7 +23,7 @@ macro_rules! collect_commands {
|
|||
get_cluster,
|
||||
get_clusters,
|
||||
get_settings,
|
||||
change_settings
|
||||
set_settings,
|
||||
])
|
||||
}
|
||||
};
|
||||
|
|
@ -129,12 +128,11 @@ pub async fn get_clusters() -> Result<HashMap<ClusterPath, Cluster>, String> {
|
|||
#[specta::specta]
|
||||
#[tauri::command]
|
||||
pub async fn get_settings() -> Result<Settings, String> {
|
||||
Ok(State::get().await?.settings.read().await.clone())
|
||||
settings::get().await.map_err(|err| err.into())
|
||||
}
|
||||
|
||||
#[specta::specta]
|
||||
#[tauri::command]
|
||||
pub async fn change_settings(settings: Settings) -> Result<(), String> {
|
||||
State::get().await?.settings.write().await.clone_from(&settings);
|
||||
Ok(())
|
||||
pub async fn set_settings(settings: Settings) -> Result<(), String> {
|
||||
settings::set(settings).await.map_err(|err| err.into())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,10 +9,11 @@ import { SettingsProvider } from './hooks/useSettings';
|
|||
import { bridge } from '~index';
|
||||
|
||||
function App(props: ParentProps) {
|
||||
if (!bridge.commands.isDev())
|
||||
if (!bridge.commands.isDev()) {
|
||||
document.addEventListener('contextmenu', (event) => {
|
||||
event.preventDefault();
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
<SettingsProvider>
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import type { JSX } from 'solid-js';
|
|||
import { createSignal, onMount } from 'solid-js';
|
||||
import Modal from './overlay/Modal';
|
||||
import Button from './base/Button';
|
||||
import useSettingsContext from '~ui/hooks/useSettings';
|
||||
|
||||
interface TitlebarButtonProps {
|
||||
icon: (any: any) => JSX.Element;
|
||||
|
|
@ -23,6 +24,7 @@ function TitlebarButton(props: TitlebarButtonProps) {
|
|||
|
||||
function WindowFrame() {
|
||||
const [isModalVisible, setModalVisible] = createSignal(false);
|
||||
const settings = useSettingsContext();
|
||||
|
||||
const maximize = () => Window.getCurrent().toggleMaximize();
|
||||
const minimize = () => Window.getCurrent().minimize();
|
||||
|
|
@ -31,10 +33,10 @@ function WindowFrame() {
|
|||
|
||||
onMount(() => {
|
||||
Window.getCurrent().onCloseRequested((event) => {
|
||||
// if (appSettings.settings.closeDialog) {
|
||||
// event.preventDefault();
|
||||
// setModalVisible(true);
|
||||
// }
|
||||
if (settings.hide_close_prompt !== true) {
|
||||
event.preventDefault();
|
||||
setModalVisible(true);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,17 @@
|
|||
import { type Context, type ParentProps, type Resource, Show, createContext, useContext } from 'solid-js';
|
||||
import { type Context, type ParentProps, type Resource, Show, createContext, createEffect, useContext } from 'solid-js';
|
||||
import useCommand from './useCommand';
|
||||
import type { Settings } from '~bindings';
|
||||
import { bridge } from '~index';
|
||||
|
||||
const SettingsContext = createContext<Settings>() as Context<Settings>;
|
||||
|
||||
/**
|
||||
* Sync the launcher state (CSS, text etc) with the current settings
|
||||
*/
|
||||
export function syncSettings(settings: Settings) {
|
||||
document.body.classList.toggle('reduce-motion', settings.disable_animations);
|
||||
}
|
||||
|
||||
export function getSettings(): Resource<Settings> | undefined {
|
||||
const [resource] = useCommand(bridge.commands.getSettings);
|
||||
return resource;
|
||||
|
|
@ -13,6 +20,11 @@ export function getSettings(): Resource<Settings> | undefined {
|
|||
export function SettingsProvider(props: ParentProps) {
|
||||
const settings = getSettings();
|
||||
|
||||
createEffect(() => {
|
||||
if (settings !== undefined && settings() !== undefined)
|
||||
syncSettings(settings!()!);
|
||||
});
|
||||
|
||||
return (
|
||||
<Show when={settings !== undefined && settings() !== undefined}>
|
||||
<SettingsContext.Provider value={settings!()!}>
|
||||
|
|
@ -28,7 +40,21 @@ export function useSettingsContext() {
|
|||
if (!context)
|
||||
throw new Error('useSettingsContext should be called inside its SettingsProvider');
|
||||
|
||||
return context;
|
||||
const contextProxy = new Proxy(context, {
|
||||
set(target, key, value) {
|
||||
// @ts-expect-error typescript
|
||||
target[key] = value;
|
||||
save(target); // TODO: Possibly make a "Save confirmation" instead of writing to the settings file every time?
|
||||
return true;
|
||||
},
|
||||
});
|
||||
|
||||
return contextProxy;
|
||||
}
|
||||
|
||||
function save(settings: Settings) {
|
||||
bridge.commands.setSettings(settings);
|
||||
syncSettings(settings);
|
||||
}
|
||||
|
||||
export default useSettingsContext;
|
||||
|
|
|
|||
|
|
@ -4,8 +4,11 @@ import ScrollableContainer from '~ui/components/ScrollableContainer';
|
|||
import Button from '~ui/components/base/Button';
|
||||
import Toggle from '~ui/components/base/Toggle';
|
||||
import Sidebar from '~ui/components/Sidebar';
|
||||
import useSettingsContext from '~ui/hooks/useSettings';
|
||||
|
||||
function SettingsAppearance() {
|
||||
const settings = useSettingsContext();
|
||||
|
||||
return (
|
||||
<Sidebar.Page>
|
||||
<h1>Appearance</h1>
|
||||
|
|
@ -27,7 +30,10 @@ function SettingsAppearance() {
|
|||
description="Toggle all animations in the launcher."
|
||||
icon={<Speedometer04Icon />}
|
||||
>
|
||||
<Toggle />
|
||||
<Toggle
|
||||
defaultChecked={settings.disable_animations ?? false}
|
||||
onChecked={value => settings.disable_animations = value}
|
||||
/>
|
||||
</SettingsRow>
|
||||
</ScrollableContainer>
|
||||
</Sidebar.Page>
|
||||
|
|
|
|||
|
|
@ -1,31 +1,29 @@
|
|||
import { XIcon } from '@untitled-theme/icons-solid';
|
||||
import { createEffect } from 'solid-js';
|
||||
import SettingsRow from '../../../components/SettingsRow';
|
||||
import ScrollableContainer from '~ui/components/ScrollableContainer';
|
||||
import Toggle from '~ui/components/base/Toggle';
|
||||
import Sidebar from '~ui/components/Sidebar';
|
||||
import { bridge } from '~index';
|
||||
import useCommand from '~ui/hooks/useCommand';
|
||||
import useSettingsContext from '~ui/hooks/useSettings';
|
||||
|
||||
function SettingsGeneral() {
|
||||
const settings = useSettingsContext();
|
||||
|
||||
createEffect(() => {
|
||||
console.log(settings);
|
||||
});
|
||||
|
||||
return (
|
||||
<Sidebar.Page>
|
||||
<h1>General</h1>
|
||||
<ScrollableContainer>
|
||||
|
||||
<SettingsRow
|
||||
title="Show Close Dialog"
|
||||
description="Show a confirmation dialog when closing the launcher."
|
||||
title="Hide Close Dialog"
|
||||
description="Hide the close confirmation dialog when closing the launcher."
|
||||
icon={<XIcon />}
|
||||
>
|
||||
<Toggle />
|
||||
<Toggle
|
||||
defaultChecked={settings.hide_close_prompt ?? true}
|
||||
onChecked={value => settings.hide_close_prompt = value}
|
||||
/>
|
||||
</SettingsRow>
|
||||
|
||||
</ScrollableContainer>
|
||||
</Sidebar.Page>
|
||||
);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue