Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion gui/.lintstagedrc.mjs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export default {
'**/*.{ts,tsx}': () => 'tsc -p tsconfig.json --noEmit',
'src/**/*.{js,jsx,ts,tsx}': 'eslint --max-warnings=0 --no-warn-ignored --cache --fix',
'{electron,src}/**/*.{js,jsx,ts,tsx}': 'eslint --max-warnings=0 --no-warn-ignored --cache --fix',
'**/*.{js,jsx,ts,tsx,css,scss,md,json}': 'prettier --write',
};
6 changes: 3 additions & 3 deletions gui/electron/main/cli.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Option, program } from "commander";
import { Option, program } from 'commander';

program
.option('-p, --path <path>', 'set launch path')
Expand All @@ -12,10 +12,10 @@ program
// Allow passing arguments to Electron.
.allowExcessArguments();

if (process.platform === "linux") {
if (process.platform === 'linux') {
const noUdevOption = new Option('--no-udev', 'disable udev warning');
noUdevOption.negate = false;
program.addOption(noUdevOption)
program.addOption(noUdevOption);
}

program.parse(process.argv);
Expand Down
48 changes: 23 additions & 25 deletions gui/electron/main/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,14 +127,14 @@ handleIpc(IPC_CHANNELS.LOG, (e, type, ...args) => {
});

handleIpc(IPC_CHANNELS.OPEN_URL, (e, url) => {
const allowed_urls = [
const allowedUrls = [
/^steam:\/\//,
/^ms-settings:network$/,
/^https:\/\/(?:.+\.)?slimevr\.dev(?:\/.+)?$/,
/^https:\/\/github\.com\/SlimeVR(?:\/.+)?$/,
/^https:\/\/discord\.gg\/slimevr$/,
];
if (allowed_urls.find((a) => url.match(a))) open(url);
if (allowedUrls.find((a) => url.match(a))) open(url);
else logger.error({ url }, 'attempted to open non-whitelisted URL');
});

Expand All @@ -156,8 +156,7 @@ handleIpc(IPC_CHANNELS.STORAGE, async (e, { type, method, key, value }) => {

handleIpc(IPC_CHANNELS.DISCORD_PRESENCE, async (e, options) => {
if (options.enable) {
if (!discordPresence.state.ready)
await discordPresence.connect();
if (!discordPresence.state.ready) await discordPresence.connect();
discordPresence.updateActivity(options.activity, options.iconText);
} else if (discordPresence.state.ready) {
discordPresence.destroy();
Expand Down Expand Up @@ -208,11 +207,11 @@ const defaultWindowState: {
const windowState = await readFile(getWindowStateFile(), {
encoding: 'utf-8',
})
.then(data => JSON.parse(data))
.catch(() => {
logger.error('Failed to load window state, using defaults');
return defaultWindowState;
});
.then((data) => JSON.parse(data))
.catch(() => {
logger.error('Failed to load window state, using defaults');
return defaultWindowState;
});

const MIN_WIDTH = 393;
const MIN_HEIGHT = 667;
Expand Down Expand Up @@ -245,7 +244,9 @@ function validateWindowState(state: typeof defaultWindowState) {

const saveWindowState = async () => {
await mkdir(dirname(getWindowStateFile()), { recursive: true });
await writeFile(getWindowStateFile(), JSON.stringify(windowState), { encoding: 'utf-8' });
await writeFile(getWindowStateFile(), JSON.stringify(windowState), {
encoding: 'utf-8',
});
};

function createWindow() {
Expand Down Expand Up @@ -293,10 +294,8 @@ function createWindow() {
mainWindow.minimize();
break;
case 'toggle-maximize':
if (mainWindow.isMaximized())
mainWindow.unmaximize();
else
mainWindow.maximize();
if (mainWindow.isMaximized()) mainWindow.unmaximize();
else mainWindow.maximize();
break;
}
});
Expand Down Expand Up @@ -368,9 +367,9 @@ function createWindow() {
}

const checkEnvironmentVariables = () => {
const to_check = ['_JAVA_OPTIONS', 'JAVA_TOOL_OPTIONS'];
const disallowedVars = ['_JAVA_OPTIONS', 'JAVA_TOOL_OPTIONS'];

const set = to_check.filter((env) => !!process.env[env]);
const set = disallowedVars.filter((env) => !!process.env[env]);
if (set.length > 0) {
dialog.showErrorBox(
'SlimeVR',
Expand Down Expand Up @@ -401,9 +400,9 @@ const spawnServer = async () => {
if (!javaBin) {
dialog.showErrorBox(
'SlimeVR',
`Couldn't find a compatible Java version, please download Java 17 or higher`
'Unable to find a compatible Java version, please download Java 17 or higher'
);
app.quit()
app.quit();
return;
}

Expand All @@ -425,7 +424,9 @@ const spawnServer = async () => {
? {
...process.env,
APPDATA: app.getPath('appData'),
LOCALAPPDATA: process.env['USERPROFILE'] ? path.join(process.env['USERPROFILE'], 'AppData', 'Local') : undefined,
LOCALAPPDATA: process.env['USERPROFILE']
? path.join(process.env['USERPROFILE'], 'AppData', 'Local')
: undefined,
}
: undefined,
});
Expand All @@ -447,11 +448,11 @@ const spawnServer = async () => {
serverProcess.on('error', (err) => {
logger.info({ err }, 'Error launching the java server');
if (!isQuitting) app.quit();
})
});

serverProcess.on('exit', () => {
logger.info('Server process exiting');
})
});

const exited = new Promise<void>((resolve) => serverProcess.once('exit', resolve));

Expand All @@ -465,8 +466,7 @@ const spawnServer = async () => {
const createFolders = async () => {
await mkdir(getServerDataFolder(), { recursive: true });
await mkdir(getGuiDataFolder(), { recursive: true });
}

};

let isQuitting = false;

Expand All @@ -477,7 +477,6 @@ app.whenReady().then(async () => {
return net.fetch(pathToFileURL(filePath).toString(), { headers: request.headers });
});


try {
await createFolders();
} catch (err) {
Expand All @@ -490,7 +489,6 @@ app.whenReady().then(async () => {
return;
}


stores = await initStores();
checkEnvironmentVariables();
const server = await spawnServer();
Expand Down
23 changes: 15 additions & 8 deletions gui/electron/main/store.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { access, mkdir, readFile, writeFile } from "fs/promises";
import { dirname, join } from "path";
import { logger } from "./logger";
import { getGuiDataFolder } from "./paths";

import { access, mkdir, readFile, writeFile } from 'fs/promises';
import { dirname, join } from 'path';
import { logger } from './logger';
import { getGuiDataFolder } from './paths';

export class CustomStore {
private data: Record<string, unknown> = {};
Expand All @@ -15,7 +14,10 @@ export class CustomStore {
this.debounceMs = debounceMs;
}

static async create(filePath: string, debounceMs: number = 2000): Promise<CustomStore> {
static async create(
filePath: string,
debounceMs: number = 2000
): Promise<CustomStore> {
const store = new CustomStore(filePath, debounceMs);
await store.load();
return store;
Expand All @@ -28,7 +30,9 @@ export class CustomStore {
this.data = JSON.parse(raw);
} catch {
this.data = {};
logger.warn(`No existing store found at ${this.filePath}, starting with empty store.`);
logger.warn(
`No existing store found at ${this.filePath}, starting with empty store.`
);
}
}

Expand Down Expand Up @@ -73,7 +77,10 @@ export class CustomStore {

export async function initStores() {
return {
settings: await CustomStore.create(join(getGuiDataFolder(), 'gui-settings.dat'), 1000),
settings: await CustomStore.create(
join(getGuiDataFolder(), 'gui-settings.dat'),
1000
),
cache: await CustomStore.create(join(getGuiDataFolder(), 'gui-cache.dat'), 100),
};
}
37 changes: 18 additions & 19 deletions gui/electron/main/utils.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import os from 'os'
import { OSStats } from "../preload/interface";
import os from 'os';
import { OSStats } from '../preload/interface';
import { ipcMain, IpcMainInvokeEvent } from 'electron';
import { IpcInvokeMap } from '../shared';
import net from 'net'
import net from 'net';

export const getPlatform = (): OSStats['type'] => {
switch (os.platform()) {
Expand All @@ -19,21 +19,21 @@ export const getPlatform = (): OSStats['type'] => {

export const isPortAvailable = (port: number) => {
return new Promise((resolve) => {
const s = net.createServer();
s.once('error', (err) => {
s.close();
if ("code" in err && err["code"] == "EADDRINUSE") {
resolve(false);
} else {
resolve(false);
}
});
s.once('listening', () => {
resolve(true);
s.close();
});
s.listen(port);
const s = net.createServer();
s.once('error', (err) => {
s.close();
if ('code' in err && err['code'] == 'EADDRINUSE') {
resolve(false);
} else {
resolve(false);
}
});
s.once('listening', () => {
resolve(true);
s.close();
});
s.listen(port);
});
};

export function handleIpc<K extends keyof IpcInvokeMap>(
Expand All @@ -44,7 +44,6 @@ export function handleIpc<K extends keyof IpcInvokeMap>(
) => ReturnType<IpcInvokeMap[K]>
) {
ipcMain.handle(channel, (event, ...args) => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return handler(event, ...args as any);
return handler(event, ...(args as any));
});
}
15 changes: 12 additions & 3 deletions gui/electron/preload/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ contextBridge.exposeInMainWorld('electronAPI', {
close: () => ipcRenderer.invoke(IPC_CHANNELS.WINDOW_ACTIONS, 'close'),
hide: () => ipcRenderer.invoke(IPC_CHANNELS.WINDOW_ACTIONS, 'hide'),
minimize: () => ipcRenderer.invoke(IPC_CHANNELS.WINDOW_ACTIONS, 'minimize'),
toggleMaximize: () => ipcRenderer.invoke(IPC_CHANNELS.WINDOW_ACTIONS, 'toggle-maximize'),
toggleMaximize: () =>
ipcRenderer.invoke(IPC_CHANNELS.WINDOW_ACTIONS, 'toggle-maximize'),
getStorage: async (type) => {
return {
get: (key) =>
Expand All @@ -32,8 +33,16 @@ contextBridge.exposeInMainWorld('electronAPI', {
setTranslations: () => {},
openDialog: (options) => ipcRenderer.invoke(IPC_CHANNELS.OPEN_DIALOG, options),
saveDialog: (options) => ipcRenderer.invoke(IPC_CHANNELS.SAVE_DIALOG, options),
openConfigFolder: async () => ipcRenderer.invoke(IPC_CHANNELS.OPEN_FILE, await ipcRenderer.invoke(IPC_CHANNELS.GET_FOLDER, 'config')),
openLogsFolder: async () => ipcRenderer.invoke(IPC_CHANNELS.OPEN_FILE, await ipcRenderer.invoke(IPC_CHANNELS.GET_FOLDER, 'logs')),
openConfigFolder: async () =>
ipcRenderer.invoke(
IPC_CHANNELS.OPEN_FILE,
await ipcRenderer.invoke(IPC_CHANNELS.GET_FOLDER, 'config')
),
openLogsFolder: async () =>
ipcRenderer.invoke(
IPC_CHANNELS.OPEN_FILE,
await ipcRenderer.invoke(IPC_CHANNELS.GET_FOLDER, 'logs')
),
openFile: (path) => ipcRenderer.invoke(IPC_CHANNELS.OPEN_FILE, path),
ghGet: (req) => ipcRenderer.invoke(IPC_CHANNELS.GH_FETCH, req),
setPresence: (options) => ipcRenderer.invoke(IPC_CHANNELS.DISCORD_PRESENCE, options),
Expand Down
2 changes: 1 addition & 1 deletion gui/electron/shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export const IPC_CHANNELS = {
OPEN_FILE: 'open-file',
GET_FOLDER: 'get-folder',
GH_FETCH: 'gh-fetch',
DISCORD_PRESENCE: 'discord-presence'
DISCORD_PRESENCE: 'discord-presence',
} as const;

export interface IpcInvokeMap {
Expand Down
2 changes: 1 addition & 1 deletion gui/eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export const gui = [
...globals.jest,
},
},
files: ['src/**/*.{js,jsx,ts,tsx,json}'],
files: ['{electron,src}/**/*.{js,jsx,ts,tsx,json}'],
plugins: {
'@typescript-eslint': tseslint.plugin,
'@stylistic': stylistic,
Expand Down
6 changes: 3 additions & 3 deletions gui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@
"package:build": "pnpm build && pnpm package",
"preview": "electron-vite preview --config electron.vite.config.ts",
"skipbundler": "vite build",
"lint": "tsc --noEmit && eslint --max-warnings=0 \"src/**/*.{js,jsx,ts,tsx,json}\" && prettier --check \"src/**/*.{js,jsx,ts,tsx,css,scss,md,json}\"",
"lint:fix": "tsc --noEmit && eslint --fix --max-warnings=0 \"src/**/*.{js,jsx,ts,tsx,json}\" && pnpm run format",
"format": "prettier --write \"src/**/*.{js,jsx,ts,tsx,css,scss,md,json}\"",
"lint": "tsc --noEmit && eslint --max-warnings=0 \"{electron,src}/**/*.{js,jsx,ts,tsx,json}\" && prettier --check \"{electron,src}/**/*.{js,jsx,ts,tsx,css,scss,md,json}\"",
"lint:fix": "tsc --noEmit && eslint --fix --max-warnings=0 \"{electron,src}/**/*.{js,jsx,ts,tsx,json}\" && pnpm run format",
"format": "prettier --write \"{electron,src}/**/*.{js,jsx,ts,tsx,css,scss,md,json}\"",
"javaversion-build": "cd electron/resources/java-version/ && javac JavaVersion.java && jar cvfe JavaVersion.jar JavaVersion JavaVersion.class",
"gen:javaversion": "cd electron/resources/java-version/ && javac JavaVersion.java && jar cvfe JavaVersion.jar JavaVersion JavaVersion.class",
"gen:firmware-tool": "openapi-codegen gen firmwareTool"
Expand Down
8 changes: 4 additions & 4 deletions gui/src/components/commons/SystemFileInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@ export function InnerSystemFileInput({
value,
onChange,
directory,
ref,
refCallback: refCallback,
}: {
label: string;
value: string | null;
onChange: (...event: any[]) => void;
directory: boolean;
ref: RefCallBack;
refCallback: RefCallBack;
}) {
const electron = useElectron();

Expand All @@ -38,7 +38,7 @@ export function InnerSystemFileInput({
};

return (
<div ref={ref} onClick={handleClick}>
<div ref={refCallback} onClick={handleClick}>
{value !== null
? FileInputContentFile({
directory,
Expand Down Expand Up @@ -77,7 +77,7 @@ export function SystemFileInput<T extends FieldValues = FieldValues>({
label={label}
value={value}
onChange={onChange}
ref={ref}
refCallback={ref}
directory={directory}
/>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ function PosePage({
return (
<div className="flex flex-col py-2">
<div className="flex flex-col gap-2">
{descriptionKeys.map((descriptionKey) => (
<Typography>{l10n.getString(descriptionKey)}</Typography>
{descriptionKeys.map((descriptionKey, i) => (
<Typography key={i}>{l10n.getString(descriptionKey)}</Typography>
))}
</div>
<div className="flex pt-1 items-center fill-background-50 justify-center px-12">
Expand Down
Loading
Loading