@@ -7,9 +7,73 @@ import { Question } from './src/Annotation.js';
77import { ExportSessionCSV } from './src/ExportSessionCSV.js' ;
88import { JSonSessionService } from './src/JSonSessionService.js' ;
99import { getSystemInfo } from './src/browserInfo.js' ;
10+ import { GoogleDriveService } from './src/GoogleDriveService.js' ;
1011
1112let session = new Session ( ) ;
1213
14+ // --- Google Drive state ---
15+ const driveService = new GoogleDriveService ( ) ;
16+ let driveAutoSave = false ;
17+ let driveFileId = null ;
18+ let driveSyncStatus = 'idle' ; // idle | syncing | synced | error
19+ let syncTimeout = null ;
20+
21+ async function loadDriveSettings ( ) {
22+ const data = await chrome . storage . local . get ( [ 'driveAutoSave' , 'driveFileId' ] ) ;
23+ driveAutoSave = data . driveAutoSave || false ;
24+ driveFileId = data . driveFileId || null ;
25+
26+ // Try to restore token silently if auto-save was on
27+ if ( driveAutoSave ) {
28+ try {
29+ await driveService . getToken ( ) ;
30+ } catch ( e ) {
31+ driveAutoSave = false ;
32+ await chrome . storage . local . set ( { driveAutoSave : false } ) ;
33+ }
34+ }
35+ }
36+
37+ async function saveDriveSettings ( ) {
38+ await chrome . storage . local . set ( { driveAutoSave, driveFileId } ) ;
39+ }
40+
41+ function scheduleDriveSync ( ) {
42+ if ( ! driveAutoSave || ! driveService . isAuthenticated ( ) ) return ;
43+ if ( syncTimeout ) clearTimeout ( syncTimeout ) ;
44+ syncTimeout = setTimeout ( ( ) => syncToDrive ( ) , 1500 ) ;
45+ }
46+
47+ async function syncToDrive ( ) {
48+ if ( ! driveService . isAuthenticated ( ) ) return ;
49+ if ( session . getAnnotations ( ) . length === 0 ) return ;
50+
51+ driveSyncStatus = 'syncing' ;
52+ try {
53+ const jsonService = new JSonSessionService ( ) ;
54+ const sessionJson = jsonService . getJSon ( session ) ;
55+ const fileName = getDriveFileName ( ) ;
56+
57+ const result = await driveService . uploadSession ( sessionJson , fileName , driveFileId ) ;
58+ driveFileId = result . id ;
59+ driveSyncStatus = 'synced' ;
60+ await saveDriveSettings ( ) ;
61+ } catch ( error ) {
62+ console . error ( 'Drive sync failed:' , error ) ;
63+ driveSyncStatus = 'error' ;
64+ }
65+ }
66+
67+ function getDriveFileName ( ) {
68+ const date = new Date ( session . getStartDateTime ( ) ) ;
69+ const startDateTime = date . getFullYear ( ) +
70+ ( '0' + ( date . getMonth ( ) + 1 ) ) . slice ( - 2 ) +
71+ ( '0' + date . getDate ( ) ) . slice ( - 2 ) + '_' +
72+ ( '0' + date . getHours ( ) ) . slice ( - 2 ) +
73+ ( '0' + date . getMinutes ( ) ) . slice ( - 2 ) ;
74+ return `ExploratorySession_${ startDateTime } .json` ;
75+ }
76+
1377// Función para guardar la sesión en el storage
1478async function saveSession ( ) {
1579 try {
@@ -78,6 +142,9 @@ async function saveSession() {
78142 throw error ;
79143 }
80144 }
145+
146+ // Trigger Drive auto-sync after local save
147+ scheduleDriveSync ( ) ;
81148}
82149
83150// Función para cargar la sesión desde el storage
@@ -113,8 +180,9 @@ async function loadSession() {
113180 }
114181}
115182
116- // Cargar la sesión al iniciar
183+ // Cargar la sesión y configuración de Drive al iniciar
117184loadSession ( ) ;
185+ loadDriveSettings ( ) ;
118186
119187// Helper function for notifications of processing errors (before addAnnotation is called)
120188function notifyProcessingError ( annotationType , descriptionName , errorMessage = "" ) {
@@ -328,6 +396,105 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
328396 } ) )
329397 } ) ;
330398 break ;
399+
400+ // --- Google Drive handlers ---
401+ case "driveConnect" :
402+ driveService . authenticate ( )
403+ . then ( ( ) => {
404+ sendResponse ( { status : "ok" } ) ;
405+ } )
406+ . catch ( error => {
407+ sendResponse ( { status : "error" , error : error . message } ) ;
408+ } ) ;
409+ isAsync = true ;
410+ break ;
411+
412+ case "driveDisconnect" :
413+ driveService . disconnect ( )
414+ . then ( async ( ) => {
415+ driveAutoSave = false ;
416+ driveFileId = null ;
417+ driveSyncStatus = 'idle' ;
418+ await saveDriveSettings ( ) ;
419+ sendResponse ( { status : "ok" } ) ;
420+ } )
421+ . catch ( error => {
422+ sendResponse ( { status : "error" , error : error . message } ) ;
423+ } ) ;
424+ isAsync = true ;
425+ break ;
426+
427+ case "driveGetStatus" :
428+ sendResponse ( {
429+ connected : driveService . isAuthenticated ( ) ,
430+ autoSave : driveAutoSave ,
431+ syncStatus : driveSyncStatus ,
432+ fileId : driveFileId
433+ } ) ;
434+ break ;
435+
436+ case "driveSetAutoSave" :
437+ driveAutoSave = request . enabled ;
438+ saveDriveSettings ( ) . then ( ( ) => {
439+ sendResponse ( { status : "ok" , autoSave : driveAutoSave } ) ;
440+ } ) ;
441+ isAsync = true ;
442+ break ;
443+
444+ case "driveSaveNow" :
445+ syncToDrive ( )
446+ . then ( ( ) => {
447+ sendResponse ( { status : "ok" , syncStatus : driveSyncStatus , fileId : driveFileId } ) ;
448+ } )
449+ . catch ( error => {
450+ sendResponse ( { status : "error" , error : error . message , syncStatus : driveSyncStatus } ) ;
451+ } ) ;
452+ isAsync = true ;
453+ break ;
454+
455+ case "driveListSessions" :
456+ driveService . listSessions ( )
457+ . then ( files => {
458+ sendResponse ( { status : "ok" , files } ) ;
459+ } )
460+ . catch ( error => {
461+ sendResponse ( { status : "error" , error : error . message } ) ;
462+ } ) ;
463+ isAsync = true ;
464+ break ;
465+
466+ case "driveLoadSession" :
467+ driveService . downloadSession ( request . fileId )
468+ . then ( jsonData => {
469+ if ( importSessionJSon ( jsonData ) ) {
470+ driveFileId = request . fileId ;
471+ return saveDriveSettings ( ) . then ( ( ) => saveSession ( ) ) . then ( ( ) => {
472+ sendResponse ( { status : "ok" } ) ;
473+ } ) ;
474+ } else {
475+ sendResponse ( { status : "error" , error : "Invalid session data" } ) ;
476+ }
477+ } )
478+ . catch ( error => {
479+ sendResponse ( { status : "error" , error : error . message } ) ;
480+ } ) ;
481+ isAsync = true ;
482+ break ;
483+
484+ case "driveDeleteSession" :
485+ driveService . deleteSession ( request . fileId )
486+ . then ( ( ) => {
487+ if ( driveFileId === request . fileId ) {
488+ driveFileId = null ;
489+ saveDriveSettings ( ) ;
490+ }
491+ sendResponse ( { status : "ok" } ) ;
492+ } )
493+ . catch ( error => {
494+ sendResponse ( { status : "error" , error : error . message } ) ;
495+ } ) ;
496+ isAsync = true ;
497+ break ;
331498 }
332499 return isAsync ; // Return true only if sendResponse is used asynchronously in any of the handled cases.
333500} ) ;
@@ -511,6 +678,8 @@ async function startSession() {
511678
512679async function clearSession ( ) {
513680 session . clearAnnotations ( ) ;
681+ driveFileId = null ;
682+ await saveDriveSettings ( ) ;
514683 await saveSession ( ) ;
515684}
516685
0 commit comments