mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-05-28 00:55:16 -07:00
Compare commits
38 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
eff33e2027
|
|||
|
47499eccff
|
|||
|
0b72fa108f
|
|||
|
2b60c20711
|
|||
|
8f43f8825d
|
|||
|
5396b08972
|
|||
|
934a7281b0
|
|||
|
4497d0a39f
|
|||
|
2d1e51e7e1
|
|||
|
c97888f811
|
|||
|
77f5a48f5d
|
|||
|
f2fb9fa1b9
|
|||
|
3284c40ab5
|
|||
|
4bd8fc3db4
|
|||
|
837f21b346
|
|||
|
12e1e783c9
|
|||
|
42576d99b1
|
|||
|
a2fd3cd194
|
|||
|
805b68dd92
|
|||
|
dacae39544
|
|||
|
41b2c7eccf
|
|||
|
9c8784672c
|
|||
|
cb1650d366
|
|||
|
f17255c8e2
|
|||
|
1c1f498f9e
|
|||
|
939a0e650e
|
|||
|
166cdb06ec
|
|||
|
a69e5ecfdf
|
|||
|
d991499dda
|
|||
|
6053a1b6ac
|
|||
|
5cc5df4b18
|
|||
|
d92a2072eb
|
|||
|
2bb7be3552
|
|||
|
0855a7dfcc
|
|||
|
077c852a08
|
|||
|
09e10c18d2
|
|||
|
8b26559203
|
|||
|
b68d17614d
|
@@ -0,0 +1,54 @@
|
||||
---
|
||||
id: TASK-342
|
||||
title: Improve docs homepage indexability
|
||||
status: Done
|
||||
assignee:
|
||||
- codex
|
||||
created_date: '2026-05-11 04:53'
|
||||
updated_date: '2026-05-11 05:06'
|
||||
labels:
|
||||
- docs
|
||||
- seo
|
||||
dependencies: []
|
||||
references:
|
||||
- 'https://docs.subminer.moe/'
|
||||
- >-
|
||||
https://developers.google.com/search/docs/crawling-indexing/consolidate-duplicate-urls
|
||||
priority: medium
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
Google Search Console reports https://docs.subminer.moe/ as Crawled - currently not indexed. Investigate and improve the docs-site homepage and crawl signals so the root docs page has clear unique content, self-consistent canonical metadata, and no avoidable duplicate sitemap entry from VitePress README output. Keep the change scoped to docs-site SEO/content and verify with docs tests/build plus live-style generated HTML inspection.
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
<!-- AC:BEGIN -->
|
||||
- [x] #1 Generated docs HTML for https://docs.subminer.moe/ declares a self-referential canonical URL and does not declare noindex.
|
||||
- [x] #2 Generated sitemap does not advertise a duplicate /README docs page when the docs homepage is the intended canonical root.
|
||||
- [x] #3 Docs tests cover the SEO/indexing signals so canonical and duplicate sitemap regressions are caught.
|
||||
- [x] #4 Docs build/test commands pass or any blocker is documented with exact failure output.
|
||||
<!-- AC:END -->
|
||||
|
||||
## Implementation Plan
|
||||
|
||||
<!-- SECTION:PLAN:BEGIN -->
|
||||
1. Add failing docs-site tests for canonical head generation and sitemap duplicate filtering. 2. Update VitePress config to emit canonical URLs and exclude /README from the sitemap. 3. Strengthen docs homepage content with unique overview/decision-path copy. 4. Run docs tests/build and inspect generated HTML/sitemap.
|
||||
<!-- SECTION:PLAN:END -->
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
<!-- SECTION:NOTES:BEGIN -->
|
||||
2026-05-11: Added docs SEO tests, root canonical generation, sitemap README filtering, and stronger docs homepage orientation copy. Verified generated index.html contains self canonical/no noindex and generated sitemap omits /README.
|
||||
|
||||
2026-05-11: Added changes/342-docs-indexability.md and verified changelog lint. Final verification: bun run --cwd docs-site test, bun run docs:build, bun x prettier --check touched docs/changelog files, bun run changelog:lint.
|
||||
|
||||
2026-05-11: User requested removal of the added homepage orientation block. Removed it, removed the matching content test, and updated the changelog fragment. Generated index.html no longer contains the removed headings while preserving canonical metadata.
|
||||
<!-- SECTION:NOTES:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
Improved docs homepage indexability signals for https://docs.subminer.moe/. Added self-referential canonical generation for VitePress pages and filtered the duplicate /README page out of the generated sitemap. Added docs SEO regression coverage, kept the existing Plausible hostname test aligned with the shared hostname constant, and added a docs changelog fragment. Per follow-up request, the extra homepage orientation copy was removed before handoff. Verification passed: docs tests, docs build, targeted generated HTML/sitemap inspection, Prettier check for touched files, and changelog lint.
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
@@ -0,0 +1,44 @@
|
||||
---
|
||||
id: TASK-343
|
||||
title: Fix macOS character dictionary selector session shortcut
|
||||
status: Done
|
||||
assignee: []
|
||||
created_date: '2026-05-11 08:05'
|
||||
updated_date: '2026-05-11 08:06'
|
||||
labels:
|
||||
- bug
|
||||
- macos
|
||||
- character-dictionary
|
||||
- plugin
|
||||
dependencies: []
|
||||
modified_files:
|
||||
- plugin/subminer/session_bindings.lua
|
||||
- scripts/test-plugin-session-bindings.lua
|
||||
priority: medium
|
||||
ordinal: 181500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
Opening the character dictionary AniList selector from mpv/session shortcuts should work on macOS. Current generated session bindings include the openCharacterDictionary session action, but the Lua plugin CLI dispatch table does not map that action to the app flag, so the shortcut cannot reach the runtime selector.
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
<!-- AC:BEGIN -->
|
||||
- [x] #1 The openCharacterDictionary session action invokes the app with --open-character-dictionary from the mpv plugin.
|
||||
- [x] #2 Regression coverage proves the Lua session-binding CLI map forwards openCharacterDictionary correctly.
|
||||
- [x] #3 Existing session-binding regression coverage still passes.
|
||||
<!-- AC:END -->
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
<!-- SECTION:NOTES:BEGIN -->
|
||||
TDD red: `lua scripts/test-plugin-session-bindings.lua` failed because openCharacterDictionary did not emit --open-character-dictionary. Green after adding the missing Lua CLI mapping.
|
||||
<!-- SECTION:NOTES:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
Fixed the mpv plugin session action mapping so the character dictionary selector shortcut dispatches `--open-character-dictionary` to the app. Added Lua regression coverage for the macOS-style Alt+Meta+A binding and verified adjacent TypeScript session binding tests.
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
@@ -0,0 +1,74 @@
|
||||
---
|
||||
id: TASK-344
|
||||
title: Fix macOS overlay tracker hiding while mpv remains active
|
||||
status: Done
|
||||
assignee:
|
||||
- codex
|
||||
created_date: '2026-05-11 08:27'
|
||||
updated_date: '2026-05-11 08:41'
|
||||
labels:
|
||||
- bug
|
||||
- macos
|
||||
- overlay
|
||||
dependencies: []
|
||||
references:
|
||||
- src/main/runtime/overlay-visibility-runtime.ts
|
||||
- src/window-trackers
|
||||
modified_files:
|
||||
- src/core/services/overlay-visibility.ts
|
||||
- src/core/services/overlay-visibility.test.ts
|
||||
- changes/344-macos-overlay-active-mpv.md
|
||||
priority: high
|
||||
ordinal: 182500
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
macOS playback overlay should match Windows behavior: the tracker may only hide or alter overlay layering when mpv is no longer the active playback window. When mpv remains topmost or fullscreen, the visible overlay must stay present and interactive unless the user manually hides it or minimizes mpv.
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
<!-- AC:BEGIN -->
|
||||
- [x] #1 With mpv active on macOS, window-tracker updates do not hide the visible overlay or make it click-through.
|
||||
- [x] #2 With mpv fullscreen on macOS, tracker geometry/layering refreshes preserve overlay interactivity.
|
||||
- [x] #3 Overlay visibility still changes when mpv is no longer active, and manual hide/minimize behavior remains intact.
|
||||
- [x] #4 A regression test covers the macOS active-mpv path that previously produced an overlay loading OSD and non-interactive overlay.
|
||||
<!-- AC:END -->
|
||||
|
||||
## Implementation Plan
|
||||
|
||||
<!-- SECTION:PLAN:BEGIN -->
|
||||
1. Add a focused regression in `src/core/services/overlay-visibility.test.ts` for macOS with mpv tracked/focused and retained geometry: visibility refresh must not hide the overlay, must not emit loading OSD, and must leave the overlay interactive (`setIgnoreMouseEvents(false)`) unless forced passthrough is active.
|
||||
2. Update `src/core/services/overlay-visibility.ts` so macOS tracker refreshes preserve the visible overlay while mpv is active/fullscreen, and only hide/re-layer for explicit manual hide, minimized/untracked target, or non-active mpv cases.
|
||||
3. Run the focused overlay visibility tests, then a broader fast gate if the focused fix is green.
|
||||
<!-- SECTION:PLAN:END -->
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
<!-- SECTION:NOTES:BEGIN -->
|
||||
Implemented in the shared overlay visibility service. macOS now keeps tracked/focused mpv overlays interactive instead of defaulting to mouse passthrough, and preserves an already visible active-mpv overlay during temporary tracker-not-ready refreshes without showing the loading OSD. Forced passthrough, modal hide, manual hide, Windows minimized handling, and initial macOS tracker-not-ready startup behavior remain covered by tests.
|
||||
|
||||
Verification: `bun test src/core/services/overlay-visibility.test.ts` passed; affected overlay/mouse/runtime group passed; `bun run typecheck`, `bun run changelog:lint`, `bun run build`, `bun run test:env`, and `bun run test:smoke:dist` passed. `bun run test:fast` is blocked by existing cross-file test pollution: `src/core/services/subsync.test.ts` passes alone, but fails when run after `src/renderer/handlers/keyboard.test.ts` because `window.electronAPI` is undefined in a lingering keyboard handler; Bun then reports nested node:test errors for later files. `bun run format:check:src` is blocked by pre-existing formatting drift in `src/core/services/stats-window.ts`; touched files pass direct Prettier check.
|
||||
<!-- SECTION:NOTES:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
Summary:
|
||||
- Updated macOS overlay visibility logic so a tracked/focused mpv window keeps the visible overlay interactive instead of click-through.
|
||||
- Preserved an already visible active-mpv overlay during temporary macOS tracker-not-ready refreshes, avoiding the loading OSD/hide path for that active playback case.
|
||||
- Added regression coverage for active mpv tracker refreshes and transient tracker-not-ready refreshes, plus updated old macOS expectations to the new active-mpv contract.
|
||||
- Added a changelog fragment for the user-visible overlay fix.
|
||||
|
||||
Verification:
|
||||
- Passed: `bun test src/core/services/overlay-visibility.test.ts`
|
||||
- Passed: `bun test src/core/services/overlay-visibility.test.ts src/core/services/overlay-runtime-init.test.ts src/core/services/overlay-shortcut-handler.test.ts src/renderer/handlers/mouse.test.ts`
|
||||
- Passed: `bun run typecheck`
|
||||
- Passed: `bun run changelog:lint`
|
||||
- Passed: `bun run build`
|
||||
- Passed: `bun run test:env`
|
||||
- Passed: `bun run test:smoke:dist`
|
||||
- Blocked: `bun run test:fast` by existing keyboard/subsync cross-file global pollution; isolated `bun test src/core/services/subsync.test.ts` passes.
|
||||
- Blocked: `bun run format:check:src` by pre-existing formatting drift in `src/core/services/stats-window.ts`; touched files pass direct Prettier check.
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
@@ -0,0 +1,4 @@
|
||||
type: docs
|
||||
area: docs
|
||||
|
||||
- Improved the docs homepage indexing signals with canonical URLs and a cleaner sitemap.
|
||||
@@ -0,0 +1,4 @@
|
||||
type: fixed
|
||||
area: overlay
|
||||
|
||||
- Overlay: Kept the macOS overlay visible and interactive while mpv remains the active tracked window, including transient tracker refreshes.
|
||||
@@ -1,3 +1,15 @@
|
||||
const DOCS_HOSTNAME = 'https://docs.subminer.moe';
|
||||
|
||||
function pageToCanonicalHref(page: string): string | null {
|
||||
if (page === '404.md') return null;
|
||||
|
||||
const route = page
|
||||
.replace(/(^|\/)index\.md$/, '')
|
||||
.replace(/\.md$/, '')
|
||||
.replace(/\/$/, '');
|
||||
return route ? `${DOCS_HOSTNAME}/${route}` : `${DOCS_HOSTNAME}/`;
|
||||
}
|
||||
|
||||
export default {
|
||||
title: 'SubMiner Docs',
|
||||
description:
|
||||
@@ -34,7 +46,18 @@ export default {
|
||||
appearance: 'dark',
|
||||
cleanUrls: true,
|
||||
metaChunk: true,
|
||||
sitemap: { hostname: 'https://docs.subminer.moe' },
|
||||
sitemap: {
|
||||
hostname: DOCS_HOSTNAME,
|
||||
transformItems(items) {
|
||||
return items.filter(
|
||||
(item) => item.url !== 'README' && item.url !== `${DOCS_HOSTNAME}/README`,
|
||||
);
|
||||
},
|
||||
},
|
||||
transformHead({ page }) {
|
||||
const href = pageToCanonicalHref(page);
|
||||
return href ? [['link', { rel: 'canonical', href }]] : [];
|
||||
},
|
||||
lastUpdated: true,
|
||||
srcExclude: ['subagents/**'],
|
||||
markdown: {
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
"docs:dev": "VITE_EXTRA_EXTENSIONS=jsonc vitepress dev --host 0.0.0.0 --port 5173 --strictPort",
|
||||
"docs:build": "VITE_EXTRA_EXTENSIONS=jsonc vitepress build",
|
||||
"docs:preview": "VITE_EXTRA_EXTENSIONS=jsonc vitepress preview --host 0.0.0.0 --port 4173 --strictPort",
|
||||
"test": "bun test plausible.test.ts index.assets.test.ts docs-sync.test.ts"
|
||||
"test": "bun test plausible.test.ts index.assets.test.ts docs-sync.test.ts seo.test.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"@catppuccin/vitepress": "^0.1.2",
|
||||
|
||||
@@ -7,7 +7,8 @@ const docsConfigContents = readFileSync(docsConfigPath, 'utf8');
|
||||
const docsThemeContents = readFileSync(docsThemePath, 'utf8');
|
||||
|
||||
test('docs site keeps docs hostname while sending plausible events to subminer.moe via worker.subminer.moe capture endpoint', () => {
|
||||
expect(docsConfigContents).toContain("hostname: 'https://docs.subminer.moe'");
|
||||
expect(docsConfigContents).toContain("const DOCS_HOSTNAME = 'https://docs.subminer.moe'");
|
||||
expect(docsConfigContents).toContain('hostname: DOCS_HOSTNAME');
|
||||
expect(docsThemeContents).toContain("const PLAUSIBLE_DOMAIN = 'subminer.moe'");
|
||||
expect(docsThemeContents).toContain('const PLAUSIBLE_ENABLED_HOSTNAMES = new Set([');
|
||||
expect(docsThemeContents).toContain("'docs.subminer.moe'");
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
import { expect, test } from 'bun:test';
|
||||
import type { TransformContext } from 'vitepress';
|
||||
import docsConfig from './.vitepress/config';
|
||||
|
||||
function makeTransformContext(page: string): TransformContext {
|
||||
return {
|
||||
page,
|
||||
siteConfig: {} as TransformContext['siteConfig'],
|
||||
siteData: {} as TransformContext['siteData'],
|
||||
pageData: {} as TransformContext['pageData'],
|
||||
title: 'SubMiner',
|
||||
description: 'SubMiner docs',
|
||||
head: [],
|
||||
content: '',
|
||||
assets: [],
|
||||
};
|
||||
}
|
||||
|
||||
test('docs pages emit stable self-referential canonical URLs', async () => {
|
||||
const rootHead = await docsConfig.transformHead?.(makeTransformContext('index.md'));
|
||||
const usageHead = await docsConfig.transformHead?.(makeTransformContext('usage.md'));
|
||||
|
||||
expect(rootHead).toContainEqual([
|
||||
'link',
|
||||
{ rel: 'canonical', href: 'https://docs.subminer.moe/' },
|
||||
]);
|
||||
expect(usageHead).toContainEqual([
|
||||
'link',
|
||||
{ rel: 'canonical', href: 'https://docs.subminer.moe/usage' },
|
||||
]);
|
||||
expect(JSON.stringify(rootHead).toLowerCase()).not.toContain('noindex');
|
||||
});
|
||||
|
||||
test('docs sitemap excludes duplicate README page from indexable URLs', async () => {
|
||||
const items = [{ url: '' }, { url: 'README' }, { url: 'usage' }];
|
||||
|
||||
const transformedItems = await docsConfig.sitemap?.transformItems?.(items);
|
||||
|
||||
expect(transformedItems?.map((item) => item.url)).toEqual(['', 'usage']);
|
||||
});
|
||||
@@ -159,6 +159,8 @@ function M.create(ctx)
|
||||
return { "--open-youtube-picker" }
|
||||
elseif action_id == "openSessionHelp" then
|
||||
return { "--open-session-help" }
|
||||
elseif action_id == "openCharacterDictionary" then
|
||||
return { "--open-character-dictionary" }
|
||||
elseif action_id == "openControllerSelect" then
|
||||
return { "--open-controller-select" }
|
||||
elseif action_id == "openControllerDebug" then
|
||||
|
||||
@@ -79,6 +79,14 @@ local ctx = {
|
||||
actionType = "session-action",
|
||||
actionId = "playNextSubtitle",
|
||||
},
|
||||
{
|
||||
key = {
|
||||
code = "KeyA",
|
||||
modifiers = { "alt", "meta" },
|
||||
},
|
||||
actionType = "session-action",
|
||||
actionId = "openCharacterDictionary",
|
||||
},
|
||||
{
|
||||
key = {
|
||||
code = "KeyL",
|
||||
@@ -153,6 +161,23 @@ local play_next_call = recorded.async_calls[#recorded.async_calls]
|
||||
assert_true(play_next_call ~= nil, "play-next binding should invoke CLI action")
|
||||
assert_true(play_next_call[2] == "--play-next-subtitle", "play-next binding should pass CLI flag")
|
||||
|
||||
local character_dictionary = nil
|
||||
for _, binding in ipairs(recorded.bindings) do
|
||||
if binding.keys == "Alt+Meta+a" then
|
||||
character_dictionary = binding
|
||||
break
|
||||
end
|
||||
end
|
||||
assert_true(character_dictionary ~= nil, "character dictionary binding should be registered")
|
||||
|
||||
character_dictionary.fn()
|
||||
local character_dictionary_call = recorded.async_calls[#recorded.async_calls]
|
||||
assert_true(character_dictionary_call ~= nil, "character dictionary binding should invoke CLI action")
|
||||
assert_true(
|
||||
character_dictionary_call[2] == "--open-character-dictionary",
|
||||
"character dictionary binding should pass CLI flag"
|
||||
)
|
||||
|
||||
starter.fn()
|
||||
|
||||
local modified_digit = nil
|
||||
|
||||
@@ -883,7 +883,7 @@ test('visible overlay stays hidden while a modal window is active', () => {
|
||||
assert.ok(!calls.includes('update-bounds'));
|
||||
});
|
||||
|
||||
test('macOS tracked visible overlay stays click-through without passively stealing focus', () => {
|
||||
test('macOS tracked visible overlay stays interactive without passively stealing focus', () => {
|
||||
const { window, calls } = createMainWindowRecorder();
|
||||
const tracker: WindowTrackerStub = {
|
||||
isTracking: () => true,
|
||||
@@ -915,11 +915,113 @@ test('macOS tracked visible overlay stays click-through without passively steali
|
||||
isWindowsPlatform: false,
|
||||
} as never);
|
||||
|
||||
assert.ok(calls.includes('mouse-ignore:true:forward'));
|
||||
assert.ok(calls.includes('mouse-ignore:false:plain'));
|
||||
assert.ok(calls.includes('show'));
|
||||
assert.ok(!calls.includes('focus'));
|
||||
});
|
||||
|
||||
test('macOS keeps active mpv overlay visible and interactive during tracker refresh', () => {
|
||||
const { window, calls } = createMainWindowRecorder();
|
||||
const osdMessages: string[] = [];
|
||||
const tracker: WindowTrackerStub = {
|
||||
isTracking: () => true,
|
||||
getGeometry: () => ({ x: 0, y: 0, width: 1280, height: 720 }),
|
||||
isTargetWindowFocused: () => true,
|
||||
};
|
||||
|
||||
updateVisibleOverlayVisibility({
|
||||
visibleOverlayVisible: true,
|
||||
mainWindow: window as never,
|
||||
windowTracker: tracker as never,
|
||||
trackerNotReadyWarningShown: false,
|
||||
setTrackerNotReadyWarningShown: () => {
|
||||
calls.push('tracker-warning');
|
||||
},
|
||||
updateVisibleOverlayBounds: () => {
|
||||
calls.push('update-bounds');
|
||||
},
|
||||
ensureOverlayWindowLevel: () => {
|
||||
calls.push('ensure-level');
|
||||
},
|
||||
syncPrimaryOverlayWindowLayer: () => {
|
||||
calls.push('sync-layer');
|
||||
},
|
||||
enforceOverlayLayerOrder: () => {
|
||||
calls.push('enforce-order');
|
||||
},
|
||||
syncOverlayShortcuts: () => {
|
||||
calls.push('sync-shortcuts');
|
||||
},
|
||||
isMacOSPlatform: true,
|
||||
isWindowsPlatform: false,
|
||||
showOverlayLoadingOsd: (message: string) => {
|
||||
osdMessages.push(message);
|
||||
},
|
||||
} as never);
|
||||
|
||||
assert.ok(calls.includes('update-bounds'));
|
||||
assert.ok(calls.includes('sync-layer'));
|
||||
assert.ok(calls.includes('mouse-ignore:false:plain'));
|
||||
assert.ok(calls.includes('ensure-level'));
|
||||
assert.ok(calls.includes('enforce-order'));
|
||||
assert.ok(calls.includes('sync-shortcuts'));
|
||||
assert.ok(!calls.includes('hide'));
|
||||
assert.deepEqual(osdMessages, []);
|
||||
});
|
||||
|
||||
test('macOS preserves an already visible active mpv overlay while tracker is temporarily not ready', () => {
|
||||
const { window, calls } = createMainWindowRecorder();
|
||||
const osdMessages: string[] = [];
|
||||
let trackerWarning = false;
|
||||
const tracker: WindowTrackerStub = {
|
||||
isTracking: () => false,
|
||||
getGeometry: () => null,
|
||||
isTargetWindowFocused: () => true,
|
||||
};
|
||||
|
||||
window.show();
|
||||
calls.length = 0;
|
||||
|
||||
updateVisibleOverlayVisibility({
|
||||
visibleOverlayVisible: true,
|
||||
mainWindow: window as never,
|
||||
windowTracker: tracker as never,
|
||||
trackerNotReadyWarningShown: trackerWarning,
|
||||
setTrackerNotReadyWarningShown: (shown: boolean) => {
|
||||
trackerWarning = shown;
|
||||
calls.push(`tracker-warning:${shown}`);
|
||||
},
|
||||
updateVisibleOverlayBounds: () => {
|
||||
calls.push('update-bounds');
|
||||
},
|
||||
ensureOverlayWindowLevel: () => {
|
||||
calls.push('ensure-level');
|
||||
},
|
||||
syncPrimaryOverlayWindowLayer: () => {
|
||||
calls.push('sync-layer');
|
||||
},
|
||||
enforceOverlayLayerOrder: () => {
|
||||
calls.push('enforce-order');
|
||||
},
|
||||
syncOverlayShortcuts: () => {
|
||||
calls.push('sync-shortcuts');
|
||||
},
|
||||
isMacOSPlatform: true,
|
||||
isWindowsPlatform: false,
|
||||
showOverlayLoadingOsd: (message: string) => {
|
||||
osdMessages.push(message);
|
||||
},
|
||||
} as never);
|
||||
|
||||
assert.equal(trackerWarning, false);
|
||||
assert.ok(calls.includes('sync-layer'));
|
||||
assert.ok(calls.includes('mouse-ignore:false:plain'));
|
||||
assert.ok(calls.includes('ensure-level'));
|
||||
assert.ok(calls.includes('sync-shortcuts'));
|
||||
assert.ok(!calls.includes('hide'));
|
||||
assert.deepEqual(osdMessages, []);
|
||||
});
|
||||
|
||||
test('forced mouse passthrough keeps macOS tracked overlay passive while visible', () => {
|
||||
const { window, calls } = createMainWindowRecorder();
|
||||
const tracker: WindowTrackerStub = {
|
||||
@@ -1243,7 +1345,7 @@ test('macOS preserves visible overlay during transient tracker loss with retaine
|
||||
assert.deepEqual(osdMessages, []);
|
||||
assert.ok(calls.includes('update-bounds'));
|
||||
assert.ok(calls.includes('sync-layer'));
|
||||
assert.ok(calls.includes('mouse-ignore:true:forward'));
|
||||
assert.ok(calls.includes('mouse-ignore:false:plain'));
|
||||
assert.ok(calls.includes('ensure-level'));
|
||||
assert.ok(calls.includes('enforce-order'));
|
||||
assert.ok(calls.includes('sync-shortcuts'));
|
||||
|
||||
@@ -92,10 +92,14 @@ export function updateVisibleOverlayVisibility(args: {
|
||||
const showPassiveVisibleOverlay = (): void => {
|
||||
const forceMousePassthrough = args.forceMousePassthrough === true;
|
||||
const wasVisible = mainWindow.isVisible();
|
||||
const shouldDefaultToPassthrough =
|
||||
args.isMacOSPlatform || args.isWindowsPlatform || forceMousePassthrough;
|
||||
const isVisibleOverlayFocused =
|
||||
typeof mainWindow.isFocused === 'function' && mainWindow.isFocused();
|
||||
const shouldDefaultToPassthrough =
|
||||
args.isWindowsPlatform ||
|
||||
forceMousePassthrough ||
|
||||
(args.isMacOSPlatform &&
|
||||
!isVisibleOverlayFocused &&
|
||||
!(args.windowTracker?.isTargetWindowFocused?.() ?? true));
|
||||
const windowsForegroundProcessName =
|
||||
args.lastKnownWindowsForegroundProcessName?.trim().toLowerCase() ?? null;
|
||||
const windowsOverlayProcessName = args.windowsOverlayProcessName?.trim().toLowerCase() ?? null;
|
||||
@@ -261,8 +265,11 @@ export function updateVisibleOverlayVisibility(args: {
|
||||
}
|
||||
|
||||
const hasRetainedTrackedGeometry = args.windowTracker.getGeometry() !== null;
|
||||
const hasActiveMacOSTargetSignal =
|
||||
args.isMacOSPlatform && (args.windowTracker.isTargetWindowFocused?.() ?? false);
|
||||
const shouldPreserveTransientTrackedOverlay =
|
||||
(args.isMacOSPlatform && hasRetainedTrackedGeometry) ||
|
||||
(args.isMacOSPlatform &&
|
||||
(hasRetainedTrackedGeometry || (mainWindow.isVisible() && hasActiveMacOSTargetSignal))) ||
|
||||
(args.isWindowsPlatform &&
|
||||
typeof args.windowTracker.isTargetWindowMinimized === 'function' &&
|
||||
!args.windowTracker.isTargetWindowMinimized());
|
||||
|
||||
Reference in New Issue
Block a user