mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-04-26 04:19:27 -07:00
feat: open session help from tray
This commit is contained in:
57
backlog/tasks/task-303 - Update-tray-menu-help-action.md
Normal file
57
backlog/tasks/task-303 - Update-tray-menu-help-action.md
Normal file
@@ -0,0 +1,57 @@
|
||||
---
|
||||
id: TASK-303
|
||||
title: Update tray menu help action
|
||||
status: Done
|
||||
assignee:
|
||||
- Codex
|
||||
created_date: '2026-04-26 03:54'
|
||||
updated_date: '2026-04-26 04:12'
|
||||
labels:
|
||||
- tray
|
||||
- overlay
|
||||
dependencies: []
|
||||
priority: medium
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
Replace the tray menu's direct visible-overlay open action with an action that opens the existing in-session help modal. The tray should no longer expose an "Open Overlay" menu item; users should be able to open help from the tray instead.
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
<!-- AC:BEGIN -->
|
||||
- [x] #1 Tray menu no longer includes an "Open Overlay" option.
|
||||
- [x] #2 Tray menu includes an option to open the session help modal.
|
||||
- [x] #3 Selecting the new tray help option initializes overlay runtime if needed and invokes the existing session help modal path.
|
||||
- [x] #4 Focused regression tests cover the menu label and action wiring.
|
||||
<!-- AC:END -->
|
||||
|
||||
## Implementation Plan
|
||||
|
||||
<!-- SECTION:PLAN:BEGIN -->
|
||||
1. Add focused regression coverage for tray menu template labels and main-process action wiring: assert Open Overlay is absent, Open Help is present, and clicking help initializes overlay runtime if needed before opening the existing session help modal path.
|
||||
2. Update tray runtime action types/template to replace openOverlay with openSessionHelp.
|
||||
3. Update tray main action builder dependencies to call the existing openSessionHelpModal function after overlay runtime initialization.
|
||||
4. Run targeted tray tests, then broader relevant fast tests if needed.
|
||||
5. Check acceptance criteria and finalize backlog notes.
|
||||
<!-- SECTION:PLAN:END -->
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
<!-- SECTION:NOTES:BEGIN -->
|
||||
Implemented tray menu replacement via existing session help overlay path. Verification passed: targeted tray tests (`bun test src/main/runtime/tray-runtime.test.ts src/main/runtime/tray-main-actions.test.ts src/main/runtime/tray-main-deps.test.ts src/main/runtime/tray-runtime-handlers.test.ts`), SubMiner verifier lanes `runtime-compat` and `docs`, and `bun run changelog:lint`.
|
||||
<!-- SECTION:NOTES:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
Replaced the tray menu's `Open Overlay` item with `Open Help`, wired it to initialize overlay runtime when needed, and then open the existing session help modal path. Updated tray runtime/main-deps/action tests to assert the old label is absent, the new label is present, and the new action calls the help modal. Added changelog fragment `changes/303-tray-help-menu.md`.
|
||||
|
||||
Verification:
|
||||
- `bun test src/main/runtime/tray-runtime.test.ts src/main/runtime/tray-main-actions.test.ts src/main/runtime/tray-main-deps.test.ts src/main/runtime/tray-runtime-handlers.test.ts`
|
||||
- `bash plugins/subminer-workflow/skills/subminer-change-verification/scripts/verify_subminer_change.sh --lane runtime-compat --lane docs src/main/runtime/tray-runtime.ts src/main/runtime/tray-main-actions.ts src/main/runtime/tray-main-deps.ts src/main.ts changes/303-tray-help-menu.md`
|
||||
- `bun run changelog:lint`
|
||||
|
||||
Verifier artifacts: `.tmp/skill-verification/subminer-verify-20260425-211156-9fkdDf/`.
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
4
changes/303-tray-help-menu.md
Normal file
4
changes/303-tray-help-menu.md
Normal file
@@ -0,0 +1,4 @@
|
||||
type: changed
|
||||
area: tray
|
||||
|
||||
- Tray: Replaced the Open Overlay tray menu item with Open Help, which opens the session help modal.
|
||||
@@ -5139,7 +5139,7 @@ const { ensureTray: ensureTrayHandler, destroyTray: destroyTrayHandler } =
|
||||
buildTrayMenuTemplateRuntime,
|
||||
initializeOverlayRuntime: () => initializeOverlayRuntime(),
|
||||
isOverlayRuntimeInitialized: () => appState.overlayRuntimeInitialized,
|
||||
setVisibleOverlayVisible: (visible) => setVisibleOverlayVisible(visible),
|
||||
openSessionHelpModal: () => openSessionHelpOverlay(),
|
||||
showFirstRunSetup: () => !firstRunSetupService.isSetupCompleted(),
|
||||
openFirstRunSetupWindow: () => openFirstRunSetupWindow(),
|
||||
showWindowsMpvLauncherSetup: () => process.platform === 'win32',
|
||||
|
||||
@@ -41,7 +41,7 @@ test('build tray template handler wires actions and init guards', () => {
|
||||
let initialized = false;
|
||||
const buildTemplate = createBuildTrayMenuTemplateHandler({
|
||||
buildTrayMenuTemplateRuntime: (handlers) => {
|
||||
handlers.openOverlay();
|
||||
handlers.openSessionHelp();
|
||||
handlers.openFirstRunSetup();
|
||||
handlers.openWindowsMpvLauncherSetup();
|
||||
handlers.openYomitanSettings();
|
||||
@@ -56,7 +56,7 @@ test('build tray template handler wires actions and init guards', () => {
|
||||
calls.push('init');
|
||||
},
|
||||
isOverlayRuntimeInitialized: () => initialized,
|
||||
setVisibleOverlayVisible: (visible) => calls.push(`visible:${visible}`),
|
||||
openSessionHelpModal: () => calls.push('help'),
|
||||
showFirstRunSetup: () => true,
|
||||
openFirstRunSetupWindow: () => calls.push('setup'),
|
||||
showWindowsMpvLauncherSetup: () => true,
|
||||
@@ -71,7 +71,7 @@ test('build tray template handler wires actions and init guards', () => {
|
||||
assert.deepEqual(template, [{ label: 'ok' }]);
|
||||
assert.deepEqual(calls, [
|
||||
'init',
|
||||
'visible:true',
|
||||
'help',
|
||||
'setup',
|
||||
'setup',
|
||||
'yomitan',
|
||||
|
||||
@@ -28,7 +28,7 @@ export function createResolveTrayIconPathHandler(deps: {
|
||||
|
||||
export function createBuildTrayMenuTemplateHandler<TMenuItem>(deps: {
|
||||
buildTrayMenuTemplateRuntime: (handlers: {
|
||||
openOverlay: () => void;
|
||||
openSessionHelp: () => void;
|
||||
openFirstRunSetup: () => void;
|
||||
showFirstRunSetup: boolean;
|
||||
openWindowsMpvLauncherSetup: () => void;
|
||||
@@ -41,7 +41,7 @@ export function createBuildTrayMenuTemplateHandler<TMenuItem>(deps: {
|
||||
}) => TMenuItem[];
|
||||
initializeOverlayRuntime: () => void;
|
||||
isOverlayRuntimeInitialized: () => boolean;
|
||||
setVisibleOverlayVisible: (visible: boolean) => void;
|
||||
openSessionHelpModal: () => void;
|
||||
showFirstRunSetup: () => boolean;
|
||||
openFirstRunSetupWindow: () => void;
|
||||
showWindowsMpvLauncherSetup: () => boolean;
|
||||
@@ -53,11 +53,11 @@ export function createBuildTrayMenuTemplateHandler<TMenuItem>(deps: {
|
||||
}) {
|
||||
return (): TMenuItem[] => {
|
||||
return deps.buildTrayMenuTemplateRuntime({
|
||||
openOverlay: () => {
|
||||
openSessionHelp: () => {
|
||||
if (!deps.isOverlayRuntimeInitialized()) {
|
||||
deps.initializeOverlayRuntime();
|
||||
}
|
||||
deps.setVisibleOverlayVisible(true);
|
||||
deps.openSessionHelpModal();
|
||||
},
|
||||
openFirstRunSetup: () => {
|
||||
deps.openFirstRunSetupWindow();
|
||||
|
||||
@@ -24,7 +24,7 @@ test('tray main deps builders return mapped handlers', () => {
|
||||
buildTrayMenuTemplateRuntime: () => [{ label: 'tray' }] as never,
|
||||
initializeOverlayRuntime: () => calls.push('init'),
|
||||
isOverlayRuntimeInitialized: () => false,
|
||||
setVisibleOverlayVisible: (visible) => calls.push(`visible:${visible}`),
|
||||
openSessionHelpModal: () => calls.push('help'),
|
||||
showFirstRunSetup: () => true,
|
||||
openFirstRunSetupWindow: () => calls.push('setup'),
|
||||
showWindowsMpvLauncherSetup: () => true,
|
||||
@@ -36,7 +36,7 @@ test('tray main deps builders return mapped handlers', () => {
|
||||
})();
|
||||
|
||||
const template = menuDeps.buildTrayMenuTemplateRuntime({
|
||||
openOverlay: () => calls.push('open-overlay'),
|
||||
openSessionHelp: () => calls.push('open-help'),
|
||||
openFirstRunSetup: () => calls.push('open-setup'),
|
||||
showFirstRunSetup: true,
|
||||
openWindowsMpvLauncherSetup: () => calls.push('open-windows-mpv'),
|
||||
|
||||
@@ -27,7 +27,7 @@ export function createBuildResolveTrayIconPathMainDepsHandler(deps: {
|
||||
|
||||
export function createBuildTrayMenuTemplateMainDepsHandler<TMenuItem>(deps: {
|
||||
buildTrayMenuTemplateRuntime: (handlers: {
|
||||
openOverlay: () => void;
|
||||
openSessionHelp: () => void;
|
||||
openFirstRunSetup: () => void;
|
||||
showFirstRunSetup: boolean;
|
||||
openWindowsMpvLauncherSetup: () => void;
|
||||
@@ -40,7 +40,7 @@ export function createBuildTrayMenuTemplateMainDepsHandler<TMenuItem>(deps: {
|
||||
}) => TMenuItem[];
|
||||
initializeOverlayRuntime: () => void;
|
||||
isOverlayRuntimeInitialized: () => boolean;
|
||||
setVisibleOverlayVisible: (visible: boolean) => void;
|
||||
openSessionHelpModal: () => void;
|
||||
showFirstRunSetup: () => boolean;
|
||||
openFirstRunSetupWindow: () => void;
|
||||
showWindowsMpvLauncherSetup: () => boolean;
|
||||
@@ -54,7 +54,7 @@ export function createBuildTrayMenuTemplateMainDepsHandler<TMenuItem>(deps: {
|
||||
buildTrayMenuTemplateRuntime: deps.buildTrayMenuTemplateRuntime,
|
||||
initializeOverlayRuntime: deps.initializeOverlayRuntime,
|
||||
isOverlayRuntimeInitialized: deps.isOverlayRuntimeInitialized,
|
||||
setVisibleOverlayVisible: deps.setVisibleOverlayVisible,
|
||||
openSessionHelpModal: deps.openSessionHelpModal,
|
||||
showFirstRunSetup: deps.showFirstRunSetup,
|
||||
openFirstRunSetupWindow: deps.openFirstRunSetupWindow,
|
||||
showWindowsMpvLauncherSetup: deps.showWindowsMpvLauncherSetup,
|
||||
|
||||
@@ -19,14 +19,12 @@ test('tray runtime handlers compose resolve/menu/ensure/destroy handlers', () =>
|
||||
fileExists: () => true,
|
||||
},
|
||||
buildTrayMenuTemplateDeps: {
|
||||
buildTrayMenuTemplateRuntime: () => [{ label: 'Open Overlay' }],
|
||||
buildTrayMenuTemplateRuntime: () => [{ label: 'Open Help' }],
|
||||
initializeOverlayRuntime: () => {
|
||||
overlayInitialized = true;
|
||||
},
|
||||
isOverlayRuntimeInitialized: () => overlayInitialized,
|
||||
setVisibleOverlayVisible: (visible) => {
|
||||
visibleOverlay = visible;
|
||||
},
|
||||
openSessionHelpModal: () => {},
|
||||
showFirstRunSetup: () => true,
|
||||
openFirstRunSetupWindow: () => {},
|
||||
showWindowsMpvLauncherSetup: () => true,
|
||||
@@ -88,7 +86,7 @@ test('tray runtime handlers compose resolve/menu/ensure/destroy handlers', () =>
|
||||
});
|
||||
|
||||
assert.equal(runtime.resolveTrayIconPath(), '/tmp/SubMiner.png');
|
||||
assert.deepEqual(runtime.buildTrayMenu(), { template: [{ label: 'Open Overlay' }] });
|
||||
assert.deepEqual(runtime.buildTrayMenu(), { template: [{ label: 'Open Help' }] });
|
||||
runtime.ensureTray();
|
||||
assert.equal(overlayInitialized, true);
|
||||
assert.equal(visibleOverlay, true);
|
||||
|
||||
@@ -29,7 +29,7 @@ test('resolve tray icon returns null when no asset exists', () => {
|
||||
test('tray menu template contains expected entries and handlers', () => {
|
||||
const calls: string[] = [];
|
||||
const template = buildTrayMenuTemplateRuntime({
|
||||
openOverlay: () => calls.push('overlay'),
|
||||
openSessionHelp: () => calls.push('help'),
|
||||
openFirstRunSetup: () => calls.push('setup'),
|
||||
showFirstRunSetup: true,
|
||||
openWindowsMpvLauncherSetup: () => calls.push('windows-mpv'),
|
||||
@@ -42,15 +42,17 @@ test('tray menu template contains expected entries and handlers', () => {
|
||||
});
|
||||
|
||||
assert.equal(template.length, 9);
|
||||
assert.equal(template.some((entry) => entry.label === 'Open Overlay'), false);
|
||||
assert.equal(template[0]!.label, 'Open Help');
|
||||
template[0]!.click?.();
|
||||
template[7]!.type === 'separator' ? calls.push('separator') : calls.push('bad');
|
||||
template[8]!.click?.();
|
||||
assert.deepEqual(calls, ['overlay', 'separator', 'quit']);
|
||||
assert.deepEqual(calls, ['help', 'separator', 'quit']);
|
||||
});
|
||||
|
||||
test('tray menu template omits first-run setup entry when setup is complete', () => {
|
||||
const labels = buildTrayMenuTemplateRuntime({
|
||||
openOverlay: () => undefined,
|
||||
openSessionHelp: () => undefined,
|
||||
openFirstRunSetup: () => undefined,
|
||||
showFirstRunSetup: false,
|
||||
openWindowsMpvLauncherSetup: () => undefined,
|
||||
|
||||
@@ -30,7 +30,7 @@ export function resolveTrayIconPathRuntime(deps: {
|
||||
}
|
||||
|
||||
export type TrayMenuActionHandlers = {
|
||||
openOverlay: () => void;
|
||||
openSessionHelp: () => void;
|
||||
openFirstRunSetup: () => void;
|
||||
showFirstRunSetup: boolean;
|
||||
openWindowsMpvLauncherSetup: () => void;
|
||||
@@ -49,8 +49,8 @@ export function buildTrayMenuTemplateRuntime(handlers: TrayMenuActionHandlers):
|
||||
}> {
|
||||
return [
|
||||
{
|
||||
label: 'Open Overlay',
|
||||
click: handlers.openOverlay,
|
||||
label: 'Open Help',
|
||||
click: handlers.openSessionHelp,
|
||||
},
|
||||
...(handlers.showFirstRunSetup
|
||||
? [
|
||||
|
||||
Reference in New Issue
Block a user