fix(stage-tamagotchi): harden caption overlay follow+mouse handling (#1402)
This commit is contained in:
@@ -194,9 +194,12 @@ export function setupCaptionWindowManager(params: {
|
||||
const settleTo = (toX: number, toY: number) => {
|
||||
if (win.isDestroyed())
|
||||
return
|
||||
if (!Number.isFinite(toX) || !Number.isFinite(toY))
|
||||
return
|
||||
|
||||
const b = win.getBounds()
|
||||
state.x = b.x
|
||||
state.y = b.y
|
||||
state.x = Number.isFinite(b.x) ? b.x : 0
|
||||
state.y = Number.isFinite(b.y) ? b.y : 0
|
||||
animation?.pause()
|
||||
animation = animate(state, {
|
||||
x: toX,
|
||||
@@ -207,8 +210,13 @@ export function setupCaptionWindowManager(params: {
|
||||
onRender: () => {
|
||||
if (win.isDestroyed())
|
||||
return
|
||||
if (!Number.isFinite(state.x) || !Number.isFinite(state.y))
|
||||
return
|
||||
|
||||
const toX = Math.round(state.x)
|
||||
const toY = Math.round(state.y)
|
||||
lastProgrammaticMoveAt = Date.now()
|
||||
win.setPosition(state.x, state.y)
|
||||
win.setPosition(toX, toY)
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -219,6 +227,9 @@ export function setupCaptionWindowManager(params: {
|
||||
let lastAppliedTy = Number.NaN
|
||||
|
||||
const moveThrottled = throttle(() => {
|
||||
if (win.isDestroyed())
|
||||
return
|
||||
|
||||
const stored = getConfig()?.matrices[matrixHash]?.relativeToMain ?? initialOffset
|
||||
const main = params.mainWindow.getBounds()
|
||||
const b = win.getBounds()
|
||||
@@ -277,6 +288,18 @@ export function setupCaptionWindowManager(params: {
|
||||
}
|
||||
}
|
||||
|
||||
function applyIgnoreMouseEvents(win: BrowserWindow, ignore: boolean) {
|
||||
try {
|
||||
if (ignore)
|
||||
win.setIgnoreMouseEvents(true, { forward: true })
|
||||
else
|
||||
win.setIgnoreMouseEvents(false)
|
||||
}
|
||||
catch {
|
||||
// ignore failures during early window lifecycle
|
||||
}
|
||||
}
|
||||
|
||||
const reusable = createReusableWindow(async () => {
|
||||
// TODO: once we refactored eventa to support window-namespaced contexts,
|
||||
// we can remove the setMaxListeners call below since eventa will be able to dispatch and
|
||||
@@ -290,6 +313,8 @@ export function setupCaptionWindowManager(params: {
|
||||
|
||||
await setupBaseWindowElectronInvokes({ context, window, serverChannel: params.serverChannel, i18n: params.i18n })
|
||||
|
||||
applyIgnoreMouseEvents(window, isFollowing)
|
||||
|
||||
const cfg = getConfig()
|
||||
const saved = cfg?.matrices?.[matrixHash]?.bounds
|
||||
|
||||
@@ -359,22 +384,26 @@ export function setupCaptionWindowManager(params: {
|
||||
async function setFollowWindow(isFollowingWindow: boolean) {
|
||||
isFollowing = isFollowingWindow
|
||||
const window = await reusable.getWindow()
|
||||
|
||||
applyIgnoreMouseEvents(window, isFollowing)
|
||||
|
||||
if (isFollowing) {
|
||||
// Compute and persist current relative offset based on existing positions
|
||||
const rel = computeRelativeOffset(window)
|
||||
const cfg = getConfig() ?? { isFollowing, matrices: {} }
|
||||
cfg.matrices[matrixHash] = { ...cfg.matrices[matrixHash], relativeToMain: rel }
|
||||
updateConfig(cfg)
|
||||
const config = getConfig() ?? { isFollowing, matrices: {} }
|
||||
config.isFollowing = isFollowing
|
||||
config.matrices[matrixHash] = { ...config.matrices[matrixHash], relativeToMain: rel }
|
||||
updateConfig(config)
|
||||
|
||||
// Start following main without re-docking; keep current position
|
||||
followMainWindow(window)
|
||||
}
|
||||
else {
|
||||
detachFromMain()
|
||||
}
|
||||
|
||||
const config = getConfig() ?? { isFollowing, matrices: {} }
|
||||
config.isFollowing = isFollowing
|
||||
updateConfig(config)
|
||||
const config = getConfig() ?? { isFollowing, matrices: {} }
|
||||
config.isFollowing = isFollowing
|
||||
updateConfig(config)
|
||||
}
|
||||
|
||||
// Keep window visible after toggle
|
||||
window.show()
|
||||
@@ -399,6 +428,8 @@ export function setupCaptionWindowManager(params: {
|
||||
async function resetToSide() {
|
||||
const window = await reusable.getWindow()
|
||||
|
||||
applyIgnoreMouseEvents(window, isFollowing)
|
||||
|
||||
// Prevent user-move persistence from overwriting our programmatic move
|
||||
lastProgrammaticMoveAt = Date.now()
|
||||
const initialBounds = computeInitialCaptionBounds({ mainWindow: params.mainWindow })
|
||||
|
||||
@@ -21,7 +21,7 @@ menu:
|
||||
close_caption: Close Caption...
|
||||
caption_overlay: Lớp phủ phụ đề
|
||||
follow_window: Theo cửa sổ
|
||||
reset_position: Đặt lại vị trí
|
||||
reset_position: Đặt lại vị trí
|
||||
devtools: Công cụ phát triển
|
||||
troubleshoot_beatsync: Sửa lỗi BeatSync...
|
||||
quit: Thoát ra
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { VRM } from '@pixiv/three-vrm'
|
||||
import type { AnimationMixer, Material, WebGLRenderer } from 'three'
|
||||
import type { AnimationMixer, Material, Object3D, WebGLRenderer } from 'three'
|
||||
|
||||
import type {
|
||||
ThreeRendererMemorySnapshot,
|
||||
@@ -74,7 +74,7 @@ export function createVrmSceneSummarySnapshot(input?: VrmSceneSnapshotInput | VR
|
||||
const materials = new Set<Material>()
|
||||
const textures = new Set<Texture>()
|
||||
|
||||
activeVrm.scene.traverse((child) => {
|
||||
activeVrm.scene.traverse((child: Object3D) => {
|
||||
if (child instanceof Mesh)
|
||||
meshCount += 1
|
||||
|
||||
|
||||
Generated
+30
-5
@@ -1836,7 +1836,7 @@ importers:
|
||||
version: 5.0.0(vue@3.5.29(typescript@5.9.3))
|
||||
'@intlify/unplugin-vue-i18n':
|
||||
specifier: ^11.0.7
|
||||
version: 11.0.7(@vue/compiler-dom@3.5.29)(eslint@9.39.3(jiti@2.6.1))(rollup@4.59.0)(typescript@5.9.3)(vite@8.0.0-beta.15(@types/node@24.10.14)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))(vue-i18n@11.2.8(vue@3.5.29(typescript@5.9.3)))(vue@3.5.29(typescript@5.9.3))
|
||||
version: 11.0.7(@vue/compiler-dom@3.5.29)(eslint@9.39.3(jiti@2.6.1))(rollup@4.59.0)(typescript@5.9.3)(vite@7.3.1(@types/node@24.10.14)(jiti@2.6.1)(less@4.5.1)(lightningcss@1.31.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))(vue-i18n@11.2.8(vue@3.5.29(typescript@5.9.3)))(vue@3.5.29(typescript@5.9.3))
|
||||
'@mdit/plugin-footnote':
|
||||
specifier: ^0.22.4
|
||||
version: 0.22.4(markdown-it@14.1.1)
|
||||
@@ -1896,7 +1896,7 @@ importers:
|
||||
version: 0.1.3
|
||||
unplugin-yaml:
|
||||
specifier: ^4.0.0
|
||||
version: 4.0.0(esbuild@0.27.2)(rolldown@1.0.0-rc.3)(rollup@4.59.0)(vite@8.0.0-beta.15(@types/node@24.10.14)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))
|
||||
version: 4.0.0(@nuxt/kit@3.20.2(magicast@0.5.2))(esbuild@0.27.2)(rolldown@1.0.0-rc.3)(rollup@4.59.0)(vite@7.3.1(@types/node@24.10.14)(jiti@2.6.1)(less@4.5.1)(lightningcss@1.31.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))
|
||||
vitepress:
|
||||
specifier: ^2.0.0-alpha.16
|
||||
version: 2.0.0-alpha.16(@types/node@24.10.14)(change-case@5.4.4)(fuse.js@7.1.0)(idb-keyval@6.2.2)(jiti@2.6.1)(less@4.5.1)(lightningcss@1.31.1)(nprogress@0.2.0)(postcss@8.5.6)(terser@5.46.0)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2)
|
||||
@@ -3234,7 +3234,7 @@ importers:
|
||||
version: 14.1.0(vue@3.5.29(typescript@5.9.3))
|
||||
'@wxt-dev/module-vue':
|
||||
specifier: ^1.0.3
|
||||
version: 1.0.3(vite@8.0.0-beta.15(@types/node@24.10.14)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))(vue@3.5.29(typescript@5.9.3))(wxt@0.20.18(@types/node@24.10.14)(canvas@3.2.1)(eslint@9.39.3(jiti@2.6.1))(jiti@2.6.1)(less@4.5.1)(lightningcss@1.31.1)(rollup@4.59.0)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))
|
||||
version: 1.0.3(vite@7.3.1(@types/node@24.10.14)(jiti@2.6.1)(less@4.5.1)(lightningcss@1.31.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))(vue@3.5.29(typescript@5.9.3))(wxt@0.20.18(@types/node@24.10.14)(canvas@3.2.1)(eslint@9.39.3(jiti@2.6.1))(jiti@2.6.1)(less@4.5.1)(lightningcss@1.31.1)(rollup@4.59.0)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))
|
||||
nanoid:
|
||||
specifier: ^5.1.6
|
||||
version: 5.1.6
|
||||
@@ -19667,6 +19667,31 @@ snapshots:
|
||||
- supports-color
|
||||
- typescript
|
||||
|
||||
'@intlify/unplugin-vue-i18n@11.0.7(@vue/compiler-dom@3.5.29)(eslint@9.39.3(jiti@2.6.1))(rollup@4.59.0)(typescript@5.9.3)(vite@7.3.1(@types/node@24.10.14)(jiti@2.6.1)(less@4.5.1)(lightningcss@1.31.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))(vue-i18n@11.2.8(vue@3.5.29(typescript@5.9.3)))(vue@3.5.29(typescript@5.9.3))':
|
||||
dependencies:
|
||||
'@eslint-community/eslint-utils': 4.9.1(eslint@9.39.3(jiti@2.6.1))
|
||||
'@intlify/bundle-utils': 11.0.7(vue-i18n@11.2.8(vue@3.5.29(typescript@5.9.3)))
|
||||
'@intlify/shared': 11.2.8
|
||||
'@intlify/vue-i18n-extensions': 8.0.0(@intlify/shared@11.2.8)(@vue/compiler-dom@3.5.29)(vue-i18n@11.2.8(vue@3.5.29(typescript@5.9.3)))(vue@3.5.29(typescript@5.9.3))
|
||||
'@rollup/pluginutils': 5.3.0(rollup@4.59.0)
|
||||
'@typescript-eslint/scope-manager': 8.56.1
|
||||
'@typescript-eslint/typescript-estree': 8.56.1(typescript@5.9.3)
|
||||
debug: 4.4.3
|
||||
fast-glob: 3.3.3
|
||||
pathe: 2.0.3
|
||||
picocolors: 1.1.1
|
||||
unplugin: 2.3.11
|
||||
vite: 7.3.1(@types/node@24.10.14)(jiti@2.6.1)(less@4.5.1)(lightningcss@1.31.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)
|
||||
vue: 3.5.29(typescript@5.9.3)
|
||||
optionalDependencies:
|
||||
vue-i18n: 11.2.8(vue@3.5.29(typescript@5.9.3))
|
||||
transitivePeerDependencies:
|
||||
- '@vue/compiler-dom'
|
||||
- eslint
|
||||
- rollup
|
||||
- supports-color
|
||||
- typescript
|
||||
|
||||
'@intlify/unplugin-vue-i18n@11.0.7(@vue/compiler-dom@3.5.29)(eslint@9.39.3(jiti@2.6.1))(rollup@4.59.0)(typescript@5.9.3)(vite@8.0.0-beta.15(@types/node@24.10.14)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))(vue-i18n@11.2.8(vue@3.5.29(typescript@5.9.3)))(vue@3.5.29(typescript@5.9.3))':
|
||||
dependencies:
|
||||
'@eslint-community/eslint-utils': 4.9.1(eslint@9.39.3(jiti@2.6.1))
|
||||
@@ -23891,9 +23916,9 @@ snapshots:
|
||||
'@types/filesystem': 0.0.36
|
||||
'@types/har-format': 1.2.16
|
||||
|
||||
'@wxt-dev/module-vue@1.0.3(vite@8.0.0-beta.15(@types/node@24.10.14)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))(vue@3.5.29(typescript@5.9.3))(wxt@0.20.18(@types/node@24.10.14)(canvas@3.2.1)(eslint@9.39.3(jiti@2.6.1))(jiti@2.6.1)(less@4.5.1)(lightningcss@1.31.1)(rollup@4.59.0)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))':
|
||||
'@wxt-dev/module-vue@1.0.3(vite@7.3.1(@types/node@24.10.14)(jiti@2.6.1)(less@4.5.1)(lightningcss@1.31.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))(vue@3.5.29(typescript@5.9.3))(wxt@0.20.18(@types/node@24.10.14)(canvas@3.2.1)(eslint@9.39.3(jiti@2.6.1))(jiti@2.6.1)(less@4.5.1)(lightningcss@1.31.1)(rollup@4.59.0)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))':
|
||||
dependencies:
|
||||
'@vitejs/plugin-vue': 6.0.4(vite@8.0.0-beta.15(@types/node@24.10.14)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))(vue@3.5.29(typescript@5.9.3))
|
||||
'@vitejs/plugin-vue': 6.0.4(vite@7.3.1(@types/node@24.10.14)(jiti@2.6.1)(less@4.5.1)(lightningcss@1.31.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))(vue@3.5.29(typescript@5.9.3))
|
||||
wxt: 0.20.18(@types/node@24.10.14)(canvas@3.2.1)(eslint@9.39.3(jiti@2.6.1))(jiti@2.6.1)(less@4.5.1)(lightningcss@1.31.1)(rollup@4.59.0)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)
|
||||
transitivePeerDependencies:
|
||||
- vite
|
||||
|
||||
Reference in New Issue
Block a user