Skip to content

Commit

Permalink
$mol_service review fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
zerkalica committed Nov 1, 2024
1 parent 4b10be0 commit d12f71f
Show file tree
Hide file tree
Showing 9 changed files with 144 additions and 105 deletions.
14 changes: 12 additions & 2 deletions notify/notify.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,21 @@ namespace $ {
}

static show( info: $mol_notify_info ) {
this.$.$mol_service_host.send(info)
this.$.$mol_service_worker.send(info)
}

}

$mol_notify_service
export class $mol_notify_service extends $mol_service_plugin {
static override message_data(data: {}) {
if ('uri' in data && 'message' in data) {
this.show(data as $mol_notify_info)
}
return null
}

static async show(info: $mol_notify_info) {}

}

}
53 changes: 53 additions & 0 deletions notify/notify.web.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,57 @@ namespace $ {
}

$.$mol_notify = $mol_notify_web

export class $mol_notify_service_web extends $mol_notify_service {
static override init() {
const scope = this.$.$mol_service_worker_web.scope()
scope.addEventListener( 'notificationclick', this.notification_click_event.bind(this))
}

protected static notification_click_event(event: NotificationEvent) {
event.waitUntil(this.notification_click(event.notification))
}

static override async show({ context: title, message: body, uri: data }: $mol_notify_info) {
const scope = this.$.$mol_service_worker_web.scope()
const tag = data
const existen = await scope.registration.getNotifications({ tag })

for( const not of existen ) {

if( not.body.indexOf( body ) !== -1 ) body = not.body
else if( body.indexOf( not.body ) === -1 ) body = not.body + '\n' + body

not.close()
}

// const vibrate = [ 100, 200, 300, 400, 500 ]

await scope.registration.showNotification( title, { body, data, /*vibrate,*/ tag } )

}

static async notification_click( notification: Notification ) {
const scope = this.$.$mol_service_worker_web.scope()

const clients = await scope.clients.matchAll({ includeUncontrolled: true, type: 'window' })
const last = clients.at(-1)

if( last ) {
await last.focus()
await last.navigate( notification.data )

return
}

await scope.clients.openWindow( notification.data )
}
}

$.$mol_notify_service = $mol_notify_service_web

export namespace $mol_service {
export const $mol_notify_service = $mol_notify_service_web
}

}
14 changes: 0 additions & 14 deletions notify/service/service.ts

This file was deleted.

53 changes: 0 additions & 53 deletions notify/service/service.web.ts

This file was deleted.

4 changes: 4 additions & 0 deletions offline/offline.web.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ namespace $ {
protected static override fetch(request: Request) {
return fetch(request)
}

static override activate() {
return this.$.$mol_service_worker_web.scope().clients.claim()
}
}

$.$mol_offline = $mol_offline_web
Expand Down
4 changes: 2 additions & 2 deletions service/plugin/plugin.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
namespace $ {
export class $mol_service_plugin extends $mol_object {
static init() {}
static before_install() {}
static prepare(event: $mol_service_prepare_event) { return null as null | undefined | boolean }
static install() { return null as undefined | null | Promise<unknown> }
static activate() { return null as undefined | null | Promise<unknown> }
static state_change() {}
Expand All @@ -12,6 +12,6 @@ namespace $ {
return null as null | Response | PromiseLike<Response>
}

static service() { return this.$.$mol_service_host }
static service() { return this.$.$mol_service_worker }
}
}
10 changes: 10 additions & 0 deletions service/prepare/event.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace $ {
export interface $mol_service_prepare_event {
preventDefault(): void
prompt(): Promise<unknown>
platforms: readonly string[]
userChoise: Promise<{
outcome: 'accepted' | 'dismissed'
}>
}
}
4 changes: 2 additions & 2 deletions service/host/host.ts → service/worker/worker.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
namespace $ {
export class $mol_service_host extends $mol_object {
static in_worker() { return typeof window === 'undefined' }
export class $mol_service_worker extends $mol_object {
protected static in_worker() { return typeof window === 'undefined' }

static path() { return 'web.js' }

Expand Down
93 changes: 61 additions & 32 deletions service/host/host.web.ts → service/worker/worker.web.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
/// <reference lib="webworker" />

namespace $ {
export class $mol_service_host_web extends $mol_service_host {

export class $mol_service_worker_web extends $mol_service_worker {
static is_supported() {
if( location.protocol !== 'https:' && location.hostname !== 'localhost' ) {
console.warn( 'HTTPS or localhost is required for service workers.' )
Expand Down Expand Up @@ -32,12 +33,7 @@ namespace $ {
return this._registration
}

protected static inited = false

static override init() {
if (this.inited) return
this.inited = true

if ( this.in_worker() ) {
this.worker_init()
} else if ( this.is_supported() ) {
Expand All @@ -48,6 +44,7 @@ namespace $ {
static plugins = [] as (typeof $mol_service_plugin)[]

static async registration_init() {
window.addEventListener( 'beforeinstallprompt' , this.prepare.bind(this) as unknown as (e: Event) => unknown )

const navigator = this.$.$mol_dom_context.navigator

Expand Down Expand Up @@ -102,15 +99,25 @@ namespace $ {
static async worker_init() {
await Promise.resolve()
const scope = this.scope()
scope.addEventListener( 'beforeinstallprompt' , this.before_install.bind(this) )
scope.addEventListener( 'install' , this.install.bind(this))
scope.addEventListener( 'activate' , this.activate.bind(this))
scope.addEventListener( 'message', this.message.bind(this))
scope.addEventListener( 'fetch', this.fetch_event.bind(this))
scope.addEventListener( 'fetch', this.fetch.bind(this))

this.plugins = Object.values(this.$.$mol_service)

for (const plugin of this.plugins) plugin.init()
for (const plugin of this.plugins) {
try {
plugin.init()
} catch (error) {
this.log_error(plugin, error)
}
}
}

protected static log_error(plugin: typeof $mol_service_plugin, error: unknown) {
;(error as Error).message = `${plugin.toString()}: ${(error as Error).message}`
console.error(error)
}

static scope() {
Expand All @@ -121,6 +128,7 @@ namespace $ {

@ $mol_action
static override send(data: {}) {
if ( this.in_worker() ) return
const worker = this.worker()

if (worker) {
Expand All @@ -130,69 +138,90 @@ namespace $ {
}
}

static prepare(event: $mol_service_prepare_event) {
for (const plugin of this.plugins) {
try {
if ( plugin.prepare(event) ) return
} catch (error) {
this.log_error(plugin, error)
}
}

}

static message(event: ExtendableMessageEvent) {
const data = event.data as string | null | {
[k: string]: unknown
}
if ( ! data || typeof data !== 'object' ) return false

for (const plugin of this.plugins) {
const result = plugin.message_data(data)
if (result) event.waitUntil(result)
}
}

static before_install(event: Event & { prompt?(): void }) {
for (const plugin of this.plugins) {
plugin.before_install()
try {
const result = plugin.message_data(data)
if (result) event.waitUntil(result)
} catch (error) {
this.log_error(plugin, error)
}
}

event.prompt?.()
}

static install(event: ExtendableEvent) {
for (const plugin of this.plugins) {
const result = plugin.install()
if (result) event.waitUntil(result)
try {
const result = plugin.install()
if (result) event.waitUntil(result)
} catch (error) {
this.log_error(plugin, error)
}
}

this.scope().skipWaiting()
}

static activate(event: ExtendableEvent) {
for (const plugin of this.plugins) {
const result = plugin.activate()
if (result) event.waitUntil(result)
try {
const result = plugin.activate()
if (result) event.waitUntil(result)
} catch (error) {
this.log_error(plugin, error)
}
}

event.waitUntil( this.scope().clients.claim() )

this.$.$mol_log3_done({
place: `${this}.activate()`,
message: 'Activated',
})
}

static fetch_event(event: FetchEvent) {
static fetch(event: FetchEvent) {
const request = event.request

for (const plugin of this.plugins) {
if (plugin.blocked(request)) {
return event.respondWith(this.blocked_response())
try {
if (plugin.blocked(request)) {
return event.respondWith(this.blocked_response())
}
} catch (error) {
this.log_error(plugin, error)
}
}

const waitUntil = event.waitUntil.bind(event)

for (const plugin of this.plugins) {
const response = plugin.modify(request, waitUntil)
if (response) return event.respondWith(response)
try {
const response = plugin.modify(request, waitUntil)
if (response) return event.respondWith(response)
} catch (error) {
this.log_error(plugin, error)
}
}
}
}

$.$mol_service_host = $mol_service_host_web
$.$mol_service_worker = $mol_service_worker_web

$mol_service_host_web.init()
$mol_service_worker_web.init()

}

0 comments on commit d12f71f

Please sign in to comment.