Skip to content

Commit

Permalink
$mol_service_worker refactor, extracted prompt events
Browse files Browse the repository at this point in the history
  • Loading branch information
zerkalica committed Nov 3, 2024
1 parent 10b0cef commit 1efed9b
Show file tree
Hide file tree
Showing 7 changed files with 97 additions and 134 deletions.
2 changes: 1 addition & 1 deletion notify/notify.web.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ namespace $ {
}

static override notification( notification: Notification ) {
const matched = this.$.$mol_service_worker_web.clients_filter({ includeUncontrolled: true, type: 'window' })
const matched = this.$.$mol_service_worker_web.clients_grab({ includeUncontrolled: true, type: 'window' })
const last = matched.at(-1)

if( last ) {
Expand Down
7 changes: 7 additions & 0 deletions offline/offline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ namespace $ {
'//cse.google.com/adsense/search/async-ads.js'
]

@ $mol_mem
static prompt() {
this.$.$mol_service_prompt.last()?.prompt()
}

static override blocked( request: Request ) {
const normalized_url = request.url.replace( /^https?:/, '' )

Expand Down Expand Up @@ -63,6 +68,8 @@ namespace $ {
}
}

$mol_offline.prompt()

export namespace $mol_service_plugin {
export let $mol_offline = $.$mol_offline
}
Expand Down
22 changes: 0 additions & 22 deletions service/message/event/event.ts

This file was deleted.

10 changes: 0 additions & 10 deletions service/prepare/event.ts

This file was deleted.

40 changes: 40 additions & 0 deletions service/prompt/prompt.web.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
namespace $ {
// https://web.dev/learn/pwa/installation-prompt
interface BeforeInstallEvent extends Event {
prompt(): Promise<unknown>
platforms: readonly string[]
userChoise: Promise<{
outcome: 'accepted' | 'dismissed'
}>
}

export class $mol_service_prompt extends $mol_object {
@ $mol_mem
protected static event() {
const install = (event: Event) => {
this.last(new this.$.$mol_service_prompt(event as BeforeInstallEvent))
}

const win = this.$.$mol_dom_context
win.addEventListener( 'beforeinstallprompt' , install)

return {
destructor: () => win.removeEventListener('beforeinstallprompt', install)
}
}

@ $mol_mem
static last(next?: $mol_service_prompt) {
this.event()
return next ?? null
}
platforms() { return this.native.platforms }

constructor(readonly native: BeforeInstallEvent) { super() }

prompt() { return $mol_wire_sync(this.native).prompt() }
choise_async() { return this.native.userChoise }
choise() { return $mol_wire_sync(this).choise_async() }
}

}
12 changes: 0 additions & 12 deletions service/worker/worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,8 @@ namespace $ {
static send(data: {}) { return null as unknown }

static init() {}

@ $mol_mem
static prepare(next?: $mol_service_prepare_event) {
next?.prompt()
return next ?? null
}

static claim() {}

@ $mol_mem
static prepare_choise() { return $mol_wire_sync(this).choise_promise()?.outcome ?? null }

static choise_promise() { return this.prepare()?.userChoise }

static blocked_response() {
return new Response(
null,
Expand Down
138 changes: 49 additions & 89 deletions service/worker/worker.web.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@ namespace $ {
throw new Error( 'HTTPS or localhost is required for service workers.' )
}

win.addEventListener( 'beforeinstallprompt' , this.prepare.bind(this) as unknown as (e: Event) => unknown )

return $mol_wire_sync(win.navigator.serviceWorker)
}

Expand Down Expand Up @@ -102,64 +100,65 @@ namespace $ {
static override claim() { return this.clients().claim() }

@ $mol_mem_key
static client(id: string) {
const client = this.clients().get(id)
static client<Cli extends Client>(id: string, next?: Cli) {
const client = next ?? (this.clients().get(id) as Cli)
return client ? $mol_wire_sync(client) : null
}

@ $mol_action
static clients_filter<Query extends ClientQueryOptions>(
query?: Query
) {
static clients_grab<Query extends ClientQueryOptions>(query?: Query) {
return this.clients().matchAll(query)
.map(client => $mol_wire_sync(client)) as unknown as readonly (
Query['type'] extends 'window'
? WindowClient
: Client
)[]
.map(client => this.client(client.id, client as Query extends 'window' ? WindowClient : Client)!)
}

static window_open(url: string | URL) {
return this.clients().openWindow(url)
}


static message_error(event: MessageEvent) {
const error = new $mol_error_mix('Message deserialization failed', { cause: event })
console.error(error)
const message = 'Message deserialization failed'

this.$.$mol_log3_fail({ place: `${this}.message_error()`, message })

const port = event.ports[0]
port?.postMessage({ result: null, error: error.toString() })
port?.postMessage({ result: null, error: message })
}

static message(event: ExtendableMessageEvent) {
const data = event.data as string | null | { [k: string]: unknown }
const port = event.ports[0]

if ( ! data || typeof data !== 'object' ) {
const error = data ? 'Message data empty' : 'Message data is not object'
return port?.postMessage({ error, result: null })
}

let result

for (const plugin of this.plugins()) {
try {
const result = plugin.data(data)
if (result) break
if (! result) continue
port?.postMessage({ error: null, result })
return
} catch (error) {
if ( $mol_fail_catch(error) ) {
this.$.$mol_log3_fail({
place: `${plugin}.data()`,
message: error.message,
error,
})
port?.postMessage({ error: error.toString(), result: null })
return null
}
if ( ! $mol_fail_catch(error) ) continue
this.plugin_error(error, `${plugin}.data()`)
port?.postMessage({ error: error.toString(), result: null })
return
}
}

port?.postMessage({ error: null, result })
return null
}

static plugin_error(error: unknown, place: string) {
if ($mol_promise_like(error)) {
error = new Error('Promise not allowed', { cause: error })
}

this.$.$mol_log3_fail({
place,
message: (error as Error).message,
error,
})
}

static install(event: ExtendableEvent) {
Expand All @@ -171,13 +170,8 @@ namespace $ {
try {
plugin.install()
} catch (error) {
if ($mol_fail_catch(error)) {
this.$.$mol_log3_fail({
place: `${plugin}.install()`,
message: error.message,
error,
})
}
if ( ! $mol_fail_catch(error) ) continue
this.plugin_error(error, `${plugin}.install()`)
}
}
}
Expand All @@ -187,13 +181,8 @@ namespace $ {
try {
plugin.activate()
} catch (error) {
if ($mol_fail_catch(error)) {
this.$.$mol_log3_fail({
place: `${plugin}.activate()`,
message: error.message,
error,
})
}
if ( ! $mol_fail_catch(error) ) continue
this.plugin_error(error, `${plugin}.activate()`)
}
}

Expand Down Expand Up @@ -225,13 +214,8 @@ namespace $ {
try {
plugin.push(event.data)
} catch (error) {
if ($mol_fail_catch(error)) {
this.$.$mol_log3_fail({
place: `${plugin}.push()`,
message: error.message,
error,
})
}
if ( ! $mol_fail_catch(error) ) continue
this.plugin_error(error, `${plugin}.push()`)
}
}
}
Expand All @@ -241,57 +225,33 @@ namespace $ {
try {
closing ? plugin.notification_close(event.notification) : plugin.notification(event.notification)
} catch (error) {
if ($mol_fail_catch(error)) {
this.$.$mol_log3_fail({
place: `${plugin}.notification()`,
message: error.message,
error,
})
}
if ( ! $mol_fail_catch(error) ) continue
this.plugin_error(error, `${plugin}.${closing ? 'notification_close' : 'notification'}()`)
}
}
}

@ $mol_action
static block(request: Request) {
static fetch(event: FetchEvent) {
for (const plugin of this.plugins_cache()) {
try {
if (plugin.blocked(request)) {
return this.blocked_response()
}
if (! plugin.blocked(event.request)) continue
return this.blocked_response()
} catch (error) {
if ($mol_fail_catch(error)) {
this.$.$mol_log3_fail({
place: `${plugin}.blocked()`,
message: error.message,
error,
})
}
this.plugin_error(error, `${plugin}.blocked()`)
}
}
return null
}

static fetch(event: FetchEvent) {
const response = this.block(event.request)
if (response) return response

for (const plugin of this.plugins_cache()) {
try {
if (plugin.need_modify(event.request)) {
return $mol_wire_async(plugin).modify(event.request)
}
if (! plugin.need_modify(event.request)) continue

return $mol_wire_async(plugin).modify(event.request)
.catch(error => {
this.plugin_error(error, `${plugin}.need_modify()`)
throw error
})
} catch (error) {
this.$.$mol_log3_fail($mol_promise_like(error) ? {
place: `${plugin}.need_modify()`,
message: 'Promise not allowed, FetchEvent.respondWith count not be called async',
promise: error,
} : {
place: `${plugin}.modify()`,
message: (error as Error).message,
error,
}
)
this.plugin_error(error, `${plugin}.need_modify()`)
}
}

Expand Down

0 comments on commit 1efed9b

Please sign in to comment.