feat: debug page (#493)
* fix: discordRPC route sorting It wasn't alphabetical and it was annoying me * feat: debug page * move stuff into hooks where they should be * fix: building
This commit is contained in:
parent
963e7044f2
commit
adf9f4bd63
13 changed files with 293 additions and 139 deletions
|
|
@ -29,7 +29,7 @@ export type DaoError = { type: "NotFound"; data: string } | { type: "AlreadyExis
|
|||
|
||||
export type DbVec = T[]
|
||||
|
||||
export type DebugInfoData = { inDev: boolean; platform: string; arch: string; family: string; locale: string; osType: string; osVersion: string; osDistro: string; commitHash: string; buildTimestamp: string; buildVersion: string }
|
||||
export type DebugInfoData = { inDev: boolean; platform: string; arch: string; family: string; locale: string; osType: string; osVersion: string; osDistro: string; commitHash: string; buildTimestamp: string; buildVersion: string; hasDevSettings: boolean }
|
||||
|
||||
export type DebugInfoParsedLine = { title: string; value: string }
|
||||
|
||||
|
|
@ -250,7 +250,7 @@ export type SettingProfileModel = { name: string; java_id: number | null; res: R
|
|||
|
||||
export type Settings = { global_game_settings: SettingProfileModel; allow_parallel_running_clusters: boolean; enable_gamemode: boolean; discord_enabled: boolean; seen_onboarding: boolean; mod_list_use_grid: boolean; max_concurrent_requests: number; settings_version: number; native_window_frame: boolean; log_debug_info: boolean; show_tanstack_dev_tools: boolean }
|
||||
|
||||
export type SettingsOsExtra = Record<string, never>
|
||||
export type SettingsOsExtra = { enable_gamemode: boolean | null }
|
||||
|
||||
export type SkinVariant = "classic" | "slim"
|
||||
|
||||
|
|
@ -317,10 +317,20 @@ export type VersionType =
|
|||
*/
|
||||
"old_beta"
|
||||
|
||||
const ARGS_MAP = { 'debug':'{"openDevTools":[],"getLocale":[],"getFullDebugInfoParsedString":[],"getArch":[],"getPlatform":[],"getOsVersion":[],"getOsDistro":[],"isInDev":[],"getFullDebugInfoParsed":[],"getFamily":[],"getGitCommitHash":[],"getType":[],"getPackageVersion":[],"getFullDebugInfo":[],"getBuildTimestamp":[]}', 'events':'{"message":["event"],"process":["event"],"ingress":["event"]}', 'folders':'{"fromCluster":["folder_name"],"openCluster":["folder_name"]}', 'core':'{"launchCluster":["id","uuid","search_for_java"],"getRunningProcessesByClusterId":["cluster_id"],"getDefaultUser":["fallback"],"refreshAccounts":[],"getPackage":["provider","slug"],"searchPackages":["provider","query"],"getProcessLogTail":["id","max_lines"],"getMultiplePackages":["provider","slugs"],"getUsersFromAuthor":["provider","author"],"togglePackage":["cluster_id","package_hash"],"fetchLoggedInProfile":["access_token"],"downloadExternalPackage":["package","cluster_id","force","skip_compatibility"],"changeCape":["access_token","cape_uuid"],"fetchMinecraftProfile":["uuid"],"setClusterStage":["id","stage"],"convertUsernameUUID":["username_uuid"],"getGlobalProfile":[],"writeSettings":["setting"],"getScreenshots":["id"],"removeUser":["uuid"],"setDiscordRPCMessage":["message"],"isClusterRunning":["cluster_id"],"updateClusterProfile":["name","profile"],"getGameVersions":[],"installModpack":["modpack","cluster_id"],"getRunningProcesses":[],"syncCluster":["cluster_id"],"changeSkin":["access_token","skin_url","skin_variant"],"removeCape":["access_token"],"getLoadersForVersion":["mc_version"],"open":["input"],"getLinkedPackages":["cluster_id"],"getWorlds":["id"],"getLogs":["id"],"createCluster":["options"],"getLogByName":["id","name"],"getClusters":[],"getProfileOrDefault":["name"],"getUser":["uuid"],"createSettingsProfile":["name"],"openMsaLogin":[],"readSettings":[],"getPackageBody":["provider","body"],"removeCluster":["id"],"downloadPackage":["provider","package_id","version_id","cluster_id","skip_compatibility"],"getClusterById":["id"],"updateClusterById":["id","request"],"killProcess":["pid"],"setDefaultUser":["uuid"],"removePackage":["cluster_id","package_hash"],"getUsers":[],"getPackageVersions":["provider","slug","mc_version","loader","offset","limit"],"uploadSkinBytes":["access_token","skin_data","image_format","skin_variant"],"refreshAccount":["uuid"]}', 'oneclient':'{"cacheArt":["path"],"getClustersGroupedByMajor":[],"refreshArt":["path"],"installUpdate":[],"extractBundleOverrides":["bundle_path","cluster_id"],"checkForUpdate":[],"updateBundlePackages":["cluster_id"],"getBundlesFor":["cluster_id"],"isBundleSyncing":[],"getVersions":[],"downloadPackageFromBundle":["package","cluster_id","bundle_name","skip_compatibility"]}' }
|
||||
export type Router = { 'events': { ingress: (event: IngressPayload) => Promise<void>,
|
||||
message: (event: MessagePayload) => Promise<void>,
|
||||
process: (event: ProcessPayload) => Promise<void> },
|
||||
const ARGS_MAP = { 'debug':'{"getFullDebugInfoParsed":[],"getLocale":[],"getType":[],"hasDevSettings":[],"isInDev":[],"getFamily":[],"getPackageVersion":[],"getOsVersion":[],"getGitCommitHash":[],"getPlatform":[],"getBuildTimestamp":[],"getOsDistro":[],"getArch":[],"getFullDebugInfo":[],"getFullDebugInfoParsedString":[],"openDevTools":[]}', 'folders':'{"fromCluster":["folder_name"],"openCluster":["folder_name"]}', 'events':'{"process":["event"],"message":["event"],"ingress":["event"]}', 'core':'{"searchPackages":["provider","query"],"getLinkedPackages":["cluster_id"],"getProcessLogTail":["id","max_lines"],"downloadExternalPackage":["package","cluster_id","force","skip_compatibility"],"uploadSkinBytes":["access_token","skin_data","image_format","skin_variant"],"updateClusterById":["id","request"],"getLogs":["id"],"getGameVersions":[],"refreshAccounts":[],"syncCluster":["cluster_id"],"removeCape":["access_token"],"getClusterById":["id"],"openMsaLogin":[],"refreshAccount":["uuid"],"convertUsernameUUID":["username_uuid"],"getRunningProcessesByClusterId":["cluster_id"],"setDiscordRPCMessage":["message"],"open":["input"],"getClusters":[],"getProfileOrDefault":["name"],"getLogByName":["id","name"],"getPackage":["provider","slug"],"getUsers":[],"createSettingsProfile":["name"],"removeCluster":["id"],"getPackageBody":["provider","body"],"killProcess":["pid"],"changeSkin":["access_token","skin_url","skin_variant"],"getGlobalProfile":[],"getUser":["uuid"],"removeUser":["uuid"],"getDefaultUser":["fallback"],"getMultiplePackages":["provider","slugs"],"downloadPackage":["provider","package_id","version_id","cluster_id","skip_compatibility"],"changeCape":["access_token","cape_uuid"],"launchCluster":["id","uuid","search_for_java"],"createCluster":["options"],"updateClusterProfile":["name","profile"],"getWorlds":["id"],"getScreenshots":["id"],"getLoadersForVersion":["mc_version"],"getUsersFromAuthor":["provider","author"],"isClusterRunning":["cluster_id"],"setClusterStage":["id","stage"],"setDefaultUser":["uuid"],"getRunningProcesses":[],"writeSettings":["setting"],"readSettings":[],"removePackage":["cluster_id","package_hash"],"fetchMinecraftProfile":["uuid"],"fetchLoggedInProfile":["access_token"],"getPackageVersions":["provider","slug","mc_version","loader","offset","limit"],"togglePackage":["cluster_id","package_hash"],"installModpack":["modpack","cluster_id"]}', 'oneclient':'{"getVersions":[],"extractBundleOverrides":["bundle_path","cluster_id"],"downloadPackageFromBundle":["package","cluster_id","bundle_name","skip_compatibility"],"getBundlesFor":["cluster_id"],"isBundleSyncing":[],"installUpdate":[],"cacheArt":["path"],"refreshArt":["path"],"checkForUpdate":[],"getClustersGroupedByMajor":[],"updateBundlePackages":["cluster_id"]}' }
|
||||
export type Router = { 'folders': { fromCluster: (folderName: string) => Promise<string>,
|
||||
openCluster: (folderName: string) => Promise<null> },
|
||||
'oneclient': { getClustersGroupedByMajor: () => Promise<Partial<{ [key in number]: ClusterModel[] }>>,
|
||||
getBundlesFor: (clusterId: number) => Promise<ModpackArchive[]>,
|
||||
getVersions: () => Promise<OnlineClusterManifest>,
|
||||
extractBundleOverrides: (bundlePath: string, clusterId: number) => Promise<null>,
|
||||
checkForUpdate: () => Promise<Update | null>,
|
||||
installUpdate: () => Promise<null>,
|
||||
downloadPackageFromBundle: (package: ModpackFileKind, clusterId: number, bundleName: string, skipCompatibility: boolean | null) => Promise<PackageModel>,
|
||||
updateBundlePackages: (clusterId: number) => Promise<ApplyBundleUpdatesResult>,
|
||||
isBundleSyncing: () => Promise<boolean>,
|
||||
cacheArt: (path: string) => Promise<string>,
|
||||
refreshArt: (path: string) => Promise<null> },
|
||||
'debug': { openDevTools: () => Promise<void>,
|
||||
isInDev: () => Promise<boolean>,
|
||||
getArch: () => Promise<string>,
|
||||
|
|
@ -335,9 +345,11 @@ getBuildTimestamp: () => Promise<string>,
|
|||
getPackageVersion: () => Promise<string>,
|
||||
getFullDebugInfo: () => Promise<DebugInfoData>,
|
||||
getFullDebugInfoParsed: () => Promise<DebugInfoParsedLine[]>,
|
||||
getFullDebugInfoParsedString: () => Promise<string> },
|
||||
'folders': { fromCluster: (folderName: string) => Promise<string>,
|
||||
openCluster: (folderName: string) => Promise<null> },
|
||||
getFullDebugInfoParsedString: () => Promise<string>,
|
||||
hasDevSettings: () => Promise<boolean> },
|
||||
'events': { ingress: (event: IngressPayload) => Promise<void>,
|
||||
message: (event: MessagePayload) => Promise<void>,
|
||||
process: (event: ProcessPayload) => Promise<void> },
|
||||
'core': { getClusters: () => Promise<ClusterModel[]>,
|
||||
getClusterById: (id: number) => Promise<ClusterModel | null>,
|
||||
removeCluster: (id: number) => Promise<null>,
|
||||
|
|
@ -391,18 +403,7 @@ changeCape: (accessToken: string, capeUuid: string) => Promise<MojangFullPlayerP
|
|||
removeCape: (accessToken: string) => Promise<MojangFullPlayerProfile>,
|
||||
convertUsernameUUID: (usernameUuid: string) => Promise<MowojangProfile>,
|
||||
setDiscordRPCMessage: (message: string) => Promise<null>,
|
||||
open: (input: string) => Promise<null> },
|
||||
'oneclient': { getClustersGroupedByMajor: () => Promise<Partial<{ [key in number]: ClusterModel[] }>>,
|
||||
getBundlesFor: (clusterId: number) => Promise<ModpackArchive[]>,
|
||||
getVersions: () => Promise<OnlineClusterManifest>,
|
||||
extractBundleOverrides: (bundlePath: string, clusterId: number) => Promise<null>,
|
||||
checkForUpdate: () => Promise<Update | null>,
|
||||
installUpdate: () => Promise<null>,
|
||||
downloadPackageFromBundle: (package: ModpackFileKind, clusterId: number, bundleName: string, skipCompatibility: boolean | null) => Promise<PackageModel>,
|
||||
updateBundlePackages: (clusterId: number) => Promise<ApplyBundleUpdatesResult>,
|
||||
isBundleSyncing: () => Promise<boolean>,
|
||||
cacheArt: (path: string) => Promise<string>,
|
||||
refreshArt: (path: string) => Promise<null> } };
|
||||
open: (input: string) => Promise<null> } };
|
||||
|
||||
|
||||
export type { InferCommandOutput }
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { copyDebugInfo } from '@/hooks/useDebugInfo';
|
||||
import { bindings } from '@/main';
|
||||
import { copyDebugInfo } from '@/utils/debugInfo';
|
||||
import { useCommand } from '@onelauncher/common';
|
||||
import { Button } from '@onelauncher/common/components';
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import type { ButtonProps } from '@onelauncher/common/components';
|
|||
import type { LinkProps, RegisteredRouter } from '@tanstack/react-router';
|
||||
import LauncherLogo from '@/assets/logos/oneclient.svg?react';
|
||||
import { AccountAvatar, AccountPopup, Overlay, SuperSecretDevOptions } from '@/components';
|
||||
import { useSettings } from '@/hooks/useSettings';
|
||||
import { bindings } from '@/main';
|
||||
import { useCommand } from '@onelauncher/common';
|
||||
import { Button, Popup } from '@onelauncher/common/components';
|
||||
|
|
@ -12,6 +13,7 @@ import { twMerge } from 'tailwind-merge';
|
|||
|
||||
export function Navbar() {
|
||||
const { data: currentAccount } = useCommand(['getDefaultUser'], () => bindings.core.getDefaultUser(true));
|
||||
const { setting } = useSettings();
|
||||
const navigate = useNavigate();
|
||||
|
||||
const onMinimize = () => Window.getCurrent().minimize();
|
||||
|
|
@ -36,6 +38,7 @@ export function Navbar() {
|
|||
<NavbarLink to=".">Home</NavbarLink>
|
||||
<NavbarLink to="./clusters">Versions</NavbarLink>
|
||||
<NavbarLink to="./accounts">Accounts</NavbarLink>
|
||||
{setting('show_tanstack_dev_tools') && <NavbarLink to="./debug">Debug</NavbarLink>}
|
||||
</div>
|
||||
|
||||
<div className="flex flex-1 items-center justify-end gap-6 pointer-events-none">
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import type { DebugInfoArray } from '@/utils/debugInfo';
|
||||
import type { DebugInfoArray } from '@/hooks/useDebugInfo';
|
||||
import { Overlay } from '@/components';
|
||||
import { copyDebugInfo, useDebugInfo } from '@/utils/debugInfo';
|
||||
import { copyDebugInfo, useDebugInfo } from '@/hooks/useDebugInfo';
|
||||
import { Button } from '@onelauncher/common/components';
|
||||
|
||||
export function DebugInfo() {
|
||||
|
|
|
|||
|
|
@ -1,96 +1,42 @@
|
|||
import { MinecraftAuthErrorModal, minecraftAuthErrors, Overlay, RawDebugInfo, SettingsRow, SettingsSwitch } from '@/components';
|
||||
import { Overlay, SettingsRow, SettingsSwitch } from '@/components';
|
||||
import { copyDebugInfo } from '@/hooks/useDebugInfo';
|
||||
import { useSettings } from '@/hooks/useSettings';
|
||||
import { bindings } from '@/main';
|
||||
import { useDebugInfo } from '@/utils/debugInfo';
|
||||
import { Button } from '@onelauncher/common/components';
|
||||
import { Link } from '@tanstack/react-router';
|
||||
import { dataDir, join } from '@tauri-apps/api/path';
|
||||
import { Code02Icon } from '@untitled-theme/icons-react';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
export function SuperSecretDevOptions() {
|
||||
const { createSetting } = useSettings();
|
||||
const debugInfo = useDebugInfo();
|
||||
const [previewError, setPreviewError] = useState<string | null>(null);
|
||||
|
||||
const [launcherDir, setLauncherDir] = useState('');
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
setLauncherDir(await join(await dataDir(), 'OneClient'));
|
||||
})();
|
||||
}, []);
|
||||
|
||||
const openLauncherDir = () => bindings.core.open(launcherDir);
|
||||
const logRunningProcesses = () => {
|
||||
(async () => {
|
||||
const running = await bindings.core.getRunningProcesses();
|
||||
// eslint-disable-next-line no-console -- Designed to log
|
||||
console.log(running);
|
||||
})();
|
||||
};
|
||||
|
||||
return (
|
||||
<Overlay.Dialog>
|
||||
<Overlay.Title>Super Secret Dev Options</Overlay.Title>
|
||||
|
||||
<div>
|
||||
<SettingsRow description="WARNING! This requires a restart to apply. Logs out debug info" icon={<Code02Icon />} title="Log Debug Info">
|
||||
<SettingsSwitch setting={createSetting('log_debug_info')} />
|
||||
</SettingsRow>
|
||||
|
||||
<SettingsRow description="Enable The Tanstack Dev Tools" icon={<Code02Icon />} title="Tanstack Dev Tools">
|
||||
<SettingsRow description="Enable The Tanstack Dev Tools and shows debug page" title="Show Dev stuff">
|
||||
<SettingsSwitch setting={createSetting('show_tanstack_dev_tools')} />
|
||||
</SettingsRow>
|
||||
|
||||
<div className="grid grid-cols-3 gap-3 justify-items-center">
|
||||
<Button onPress={bindings.debug.openDevTools} size="normal">Dev Tools</Button>
|
||||
<SettingsRow description="WARNING! This requires a restart to apply. Logs out debug info" title="Log Debug Info">
|
||||
<SettingsSwitch setting={createSetting('log_debug_info')} />
|
||||
</SettingsRow>
|
||||
|
||||
<div className="grid grid-cols-4 gap-3 justify-items-center">
|
||||
<Button onPress={bindings.debug.openDevTools} size="normal">Open Dev Tools</Button>
|
||||
|
||||
<Button onPress={copyDebugInfo}>Copy Debug Info</Button>
|
||||
|
||||
<Link to="/app/debug">
|
||||
<Button size="normal">Debug Page</Button>
|
||||
</Link>
|
||||
|
||||
<Link to="/onboarding/finished">
|
||||
<Button size="normal">Skip Onboarding</Button>
|
||||
</Link>
|
||||
|
||||
<Button onClick={openLauncherDir} size="normal">Open Launcher Data</Button>
|
||||
|
||||
<Button onClick={logRunningProcesses} size="normal">Console log processes</Button>
|
||||
</div>
|
||||
|
||||
<div className="mt-3 border-t border-component-border pt-3">
|
||||
<p className="text-fg-secondary text-xs mb-2">Auth Error Preview</p>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{minecraftAuthErrors.map(err => (
|
||||
<Button
|
||||
key={err.errorCode}
|
||||
onClick={() => setPreviewError(`Minecraft authentication error: ${err.errorCode} during MSA step XstsAuthorize`)}
|
||||
size="normal"
|
||||
>
|
||||
{err.errorCode}
|
||||
</Button>
|
||||
))}
|
||||
<Button
|
||||
onClick={() => setPreviewError('Some unknown auth error occurred')}
|
||||
size="normal"
|
||||
>
|
||||
Unknown
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<RawDebugInfo debugInfo={debugInfo} />
|
||||
|
||||
{previewError && (
|
||||
<Overlay
|
||||
isDismissable
|
||||
isOpen
|
||||
onOpenChange={(open) => {
|
||||
if (!open)
|
||||
setPreviewError(null);
|
||||
}}
|
||||
>
|
||||
<MinecraftAuthErrorModal error={previewError} />
|
||||
</Overlay>
|
||||
)}
|
||||
</Overlay.Dialog>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,27 +15,28 @@ export const ResolvedPathNames: Record<URLPath, string> = {
|
|||
'/app/cluster': 'Viewing Versions',
|
||||
'/app/cluster/browser': 'Viewing {clusterName}\'s mods',
|
||||
'/app/cluster/browser/package': 'Browsing {packageName}',
|
||||
'/app/cluster/datapacks': 'Viewing {clusterName}\'s data packs',
|
||||
'/app/cluster/logs': 'Viewing {clusterName}\'s logs',
|
||||
'/app/cluster/mods': 'Viewing {clusterName}\'s mods',
|
||||
'/app/cluster/resource-packs': 'Viewing {clusterName}\'s resource packs',
|
||||
'/app/cluster/shaders': 'Viewing {clusterName}\'s shaders',
|
||||
'/app/cluster/datapacks': 'Viewing {clusterName}\'s data packs',
|
||||
'/app/cluster/process': 'Viewing {clusterName}',
|
||||
'/app/cluster/resource-packs': 'Viewing {clusterName}\'s resource packs',
|
||||
'/app/cluster/settings': 'Viewing {clusterName}\'s settings',
|
||||
'/app/cluster/shaders': 'Viewing {clusterName}\'s shaders',
|
||||
'/app/settings': 'Viewing Settings',
|
||||
'/app/settings/appearance': 'Viewing Settings',
|
||||
'/app/settings/changelog': 'Viewing Settings',
|
||||
'/app/settings/developer': 'Viewing Settings',
|
||||
'/app/settings/minecraft': 'Viewing Settings',
|
||||
'/app/settings/changelog': 'Viewing Settings',
|
||||
'/app/accounts': 'Viewing Accounts',
|
||||
'/app/clusters': 'Viewing Versions',
|
||||
'/app/debug': 'Viewing Debug',
|
||||
'/onboarding': 'Preparing OneClient',
|
||||
'/onboarding/account': 'Preparing OneClient',
|
||||
'/onboarding/finished': 'Preparing OneClient',
|
||||
'/onboarding/language': 'Preparing OneClient',
|
||||
'/onboarding/preferences/version': 'Preparing OneClient',
|
||||
'/onboarding/preferences/versionCategory': 'Preparing OneClient',
|
||||
'/onboarding/preferences': 'Preparing OneClient',
|
||||
'/onboarding/account': 'Preparing OneClient',
|
||||
'/onboarding/finished': 'Preparing OneClient',
|
||||
'/onboarding/language': 'Preparing OneClient',
|
||||
};
|
||||
|
||||
// Credit - https://github.com/DuckySoLucky/hypixel-discord-chat-bridge/blob/d3ea84a26ebf094c8191d50b4954549e2dd4dc7f/src/contracts/helperFunctions.js#L216-L225
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
import type { QueryClient } from '@tanstack/react-query';
|
||||
import type { NavigateOptions, ToOptions } from '@tanstack/react-router';
|
||||
import { Toasts } from '@/components';
|
||||
import { useDebugKeybind } from '@/hooks/useDebugInfo';
|
||||
import { useDiscordRPC } from '@/hooks/useDiscordRPC';
|
||||
import { useSettings } from '@/hooks/useSettings';
|
||||
import { useDebugKeybind } from '@/utils/debugInfo';
|
||||
import { useDiscordRPC } from '@/utils/discordRPC';
|
||||
import { useAutoUpdater } from '@/utils/updater';
|
||||
import { useAutoUpdater } from '@/hooks/useUpdater';
|
||||
import { TanStackDevtools } from '@tanstack/react-devtools';
|
||||
import { ReactQueryDevtoolsPanel } from '@tanstack/react-query-devtools';
|
||||
import { createRootRouteWithContext, Outlet, useRouter } from '@tanstack/react-router';
|
||||
|
|
|
|||
218
apps/oneclient/frontend/src/routes/app/debug.tsx
Normal file
218
apps/oneclient/frontend/src/routes/app/debug.tsx
Normal file
|
|
@ -0,0 +1,218 @@
|
|||
import type { ToastData } from '@/utils/toast';
|
||||
import { MinecraftAuthErrorModal, minecraftAuthErrors, Overlay, RawDebugInfo, SettingsRow, SettingsSwitch, SheetPage } from '@/components';
|
||||
import { useDebugInfo } from '@/hooks/useDebugInfo';
|
||||
import { useSettings } from '@/hooks/useSettings';
|
||||
import { bindings } from '@/main';
|
||||
import { toast, ToastTypes } from '@/utils/toast';
|
||||
import { Button, Dropdown, TextField } from '@onelauncher/common/components';
|
||||
import { createFileRoute } from '@tanstack/react-router';
|
||||
import { dataDir, join } from '@tauri-apps/api/path';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
export const Route = createFileRoute('/app/debug')({
|
||||
component: RouteComponent,
|
||||
});
|
||||
|
||||
function RouteComponent() {
|
||||
return (
|
||||
<SheetPage
|
||||
headerLarge={<HeaderLarge />}
|
||||
headerSmall={<HeaderSmall />}
|
||||
>
|
||||
<SheetPage.Content>
|
||||
<div className="flex flex-col gap-4">
|
||||
|
||||
<AuthError />
|
||||
<div className="w-full h-1 my-2 rounded bg-component-border"></div>
|
||||
<Toasts />
|
||||
<div className="w-full h-1 my-2 rounded bg-component-border"></div>
|
||||
<Settings />
|
||||
<div className="w-full h-1 my-2 rounded bg-component-border"></div>
|
||||
<Other />
|
||||
<div className="w-full h-1 my-2 rounded bg-component-border"></div>
|
||||
<Info />
|
||||
|
||||
</div>
|
||||
|
||||
</SheetPage.Content>
|
||||
</SheetPage>
|
||||
);
|
||||
}
|
||||
|
||||
function AuthError() {
|
||||
const [errorInput, setErrorInput] = useState<string>('Some unknown auth error occurred');
|
||||
const [previewError, setPreviewError] = useState<string | null>(null);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="flex flex-col gap-4">
|
||||
<h1 className="text-3xl font-semibold">Auth Error Preview</h1>
|
||||
<div className="flex flex-row gap-4 items-center">
|
||||
<p>Custom Input:</p>
|
||||
<TextField className="flex-1" onChange={e => setErrorInput(e.target.value)} value={errorInput} />
|
||||
</div>
|
||||
<div className="flex flex-row flex-wrap gap-4">
|
||||
{minecraftAuthErrors.map(err => (
|
||||
<Button
|
||||
key={err.errorCode}
|
||||
onClick={() => setPreviewError(`Minecraft authentication error: ${err.errorCode} during MSA step XstsAuthorize`)}
|
||||
size="normal"
|
||||
>
|
||||
{err.errorCode}
|
||||
</Button>
|
||||
))}
|
||||
<Button onClick={() => setPreviewError(errorInput)} size="normal">Custom</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{previewError && (
|
||||
<Overlay
|
||||
isDismissable
|
||||
isOpen
|
||||
onOpenChange={(open) => {
|
||||
if (!open)
|
||||
setPreviewError(null);
|
||||
}}
|
||||
>
|
||||
<MinecraftAuthErrorModal error={previewError} />
|
||||
</Overlay>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
// Credit - https://github.com/DuckySoLucky/hypixel-discord-chat-bridge/blob/52887f12fce3bc9ebe91befaf394f289abd234a1/src/contracts/helperFunctions.js#L260-L278
|
||||
function TitleCase(str: string): string {
|
||||
if (!str)
|
||||
return '';
|
||||
|
||||
if (typeof str !== 'string')
|
||||
return '';
|
||||
|
||||
return str
|
||||
.toLowerCase()
|
||||
.replaceAll('_', ' ')
|
||||
.split(' ')
|
||||
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
|
||||
.join(' ');
|
||||
}
|
||||
|
||||
function Toasts() {
|
||||
const [title, setTitle] = useState<string>('Title');
|
||||
const [message, setMessage] = useState<string | undefined>('Message');
|
||||
const [type, setType] = useState<ToastData['type']>('info');
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-4">
|
||||
<h1 className="text-3xl font-semibold">Toasts</h1>
|
||||
<div className="flex flex-row gap-4 items-center">
|
||||
<p>Title:</p>
|
||||
<TextField className="flex-1" onChange={e => setTitle(e.target.value)} value={title} />
|
||||
</div>
|
||||
<div className="flex flex-row gap-4 items-center">
|
||||
<p>Message:</p>
|
||||
<TextField className="flex-1" onChange={e => setMessage(e.target.value)} value={message} />
|
||||
</div>
|
||||
<div className="flex flex-row gap-4 items-center">
|
||||
<p>Toast Type:</p>
|
||||
<Dropdown onSelectionChange={key => setType(key as ToastData['type'])} selectedKey={type}>
|
||||
{ToastTypes.map(type => <Dropdown.Item id={type} key={type}>{TitleCase(type)}</Dropdown.Item>)}
|
||||
</Dropdown>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-row gap-4">
|
||||
<Button onPress={() => toast({ type, title, message })} size="normal">Send Toast</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function Settings() {
|
||||
const { createSetting } = useSettings();
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-4">
|
||||
<h1 className="text-3xl font-semibold">Settings</h1>
|
||||
<div className="flex flex-row gap-4 flex-wrap">
|
||||
|
||||
<SettingsRow description="WARNING! This requires a restart to apply. Logs out debug info" title="Log Debug Info">
|
||||
<SettingsSwitch setting={createSetting('log_debug_info')} />
|
||||
</SettingsRow>
|
||||
|
||||
<SettingsRow description="Enable The Tanstack Dev Tools and shows debug page" title="Show Dev stuff">
|
||||
<SettingsSwitch setting={createSetting('show_tanstack_dev_tools')} />
|
||||
</SettingsRow>
|
||||
|
||||
<SettingsRow description="Seen onboarding" title="Seen Onboarding">
|
||||
<SettingsSwitch setting={createSetting('seen_onboarding')} />
|
||||
</SettingsRow>
|
||||
|
||||
<SettingsRow description="Use Grid On Mods List" title="Use Grid On Mods List">
|
||||
<SettingsSwitch setting={createSetting('mod_list_use_grid')} />
|
||||
</SettingsRow>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function Other() {
|
||||
const [launcherDir, setLauncherDir] = useState('');
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
setLauncherDir(await join(await dataDir(), 'OneClient'));
|
||||
})();
|
||||
}, []);
|
||||
|
||||
const openLauncherDir = () => bindings.core.open(launcherDir);
|
||||
|
||||
const logRunningProcesses = () => {
|
||||
(async () => {
|
||||
const running = await bindings.core.getRunningProcesses();
|
||||
// eslint-disable-next-line no-console -- Designed to log
|
||||
console.log(running);
|
||||
})();
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-4">
|
||||
<h1 className="text-3xl font-semibold">Other</h1>
|
||||
<div className="flex flex-row gap-4">
|
||||
<Button onPress={bindings.debug.openDevTools} size="normal">Open Dev Tools</Button>
|
||||
<Button onClick={openLauncherDir} size="normal">Open Launcher Data</Button>
|
||||
<Button onClick={logRunningProcesses} size="normal">Log Running Processes to frontend</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function Info() {
|
||||
const debugInfo = useDebugInfo();
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-4">
|
||||
<h1 className="text-3xl font-semibold">Info</h1>
|
||||
<div className="flex flex-row gap-4">
|
||||
<RawDebugInfo debugInfo={debugInfo} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function HeaderLarge() {
|
||||
return (
|
||||
<div className="flex flex-row justify-between items-end gap-16">
|
||||
<div className="flex-1 flex flex-col">
|
||||
<h1 className="text-3xl font-semibold">Debug</h1>
|
||||
<p>The end user won't really be looking at this page. Design skills go out the window</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function HeaderSmall() {
|
||||
return (
|
||||
<div className="flex flex-row justify-between items-center h-full">
|
||||
<h1 className="text-2lg h-full font-medium">Debug</h1>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -1,10 +1,8 @@
|
|||
import { DebugInfo, Overlay, SettingsRow, SettingsSwitch } from '@/components';
|
||||
import { useSettings } from '@/hooks/useSettings';
|
||||
import { bindings } from '@/main';
|
||||
import { Sidebar } from '@/routes/app/settings/route';
|
||||
import { Button } from '@onelauncher/common/components';
|
||||
import { createFileRoute, Link } from '@tanstack/react-router';
|
||||
import { Code02Icon } from '@untitled-theme/icons-react';
|
||||
import { createFileRoute } from '@tanstack/react-router';
|
||||
|
||||
export const Route = createFileRoute('/app/settings/developer')({
|
||||
component: RouteComponent,
|
||||
|
|
@ -32,42 +30,13 @@ function RouteComponent() {
|
|||
</SettingsRow>
|
||||
|
||||
<SettingsRow.Header>Dev Tools</SettingsRow.Header>
|
||||
<SettingsRow description="WARNING! This requires a restart to apply. Logs out debug info" icon={<Code02Icon />} title="Log Debug Info">
|
||||
|
||||
<SettingsRow description="WARNING! This requires a restart to apply. Logs out debug info" title="Log Debug Info">
|
||||
<SettingsSwitch setting={createSetting('log_debug_info')} />
|
||||
</SettingsRow>
|
||||
<SettingsRow
|
||||
description="Enable The Tanstack Dev Tools"
|
||||
title="Tanstack Dev Tools"
|
||||
>
|
||||
<SettingsSwitch setting={createSetting('show_tanstack_dev_tools')} />
|
||||
</SettingsRow>
|
||||
<SettingsRow
|
||||
description="Open Dev Tools"
|
||||
title="Open Dev Tools"
|
||||
>
|
||||
<Button onPress={bindings.debug.openDevTools} size="normal">Open</Button>
|
||||
</SettingsRow>
|
||||
|
||||
<SettingsRow.Header>Onboarding</SettingsRow.Header>
|
||||
<SettingsRow
|
||||
description="Open Onboarding"
|
||||
title="Open Onboarding"
|
||||
>
|
||||
<Link to="/onboarding">
|
||||
<Button size="normal">Open</Button>
|
||||
</Link>
|
||||
</SettingsRow>
|
||||
<SettingsRow
|
||||
description="Seen onboarding"
|
||||
title="Seen Onboarding"
|
||||
>
|
||||
<SettingsSwitch setting={createSetting('seen_onboarding')} />
|
||||
</SettingsRow>
|
||||
<SettingsRow
|
||||
description="Use Grid On Mods List"
|
||||
title="Use Grid On Mods List"
|
||||
>
|
||||
<SettingsSwitch setting={createSetting('mod_list_use_grid')} />
|
||||
<SettingsRow description="Enable The Tanstack Dev Tools and shows debug page" title="Show Dev stuff">
|
||||
<SettingsSwitch setting={createSetting('show_tanstack_dev_tools')} />
|
||||
</SettingsRow>
|
||||
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ export interface ToastData {
|
|||
title: string;
|
||||
message?: string | undefined;
|
||||
}
|
||||
export const ToastTypes: Array<ToastData['type']> = ['info', 'success', 'warning', 'error'];
|
||||
|
||||
export interface ToastOptions extends ToastData {
|
||||
progress?: number;
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
use crate::store::State;
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
use tauri::Runtime;
|
||||
use tauri_plugin_os::{arch, family, locale, platform, type_, version};
|
||||
|
|
@ -18,6 +19,7 @@ pub struct DebugInfoData {
|
|||
pub commit_hash: String,
|
||||
pub build_timestamp: String,
|
||||
pub build_version: String,
|
||||
pub has_dev_settings: bool,
|
||||
}
|
||||
|
||||
#[onelauncher_macro::specta]
|
||||
|
|
@ -82,6 +84,9 @@ pub trait TauriLauncherDebugApi {
|
|||
|
||||
#[taurpc(alias = "getFullDebugInfoParsedString")]
|
||||
async fn get_full_debug_info_parsed_string() -> String;
|
||||
|
||||
#[taurpc(alias = "hasDevSettings")]
|
||||
async fn get_has_dev_settings() -> bool;
|
||||
}
|
||||
|
||||
#[taurpc::ipc_type]
|
||||
|
|
@ -158,6 +163,11 @@ impl TauriLauncherDebugApi for TauriLauncherDebugApiImpl {
|
|||
crate::build::PKG_VERSION.to_string()
|
||||
}
|
||||
|
||||
async fn get_has_dev_settings(self) -> bool {
|
||||
let state = State::get().await.expect("failed to get state");
|
||||
return state.settings.read().await.show_tanstack_dev_tools;
|
||||
}
|
||||
|
||||
async fn get_full_debug_info(self) -> DebugInfoData {
|
||||
DebugInfoData {
|
||||
in_dev: self.clone().is_in_dev().await,
|
||||
|
|
@ -171,6 +181,7 @@ impl TauriLauncherDebugApi for TauriLauncherDebugApiImpl {
|
|||
commit_hash: self.clone().get_git_commit_hash().await,
|
||||
build_timestamp: self.clone().get_build_timestamp().await,
|
||||
build_version: self.clone().get_package_version().await,
|
||||
has_dev_settings: self.clone().get_has_dev_settings().await,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -189,6 +200,10 @@ impl TauriLauncherDebugApi for TauriLauncherDebugApiImpl {
|
|||
DebugInfoParsedLine::new("Commit Hash", info.commit_hash),
|
||||
DebugInfoParsedLine::new("Build Timestamp", info.build_timestamp),
|
||||
DebugInfoParsedLine::new("Version", info.build_version),
|
||||
DebugInfoParsedLine::new(
|
||||
"Has Dev Settings",
|
||||
if info.has_dev_settings { "yes" } else { "no" },
|
||||
),
|
||||
]
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue