perf: cut ControlApp re-renders and lazy-load VFX packs
Move audio scrub/volume and brush drafts off root React ticks, coalesce overlay layout IPC, cache machine fingerprint and asset URLs, share one scene overlay host, and stop idle Pixi ticker. Also harden console against EPIPE on window load failures. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -4,6 +4,8 @@ import fs from 'node:fs';
|
||||
import os from 'node:os';
|
||||
import path from 'node:path';
|
||||
|
||||
import { machineFingerprintCachePath } from './paths';
|
||||
|
||||
type ExecFile = (
|
||||
file: string,
|
||||
args: readonly string[],
|
||||
@@ -13,6 +15,8 @@ type ExecFile = (
|
||||
export type MachineFingerprintDeps = {
|
||||
platform?: NodeJS.Platform;
|
||||
env?: NodeJS.ProcessEnv;
|
||||
/** Electron userData — для дискового кэша hashed fingerprint. */
|
||||
userData?: string;
|
||||
execFileSync?: ExecFile;
|
||||
readFileSync?: (p: string, encoding: 'utf8') => string;
|
||||
existsSync?: (p: string) => boolean;
|
||||
@@ -20,6 +24,18 @@ export type MachineFingerprintDeps = {
|
||||
writeFileSync?: (p: string, data: string, opts?: { mode?: number }) => void;
|
||||
};
|
||||
|
||||
/** Process-level кэш: повторные вызовы в том же процессе без I/O. */
|
||||
let memoryFingerprint: string | null = null;
|
||||
|
||||
/** Только для тестов. */
|
||||
export function clearMachineFingerprintMemoryCache(): void {
|
||||
memoryFingerprint = null;
|
||||
}
|
||||
|
||||
function isPlausiblyFingerprint(id: string): boolean {
|
||||
return id.length >= 8 && id.length <= 128 && !/\s/.test(id);
|
||||
}
|
||||
|
||||
const HASH_PREFIX = 'TTRPGPlayer.machine.v1\0';
|
||||
|
||||
/** Стабильный opaque id из сырого машинного идентификатора ОС. */
|
||||
@@ -149,9 +165,38 @@ function readOrCreateMachineWideFallback(
|
||||
}
|
||||
}
|
||||
|
||||
function readDiskFingerprintCache(
|
||||
cacheFile: string,
|
||||
readFile: (p: string, encoding: 'utf8') => string,
|
||||
existsSync: (p: string) => boolean,
|
||||
): string | null {
|
||||
try {
|
||||
if (!existsSync(cacheFile)) return null;
|
||||
const cached = readFile(cacheFile, 'utf8').trim();
|
||||
return isPlausiblyFingerprint(cached) ? cached : null;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function writeDiskFingerprintCache(
|
||||
cacheFile: string,
|
||||
fingerprint: string,
|
||||
mkdirSync: (p: string, opts: { recursive: boolean }) => void,
|
||||
writeFileSync: (p: string, data: string, opts?: { mode?: number }) => void,
|
||||
): void {
|
||||
try {
|
||||
mkdirSync(path.dirname(cacheFile), { recursive: true });
|
||||
writeFileSync(cacheFile, `${fingerprint}\n`, { mode: 0o644 });
|
||||
} catch {
|
||||
/* кэш необязателен */
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Стабильный идентификатор физической машины (одинаковый для всех пользователей ОС на одном ПК).
|
||||
* Источники: Windows MachineGuid, macOS IOPlatformUUID, Linux /etc/machine-id.
|
||||
* Кэш: память процесса → userData/machine.fingerprint → sync probe ОС только при miss.
|
||||
*/
|
||||
export function resolveMachineFingerprint(deps: MachineFingerprintDeps = {}): string {
|
||||
const platform = deps.platform ?? process.platform;
|
||||
@@ -167,7 +212,24 @@ export function resolveMachineFingerprint(deps: MachineFingerprintDeps = {}): st
|
||||
});
|
||||
|
||||
const override = env.DND_LICENSE_DEVICE_ID?.trim();
|
||||
if (override && override.length >= 8) return override;
|
||||
if (override && override.length >= 8) {
|
||||
memoryFingerprint = override;
|
||||
return override;
|
||||
}
|
||||
|
||||
if (memoryFingerprint && isPlausiblyFingerprint(memoryFingerprint)) {
|
||||
return memoryFingerprint;
|
||||
}
|
||||
|
||||
const userData = deps.userData?.trim();
|
||||
const cacheFile = userData ? machineFingerprintCachePath(userData) : null;
|
||||
if (cacheFile) {
|
||||
const fromDisk = readDiskFingerprintCache(cacheFile, readFile, existsSync);
|
||||
if (fromDisk) {
|
||||
memoryFingerprint = fromDisk;
|
||||
return fromDisk;
|
||||
}
|
||||
}
|
||||
|
||||
let raw: string | null = null;
|
||||
if (platform === 'win32') raw = readWindowsRawId(exec);
|
||||
@@ -189,5 +251,10 @@ export function resolveMachineFingerprint(deps: MachineFingerprintDeps = {}): st
|
||||
);
|
||||
}
|
||||
|
||||
return hashMachineRawId(platform, raw);
|
||||
const fingerprint = hashMachineRawId(platform, raw);
|
||||
memoryFingerprint = fingerprint;
|
||||
if (cacheFile) {
|
||||
writeDiskFingerprintCache(cacheFile, fingerprint, mkdirSync, writeFileSync);
|
||||
}
|
||||
return fingerprint;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user