mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-04-03 06:12:07 -07:00
Require mpv plugin in first-run setup
This commit is contained in:
@@ -21,7 +21,7 @@ Look up words with Yomitan, export to Anki in one key, track your immersion —
|
||||
|
||||
SubMiner runs as an invisible Electron overlay on top of mpv. Subtitles render as an interactive layer. Move your cursor over any word and trigger a [Yomitan](https://github.com/yomidevs/yomitan) lookup. Press one key to snapshot the sentence, audio, and screenshot into Anki via AnkiConnect.
|
||||
|
||||
On Windows, the recommended playback entry point is the optional `SubMiner mpv` shortcut created during setup. First-run setup requires the mpv plugin before it can finish. The shortcut launches `mpv` with SubMiner's defaults directly, so you do not need an `mpv.conf` profile just to use it.
|
||||
First-run setup requires the mpv plugin before it can finish. On Windows, the optional `SubMiner mpv` shortcut created during setup is the recommended playback entry point because it launches `mpv` with SubMiner's defaults directly, so you do not need an `mpv.conf` profile just to use it.
|
||||
|
||||
## Features
|
||||
|
||||
|
||||
@@ -2,4 +2,4 @@ type: changed
|
||||
area: setup
|
||||
|
||||
- Made mpv plugin installation mandatory in the first-run setup flow, removed the skip path, and kept Finish disabled until the plugin is installed.
|
||||
- Updated the Windows setup copy to make the `SubMiner mpv` shortcut the recommended playback entry point after setup completes.
|
||||
- Clarified that the mpv plugin requirement applies to setup on every platform, while the optional `SubMiner mpv` shortcut remains the recommended Windows playback entry point.
|
||||
|
||||
@@ -171,7 +171,7 @@ Install `mpv` separately and ensure `mpv.exe` is on `PATH`. `ffmpeg` is still re
|
||||
|
||||
### Windows Usage Notes
|
||||
|
||||
- Launch `SubMiner.exe` once to let the first-run setup flow seed `%APPDATA%\\SubMiner\\config.jsonc`, require mpv plugin installation, open bundled Yomitan settings, and optionally create `SubMiner mpv` Start Menu/Desktop shortcuts. On Windows, that shortcut is the recommended way to launch mpv playback with SubMiner defaults.
|
||||
- Launch `SubMiner.exe` once to let the first-run setup flow seed `%APPDATA%\\SubMiner\\config.jsonc`, require mpv plugin installation, and open bundled Yomitan settings. The optional `SubMiner mpv` Start Menu/Desktop shortcut can also be created during setup, and on Windows it is the recommended way to launch mpv playback with SubMiner defaults.
|
||||
- `SubMiner.exe --launch-mpv` and the optional `SubMiner mpv` shortcut pass SubMiner's default mpv socket/subtitle args directly, including the Windows-safe subtitle search paths that skip the extra current-directory scan; they do not require an `mpv.conf` profile named `subminer`.
|
||||
- First-run mpv plugin installs pin `binary_path` to the current `SubMiner.exe` automatically. Manual plugin configs can leave `binary_path` empty unless SubMiner is installed in a non-standard location.
|
||||
- Windows plugin installs rewrite `socket_path` to `\\.\pipe\subminer-socket`; do not keep `/tmp/subminer-socket` on Windows.
|
||||
|
||||
@@ -117,8 +117,10 @@ SubMiner.AppImage --help # Show all options
|
||||
|
||||
### Windows mpv Shortcut
|
||||
|
||||
First-run setup requires the mpv plugin before it can finish.
|
||||
|
||||
If you enabled the optional Windows shortcut during install, SubMiner creates a `SubMiner mpv` shortcut in the Start menu and/or on the desktop. On Windows, that shortcut is the recommended way to launch local files with SubMiner because it starts `mpv.exe` with the right defaults directly.
|
||||
First-run setup requires the mpv plugin before it can finish, so the shortcut is the normal Windows playback entry point after setup completes.
|
||||
After setup completes, the shortcut is the normal Windows playback entry point.
|
||||
|
||||
You can use it three ways:
|
||||
|
||||
|
||||
@@ -251,6 +251,48 @@ test('setup service reopens when external-yomitan completion later has no extern
|
||||
});
|
||||
});
|
||||
|
||||
test('setup service reopens when a completed setup no longer has the mpv plugin installed', async () => {
|
||||
await withTempDir(async (root) => {
|
||||
const configDir = path.join(root, 'SubMiner');
|
||||
fs.mkdirSync(configDir, { recursive: true });
|
||||
fs.writeFileSync(path.join(configDir, 'config.jsonc'), '{}');
|
||||
|
||||
const completedService = createFirstRunSetupService({
|
||||
configDir,
|
||||
getYomitanDictionaryCount: async () => 2,
|
||||
detectPluginInstalled: () => true,
|
||||
installPlugin: async () => ({
|
||||
ok: true,
|
||||
pluginInstallStatus: 'installed',
|
||||
pluginInstallPathSummary: '/tmp/mpv',
|
||||
message: 'ok',
|
||||
}),
|
||||
onStateChanged: () => undefined,
|
||||
});
|
||||
|
||||
await completedService.ensureSetupStateInitialized();
|
||||
await completedService.markSetupCompleted();
|
||||
|
||||
const service = createFirstRunSetupService({
|
||||
configDir,
|
||||
getYomitanDictionaryCount: async () => 2,
|
||||
detectPluginInstalled: () => false,
|
||||
installPlugin: async () => ({
|
||||
ok: true,
|
||||
pluginInstallStatus: 'installed',
|
||||
pluginInstallPathSummary: null,
|
||||
message: 'ok',
|
||||
}),
|
||||
onStateChanged: () => undefined,
|
||||
});
|
||||
|
||||
const snapshot = await service.ensureSetupStateInitialized();
|
||||
assert.equal(snapshot.state.status, 'incomplete');
|
||||
assert.equal(snapshot.canFinish, false);
|
||||
assert.equal(snapshot.pluginStatus, 'required');
|
||||
});
|
||||
});
|
||||
|
||||
test('setup service keeps completed when external-yomitan completion later has internal dictionaries available', async () => {
|
||||
await withTempDir(async (root) => {
|
||||
const configDir = path.join(root, 'SubMiner');
|
||||
|
||||
@@ -272,24 +272,20 @@ export function createFirstRunSetupService(deps: {
|
||||
getYomitanDictionaryCount: deps.getYomitanDictionaryCount,
|
||||
isExternalYomitanConfigured: deps.isExternalYomitanConfigured,
|
||||
});
|
||||
const yomitanSetupSatisfied = isYomitanSetupSatisfied({
|
||||
const pluginInstalled = await deps.detectPluginInstalled();
|
||||
const canFinish =
|
||||
pluginInstalled &&
|
||||
isYomitanSetupSatisfied({
|
||||
configReady,
|
||||
dictionaryCount,
|
||||
externalYomitanConfigured,
|
||||
});
|
||||
if (
|
||||
isSetupCompleted(state) &&
|
||||
!(
|
||||
state.yomitanSetupMode === 'external' &&
|
||||
!externalYomitanConfigured &&
|
||||
!yomitanSetupSatisfied
|
||||
)
|
||||
) {
|
||||
if (isSetupCompleted(state) && canFinish) {
|
||||
completed = true;
|
||||
return refreshWithState(state);
|
||||
}
|
||||
|
||||
if (yomitanSetupSatisfied) {
|
||||
if (canFinish) {
|
||||
const completedState = writeState({
|
||||
...state,
|
||||
status: 'completed',
|
||||
|
||||
Reference in New Issue
Block a user