mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-03-24 12:11:29 -07:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
842008b089
|
|||
|
6f56a0bcf6
|
@@ -1,5 +1,14 @@
|
||||
# Changelog
|
||||
|
||||
## v0.9.1 (2026-03-24)
|
||||
|
||||
### Changed
|
||||
- Release: Reduced packaged release size by excluding duplicate `extraResources` payload and pruning docs, tests, sourcemaps, and other source-only files from Electron bundles.
|
||||
|
||||
### Fixed
|
||||
- Overlay: Restored controller navigation and lookup/mining controls while the subtitle sidebar is open, while keeping true modal dialogs blocking controller actions.
|
||||
- Tokenizer: Fixed subtitle annotation clearing so explanatory contrast endings like `んですけど` are excluded consistently across the shared tokenizer filter and annotation stage.
|
||||
|
||||
## v0.9.0 (2026-03-23)
|
||||
|
||||
### Added
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
---
|
||||
id: TASK-231
|
||||
title: Restore controller input while subtitle sidebar is open
|
||||
status: Done
|
||||
assignee:
|
||||
- '@codex'
|
||||
created_date: '2026-03-24 00:15'
|
||||
updated_date: '2026-03-24 00:15'
|
||||
labels:
|
||||
- bug
|
||||
- controller
|
||||
- subtitle-sidebar
|
||||
- overlay
|
||||
dependencies: []
|
||||
references:
|
||||
- /home/sudacode/projects/japanese/SubMiner/src/renderer/renderer.ts
|
||||
- /home/sudacode/projects/japanese/SubMiner/src/renderer/controller-interaction-blocking.ts
|
||||
- /home/sudacode/projects/japanese/SubMiner/src/renderer/controller-interaction-blocking.test.ts
|
||||
priority: high
|
||||
ordinal: 54900
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
|
||||
When keyboard-only mode is active, opening the subtitle sidebar should not disable controller navigation and lookup/mining controls. Restore controller input while the sidebar is open, while keeping true modal dialogs blocking controller actions.
|
||||
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
<!-- AC:BEGIN -->
|
||||
|
||||
- [x] #1 Opening the subtitle sidebar does not block controller input for keyboard-only mode actions.
|
||||
- [x] #2 Controller-select/debug and other true modal dialogs still block controller actions while open.
|
||||
- [x] #3 Focused regression coverage exists for the sidebar-open controller gating rule.
|
||||
|
||||
<!-- AC:END -->
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
<!-- SECTION:NOTES:BEGIN -->
|
||||
|
||||
Root cause: renderer gamepad polling used the broad `isAnyModalOpen()` check as its interaction gate, and that list includes `subtitleSidebarModalOpen`. The subtitle sidebar is non-modal for controller usage, so gamepad input was being suppressed whenever the sidebar was visible.
|
||||
|
||||
Fixed by extracting a dedicated controller-interaction blocking helper that excludes the subtitle sidebar but keeps the existing blocking behavior for true modal dialogs.
|
||||
|
||||
<!-- SECTION:NOTES:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
|
||||
Restored controller input while the subtitle sidebar is open by switching gamepad polling to a dedicated modal-blocking rule that leaves the sidebar controller-passive. Added a regression test covering the sidebar-open exception and preserving hard blocks for actual modal dialogs.
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
@@ -0,0 +1,66 @@
|
||||
---
|
||||
id: TASK-232
|
||||
title: Trim release package size by pruning duplicate and source-only assets
|
||||
status: Done
|
||||
assignee:
|
||||
- '@codex'
|
||||
created_date: '2026-03-24 12:05'
|
||||
updated_date: '2026-03-24 12:30'
|
||||
labels:
|
||||
- release
|
||||
- packaging
|
||||
priority: medium
|
||||
ordinal: 54700
|
||||
dependencies: []
|
||||
references:
|
||||
- /home/sudacode/projects/japanese/SubMiner/package.json
|
||||
- /home/sudacode/projects/japanese/SubMiner/src/release-workflow.test.ts
|
||||
- /home/sudacode/projects/japanese/SubMiner/src/core/services/texthooker.ts
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
|
||||
Reduce packaged release artifact size without changing user-visible functionality by pruning files that are duplicated between `app.asar` and `extraResources`, excluding source/test/doc-only trees from Electron packaging, and trimming obviously non-runtime vendored payload.
|
||||
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
<!-- AC:BEGIN -->
|
||||
|
||||
- [x] #1 Electron packaging excludes repo content that is source-only, test-only, docs-only, or duplicated by `extraResources`.
|
||||
- [x] #2 Release packaging tests cover the new exclusion rules.
|
||||
- [x] #3 Verification includes at least targeted release-packaging tests and one packaging-oriented validation step.
|
||||
<!-- AC:END -->
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
<!-- SECTION:NOTES:BEGIN -->
|
||||
|
||||
Completed scope:
|
||||
- Exclude `assets`, `plugin`, and `vendor/yomitan-jlpt-vocab` from `files` because they are already staged via `extraResources`.
|
||||
- Exclude `dist` sourcemaps/tests, repo docs/tests/packaging metadata, and stats source leftovers from `files`.
|
||||
- Exclude non-runtime `vendor/texthooker-ui` payload such as `public/`, `.vscode/`, and package metadata.
|
||||
- Exclude Linux musl libsql binary from packaged app payload for AppImage-focused savings.
|
||||
|
||||
Verification:
|
||||
- `bun test src/release-workflow.test.ts`
|
||||
- `bun run build`
|
||||
- `node_modules/.bin/electron-builder --linux dir --publish never`
|
||||
- `node_modules/.bin/electron-builder --linux AppImage --publish never`
|
||||
|
||||
Observed result:
|
||||
- `release/linux-unpacked/resources/app.asar` dropped from about `100 MB` to `29 MB`.
|
||||
- `release/SubMiner-0.9.0.AppImage` dropped from about `256 MB` to `194 MB`.
|
||||
|
||||
<!-- SECTION:NOTES:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
|
||||
Trimmed Electron packaging so release artifacts no longer bundle duplicated `extraResources`, source/test/doc-only repo content, non-runtime `texthooker-ui` files, or the Linux musl libsql binary. Added release-packaging regression coverage and verified the Linux package shrink with fresh local builds.
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
@@ -0,0 +1,69 @@
|
||||
---
|
||||
id: TASK-233
|
||||
title: Cut patch release v0.9.1 for package size pruning
|
||||
status: Done
|
||||
assignee:
|
||||
- '@codex'
|
||||
created_date: '2026-03-24 12:40'
|
||||
updated_date: '2026-03-24 12:55'
|
||||
labels:
|
||||
- release
|
||||
- patch
|
||||
dependencies:
|
||||
- TASK-232
|
||||
references:
|
||||
- /home/sudacode/projects/japanese/SubMiner/package.json
|
||||
- /home/sudacode/projects/japanese/SubMiner/CHANGELOG.md
|
||||
- /home/sudacode/projects/japanese/SubMiner/release/release-notes.md
|
||||
- /home/sudacode/projects/japanese/SubMiner/docs-site/changelog.md
|
||||
priority: high
|
||||
ordinal: 54800
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
|
||||
Publish a patch release for the packaging-size cleanup by bumping the app version to `0.9.1`, generating committed release metadata, and keeping release-facing docs/changelog surfaces aligned.
|
||||
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
<!-- AC:BEGIN -->
|
||||
|
||||
- [x] #1 Repository version metadata is updated to `0.9.1`.
|
||||
- [x] #2 `CHANGELOG.md`, `release/release-notes.md`, and `docs-site/changelog.md` contain the committed `v0.9.1` release line and the consumed fragment is removed.
|
||||
- [x] #3 Release-readiness verification passes for changelog, docs, tests, and build lanes.
|
||||
<!-- AC:END -->
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
<!-- SECTION:NOTES:BEGIN -->
|
||||
|
||||
Completed:
|
||||
- Bumped `package.json` to `0.9.1`.
|
||||
- Ran `bun run changelog:build --version 0.9.1 --date 2026-03-24`, which generated `CHANGELOG.md` + `release/release-notes.md` and consumed both pending release fragments.
|
||||
- Synced `docs-site/changelog.md` with the generated `v0.9.1` release line.
|
||||
- Confirmed no additional README/docs wording changes were needed beyond changelog surfaces.
|
||||
|
||||
Verification:
|
||||
- `bun run changelog:lint`
|
||||
- `bun run changelog:check --version 0.9.1`
|
||||
- `bun run verify:config-example`
|
||||
- `bun run typecheck`
|
||||
- `bun run test:fast`
|
||||
- `bun run test:env`
|
||||
- `bun run build`
|
||||
- `bun run docs:test`
|
||||
- `bun run docs:build`
|
||||
|
||||
<!-- SECTION:NOTES:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
|
||||
Prepared patch release `v0.9.1` locally. Version metadata, committed changelog artifacts, release notes, and docs-site changelog are aligned, and the release gate is green. Pending manual release actions are the release-prep commit, `git tag v0.9.1`, and push/tag publication.
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
@@ -1,4 +0,0 @@
|
||||
type: fixed
|
||||
area: tokenizer
|
||||
|
||||
- Fixed subtitle annotation clearing so explanatory contrast endings like `んですけど` are excluded consistently across the shared tokenizer filter and annotation stage.
|
||||
@@ -1,5 +1,10 @@
|
||||
# Changelog
|
||||
|
||||
## v0.9.1 (2026-03-24)
|
||||
- Reduced packaged release size by excluding duplicate `extraResources` payload and pruning docs, tests, sourcemaps, and other source-only files from Electron bundles.
|
||||
- Restored controller navigation and lookup/mining controls while the subtitle sidebar is open, while keeping true modal dialogs blocking controller actions.
|
||||
- Fixed subtitle annotation clearing so explanatory contrast endings like `んですけど` are excluded consistently across the shared tokenizer filter and annotation stage.
|
||||
|
||||
## v0.9.0 (2026-03-23)
|
||||
- Added an app-owned YouTube subtitle flow with absPlayer-style timedtext parsing that auto-loads the default primary subtitle plus a best-effort secondary at startup and resumes once the primary is ready.
|
||||
- Added a manual YouTube subtitle picker on `Ctrl+Alt+C` so subtitle selection can be retried on demand during active YouTube playback.
|
||||
|
||||
28
package.json
28
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "subminer",
|
||||
"version": "0.9.0",
|
||||
"version": "0.9.1",
|
||||
"description": "All-in-one sentence mining overlay with AnkiConnect and dictionary integration",
|
||||
"packageManager": "bun@1.3.5",
|
||||
"main": "dist/main-entry.js",
|
||||
@@ -166,20 +166,44 @@
|
||||
},
|
||||
"files": [
|
||||
"**/*",
|
||||
"!assets{,/**/*}",
|
||||
"!src{,/**/*}",
|
||||
"!launcher{,/**/*}",
|
||||
"!docs{,/**/*}",
|
||||
"!tests{,/**/*}",
|
||||
"!packaging{,/**/*}",
|
||||
"!README.md",
|
||||
"!CHANGELOG.md",
|
||||
"!AGENTS.md",
|
||||
"!CLAUDE.md",
|
||||
"!stats/src{,/**/*}",
|
||||
"!stats/index.html",
|
||||
"!stats/public{,/**/*}",
|
||||
"!stats/package.json",
|
||||
"!stats/tsconfig.json",
|
||||
"!stats/vite.config.ts",
|
||||
"!docs-site{,/**/*}",
|
||||
"!changes{,/**/*}",
|
||||
"!backlog{,/**/*}",
|
||||
"!.tmp{,/**/*}",
|
||||
"!release-*{,/**/*}",
|
||||
"!dist/**/*.map",
|
||||
"!dist/**/*.test.*",
|
||||
"!dist/**/__tests__{,/**/*}",
|
||||
"!scripts/**/*.test.*",
|
||||
"!plugin{,/**/*}",
|
||||
"!vendor/subminer-yomitan{,/**/*}",
|
||||
"!vendor/yomitan-jlpt-vocab{,/**/*}",
|
||||
"!vendor/texthooker-ui/src{,/**/*}",
|
||||
"!vendor/texthooker-ui/node_modules{,/**/*}",
|
||||
"!vendor/texthooker-ui/.svelte-kit{,/**/*}",
|
||||
"!vendor/texthooker-ui/package-lock.json"
|
||||
"!vendor/texthooker-ui/.vscode{,/**/*}",
|
||||
"!vendor/texthooker-ui/public{,/**/*}",
|
||||
"!vendor/texthooker-ui/README.md",
|
||||
"!vendor/texthooker-ui/package.json",
|
||||
"!vendor/texthooker-ui/package-lock.json",
|
||||
"!vendor/texthooker-ui/tsconfig*.json",
|
||||
"!node_modules/@libsql/linux-x64-musl{,/**/*}"
|
||||
],
|
||||
"extraResources": [
|
||||
{
|
||||
|
||||
19
release/release-notes.md
Normal file
19
release/release-notes.md
Normal file
@@ -0,0 +1,19 @@
|
||||
## Highlights
|
||||
### Changed
|
||||
- Release: Reduced packaged release size by excluding duplicate `extraResources` payload and pruning docs, tests, sourcemaps, and other source-only files from Electron bundles.
|
||||
|
||||
### Fixed
|
||||
- Overlay: Restored controller navigation and lookup/mining controls while the subtitle sidebar is open, while keeping true modal dialogs blocking controller actions.
|
||||
- Tokenizer: Fixed subtitle annotation clearing so explanatory contrast endings like `んですけど` are excluded consistently across the shared tokenizer filter and annotation stage.
|
||||
|
||||
## Installation
|
||||
|
||||
See the README and docs/installation guide for full setup steps.
|
||||
|
||||
## Assets
|
||||
|
||||
- Linux: `SubMiner.AppImage`
|
||||
- macOS: `SubMiner-*.dmg` and `SubMiner-*.zip`
|
||||
- Optional extras: `subminer-assets.tar.gz` and the `subminer` launcher
|
||||
|
||||
Note: the `subminer` wrapper script uses Bun (`#!/usr/bin/env bun`), so `bun` must be installed and on `PATH`.
|
||||
@@ -78,6 +78,30 @@ test('release packaging keeps default file inclusion and excludes large source-o
|
||||
assert.ok(files.includes('!release-*{,/**/*}'));
|
||||
assert.ok(files.includes('!vendor/subminer-yomitan{,/**/*}'));
|
||||
assert.ok(files.includes('!vendor/texthooker-ui/src{,/**/*}'));
|
||||
assert.ok(files.includes('!assets{,/**/*}'));
|
||||
assert.ok(files.includes('!plugin{,/**/*}'));
|
||||
assert.ok(files.includes('!vendor/yomitan-jlpt-vocab{,/**/*}'));
|
||||
assert.ok(files.includes('!docs{,/**/*}'));
|
||||
assert.ok(files.includes('!tests{,/**/*}'));
|
||||
assert.ok(files.includes('!packaging{,/**/*}'));
|
||||
assert.ok(files.includes('!README.md'));
|
||||
assert.ok(files.includes('!CHANGELOG.md'));
|
||||
assert.ok(files.includes('!AGENTS.md'));
|
||||
assert.ok(files.includes('!CLAUDE.md'));
|
||||
assert.ok(files.includes('!stats/public{,/**/*}'));
|
||||
assert.ok(files.includes('!stats/package.json'));
|
||||
assert.ok(files.includes('!stats/tsconfig.json'));
|
||||
assert.ok(files.includes('!stats/vite.config.ts'));
|
||||
assert.ok(files.includes('!dist/**/*.map'));
|
||||
assert.ok(files.includes('!dist/**/*.test.*'));
|
||||
assert.ok(files.includes('!dist/**/__tests__{,/**/*}'));
|
||||
assert.ok(files.includes('!scripts/**/*.test.*'));
|
||||
assert.ok(files.includes('!vendor/texthooker-ui/public{,/**/*}'));
|
||||
assert.ok(files.includes('!vendor/texthooker-ui/.vscode{,/**/*}'));
|
||||
assert.ok(files.includes('!vendor/texthooker-ui/README.md'));
|
||||
assert.ok(files.includes('!vendor/texthooker-ui/package.json'));
|
||||
assert.ok(files.includes('!vendor/texthooker-ui/tsconfig*.json'));
|
||||
assert.ok(files.includes('!node_modules/@libsql/linux-x64-musl{,/**/*}'));
|
||||
});
|
||||
|
||||
test('config example generation runs directly from source without unrelated bundle prerequisites', () => {
|
||||
|
||||
36
src/renderer/controller-interaction-blocking.test.ts
Normal file
36
src/renderer/controller-interaction-blocking.test.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import test from 'node:test';
|
||||
|
||||
import { isControllerInteractionBlocked } from './controller-interaction-blocking.js';
|
||||
|
||||
test('subtitle sidebar stays controller-passive while other modals block controller input', () => {
|
||||
assert.equal(
|
||||
isControllerInteractionBlocked({
|
||||
controllerSelectModalOpen: false,
|
||||
controllerDebugModalOpen: false,
|
||||
jimakuModalOpen: false,
|
||||
kikuModalOpen: false,
|
||||
runtimeOptionsModalOpen: false,
|
||||
subsyncModalOpen: false,
|
||||
youtubePickerModalOpen: false,
|
||||
sessionHelpModalOpen: false,
|
||||
subtitleSidebarModalOpen: true,
|
||||
}),
|
||||
false,
|
||||
);
|
||||
|
||||
assert.equal(
|
||||
isControllerInteractionBlocked({
|
||||
controllerSelectModalOpen: false,
|
||||
controllerDebugModalOpen: false,
|
||||
jimakuModalOpen: false,
|
||||
kikuModalOpen: false,
|
||||
runtimeOptionsModalOpen: true,
|
||||
subsyncModalOpen: false,
|
||||
youtubePickerModalOpen: false,
|
||||
sessionHelpModalOpen: false,
|
||||
subtitleSidebarModalOpen: false,
|
||||
}),
|
||||
true,
|
||||
);
|
||||
});
|
||||
24
src/renderer/controller-interaction-blocking.ts
Normal file
24
src/renderer/controller-interaction-blocking.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
type ControllerInteractionModalState = {
|
||||
controllerSelectModalOpen: boolean;
|
||||
controllerDebugModalOpen: boolean;
|
||||
jimakuModalOpen: boolean;
|
||||
kikuModalOpen: boolean;
|
||||
runtimeOptionsModalOpen: boolean;
|
||||
subsyncModalOpen: boolean;
|
||||
youtubePickerModalOpen: boolean;
|
||||
sessionHelpModalOpen: boolean;
|
||||
subtitleSidebarModalOpen: boolean;
|
||||
};
|
||||
|
||||
export function isControllerInteractionBlocked(state: ControllerInteractionModalState): boolean {
|
||||
return (
|
||||
state.controllerSelectModalOpen ||
|
||||
state.controllerDebugModalOpen ||
|
||||
state.jimakuModalOpen ||
|
||||
state.kikuModalOpen ||
|
||||
state.runtimeOptionsModalOpen ||
|
||||
state.subsyncModalOpen ||
|
||||
state.youtubePickerModalOpen ||
|
||||
state.sessionHelpModalOpen
|
||||
);
|
||||
}
|
||||
@@ -35,6 +35,7 @@ import { createJimakuModal } from './modals/jimaku.js';
|
||||
import { createKikuModal } from './modals/kiku.js';
|
||||
import { createSessionHelpModal } from './modals/session-help.js';
|
||||
import { createSubtitleSidebarModal } from './modals/subtitle-sidebar.js';
|
||||
import { isControllerInteractionBlocked } from './controller-interaction-blocking.js';
|
||||
import { createRuntimeOptionsModal } from './modals/runtime-options.js';
|
||||
import { createSubsyncModal } from './modals/subsync.js';
|
||||
import { createYoutubeTrackPickerModal } from './modals/youtube-track-picker.js';
|
||||
@@ -88,6 +89,10 @@ function isAnyModalOpen(): boolean {
|
||||
);
|
||||
}
|
||||
|
||||
function isControllerInputBlocked(): boolean {
|
||||
return isControllerInteractionBlocked(ctx.state);
|
||||
}
|
||||
|
||||
function syncSettingsModalSubtitleSuppression(): void {
|
||||
const suppressSubtitles = isAnySettingsModalOpen();
|
||||
document.body.classList.toggle('settings-modal-open', suppressSubtitles);
|
||||
@@ -323,7 +328,7 @@ function startControllerPolling(): void {
|
||||
},
|
||||
getKeyboardModeEnabled: () => ctx.state.keyboardDrivenModeEnabled,
|
||||
getLookupWindowOpen: () => ctx.state.yomitanPopupVisible || isYomitanPopupVisible(document),
|
||||
getInteractionBlocked: () => isAnyModalOpen(),
|
||||
getInteractionBlocked: () => isControllerInputBlocked(),
|
||||
toggleKeyboardMode: () => keyboardHandlers.handleKeyboardModeToggleRequested(),
|
||||
toggleLookup: () => keyboardHandlers.handleLookupWindowToggleRequested(),
|
||||
closeLookup: () => {
|
||||
|
||||
Reference in New Issue
Block a user