@@ -34,12 +34,19 @@ export default function WidgetWindow({ widgetId }: Props) {
3434 const [ isBlurred , setIsBlurred ] = useState ( false ) ;
3535 const [ idle , setIdle ] = useState ( false ) ;
3636 const idleTimer = useRef < ReturnType < typeof setTimeout > > ( ) ;
37+ const autoBlurEnabled = useRef ( false ) ;
38+ const rootRef = useRef < HTMLDivElement > ( null ) ;
3739 const [ widgetType , setWidgetType ] = useState < string > (
3840 widgetId . includes ( "-" ) ? widgetId . substring ( 0 , widgetId . lastIndexOf ( "-" ) ) : ""
3941 ) ;
4042 const [ refreshKey , setRefreshKey ] = useState ( 0 ) ;
4143 const [ paused , setPaused ] = useState ( false ) ;
4244
45+ useEffect ( ( ) => {
46+ document . documentElement . classList . add ( "widget-window" ) ;
47+ return ( ) => document . documentElement . classList . remove ( "widget-window" ) ;
48+ } , [ ] ) ;
49+
4350 const getMonitorIndexForRect = async ( x : number , y : number , width : number , height : number ) => {
4451 try {
4552 const target = await monitorFromPoint ( x + width / 2 , y + height / 2 ) ;
@@ -57,6 +64,20 @@ export default function WidgetWindow({ widgetId }: Props) {
5764 } ;
5865
5966 useEffect ( ( ) => {
67+ const autoBlurKey = `${ widgetId } -auto-blur` ;
68+ autoBlurEnabled . current = localStorage . getItem ( autoBlurKey ) === "1" ;
69+ const onAutoBlurChanged = ( event : Event ) => {
70+ const { widgetId : changedWidgetId , enabled } = ( event as CustomEvent < {
71+ widgetId ?: string ;
72+ enabled ?: boolean ;
73+ } > ) . detail ?? { } ;
74+ if ( changedWidgetId !== widgetId ) return ;
75+ autoBlurEnabled . current = enabled === true ;
76+ clearTimeout ( idleTimer . current ) ;
77+ if ( ! autoBlurEnabled . current ) setIdle ( false ) ;
78+ } ;
79+ window . addEventListener ( "timelens-widget-auto-blur-changed" , onAutoBlurChanged ) ;
80+
6081 const heartbeatKey = `timelens-widget-heartbeat:${ widgetId } ` ;
6182 const recordHeartbeat = ( event : string ) => {
6283 try {
@@ -140,6 +161,7 @@ export default function WidgetWindow({ widgetId }: Props) {
140161 return ( ) => {
141162 unlistenFocus . then ( ( u ) => u ( ) ) ;
142163 unlistenMove . then ( ( u ) => u ( ) ) ;
164+ window . removeEventListener ( "timelens-widget-auto-blur-changed" , onAutoBlurChanged ) ;
143165 window . removeEventListener ( "mousedown" , restoreOnMouseDown ) ;
144166 if ( positionSaveTimer . current ) clearTimeout ( positionSaveTimer . current ) ;
145167 } ;
@@ -211,7 +233,27 @@ export default function WidgetWindow({ widgetId }: Props) {
211233 } ;
212234
213235 const handleMouseLeave = ( ) => {
214- idleTimer . current = setTimeout ( ( ) => setIdle ( true ) , 2000 ) ;
236+ if ( ! autoBlurEnabled . current ) return ;
237+ idleTimer . current = setTimeout ( ( ) => {
238+ const activeElement = document . activeElement ;
239+ const isEditing = activeElement instanceof HTMLTextAreaElement
240+ || activeElement instanceof HTMLInputElement
241+ || activeElement instanceof HTMLElement && activeElement . isContentEditable ;
242+ if ( ! isEditing || ! rootRef . current ?. contains ( activeElement ) ) {
243+ setIdle ( true ) ;
244+ }
245+ } , 2000 ) ;
246+ } ;
247+
248+ const handleFocusCapture = ( event : React . FocusEvent < HTMLDivElement > ) => {
249+ const target = event . target ;
250+ const isEditing = target instanceof HTMLTextAreaElement
251+ || target instanceof HTMLInputElement
252+ || target instanceof HTMLElement && target . isContentEditable ;
253+ if ( isEditing ) {
254+ clearTimeout ( idleTimer . current ) ;
255+ setIdle ( false ) ;
256+ }
215257 } ;
216258
217259 // Cleanup idle timer on unmount
@@ -221,9 +263,11 @@ export default function WidgetWindow({ widgetId }: Props) {
221263
222264 return (
223265 < div
266+ ref = { rootRef }
224267 className = { `widget-root ${ isBlurred && widgetType !== "clock" ? "widget-root--faded" : "" } ${ idle ? "widget-idle" : "" } ` }
225268 onMouseEnter = { handleMouseEnter }
226269 onMouseLeave = { handleMouseLeave }
270+ onFocusCapture = { handleFocusCapture }
227271 >
228272 { widgetType === "clock" && < ClockWidget key = { refreshKey } widgetId = { widgetId } isBlurred = { isBlurred } /> }
229273 { widgetType === "todo" && < TodoWidget key = { refreshKey } widgetId = { widgetId } /> }
0 commit comments