@@ -3,9 +3,76 @@ import { getActiveWindowTab, getTab, getTabs } from './helpers'
33import config from '../config'
44import { AWClient , IEvent } from 'aw-client'
55import { getBucketId , sendHeartbeat } from './client'
6- import { getEnabled , getHeartbeatData , setHeartbeatData } from '../storage'
6+ import { getEnabled , getHeartbeatData , setHeartbeatData , getGmailEnabled } from '../storage'
77import deepEqual from 'deep-equal'
88
9+ export function setupMessageListener ( client : AWClient ) {
10+ browser . runtime . onMessage . addListener (
11+ async ( message : any , sender : browser . Runtime . MessageSender ) => {
12+ const enabled = await getEnabled ( ) ;
13+ const gmailEnabled = await getGmailEnabled ( ) ;
14+ if ( ! enabled || ! gmailEnabled ) return ;
15+
16+ if ( message . type === 'AW_GMAIL_HEARTBEAT' ) {
17+ const tab = sender . tab ;
18+ if ( ! tab || ! tab . url || ! tab . title ) return ;
19+ if ( ! tab . url . includes ( 'mail.google.com' ) ) return ;
20+ const tabs = await getTabs ( ) ;
21+
22+ const data : IEvent [ 'data' ] = {
23+ url : tab . url ,
24+ title : tab . title ,
25+ audible : tab . audible ?? false ,
26+ incognito : tab . incognito ,
27+ tabCount : tabs . length ,
28+ ...message . data ,
29+ } ;
30+ await performHeartbeat ( client , data ) ;
31+ }
32+ } ,
33+ )
34+ }
35+
36+ async function performHeartbeat (
37+ client : AWClient ,
38+ data : IEvent [ 'data' ] ,
39+ options : { finalizeOnly ?: boolean } = { }
40+ ) {
41+ const bucketId = await getBucketId ( )
42+ const now = new Date ( )
43+ const previousData = await getHeartbeatData ( )
44+ if ( previousData && ! deepEqual ( previousData , data ) ) {
45+ console . debug ( '[Background] Activity changed, finalizing previous session' , previousData )
46+ await sendHeartbeat (
47+ client ,
48+ bucketId ,
49+ new Date ( now . getTime ( ) - 1 ) ,
50+ previousData ,
51+ config . heartbeat . intervalInSeconds + 20 ,
52+ ) . catch ( ( ) => { } )
53+ }
54+
55+ if ( options . finalizeOnly ) {
56+ if ( previousData ) {
57+ await browser . storage . local . remove ( 'heartbeatData' ) ;
58+ }
59+ return ;
60+ }
61+
62+ console . debug ( '[Background] Sending heartbeat' , data )
63+ await sendHeartbeat (
64+ client ,
65+ bucketId ,
66+ now ,
67+ data ,
68+ config . heartbeat . intervalInSeconds + 20 ,
69+ ) . catch ( ( err : unknown ) => {
70+ console . error ( '[Background] Failed to send heartbeat:' , err ) ;
71+ } )
72+
73+ await setHeartbeatData ( data )
74+ }
75+
976async function heartbeat (
1077 client : AWClient ,
1178 tab : browser . Tabs . Tab | undefined ,
@@ -27,34 +94,23 @@ async function heartbeat(
2794 return
2895 }
2996
30- const now = new Date ( )
3197 const data : IEvent [ 'data' ] = {
3298 url : tab . url ,
3399 title : tab . title ,
34100 audible : tab . audible ?? false ,
35101 incognito : tab . incognito ,
36102 tabCount : tabCount ,
37103 }
38- const previousData = await getHeartbeatData ( )
39- if ( previousData && ! deepEqual ( previousData , data ) ) {
40- console . debug ( 'Sending heartbeat for previous data' , previousData )
41- await sendHeartbeat (
42- client ,
43- await getBucketId ( ) ,
44- new Date ( now . getTime ( ) - 1 ) ,
45- previousData ,
46- config . heartbeat . intervalInSeconds + 20 ,
47- )
104+
105+ const gmailEnabled = await getGmailEnabled ( ) ;
106+ if ( gmailEnabled && tab . url . includes ( 'mail.google.com' ) ) {
107+ // Sharp cut: finalize the previous activity (e.g. if we came from Google Search)
108+ // but don't start the 'Generic' Gmail event. Gmail.ts will do that with metadata.
109+ await performHeartbeat ( client , data , { finalizeOnly : true } ) ;
110+ return ;
48111 }
49- console . debug ( 'Sending heartbeat' , data )
50- await sendHeartbeat (
51- client ,
52- await getBucketId ( ) ,
53- now ,
54- data ,
55- config . heartbeat . intervalInSeconds + 20 ,
56- )
57- await setHeartbeatData ( data )
112+
113+ await performHeartbeat ( client , data ) ;
58114}
59115
60116export const sendInitialHeartbeat = async ( client : AWClient ) => {
@@ -76,9 +132,9 @@ export const heartbeatAlarmListener =
76132
77133export const tabActivatedListener =
78134 ( client : AWClient ) =>
79- async ( activeInfo : browser . Tabs . OnActivatedActiveInfoType ) => {
80- const tab = await getTab ( activeInfo . tabId )
81- const tabs = await getTabs ( )
82- console . debug ( 'Sending heartbeat for tab activation' , tab )
83- await heartbeat ( client , tab , tabs . length )
84- }
135+ async ( activeInfo : browser . Tabs . OnActivatedActiveInfoType ) => {
136+ const tab = await getTab ( activeInfo . tabId )
137+ const tabs = await getTabs ( )
138+ console . debug ( 'Sending heartbeat for tab activation' , tab )
139+ await heartbeat ( client , tab , tabs . length )
140+ }
0 commit comments