mirror of
https://github.com/k1tbyte/Wand-Enhancer.git
synced 2026-08-29 00:01:09 +00:00
13759b1db6
- reduce ASAR IO overhead with streamed archive reads, buffered copies, faster relative-path handling and placeholder integrity records - fix in-place app.asar.unpacked packing/extraction self-copy cases that caused locked-file failures - tighten JS patch discovery with candidate bundle filters and search hints - require prebuilt remote-panel dist artifacts and clean up embedded bridge/script packaging - add unified build entrypoints for PowerShell, cmd and bash and move native CMake output under .tmp - add release metadata validation, changelog section extraction, pre-commit hook and GitHub Actions validation/release pipelines - make CHANGELOG the source of truth for release notes and document the tag-driven release flow - add updater release notes UI with latest/full changelog loading and localize the new update strings - modularize bridge renderer scripts, add installed apps and game status sync, and support remote launch/stop commands - centralize bridge protocol, IPC and WebSocket constants and improve LAN IP selection for QR pairing - refactor remote panel controls/state enums, persist accent color, polish library/session UI and refresh assets
167 lines
5.2 KiB
TypeScript
167 lines
5.2 KiB
TypeScript
import { readInitialRemoteUrl, readInitialWebSocketUrl } from './constants';
|
|
import type { GameStatusPayload, InstalledAppSummary, InstalledAppsPayload, TrainerMetaPayload } from './protocol';
|
|
|
|
export enum EConnectionStatus {
|
|
Idle = 'idle',
|
|
Connecting = 'connecting',
|
|
Connected = 'connected',
|
|
Error = 'error',
|
|
}
|
|
|
|
export type PanelState = {
|
|
connectionStatus: EConnectionStatus;
|
|
wsUrl: string;
|
|
remoteUrl: string;
|
|
trainerMeta: TrainerMetaPayload | null;
|
|
gameStatus: GameStatusPayload | null;
|
|
installedApps: InstalledAppSummary[];
|
|
installedAppsUpdatedAt: string | null;
|
|
values: Record<string, unknown>;
|
|
pendingTargets: Record<string, boolean>;
|
|
pinnedTargets: Record<string, true>;
|
|
lastError: string | null;
|
|
};
|
|
|
|
export type PanelAction =
|
|
| { type: 'setWsUrl'; wsUrl: string }
|
|
| { type: 'setRemoteUrl'; remoteUrl: string }
|
|
| { type: 'connecting' }
|
|
| { type: 'connected' }
|
|
| { type: 'disconnected' }
|
|
| { type: 'trainerMeta'; payload: TrainerMetaPayload }
|
|
| { type: 'gameStatus'; payload: GameStatusPayload }
|
|
| { type: 'installedApps'; payload: InstalledAppsPayload }
|
|
| { type: 'trainerValues'; payload: Record<string, unknown> }
|
|
| { type: 'valueChanged'; target: string; value: unknown }
|
|
| { type: 'setPending'; target: string; pending: boolean }
|
|
| { type: 'trainerChanged' }
|
|
| { type: 'setPinnedTargets'; pinned: Record<string, true> }
|
|
| { type: 'togglePinnedTarget'; target: string }
|
|
| { type: 'error'; message: string | null };
|
|
|
|
export function createInitialPanelState(): PanelState {
|
|
return {
|
|
connectionStatus: EConnectionStatus.Idle,
|
|
wsUrl: readInitialWebSocketUrl(),
|
|
remoteUrl: readInitialRemoteUrl(),
|
|
trainerMeta: null,
|
|
gameStatus: null,
|
|
installedApps: [],
|
|
installedAppsUpdatedAt: null,
|
|
values: {},
|
|
pendingTargets: {},
|
|
pinnedTargets: {},
|
|
lastError: null,
|
|
};
|
|
}
|
|
|
|
export function panelReducer(state: PanelState, action: PanelAction): PanelState {
|
|
switch (action.type) {
|
|
case 'setWsUrl':
|
|
return {
|
|
...state,
|
|
wsUrl: action.wsUrl,
|
|
};
|
|
case 'setRemoteUrl':
|
|
return {
|
|
...state,
|
|
remoteUrl: action.remoteUrl,
|
|
};
|
|
case 'connecting':
|
|
return {
|
|
...state,
|
|
connectionStatus: EConnectionStatus.Connecting,
|
|
lastError: null,
|
|
};
|
|
case 'connected':
|
|
return {
|
|
...state,
|
|
connectionStatus: EConnectionStatus.Connected,
|
|
lastError: null,
|
|
};
|
|
case 'disconnected':
|
|
return {
|
|
...state,
|
|
connectionStatus: EConnectionStatus.Idle,
|
|
trainerMeta: null,
|
|
gameStatus: null,
|
|
values: {},
|
|
pendingTargets: {},
|
|
lastError: null,
|
|
};
|
|
case 'trainerMeta':
|
|
return {
|
|
...state,
|
|
trainerMeta: action.payload,
|
|
pendingTargets: {},
|
|
};
|
|
case 'gameStatus':
|
|
return {
|
|
...state,
|
|
gameStatus: action.payload,
|
|
};
|
|
case 'installedApps':
|
|
return {
|
|
...state,
|
|
installedApps: action.payload.apps,
|
|
installedAppsUpdatedAt: action.payload.updatedAt,
|
|
};
|
|
case 'trainerValues':
|
|
return {
|
|
...state,
|
|
values: action.payload,
|
|
};
|
|
case 'valueChanged':
|
|
return {
|
|
...state,
|
|
values: {
|
|
...state.values,
|
|
[action.target]: action.value,
|
|
},
|
|
pendingTargets: {
|
|
...state.pendingTargets,
|
|
[action.target]: false,
|
|
},
|
|
};
|
|
case 'setPending':
|
|
return {
|
|
...state,
|
|
pendingTargets: {
|
|
...state.pendingTargets,
|
|
[action.target]: action.pending,
|
|
},
|
|
};
|
|
case 'trainerChanged':
|
|
return {
|
|
...state,
|
|
trainerMeta: null,
|
|
values: {},
|
|
pendingTargets: {},
|
|
pinnedTargets: {},
|
|
};
|
|
case 'setPinnedTargets':
|
|
return {
|
|
...state,
|
|
pinnedTargets: action.pinned,
|
|
};
|
|
case 'togglePinnedTarget': {
|
|
const next = { ...state.pinnedTargets };
|
|
if (next[action.target]) {
|
|
delete next[action.target];
|
|
} else {
|
|
next[action.target] = true;
|
|
}
|
|
return {
|
|
...state,
|
|
pinnedTargets: next,
|
|
};
|
|
}
|
|
case 'error':
|
|
return {
|
|
...state,
|
|
connectionStatus: action.message && state.connectionStatus !== EConnectionStatus.Connected ? EConnectionStatus.Error : state.connectionStatus,
|
|
lastError: action.message,
|
|
};
|
|
}
|
|
}
|