@@ -12,7 +12,7 @@ import { isMacOS } from 'std-env'
1212
1313import icon from '../../../../resources/icon.png?asset'
1414
15- import { captionAttachedChanged , captionGetAttached } from '../../../shared/eventa'
15+ import { captionGetIsFollowingWindow , captionIsFollowingWindowChanged } from '../../../shared/eventa'
1616import { baseUrl , getElectronMainDirname , load , withHashRoute } from '../../libs/electron/location'
1717import { createReusableWindow } from '../../libs/electron/window-manager'
1818import { mapForBreakpoints , resolutionBreakpoints , widthFrom } from '../shared/display'
@@ -25,7 +25,7 @@ interface CaptionMatrixConfig {
2525}
2626
2727interface CaptionConfig {
28- attached : boolean
28+ isFollowing : boolean
2929 matrices : Record < string , CaptionMatrixConfig >
3030}
3131
@@ -140,17 +140,17 @@ export function setupCaptionWindowManager(params: { mainWindow: BrowserWindow })
140140 setup : setupConfig ,
141141 get : getConfig ,
142142 update : updateConfig ,
143- } = createConfig < CaptionConfig > ( 'windows-caption' , 'config.json' , { default : { attached : true , matrices : { } } } )
143+ } = createConfig < CaptionConfig > ( 'windows-caption' , 'config.json' , { default : { isFollowing : true , matrices : { } } } )
144144
145145 setupConfig ( )
146146
147- let isAttached = getConfig ( ) ?. attached ?? true
147+ let isFollowing = getConfig ( ) ?. isFollowing ?? true
148148 let lastProgrammaticMoveAt = 0
149149
150150 // Keep references to listeners so we can detach when toggling
151151 let detachMainMoveListener : ( ( ) => void ) | undefined
152152
153- // Note: when attaching , we compute and persist the current relative offset
153+ // Note: when following window , we compute and persist the current relative offset
154154 // and start following without docking, so no immediate reposition is needed here.
155155
156156 function computeRelativeOffset ( win : BrowserWindow ) : { dx : number , dy : number } {
@@ -159,16 +159,16 @@ export function setupCaptionWindowManager(params: { mainWindow: BrowserWindow })
159159 return { dx : caption . x - main . x , dy : caption . y - main . y }
160160 }
161161
162- function attachToMain ( win : BrowserWindow ) {
163- const cfg = getConfig ( ) ?? { attached : isAttached , matrices : { } }
162+ function followMainWindow ( win : BrowserWindow ) {
163+ const cfg = getConfig ( ) ?? { isFollowing , matrices : { } }
164164 const initialOffset = cfg ?. matrices ?. [ matrixHash ] ?. relativeToMain ?? computeRelativeOffset ( win )
165165
166166 // Store relative offset for this matrix
167- const cfgToSave = getConfig ( ) ?? { attached : isAttached , matrices : { } }
168- cfgToSave . matrices [ matrixHash ] = { ...( cfgToSave . matrices [ matrixHash ] ?? { } ) , relativeToMain : initialOffset }
167+ const cfgToSave = getConfig ( ) ?? { isFollowing , matrices : { } }
168+ cfgToSave . matrices [ matrixHash ] = { ...cfgToSave . matrices [ matrixHash ] , relativeToMain : initialOffset }
169169 updateConfig ( cfgToSave )
170170
171- let anim : ReturnType < typeof animate > | null = null
171+ let animation : ReturnType < typeof animate > | null = null
172172 const state = { x : 0 , y : 0 }
173173
174174 const settleTo = ( toX : number , toY : number ) => {
@@ -177,8 +177,8 @@ export function setupCaptionWindowManager(params: { mainWindow: BrowserWindow })
177177 const b = win . getBounds ( )
178178 state . x = b . x
179179 state . y = b . y
180- anim ?. pause ( )
181- anim = animate ( state , {
180+ animation ?. pause ( )
181+ animation = animate ( state , {
182182 x : toX ,
183183 y : toY ,
184184 duration : 160 ,
@@ -197,6 +197,7 @@ export function setupCaptionWindowManager(params: { mainWindow: BrowserWindow })
197197 let lastTy = 0
198198 let lastAppliedTx = Number . NaN
199199 let lastAppliedTy = Number . NaN
200+
200201 const moveThrottled = throttle ( ( ) => {
201202 const stored = getConfig ( ) ?. matrices [ matrixHash ] ?. relativeToMain ?? initialOffset
202203 const main = params . mainWindow . getBounds ( )
@@ -222,16 +223,18 @@ export function setupCaptionWindowManager(params: { mainWindow: BrowserWindow })
222223 settleTo ( lastTx , lastTy )
223224 } , 200 )
224225
225- const onMainChange = ( ) => { moveThrottled ( ) ; settleDebounced ( ) }
226+ const onMainChange = ( ) => {
227+ moveThrottled ( )
228+ settleDebounced ( )
229+ }
230+ onMainChange ( )
226231 params . mainWindow . on ( 'move' , onMainChange )
227232 params . mainWindow . on ( 'resize' , onMainChange )
228- // Initialize target once
229- onMainChange ( )
230233 detachMainMoveListener = ( ) => {
231234 params . mainWindow . removeListener ( 'move' , onMainChange )
232235 params . mainWindow . removeListener ( 'resize' , onMainChange )
233- anim ?. pause ( )
234- anim = null
236+ animation ?. pause ( )
237+ animation = null
235238 }
236239 }
237240
@@ -261,13 +264,13 @@ export function setupCaptionWindowManager(params: { mainWindow: BrowserWindow })
261264 }
262265
263266 const persistBounds = ( ) => {
264- const config = getConfig ( ) ?? { attached : isAttached , matrices : { } }
267+ const config = getConfig ( ) ?? { isFollowing , matrices : { } }
265268 const b = window . getBounds ( )
266- config . matrices [ matrixHash ] = { ...( config . matrices [ matrixHash ] ?? { } ) , bounds : b }
267- config . attached = isAttached
268- if ( isAttached && Date . now ( ) - lastProgrammaticMoveAt > 100 ) {
269+ config . matrices [ matrixHash ] = { ...config . matrices [ matrixHash ] , bounds : b }
270+ config . isFollowing = isFollowing
271+ if ( isFollowing && Date . now ( ) - lastProgrammaticMoveAt > 100 ) {
269272 const rel = computeRelativeOffset ( window )
270- config . matrices [ matrixHash ] = { ...( config . matrices [ matrixHash ] ?? { } ) , bounds : b , relativeToMain : rel }
273+ config . matrices [ matrixHash ] = { ...config . matrices [ matrixHash ] , bounds : b , relativeToMain : rel }
271274 }
272275 updateConfig ( config )
273276 }
@@ -276,60 +279,75 @@ export function setupCaptionWindowManager(params: { mainWindow: BrowserWindow })
276279
277280 await load ( window , withHashRoute ( baseUrl ( resolve ( getElectronMainDirname ( ) , '..' , 'renderer' ) ) , '/caption' ) )
278281
279- const cleanupGetAttached = defineInvokeHandler ( context , captionGetAttached , async ( ) => isAttached )
280- try { context . emit ( captionAttachedChanged , isAttached ) }
281- catch { }
282+ const cleanupGetAttached = defineInvokeHandler ( context , captionGetIsFollowingWindow , async ( ) => isFollowing )
283+ try {
284+ context . emit ( captionIsFollowingWindowChanged , isFollowing )
285+ }
286+ catch {
287+
288+ }
282289
283- if ( isAttached ) {
284- attachToMain ( window )
290+ if ( isFollowing ) {
291+ followMainWindow ( window )
285292 }
286293
287294 window . on ( 'closed' , ( ) => {
288295 detachFromMain ( )
289- try { cleanupGetAttached ( ) }
290- catch { }
296+ try {
297+ cleanupGetAttached ( )
298+ }
299+ catch {
300+ }
291301
292302 eventaContext = undefined
293303 } )
294304
295305 return window
296306 } )
297307
298- async function getWindow ( ) : Promise < BrowserWindow > { return reusable . getWindow ( ) }
308+ async function getWindow ( ) : Promise < BrowserWindow > {
309+ return reusable . getWindow ( )
310+ }
299311
300- async function setFollowWindow ( attached : boolean ) {
301- isAttached = attached
312+ async function setFollowWindow ( isFollowingWindow : boolean ) {
313+ isFollowing = isFollowingWindow
302314 const window = await reusable . getWindow ( )
303- if ( isAttached ) {
315+ if ( isFollowing ) {
304316 // Compute and persist current relative offset based on existing positions
305317 const rel = computeRelativeOffset ( window )
306- const cfg = getConfig ( ) ?? { attached : isAttached , matrices : { } }
307- cfg . matrices [ matrixHash ] = { ...( cfg . matrices [ matrixHash ] ?? { } ) , relativeToMain : rel }
318+ const cfg = getConfig ( ) ?? { isFollowing , matrices : { } }
319+ cfg . matrices [ matrixHash ] = { ...cfg . matrices [ matrixHash ] , relativeToMain : rel }
308320 updateConfig ( cfg )
309321 // Start following main without re-docking; keep current position
310- attachToMain ( window )
322+ followMainWindow ( window )
311323 }
312324 else {
313325 detachFromMain ( )
314326 }
315327
316- const config = getConfig ( ) ?? { attached : isAttached , matrices : { } }
317- config . attached = isAttached
328+ const config = getConfig ( ) ?? { isFollowing , matrices : { } }
329+ config . isFollowing = isFollowing
318330 updateConfig ( config )
319331
320332 // Keep window visible after toggle
321333 window . show ( )
322334
323335 // Notify renderer for UI state (handle visibility)
324- try { eventaContext ?. emit ( captionAttachedChanged , isAttached ) }
325- catch { }
336+ try {
337+ eventaContext ?. emit ( captionIsFollowingWindowChanged , isFollowing )
338+ }
339+ catch {
340+
341+ }
326342 }
327343
328344 async function toggleFollowWindow ( ) {
329- await setFollowWindow ( ! isAttached )
345+ await setFollowWindow ( ! isFollowing )
330346 }
331347
332- function getIsFollowingWindow ( ) : boolean { return isAttached }
348+ function getIsFollowingWindow ( ) : boolean {
349+ return isFollowing
350+ }
333351
334352 async function resetToSide ( ) {
335353 const window = await reusable . getWindow ( )
@@ -340,12 +358,12 @@ export function setupCaptionWindowManager(params: { mainWindow: BrowserWindow })
340358 window . setBounds ( initialBounds )
341359
342360 // Persist new bounds and a clean relative offset so follow uses it
343- const config = getConfig ( ) ?? { attached : isAttached , matrices : { } }
361+ const config = getConfig ( ) ?? { isFollowing , matrices : { } }
344362 const b = window . getBounds ( )
345363
346364 const rel = computeRelativeOffset ( window )
347- config . matrices [ matrixHash ] = { ...( config . matrices [ matrixHash ] ?? { } ) , bounds : b , relativeToMain : rel }
348- config . attached = isAttached
365+ config . matrices [ matrixHash ] = { ...config . matrices [ matrixHash ] , bounds : b , relativeToMain : rel }
366+ config . isFollowing = isFollowing
349367
350368 updateConfig ( config )
351369 }
0 commit comments