backpage
Advanced tools
Comparing version 0.0.2-1 to 0.0.2-2
@@ -17,4 +17,6 @@ import type { ReactNode } from 'react'; | ||
private root; | ||
private element; | ||
private mutationObserver; | ||
private notifyOptions; | ||
private connected; | ||
constructor({ title, notify: notifyOptions, events, ...options }?: BackPageOptions); | ||
@@ -21,0 +23,0 @@ getURL(): Promise<string>; |
@@ -35,2 +35,8 @@ import { createRequire } from 'module'; | ||
}); | ||
Object.defineProperty(this, "element", { | ||
enumerable: true, | ||
configurable: true, | ||
writable: true, | ||
value: void 0 | ||
}); | ||
Object.defineProperty(this, "mutationObserver", { | ||
@@ -48,2 +54,8 @@ enumerable: true, | ||
}); | ||
Object.defineProperty(this, "connected", { | ||
enumerable: true, | ||
configurable: true, | ||
writable: true, | ||
value: false | ||
}); | ||
Object.defineProperty(this, "lastElementDataId", { | ||
@@ -62,14 +74,23 @@ enumerable: true, | ||
}; | ||
this.content = window.document.createElement('div'); | ||
this.root = createRoot(this.content); | ||
this.tunnel = | ||
'token' in options | ||
? new CloudTunnel(options) | ||
: new FrontPageTunnel(options); | ||
const content = window.document.createElement('div'); | ||
const root = createRoot(content); | ||
const tunnel = 'token' in options | ||
? new CloudTunnel(options) | ||
: new FrontPageTunnel(options); | ||
const notifyFallback = notifyOptions === null || notifyOptions === void 0 ? void 0 : notifyOptions.fallback; | ||
if (notifyFallback) { | ||
this.tunnel.onNotifyTimeout(notification => this.handleNotifyTimeout(notification, notifyFallback)); | ||
tunnel.onNotifyTimeout(notification => this.handleNotifyTimeout(notification, notifyFallback)); | ||
} | ||
this.tunnel.onEvent(event => this.handleEvent(event)); | ||
this.tunnel.update({ | ||
tunnel.onEvent(event => this.handleEvent(event)); | ||
tunnel.onClientConnected(connected => { | ||
this.connected = connected; | ||
if (connected) { | ||
root.render(this.element); | ||
} | ||
else { | ||
root.render(React.createElement(React.Fragment, null)); | ||
tunnel.reset(); | ||
} | ||
}); | ||
tunnel.update({ | ||
settings: { | ||
@@ -80,6 +101,6 @@ events, | ||
if (title !== undefined) { | ||
this.tunnel.update({ title }); | ||
tunnel.update({ title }); | ||
} | ||
this.mutationObserver = new window.MutationObserver(() => this.updateHTML()); | ||
this.mutationObserver.observe(this.content, { | ||
const mutationObserver = new window.MutationObserver(() => this.updateHTML()); | ||
mutationObserver.observe(content, { | ||
attributes: true, | ||
@@ -90,2 +111,6 @@ childList: true, | ||
}); | ||
this.content = content; | ||
this.root = root; | ||
this.tunnel = tunnel; | ||
this.mutationObserver = mutationObserver; | ||
} | ||
@@ -111,3 +136,6 @@ getURL() { | ||
render(node) { | ||
this.root.render(React.createElement(BackPageContext.Provider, { value: this }, node)); | ||
this.element = (React.createElement(BackPageContext.Provider, { value: this }, node)); | ||
if (this.connected) { | ||
this.root.render(this.element); | ||
} | ||
} | ||
@@ -134,2 +162,5 @@ unmount() { | ||
updateHTML() { | ||
if (!this.connected) { | ||
return; | ||
} | ||
let { content, tunnel } = this; | ||
@@ -136,0 +167,0 @@ for (const element of content.querySelectorAll(`:not([${PAGE_EVENT_TARGET_ID_KEY}])`)) { |
@@ -10,2 +10,3 @@ import type { PlainNode } from 'plain-dom'; | ||
private updateDebounceImmediate; | ||
reset(): void; | ||
update(update: TunnelUpdate): void; | ||
@@ -29,2 +30,6 @@ private _update; | ||
protected handleMessage(message: FrontBackMessage): void; | ||
clientConnected: boolean; | ||
private onClientConnectedCallbackSet; | ||
onClientConnected(callback: TunnelClientConnectedCallback): void; | ||
private emitClientConnected; | ||
protected addClient(client: TunnelClient): void; | ||
@@ -48,2 +53,3 @@ protected removeClient(client: TunnelClient): void; | ||
export type TunnelEventCallback = (event: FrontBackEvent) => void; | ||
export type TunnelClientConnectedCallback = (connected: boolean) => void; | ||
export type TunnelClient = { | ||
@@ -50,0 +56,0 @@ send(message: BackFrontMessage): Promise<void>; |
@@ -57,3 +57,21 @@ import { randomUUID } from 'crypto'; | ||
}); | ||
Object.defineProperty(this, "clientConnected", { | ||
enumerable: true, | ||
configurable: true, | ||
writable: true, | ||
value: false | ||
}); | ||
Object.defineProperty(this, "onClientConnectedCallbackSet", { | ||
enumerable: true, | ||
configurable: true, | ||
writable: true, | ||
value: new Set() | ||
}); | ||
} | ||
reset() { | ||
clearImmediate(this.updateDebounceImmediate); | ||
this.snapshot = undefined; | ||
this.pendingUpdate = undefined; | ||
this.updateDebounceImmediate = undefined; | ||
} | ||
update(update) { | ||
@@ -70,3 +88,3 @@ clearImmediate(this.updateDebounceImmediate); | ||
const { settings, title, body } = pendingUpdate; | ||
if (!settings && !snapshot && !body) { | ||
if (!snapshot && !body) { | ||
return; | ||
@@ -171,3 +189,13 @@ } | ||
} | ||
onClientConnected(callback) { | ||
this.onClientConnectedCallbackSet.add(callback); | ||
} | ||
emitClientConnected() { | ||
const { clientConnected } = this; | ||
for (const callback of this.onClientConnectedCallbackSet) { | ||
callback(clientConnected); | ||
} | ||
} | ||
addClient(client) { | ||
const { clientStateMap } = this; | ||
const clientState = { | ||
@@ -177,7 +205,15 @@ idle: true, | ||
}; | ||
this.clientStateMap.set(client, clientState); | ||
clientStateMap.set(client, clientState); | ||
this.sendUpdateToClient(client, clientState); | ||
if (!this.clientConnected) { | ||
this.clientConnected = true; | ||
this.emitClientConnected(); | ||
} | ||
} | ||
removeClient(client) { | ||
this.clientStateMap.delete(client); | ||
if (this.clientStateMap.size === 0 && this.clientConnected) { | ||
this.clientConnected = false; | ||
this.emitClientConnected(); | ||
} | ||
} | ||
@@ -184,0 +220,0 @@ sendUpdateToClient(client, clientState) { |
import type { FrontBackEvent } from '../shared/index.js'; | ||
export type InputEventTarget = HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement; | ||
export declare function buildEvent(event: Event): FrontBackEvent | undefined; |
{ | ||
"name": "backpage", | ||
"version": "0.0.2-1", | ||
"version": "0.0.2-2", | ||
"description": "Naive static HTML streaming based on React for Node.js CLI applications.", | ||
@@ -5,0 +5,0 @@ "repository": "https://github.com/vilicvane/backpage.git", |
@@ -35,2 +35,10 @@ import {randomUUID} from 'crypto'; | ||
reset(): void { | ||
clearImmediate(this.updateDebounceImmediate); | ||
this.snapshot = undefined; | ||
this.pendingUpdate = undefined; | ||
this.updateDebounceImmediate = undefined; | ||
} | ||
update(update: TunnelUpdate): void { | ||
@@ -53,3 +61,3 @@ clearImmediate(this.updateDebounceImmediate); | ||
if (!settings && !snapshot && !body) { | ||
if (!snapshot && !body) { | ||
return; | ||
@@ -196,3 +204,22 @@ } | ||
clientConnected = false; | ||
private onClientConnectedCallbackSet = | ||
new Set<TunnelClientConnectedCallback>(); | ||
onClientConnected(callback: TunnelClientConnectedCallback): void { | ||
this.onClientConnectedCallbackSet.add(callback); | ||
} | ||
private emitClientConnected(): void { | ||
const {clientConnected} = this; | ||
for (const callback of this.onClientConnectedCallbackSet) { | ||
callback(clientConnected); | ||
} | ||
} | ||
protected addClient(client: TunnelClient): void { | ||
const {clientStateMap} = this; | ||
const clientState: ClientState = { | ||
@@ -203,5 +230,10 @@ idle: true, | ||
this.clientStateMap.set(client, clientState); | ||
clientStateMap.set(client, clientState); | ||
this.sendUpdateToClient(client, clientState); | ||
if (!this.clientConnected) { | ||
this.clientConnected = true; | ||
this.emitClientConnected(); | ||
} | ||
} | ||
@@ -211,2 +243,7 @@ | ||
this.clientStateMap.delete(client); | ||
if (this.clientStateMap.size === 0 && this.clientConnected) { | ||
this.clientConnected = false; | ||
this.emitClientConnected(); | ||
} | ||
} | ||
@@ -272,2 +309,4 @@ | ||
export type TunnelClientConnectedCallback = (connected: boolean) => void; | ||
type ClientState = { | ||
@@ -274,0 +313,0 @@ idle: boolean; |
import type {FrontBackEvent, FrontBackEventEffects} from '../shared/index.js'; | ||
import {PAGE_EVENT_TARGET_ID_KEY} from '../shared/index.js'; | ||
export type InputEventTarget = | ||
| HTMLInputElement | ||
| HTMLTextAreaElement | ||
| HTMLSelectElement; | ||
const EVENT_BUILDER_MAP = new Map< | ||
@@ -32,8 +37,3 @@ string, | ||
target: { | ||
value: ( | ||
event.target as | ||
| HTMLInputElement | ||
| HTMLSelectElement | ||
| HTMLTextAreaElement | ||
).value, | ||
value: (event.target as InputEventTarget).value, | ||
}, | ||
@@ -40,0 +40,0 @@ }, |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
242428
5070