diff --git a/gui/public/i18n/en/translation.ftl b/gui/public/i18n/en/translation.ftl index 012b3854f..1bf5064d3 100644 --- a/gui/public/i18n/en/translation.ftl +++ b/gui/public/i18n/en/translation.ftl @@ -280,6 +280,7 @@ settings-sidebar-utils = Utilities settings-sidebar-serial = Serial console settings-sidebar-appearance = Appearance settings-sidebar-notifications = Notifications +settings-sidebar-advanced = Advanced ## SteamVR settings settings-general-steamvr = SteamVR @@ -603,6 +604,32 @@ settings-osc-vmc-mirror_tracking = Mirror tracking settings-osc-vmc-mirror_tracking-description = Mirror the tracking horizontally. settings-osc-vmc-mirror_tracking-label = Mirror tracking +## Advanced settings +settings-utils-advanced = Advanced + +settings-utils-advanced-reset-gui = Reset GUI settings +settings-utils-advanced-reset-gui-description = Restore the default settings for the interface. +settings-utils-advanced-reset-gui-label = Reset GUI +settings-utils-advanced-reset-server = Reset tracking settings +settings-utils-advanced-reset-server-description = Restore the default settings for the tracking. +settings-utils-advanced-reset-server-label = Reset tracking +settings-utils-advanced-reset-all = Reset all settings +settings-utils-advanced-reset-all-description = Restore the default settings for both the interface and tracking. +settings-utils-advanced-reset-all-label = Reset all +settings-utils-advanced-reset_warning = + Warning: This will reset { $type -> + [gui] your GUI + [server] your tracking + *[all] all your + } settings to the defaults. + Are you sure you want to do this? +settings-utils-advanced-reset_warning-reset = Reset settings +settings-utils-advanced-reset_warning-cancel = Cancel + +settings-utils-advanced-open_data = Data folder +settings-utils-advanced-open_data-description = Open SlimeVR's data folder in file explorer, containing config and log files. +settings-utils-advanced-open_data-label = Open folder + ## Setup/onboarding menu onboarding-skip = Skip setup onboarding-continue = Continue @@ -810,11 +837,11 @@ onboarding-choose_mounting = What mounting calibration method to use? # Multiline text onboarding-choose_mounting-description = Mounting orientation corrects for the placement of trackers on your body. onboarding-choose_mounting-auto_mounting = Automatic mounting -# Italized text +# Italicized text onboarding-choose_mounting-auto_mounting-label-v2 = Recommended onboarding-choose_mounting-auto_mounting-description = This will automatically detect the mounting orientations for all of your trackers from 2 poses onboarding-choose_mounting-manual_mounting = Manual mounting -# Italized text +# Italicized text onboarding-choose_mounting-manual_mounting-label-v2 = Might not be precise enough onboarding-choose_mounting-manual_mounting-description = This will let you choose the mounting orientation manually for each tracker # Multiline text @@ -858,14 +885,14 @@ onboarding-choose_proportions-description-v1 = Body proportions are used to know When proportions of your body don't match the ones saved, your tracking precision will be worse and you will notice things like skating or sliding, or your body not matching your avatar well. You only need to measure your body once! Unless they are wrong or your body has changed, then you don't need to do them again. onboarding-choose_proportions-auto_proportions = Automatic proportions -# Italized text +# Italicized text onboarding-choose_proportions-auto_proportions-subtitle = Recommended onboarding-choose_proportions-auto_proportions-descriptionv3 = This will guess your proportions by recording a sample of your movements and passing it through an algorithm. This requires having your headset (HMD) connected to SlimeVR and on your head! onboarding-choose_proportions-manual_proportions = Manual proportions -# Italized text +# Italicized text onboarding-choose_proportions-manual_proportions-subtitle = For small touches onboarding-choose_proportions-manual_proportions-description = This will let you adjust your proportions manually by modifying them directly onboarding-choose_proportions-export = Export proportions diff --git a/gui/src-tauri/tauri.conf.json b/gui/src-tauri/tauri.conf.json index f73e7d4e6..a111b03ec 100644 --- a/gui/src-tauri/tauri.conf.json +++ b/gui/src-tauri/tauri.conf.json @@ -73,7 +73,7 @@ "all": true }, "shell": { - "open": true + "open": "^((https?://\\w+)|(file://)).+" }, "window": { "close": true, diff --git a/gui/src/App.tsx b/gui/src/App.tsx index cb9ce9bde..9865a08b9 100644 --- a/gui/src/App.tsx +++ b/gui/src/App.tsx @@ -55,6 +55,7 @@ import { AppLayout } from './AppLayout'; import { Preload } from './components/Preload'; import { UnknownDeviceModal } from './components/UnknownDeviceModal'; import { useDiscordPresence } from './hooks/discord-presence'; +import { AdvancedSettings } from './components/settings/pages/AdvancedSettings'; export const GH_REPO = 'SlimeVR/SlimeVR-Server'; export const VersionContext = createContext(''); @@ -110,6 +111,7 @@ function Layout() { } /> } /> } /> + } /> + + + ); +} diff --git a/gui/src/components/settings/HandsWarningModal.tsx b/gui/src/components/settings/HandsWarningModal.tsx index 545019b99..4d4e6d63c 100644 --- a/gui/src/components/settings/HandsWarningModal.tsx +++ b/gui/src/components/settings/HandsWarningModal.tsx @@ -19,14 +19,12 @@ export function HandsWarningModal({ */ onClose: () => void; /** - * Function when you press `i understand` + * Function when you press `Yes` */ accept: () => void; } & ReactModal.Props) { const { l10n } = useLocalization(); - // isOpen is checked by checking if the parent modal is opened + our bodyPart is the - // neck and we havent showed this warning yet return ( void; + /** + * Function when you press `Reset settings` + */ + accept: () => void; + /** + * Type of reset + */ + variant: 'gui' | 'server' | 'all'; +} & ReactModal.Props) { + const { l10n } = useLocalization(); + + return ( + +
+
+ }} + vars={{ type: variant }} + > + + Warning: This will reset your {variant} settings to the + defaults. +
+ Are you sure you want to do this? +
+
+ +
+ + +
+
+
+
+ ); +} diff --git a/gui/src/components/settings/SettingsSidebar.tsx b/gui/src/components/settings/SettingsSidebar.tsx index 5199bff75..e22fae70e 100644 --- a/gui/src/components/settings/SettingsSidebar.tsx +++ b/gui/src/components/settings/SettingsSidebar.tsx @@ -41,6 +41,7 @@ export function SettingsLink({ export function SettingsSidebar() { const { l10n } = useLocalization(); + return (
@@ -100,6 +101,11 @@ export function SettingsSidebar() { {l10n.getString('settings-sidebar-serial')}
+
+ + {l10n.getString('settings-sidebar-advanced')} + +
diff --git a/gui/src/components/settings/pages/AdvancedSettings.tsx b/gui/src/components/settings/pages/AdvancedSettings.tsx new file mode 100644 index 000000000..1df13fa03 --- /dev/null +++ b/gui/src/components/settings/pages/AdvancedSettings.tsx @@ -0,0 +1,190 @@ +import { useLocalization } from '@fluent/react'; +import { useState } from 'react'; +import { Typography } from '@/components/commons/Typography'; +import { + SettingsPageLayout, + SettingsPagePaneLayout, +} from '@/components/settings/SettingsPageLayout'; +import { BugIcon } from '@/components/commons/icon/BugIcon'; +import { Button } from '@/components/commons/Button'; +import { SettingsResetModal } from '@/components/settings/SettingsResetModal'; + +import { open } from '@tauri-apps/plugin-shell'; +import { error } from '@/utils/logging'; +import { appConfigDir } from '@tauri-apps/api/path'; +import { defaultConfig as defaultGUIConfig, useConfig } from '@/hooks/config'; +import { defaultValues as defaultDevConfig } from '@/components/widgets/DeveloperModeWidget'; +import { RpcMessage, SettingsResetRequestT } from 'solarxr-protocol'; +import { useWebsocketAPI } from '@/hooks/websocket-api'; + +function guiDefaults() { + // Destructure the properties to exclude "lang" + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const { lang, ...guiDefaults } = defaultGUIConfig; + + // Include "devSettings" which has all the properties of "defaultDevConfig" + // @ts-expect-error "devSettings" is not in the "guiDefaults" object but we want to include it (from "defaultDevConfig") + guiDefaults.devSettings = defaultDevConfig; + + return guiDefaults; +} + +export function AdvancedSettings() { + const { l10n } = useLocalization(); + const { setConfig } = useConfig(); + + const [showWarningGUI, setShowWarningGUI] = useState(false); + const [showWarningServer, setShowWarningServer] = useState(false); + const [showWarningAll, setShowWarningAll] = useState(false); + const { sendRPCPacket } = useWebsocketAPI(); + + const openConfigFolder = async () => { + try { + const configPath = await appConfigDir(); + await open('file://' + configPath); + } catch (err) { + error('Failed to open config folder:', err); + } + }; + + return ( + +
+ } id="advanced"> + <> + + {l10n.getString('settings-utils-advanced')} + + +
+
+
+ + {l10n.getString('settings-utils-advanced-reset-gui')} + +
+ + {l10n.getString( + 'settings-utils-advanced-reset-gui-description' + )} + +
+
+
+ + { + setConfig(guiDefaults()); + setShowWarningGUI(false); + }} + onClose={() => setShowWarningGUI(false)} + isOpen={showWarningGUI} + variant="gui" + > +
+
+ +
+
+ + {l10n.getString('settings-utils-advanced-reset-server')} + +
+ + {l10n.getString( + 'settings-utils-advanced-reset-server-description' + )} + +
+
+
+ + { + sendRPCPacket( + RpcMessage.SettingsResetRequest, + new SettingsResetRequestT() + ); + setShowWarningServer(false); + }} + onClose={() => setShowWarningServer(false)} + isOpen={showWarningServer} + variant="server" + > +
+
+ +
+
+ + {l10n.getString('settings-utils-advanced-reset-all')} + +
+ + {l10n.getString( + 'settings-utils-advanced-reset-all-description' + )} + +
+
+
+ + { + sendRPCPacket( + RpcMessage.SettingsResetRequest, + new SettingsResetRequestT() + ); + setConfig(guiDefaults()); + setShowWarningAll(false); + }} + onClose={() => setShowWarningAll(false)} + isOpen={showWarningAll} + variant="all" + > +
+
+ +
+
+ + {l10n.getString('settings-utils-advanced-open_data')} + +
+ + {l10n.getString( + 'settings-utils-advanced-open_data-description' + )} + +
+
+
+ +
+
+
+ +
+
+
+ ); +} diff --git a/gui/src/components/settings/pages/InterfaceSettings.tsx b/gui/src/components/settings/pages/InterfaceSettings.tsx index c455025cb..58956b5ce 100644 --- a/gui/src/components/settings/pages/InterfaceSettings.tsx +++ b/gui/src/components/settings/pages/InterfaceSettings.tsx @@ -98,6 +98,7 @@ export function InterfaceSettings() {
({ - defaultValues: { - highContrast: false, - preciseRotation: false, - fastDataFeed: false, - filterSlimesAndHMD: false, - sortByName: false, - rawSlimeRotation: false, - moreInfo: false, - }, + defaultValues: defaultValues, }); useEffect(() => { diff --git a/server/core/src/main/java/dev/slimevr/config/ConfigManager.java b/server/core/src/main/java/dev/slimevr/config/ConfigManager.java index 82fc0c106..33638cc97 100644 --- a/server/core/src/main/java/dev/slimevr/config/ConfigManager.java +++ b/server/core/src/main/java/dev/slimevr/config/ConfigManager.java @@ -139,6 +139,11 @@ public class ConfigManager { } } + public void resetConfig() { + this.vrConfig = new VRConfig(); + saveConfig(); + } + public VRConfig getVrConfig() { return vrConfig; } diff --git a/server/core/src/main/java/dev/slimevr/protocol/rpc/settings/RPCSettingsHandler.kt b/server/core/src/main/java/dev/slimevr/protocol/rpc/settings/RPCSettingsHandler.kt index cc281152e..dae1e2b10 100644 --- a/server/core/src/main/java/dev/slimevr/protocol/rpc/settings/RPCSettingsHandler.kt +++ b/server/core/src/main/java/dev/slimevr/protocol/rpc/settings/RPCSettingsHandler.kt @@ -33,6 +33,9 @@ class RPCSettingsHandler(var rpcHandler: RPCHandler, var api: ProtocolAPI) { messageHeader, ) } + rpcHandler.registerPacketListener(RpcMessage.SettingsResetRequest) { conn: GenericConnection, messageHeader: RpcMessageHeader? -> + this.onSettingsResetRequest(conn, messageHeader) + } } fun onSettingsRequest(conn: GenericConnection, messageHeader: RpcMessageHeader?) { @@ -345,6 +348,10 @@ class RPCSettingsHandler(var rpcHandler: RPCHandler, var api: ProtocolAPI) { api.server.configManager.saveConfig() } + fun onSettingsResetRequest(conn: GenericConnection, messageHeader: RpcMessageHeader?) { + api.server.configManager.resetConfig() + } + companion object { fun sendSteamVRUpdatedSettings(api: ProtocolAPI, rpcHandler: RPCHandler) { val fbb = FlatBufferBuilder(32) diff --git a/solarxr-protocol b/solarxr-protocol index 3a22ee6e5..e4540a512 160000 --- a/solarxr-protocol +++ b/solarxr-protocol @@ -1 +1 @@ -Subproject commit 3a22ee6e5b436348dfe6f33e24ca13d1a3481257 +Subproject commit e4540a5129140b5f3aa30885030910daa47768fc