const scope = ( self as any ) as ServiceWorkerGlobalScope ; const { clients } = scope ; import { IListRecord , imageDB , ISyncRecord } from '../image-db' ; import { resume } from '../sync/auth' ; import { getFileMeta } from '../sync/google-drive' ; import { ChangeType , downloadRemote , IChangeEvent , uploadLocal } from '../sync/sync' ; const VERSION = 2 ; console . log ( `SW Version ${ VERSION }` ) ; const FILES = [ '/app.min.js' , '/index.html' , '/manifest.json' , '/favicon.ico' , '/icons/icon-512.png' , ] ; scope . addEventListener ( 'install' , ( event ) => { event . waitUntil ( installHandler ( event ) ) ; } ) ; scope . addEventListener ( 'activate' , ( event ) => { clients . claim ( ) ; } ) ; scope . addEventListener ( 'fetch' , ( event ) => { event . respondWith ( fetchHandler ( event . request ) ) ; } ) ; scope . addEventListener ( 'sync' , ( event ) => { event . waitUntil ( syncHandler ( ) ) ; } ) ; async function installHandler ( event ) { const cache = await caches . open ( 'snapshot' ) ; cache . addAll ( FILES ) ; scope . skipWaiting ( ) ; } async function fetchHandler ( request ) { if ( request . mode === 'navigate' ) { const url = new URL ( request . url ) ; if ( url . origin === location . origin ) { request = new Request ( '/index.html' ) ; } } if ( request . method !== 'GET' ) { return fetch ( request ) ; } if ( request . url . match ( /googleapis.com/ ) ) { return networkFirst ( request ) ; } return cacheFirst ( request ) ; } async function cacheFirst ( request ) { const cache = await caches . open ( 'snapshot' ) ; const cacheResult = await cache . match ( request ) ; if ( cacheResult ) { return cacheResult ; } const fetchResult = await fetch ( request ) ; if ( fetchResult . ok ) { cache . put ( request , fetchResult . clone ( ) ) ; } return fetchResult ; } async function networkFirst ( request ) { const cache = await caches . open ( 'snapshot' ) ; let fetchResult = await fetch ( request ) ; try { fetchResult = await fetch ( request ) ; } catch ( e ) { console . log ( `Fetch error: ${ e }` ) ; } if ( fetchResult ) { if ( fetchResult . ok ) { cache . put ( request , fetchResult . clone ( ) ) ; } return fetchResult ; } return cache . match ( request ) ; } async function syncHandler ( ) { await resume ( ) ; const syncs = await imageDB . listSync ( ) ; for ( const sync of syncs ) { doSync ( sync ) ; } } async function doSync ( sync ) { let local ; let remote ; if ( sync . id ) { local = await imageDB . retrieveRecord ( sync . id ) ; } if ( sync . guid ) { remote = await getFileMeta ( sync . guid ) ; } if ( local && sync . upload ) { await uploadLocal ( local , local . localImageChanges , remote ) ; } else if ( remote && ! sync . upload ) { const localId = await downloadRemote ( remote , true , local ) ; if ( localId ) { sendMessage ( { id : localId , type : ChangeType . ADD } ) ; } } imageDB . removeSync ( sync . id , sync . guid ) ; } async function sendMessage ( change ) { const windows = await clients . matchAll ( { includeUncontrolled : false , type : 'window' , } ) ; for ( const client of windows ) { client . postMessage ( { channel : 'sync' , data : change } ) ; } }