mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-05-27 00:55:16 -07:00
rename config window to settings and update CLI entry points
- Replace `--config`/`subminer config` (no action) with `--settings`/`subminer settings` - `subminer config` now requires an explicit action (`path` or `show`) - `--settings` previously opened Yomitan; replaced by `--yomitan` - Linux tray update installs AppImage via electron-updater instead of manual flow - macOS update dialog activation and curl-fetch routing fixes - Delete stale compiled artifacts (main.js, app-updater.js)
This commit is contained in:
@@ -6,8 +6,8 @@ export function runAppPassthroughCommand(context: LauncherCommandContext): boole
|
||||
if (!appPath) {
|
||||
return false;
|
||||
}
|
||||
if (args.configSettings) {
|
||||
runAppCommandWithInherit(appPath, ['--config']);
|
||||
if (args.settings) {
|
||||
runAppCommandWithInherit(appPath, ['--settings']);
|
||||
return true;
|
||||
}
|
||||
if (!args.appPassthrough) {
|
||||
|
||||
@@ -53,7 +53,7 @@ function createContext(): LauncherCommandContext {
|
||||
doctor: false,
|
||||
doctorRefreshKnownWords: false,
|
||||
version: false,
|
||||
configSettings: false,
|
||||
settings: false,
|
||||
configPath: false,
|
||||
configShow: false,
|
||||
mpvIdle: false,
|
||||
|
||||
@@ -124,6 +124,7 @@ test('applyInvocationsToArgs maps config and jellyfin invocation state', () => {
|
||||
action: 'show',
|
||||
logLevel: 'warn',
|
||||
},
|
||||
settingsInvocation: null,
|
||||
mpvInvocation: null,
|
||||
appInvocation: null,
|
||||
dictionaryTriggered: false,
|
||||
@@ -159,13 +160,14 @@ test('applyInvocationsToArgs maps config and jellyfin invocation state', () => {
|
||||
assert.equal(parsed.logLevel, 'warn');
|
||||
});
|
||||
|
||||
test('applyInvocationsToArgs maps bare config invocation to settings window', () => {
|
||||
test('applyInvocationsToArgs maps settings invocation to settings window', () => {
|
||||
const parsed = createDefaultArgs({});
|
||||
|
||||
applyInvocationsToArgs(parsed, {
|
||||
jellyfinInvocation: null,
|
||||
configInvocation: {
|
||||
action: undefined,
|
||||
configInvocation: null,
|
||||
settingsInvocation: {
|
||||
logLevel: undefined,
|
||||
},
|
||||
mpvInvocation: null,
|
||||
appInvocation: null,
|
||||
@@ -190,16 +192,54 @@ test('applyInvocationsToArgs maps bare config invocation to settings window', ()
|
||||
texthookerOpenBrowser: false,
|
||||
});
|
||||
|
||||
assert.equal(parsed.configSettings, true);
|
||||
assert.equal(parsed.settings, true);
|
||||
assert.equal(parsed.configPath, false);
|
||||
});
|
||||
|
||||
test('applyInvocationsToArgs fails when config invocation has no action', () => {
|
||||
const parsed = createDefaultArgs({});
|
||||
|
||||
const error = withProcessExitIntercept(() => {
|
||||
applyInvocationsToArgs(parsed, {
|
||||
jellyfinInvocation: null,
|
||||
configInvocation: {
|
||||
action: undefined,
|
||||
},
|
||||
settingsInvocation: null,
|
||||
mpvInvocation: null,
|
||||
appInvocation: null,
|
||||
dictionaryTriggered: false,
|
||||
dictionaryTarget: null,
|
||||
dictionaryLogLevel: null,
|
||||
dictionaryCandidates: false,
|
||||
dictionarySelect: false,
|
||||
dictionaryAnilistId: null,
|
||||
statsTriggered: false,
|
||||
statsBackground: false,
|
||||
statsStop: false,
|
||||
statsCleanup: false,
|
||||
statsCleanupVocab: false,
|
||||
statsCleanupLifetime: false,
|
||||
statsLogLevel: null,
|
||||
doctorTriggered: false,
|
||||
doctorLogLevel: null,
|
||||
doctorRefreshKnownWords: false,
|
||||
texthookerTriggered: false,
|
||||
texthookerLogLevel: null,
|
||||
texthookerOpenBrowser: false,
|
||||
});
|
||||
});
|
||||
|
||||
assert.equal(error.code, 1);
|
||||
});
|
||||
|
||||
test('applyInvocationsToArgs maps texthooker browser-open request', () => {
|
||||
const parsed = createDefaultArgs({});
|
||||
|
||||
applyInvocationsToArgs(parsed, {
|
||||
jellyfinInvocation: null,
|
||||
configInvocation: null,
|
||||
settingsInvocation: null,
|
||||
mpvInvocation: null,
|
||||
appInvocation: null,
|
||||
dictionaryTriggered: false,
|
||||
|
||||
@@ -158,7 +158,7 @@ export function createDefaultArgs(
|
||||
doctorRefreshKnownWords: false,
|
||||
version: false,
|
||||
update: false,
|
||||
configSettings: false,
|
||||
settings: false,
|
||||
configPath: false,
|
||||
configShow: false,
|
||||
mpvIdle: false,
|
||||
@@ -222,7 +222,7 @@ export function applyRootOptionsToArgs(
|
||||
if (options.rofi === true) parsed.useRofi = true;
|
||||
if (options.update === true) parsed.update = true;
|
||||
if (options.version === true) parsed.version = true;
|
||||
if (options.config === true) parsed.configSettings = true;
|
||||
if (options.settings === true) parsed.settings = true;
|
||||
if (options.startOverlay === true) parsed.autoStartOverlay = true;
|
||||
if (options.texthooker === false) parsed.useTexthooker = false;
|
||||
if (typeof options.args === 'string') parsed.mpvArgs = options.args;
|
||||
@@ -311,10 +311,16 @@ export function applyInvocationsToArgs(parsed: Args, invocations: CliInvocations
|
||||
parsed.logLevel = parseLogLevel(invocations.configInvocation.logLevel);
|
||||
}
|
||||
const action = (invocations.configInvocation.action || '').toLowerCase();
|
||||
if (!action) parsed.configSettings = true;
|
||||
else if (action === 'path') parsed.configPath = true;
|
||||
if (action === 'path') parsed.configPath = true;
|
||||
else if (action === 'show') parsed.configShow = true;
|
||||
else fail(`Unknown config action: ${invocations.configInvocation.action}`);
|
||||
else fail(`Unknown config action: ${invocations.configInvocation.action || '(none)'}. Expected path or show.`);
|
||||
}
|
||||
|
||||
if (invocations.settingsInvocation) {
|
||||
if (invocations.settingsInvocation.logLevel) {
|
||||
parsed.logLevel = parseLogLevel(invocations.settingsInvocation.logLevel);
|
||||
}
|
||||
parsed.settings = true;
|
||||
}
|
||||
|
||||
if (invocations.mpvInvocation) {
|
||||
|
||||
@@ -22,6 +22,7 @@ export interface CommandActionInvocation {
|
||||
export interface CliInvocations {
|
||||
jellyfinInvocation: JellyfinInvocation | null;
|
||||
configInvocation: CommandActionInvocation | null;
|
||||
settingsInvocation: CommandActionInvocation | null;
|
||||
mpvInvocation: CommandActionInvocation | null;
|
||||
appInvocation: { appArgs: string[] } | null;
|
||||
dictionaryTriggered: boolean;
|
||||
@@ -58,7 +59,7 @@ function applyRootOptions(program: Command): void {
|
||||
.option('--start', 'Explicitly start overlay')
|
||||
.option('--log-level <level>', 'Log level')
|
||||
.option('-v, --version', 'Show SubMiner version')
|
||||
.option('--config', 'Open configuration window')
|
||||
.option('--settings', 'Open settings window')
|
||||
.option('-u, --update', 'Check for updates')
|
||||
.option('-R, --rofi', 'Use rofi picker')
|
||||
.option('-S, --start-overlay', 'Auto-start overlay')
|
||||
@@ -88,6 +89,7 @@ function getTopLevelCommand(argv: string[]): { name: string; index: number } | n
|
||||
'jf',
|
||||
'doctor',
|
||||
'config',
|
||||
'settings',
|
||||
'mpv',
|
||||
'dictionary',
|
||||
'dict',
|
||||
@@ -138,6 +140,7 @@ export function parseCliPrograms(
|
||||
} {
|
||||
let jellyfinInvocation: JellyfinInvocation | null = null;
|
||||
let configInvocation: CommandActionInvocation | null = null;
|
||||
let settingsInvocation: CommandActionInvocation | null = null;
|
||||
let mpvInvocation: CommandActionInvocation | null = null;
|
||||
let appInvocation: { appArgs: string[] } | null = null;
|
||||
let dictionaryTriggered = false;
|
||||
@@ -293,7 +296,7 @@ export function parseCliPrograms(
|
||||
|
||||
commandProgram
|
||||
.command('config')
|
||||
.description('Config helpers')
|
||||
.description('Config file helpers (path|show)')
|
||||
.argument('[action]', 'path|show')
|
||||
.option('--log-level <level>', 'Log level')
|
||||
.action((action: string | undefined, options: Record<string, unknown>) => {
|
||||
@@ -303,6 +306,16 @@ export function parseCliPrograms(
|
||||
};
|
||||
});
|
||||
|
||||
commandProgram
|
||||
.command('settings')
|
||||
.description('Open SubMiner settings window')
|
||||
.option('--log-level <level>', 'Log level')
|
||||
.action((options: Record<string, unknown>) => {
|
||||
settingsInvocation = {
|
||||
logLevel: typeof options.logLevel === 'string' ? options.logLevel : undefined,
|
||||
};
|
||||
});
|
||||
|
||||
commandProgram
|
||||
.command('mpv')
|
||||
.description('MPV helpers')
|
||||
@@ -356,6 +369,7 @@ export function parseCliPrograms(
|
||||
invocations: {
|
||||
jellyfinInvocation,
|
||||
configInvocation,
|
||||
settingsInvocation,
|
||||
mpvInvocation,
|
||||
appInvocation,
|
||||
dictionaryTriggered,
|
||||
|
||||
@@ -232,7 +232,7 @@ test('doctor refresh-known-words forwards app refresh command without requiring
|
||||
});
|
||||
});
|
||||
|
||||
test('launcher config option forwards app configuration window command', () => {
|
||||
test('launcher settings option forwards app settings window command', () => {
|
||||
withTempDir((root) => {
|
||||
const homeDir = path.join(root, 'home');
|
||||
const xdgConfigHome = path.join(root, 'xdg');
|
||||
@@ -249,14 +249,14 @@ test('launcher config option forwards app configuration window command', () => {
|
||||
SUBMINER_APPIMAGE_PATH: appPath,
|
||||
SUBMINER_TEST_CAPTURE: capturePath,
|
||||
};
|
||||
const result = runLauncher(['--config'], env);
|
||||
const result = runLauncher(['--settings'], env);
|
||||
|
||||
assert.equal(result.status, 0);
|
||||
assert.equal(fs.readFileSync(capturePath, 'utf8'), '--config\n');
|
||||
assert.equal(fs.readFileSync(capturePath, 'utf8'), '--settings\n');
|
||||
});
|
||||
});
|
||||
|
||||
test('launcher config command forwards app configuration window command', () => {
|
||||
test('launcher settings command forwards app settings window command', () => {
|
||||
withTempDir((root) => {
|
||||
const homeDir = path.join(root, 'home');
|
||||
const xdgConfigHome = path.join(root, 'xdg');
|
||||
@@ -273,14 +273,14 @@ test('launcher config command forwards app configuration window command', () =>
|
||||
SUBMINER_APPIMAGE_PATH: appPath,
|
||||
SUBMINER_TEST_CAPTURE: capturePath,
|
||||
};
|
||||
const result = runLauncher(['config'], env);
|
||||
const result = runLauncher(['settings'], env);
|
||||
|
||||
assert.equal(result.status, 0);
|
||||
assert.equal(fs.readFileSync(capturePath, 'utf8'), '--config\n');
|
||||
assert.equal(fs.readFileSync(capturePath, 'utf8'), '--settings\n');
|
||||
});
|
||||
});
|
||||
|
||||
test('launcher config command suppresses known Electron macOS menu diagnostics', () => {
|
||||
test('launcher settings command suppresses known Electron macOS menu diagnostics', () => {
|
||||
withTempDir((root) => {
|
||||
const homeDir = path.join(root, 'home');
|
||||
const xdgConfigHome = path.join(root, 'xdg');
|
||||
@@ -301,7 +301,7 @@ test('launcher config command suppresses known Electron macOS menu diagnostics',
|
||||
...makeTestEnv(homeDir, xdgConfigHome),
|
||||
SUBMINER_APPIMAGE_PATH: appPath,
|
||||
};
|
||||
const result = runLauncher(['config'], env);
|
||||
const result = runLauncher(['settings'], env);
|
||||
|
||||
assert.equal(result.status, 0);
|
||||
assert.equal(result.stderr, 'real stderr line\n');
|
||||
|
||||
@@ -569,7 +569,7 @@ function makeArgs(overrides: Partial<Args> = {}): Args {
|
||||
doctor: false,
|
||||
doctorRefreshKnownWords: false,
|
||||
version: false,
|
||||
configSettings: false,
|
||||
settings: false,
|
||||
configPath: false,
|
||||
configShow: false,
|
||||
mpvIdle: false,
|
||||
|
||||
@@ -57,10 +57,10 @@ test('parseArgs captures mpv args string', () => {
|
||||
assert.equal(parsed.mpvArgs, '--pause=yes --title="movie night"');
|
||||
});
|
||||
|
||||
test('parseArgs maps root config window option', () => {
|
||||
const parsed = parseArgs(['--config'], 'subminer', {});
|
||||
test('parseArgs maps root settings window option', () => {
|
||||
const parsed = parseArgs(['--settings'], 'subminer', {});
|
||||
|
||||
assert.equal(parsed.configSettings, true);
|
||||
assert.equal(parsed.settings, true);
|
||||
});
|
||||
|
||||
test('parseArgs maps root update flags without conflicting with jellyfin username', () => {
|
||||
@@ -107,10 +107,10 @@ test('parseArgs maps config show action', () => {
|
||||
assert.equal(parsed.configPath, false);
|
||||
});
|
||||
|
||||
test('parseArgs maps bare config command to settings window', () => {
|
||||
const parsed = parseArgs(['config'], 'subminer', {});
|
||||
test('parseArgs maps settings command to settings window', () => {
|
||||
const parsed = parseArgs(['settings'], 'subminer', {});
|
||||
|
||||
assert.equal(parsed.configSettings, true);
|
||||
assert.equal(parsed.settings, true);
|
||||
assert.equal(parsed.configPath, false);
|
||||
assert.equal(parsed.configShow, false);
|
||||
});
|
||||
@@ -119,7 +119,7 @@ test('parseArgs maps config path action to config path output', () => {
|
||||
const parsed = parseArgs(['config', 'path'], 'subminer', {});
|
||||
|
||||
assert.equal(parsed.configPath, true);
|
||||
assert.equal(parsed.configSettings, false);
|
||||
assert.equal(parsed.settings, false);
|
||||
});
|
||||
|
||||
test('parseArgs rejects removed config open and launch actions', () => {
|
||||
@@ -134,6 +134,14 @@ test('parseArgs rejects removed config open and launch actions', () => {
|
||||
assert.equal(exit.code, 1);
|
||||
});
|
||||
|
||||
test('parseArgs requires an explicit action for the config subcommand', () => {
|
||||
const exit = withProcessExitIntercept(() => {
|
||||
parseArgs(['config'], 'subminer', {});
|
||||
});
|
||||
|
||||
assert.equal(exit.code, 1);
|
||||
});
|
||||
|
||||
test('parseArgs maps mpv idle action', () => {
|
||||
const parsed = parseArgs(['mpv', 'idle'], 'subminer', {});
|
||||
|
||||
|
||||
+1
-1
@@ -133,7 +133,7 @@ export interface Args {
|
||||
doctorRefreshKnownWords: boolean;
|
||||
version: boolean;
|
||||
update?: boolean;
|
||||
configSettings: boolean;
|
||||
settings: boolean;
|
||||
configPath: boolean;
|
||||
configShow: boolean;
|
||||
mpvIdle: boolean;
|
||||
|
||||
Reference in New Issue
Block a user