2017-11-21 03:40:09 +09:00
/ * *
* Service Worker
* /
2020-05-23 13:19:31 +09:00
declare var self : ServiceWorkerGlobalScope ;
2017-11-21 03:40:09 +09:00
2021-01-23 00:56:06 +09:00
import { get , set } from 'idb-keyval' ;
2020-12-26 14:11:08 +09:00
import composeNotification from '@/sw/compose-notification' ;
2021-01-21 21:17:22 +09:00
import { I18n } from '@/scripts/i18n' ;
2021-01-23 00:56:06 +09:00
//#region Variables
2019-09-27 05:12:56 +09:00
const version = _VERSION_ ;
const cacheName = ` mk-cache- ${ version } ` ;
const apiUrl = ` ${ location . origin } /api/ ` ;
2021-02-09 20:09:45 +09:00
let lang : Promise < string > = get ( 'lang' ) . then ( async prelang = > {
if ( ! prelang ) return 'en-US' ;
return prelang ;
} ) ;
2021-01-23 00:56:06 +09:00
let i18n : I18n < any > ;
2021-01-23 01:10:12 +09:00
let pushesPool : any [ ] = [ ] ;
2021-01-23 00:56:06 +09:00
//#endregion
2021-02-09 20:09:45 +09:00
//#region Function: (Re)Load i18n instance
async function fetchLocale() {
//#region localeファイルの読み込み
// Service Workerは何度も起動しそのたびにlocaleを読み込むので、CacheStorageを使う
const localeUrl = ` /assets/locales/ ${ await lang } . ${ version } .json ` ;
let localeRes = await caches . match ( localeUrl ) ;
if ( ! localeRes ) {
localeRes = await fetch ( localeUrl ) ;
const clone = localeRes ? . clone ( ) ;
if ( ! clone ? . clone ( ) . ok ) return ;
caches . open ( cacheName ) . then ( cache = > cache . put ( localeUrl , clone ) ) ;
}
i18n = new I18n ( await localeRes . json ( ) ) ;
//#endregion
//#region i18nをきちんと読み込んだ後にやりたい処理
for ( const data of pushesPool ) {
const n = await composeNotification ( data , i18n ) ;
if ( n ) self . registration . showNotification ( . . . n ) ;
}
pushesPool = [ ] ;
//#endregion
}
2021-01-23 00:56:06 +09:00
//#endregion
//#region Lifecycle: Install
2017-11-27 22:00:48 +09:00
self . addEventListener ( 'install' , ev = > {
2021-02-09 20:09:45 +09:00
// Nothing to do
2019-09-27 05:12:56 +09:00
} ) ;
2021-01-23 00:56:06 +09:00
//#endregion
2019-09-27 05:12:56 +09:00
2021-01-23 00:56:06 +09:00
//#region Lifecycle: Activate
2019-09-27 05:12:56 +09:00
self . addEventListener ( 'activate' , ev = > {
ev . waitUntil (
caches . keys ( )
. then ( cacheNames = > Promise . all (
cacheNames
. filter ( ( v ) = > v !== cacheName )
. map ( name = > caches . delete ( name ) )
) )
. then ( ( ) = > self . clients . claim ( ) )
) ;
} ) ;
2021-01-23 00:56:06 +09:00
//#endregion
2019-09-27 05:12:56 +09:00
2021-02-07 10:46:26 +09:00
// TODO: 消せるかも ref. https://github.com/syuilo/misskey/pull/7108#issuecomment-774573666
2021-01-23 00:56:06 +09:00
//#region When: Fetching
2019-09-27 05:12:56 +09:00
self . addEventListener ( 'fetch' , ev = > {
if ( ev . request . method !== 'GET' || ev . request . url . startsWith ( apiUrl ) ) return ;
ev . respondWith (
caches . match ( ev . request )
. then ( response = > {
return response || fetch ( ev . request ) ;
} )
2021-02-09 20:09:45 +09:00
. catch ( ( ) = > new Response ( 'SW cathces error while fetching. You may not be connected to the Internet, or the server may be down.' , { status : 200 , statusText : 'OK SW' } ) )
2019-09-27 05:12:56 +09:00
) ;
2017-11-27 22:00:48 +09:00
} ) ;
2021-01-23 00:56:06 +09:00
//#endregion
2017-11-27 22:00:48 +09:00
2021-01-23 00:56:06 +09:00
//#region When: Caught Notification
2017-11-21 03:40:09 +09:00
self . addEventListener ( 'push' , ev = > {
// クライアント取得
2017-11-21 07:06:36 +09:00
ev . waitUntil ( self . clients . matchAll ( {
2017-11-21 03:40:09 +09:00
includeUncontrolled : true
2020-05-23 13:19:31 +09:00
} ) . then ( async clients = > {
2021-01-28 03:24:32 +09:00
// // クライアントがあったらストリームに接続しているということなので通知しない
// if (clients.length != 0) return;
2017-11-21 03:40:09 +09:00
2021-01-28 03:24:32 +09:00
const data = ev . data ? . json ( ) ;
2017-11-21 07:06:36 +09:00
2021-01-23 00:56:06 +09:00
// localeを読み込めておらずi18nがundefinedだった場合はpushesPoolにためておく
2021-01-28 03:24:32 +09:00
if ( ! i18n ) return pushesPool . push ( data ) ;
2021-01-23 00:56:06 +09:00
2021-01-28 03:24:32 +09:00
const n = await composeNotification ( data , i18n ) ;
2021-01-21 21:17:22 +09:00
if ( n ) return self . registration . showNotification ( . . . n ) ;
2017-11-21 07:06:36 +09:00
} ) ) ;
2017-11-21 03:40:09 +09:00
} ) ;
2021-01-23 00:56:06 +09:00
//#endregion
2021-01-21 21:17:22 +09:00
2021-01-28 03:24:32 +09:00
//#region Notification
self . addEventListener ( 'notificationclick' , ev = > {
const { action , notification } = ev ;
const { data } = notification ;
const { origin } = location ;
switch ( action ) {
case 'showUser' :
switch ( data . body . type ) {
case 'reaction' :
self . clients . openWindow ( ` ${ origin } /users/ ${ data . body . user . id } ` ) ;
break ;
default :
if ( 'note' in data . body ) {
self . clients . openWindow ( ` ${ origin } /notes/ ${ data . body . note . id } ` ) ;
}
}
break ;
default :
}
notification . close ( ) ;
} ) ;
self . addEventListener ( 'notificationclose' , async ev = > {
self . registration . showNotification ( 'notificationclose' ) ;
const { notification } = ev ;
2021-01-28 03:49:27 +09:00
const { data } = notification ;
2021-01-28 03:24:32 +09:00
if ( data . isNotification ) {
const { origin } = location ;
const accounts = await get ( 'accounts' ) ;
const account = accounts . find ( i = > i . id === data . userId ) ;
if ( ! account ) return ;
fetch ( ` ${ origin } /api/notifications/read ` , {
method : 'POST' ,
body : JSON.stringify ( {
i : account.token ,
notificationIds : [ data . data . id ]
} )
} ) ;
}
} ) ;
//#endregion
2021-01-23 00:56:06 +09:00
//#region When: Caught a message from the client
2021-01-21 21:17:22 +09:00
self . addEventListener ( 'message' , ev = > {
switch ( ev . data ) {
case 'clear' :
return ; // TODO
default :
break ;
}
if ( typeof ev . data === 'object' ) {
2021-01-24 18:17:42 +09:00
// E.g. '[object Array]' → 'array'
2021-01-21 21:17:22 +09:00
const otype = Object . prototype . toString . call ( ev . data ) . slice ( 8 , - 1 ) . toLowerCase ( ) ;
if ( otype === 'object' ) {
if ( ev . data . msg === 'initialize' ) {
2021-02-09 20:09:45 +09:00
lang = Promise . resolve ( ev . data . lang ) ;
set ( 'lang' , ev . data . lang ) ;
2021-01-23 00:56:06 +09:00
fetchLocale ( ) ;
2021-01-21 21:17:22 +09:00
}
}
}
} ) ;
2021-01-23 00:56:06 +09:00
//#endregion