Support for import as module, wabac.js 2.20 (#364)
- Extensibility for AWP (customizable toolbar, pass replay iframe messages to parent) - Support export as module, build separate index.js for module in addition to ui.js - Update to wabac.js 2.20.0 - bump to 2.2.0
This commit is contained in:
+1
-1
@@ -78,7 +78,7 @@ export class ReplayWebApp extends LitElement {
|
||||
swErrorMsg: TemplateResult<1> | string | null = null;
|
||||
|
||||
protected swName?: string;
|
||||
private swmanager: SWManager | null;
|
||||
protected swmanager: SWManager | null;
|
||||
private useRuffle = false;
|
||||
|
||||
private droppedFile: File | null = null;
|
||||
|
||||
+11
-1
@@ -5,9 +5,15 @@ import fasUpload from "@fortawesome/fontawesome-free/svgs/solid/upload.svg";
|
||||
import { customElement, property } from "lit/decorators.js";
|
||||
|
||||
export interface FileWithPath extends File {
|
||||
readonly path: string;
|
||||
path: string;
|
||||
}
|
||||
|
||||
declare let window: Window & {
|
||||
electron?: {
|
||||
getPath: (file: File) => string;
|
||||
};
|
||||
};
|
||||
|
||||
// ===========================================================================
|
||||
@customElement("wr-chooser")
|
||||
export class Chooser extends LitElement {
|
||||
@@ -89,6 +95,10 @@ export class Chooser extends LitElement {
|
||||
setFile(file: FileWithPath) {
|
||||
this.file = file;
|
||||
// file.path only available in electron app
|
||||
if (IS_APP && window.electron?.getPath) {
|
||||
this.file.path = window.electron.getPath(this.file);
|
||||
}
|
||||
|
||||
this.fileDisplayName = "file://" + (file.path || file.name);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
/*eslint-env node */
|
||||
|
||||
// @ts-expect-error [// TODO: Fix this the next time the file is edited.] - TS7016 - Could not find a declaration file for module '@webrecorder/wabac/src/loaders'. 'node_modules/@webrecorder/wabac/src/loaders.js' implicitly has an 'any' type.
|
||||
import { CollectionLoader } from "@webrecorder/wabac/src/loaders";
|
||||
import { CollectionLoader } from "@webrecorder/wabac/swlib";
|
||||
import { type IpcRendererEvent } from "electron";
|
||||
|
||||
const { ipcRenderer, contextBridge } = require("electron");
|
||||
const { ipcRenderer, contextBridge, webUtils } = require("electron");
|
||||
|
||||
contextBridge.exposeInMainWorld("electron", { IS_APP: true });
|
||||
contextBridge.exposeInMainWorld("electron", {
|
||||
IS_APP: true,
|
||||
getPath(file: File) {
|
||||
return webUtils.getPathForFile(file);
|
||||
},
|
||||
});
|
||||
|
||||
const dbs = {};
|
||||
|
||||
|
||||
@@ -16,8 +16,7 @@ import {
|
||||
import path from "path";
|
||||
import fs from "fs";
|
||||
|
||||
// @ts-expect-error [// TODO: Fix this the next time the file is edited.] - TS7016 - Could not find a declaration file for module '@webrecorder/wabac/src/rewrite'. 'node_modules/@webrecorder/wabac/src/rewrite/index.js' implicitly has an 'any' type.
|
||||
import { ArchiveResponse, Rewriter } from "@webrecorder/wabac/src/rewrite";
|
||||
import { ArchiveResponse, Rewriter } from "@webrecorder/wabac";
|
||||
|
||||
import { PassThrough, Readable } from "stream";
|
||||
|
||||
@@ -414,7 +413,7 @@ class ElectronReplayApp {
|
||||
headers = new Headers(headers);
|
||||
const date = new Date();
|
||||
|
||||
let response = new ArchiveResponse({
|
||||
let response: ArchiveResponse = new ArchiveResponse({
|
||||
payload,
|
||||
headers,
|
||||
status,
|
||||
@@ -443,6 +442,9 @@ class ElectronReplayApp {
|
||||
headers = Object.fromEntries(response.headers.entries());
|
||||
|
||||
let data = await response.getBuffer();
|
||||
if (!data) {
|
||||
data = new Uint8Array();
|
||||
}
|
||||
|
||||
if (status === 206 || status === 200) {
|
||||
const { statusCode, start, end } = this.parseRange(
|
||||
@@ -456,9 +458,9 @@ class ElectronReplayApp {
|
||||
status = statusCode;
|
||||
}
|
||||
|
||||
data = this._bufferToStream(data);
|
||||
const result = this._bufferToStream(data);
|
||||
|
||||
callback({ statusCode: status, headers, data });
|
||||
callback({ statusCode: status, headers, data: result });
|
||||
} catch (e) {
|
||||
console.warn(e);
|
||||
}
|
||||
|
||||
+1
-4
@@ -85,7 +85,7 @@ class Embed extends LitElement {
|
||||
replayfile = defaultReplayFile;
|
||||
mainElementName = "replay-app-main";
|
||||
appName = "ReplayWeb.page";
|
||||
customConfig = null;
|
||||
customConfig: Record<string, string | boolean> | null = null;
|
||||
reloadCount = 0;
|
||||
|
||||
isCrossOrigin: boolean | undefined;
|
||||
@@ -255,14 +255,11 @@ class Embed extends LitElement {
|
||||
}
|
||||
|
||||
mergeConfigs() {
|
||||
// TODO: Fix this the next time the file is edited.
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||
if (!this.customConfig) {
|
||||
return this.config;
|
||||
}
|
||||
|
||||
if (this.config) {
|
||||
// @ts-expect-error - TS2339 - Property 'customConfig' does not exist on type 'Embed'. | TS2339 - Property 'config' does not exist on type 'Embed'.
|
||||
const config = { ...this.customConfig, ...JSON.parse(this.config) };
|
||||
return JSON.stringify(config);
|
||||
} else {
|
||||
|
||||
@@ -10,6 +10,7 @@ import { Pages } from "./pages";
|
||||
import { PageEntry } from "./pageentry";
|
||||
import { Replay } from "./replay";
|
||||
import { Sorter } from "./sorter";
|
||||
import { SWManager } from "./swmanager";
|
||||
import { URLResources } from "./url-resources";
|
||||
import { Embed } from "./embed";
|
||||
import "./shoelace";
|
||||
@@ -41,6 +42,9 @@ export {
|
||||
Sorter,
|
||||
URLResources,
|
||||
Embed,
|
||||
SWManager,
|
||||
};
|
||||
|
||||
export type { ItemType, URLResource } from "./types";
|
||||
|
||||
export * from "./misc";
|
||||
|
||||
+5
-3
@@ -89,7 +89,7 @@ class ItemIndex extends LitElement {
|
||||
for (const item of this.items) {
|
||||
if (
|
||||
item.sourceUrl.indexOf(this.query) >= 0 ||
|
||||
item.filename.indexOf(this.query) >= 0 ||
|
||||
(item.filename && item.filename.indexOf(this.query) >= 0) ||
|
||||
Boolean(item.loadUrl && item.loadUrl.indexOf(this.query) >= 0) ||
|
||||
(item.title && item.title.indexOf(this.query) >= 0)
|
||||
) {
|
||||
@@ -383,8 +383,10 @@ class ItemIndex extends LitElement {
|
||||
>ArchiveWeb.page</a
|
||||
>
|
||||
to save pages as you browse the web, or
|
||||
<a href="https://browsertrix.com" target="_blank">sign up for Browsertrix</a> to archive
|
||||
entire websites with automated crawling!
|
||||
<a href="https://browsertrix.com" target="_blank"
|
||||
>sign up for Browsertrix</a
|
||||
>
|
||||
to archive entire websites with automated crawling!
|
||||
</p>
|
||||
`;
|
||||
}
|
||||
|
||||
+236
-235
@@ -1,10 +1,4 @@
|
||||
import {
|
||||
LitElement,
|
||||
html,
|
||||
css,
|
||||
type PropertyValues,
|
||||
type TemplateResult,
|
||||
} from "lit";
|
||||
import { LitElement, html, css, type PropertyValues } from "lit";
|
||||
import { property } from "lit/decorators.js";
|
||||
import { ref, createRef, type Ref } from "lit/directives/ref.js";
|
||||
import type {
|
||||
@@ -216,7 +210,8 @@ class Item extends LitElement {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.showSidebar = localStorage.getItem("pages:showSidebar") === "1";
|
||||
this.showSidebar =
|
||||
localStorage.getItem("pages:showSidebar") === "1" && this.browsable;
|
||||
}
|
||||
|
||||
firstUpdated() {
|
||||
@@ -547,7 +542,7 @@ class Item extends LitElement {
|
||||
this.tabData.view = "pages";
|
||||
}
|
||||
|
||||
if (this.tabData.url && this.tabData.query) {
|
||||
if (this.tabData.url && this.tabData.query && this.browsable) {
|
||||
this.showSidebar = true;
|
||||
}
|
||||
}
|
||||
@@ -705,7 +700,7 @@ class Item extends LitElement {
|
||||
}
|
||||
|
||||
.replay-bar {
|
||||
padding: 0.5em 0em 0.5em 0.5em;
|
||||
padding: 0.5em;
|
||||
max-width: none;
|
||||
border-bottom: solid 0.1rem #97989a;
|
||||
width: 100%;
|
||||
@@ -1110,13 +1105,101 @@ class Item extends LitElement {
|
||||
</nav>`;
|
||||
}
|
||||
|
||||
protected renderToolbarLeft() {
|
||||
const isReplay = !!this.tabData.url;
|
||||
|
||||
return html` ${this.browsable
|
||||
? html` <a
|
||||
href="#"
|
||||
role="button"
|
||||
class="button narrow is-borderless is-hidden-mobile ${!isReplay
|
||||
? "grey-disabled"
|
||||
: ""}"
|
||||
@click="${this.onShowPages}"
|
||||
@keyup="${clickOnSpacebarPress}"
|
||||
?disabled="${!isReplay}"
|
||||
title="Browse Contents"
|
||||
aria-label="Browse Contents"
|
||||
aria-controls="contents"
|
||||
>
|
||||
<span class="icon is-small">
|
||||
<fa-icon
|
||||
size="1.0em"
|
||||
class="has-text-grey"
|
||||
aria-hidden="true"
|
||||
.svg="${farListAlt}"
|
||||
></fa-icon>
|
||||
</span>
|
||||
</a>`
|
||||
: ""}
|
||||
<a
|
||||
href="#"
|
||||
role="button"
|
||||
class="button narrow is-borderless"
|
||||
@click="${this.onGoBack}"
|
||||
@keyup="${clickOnSpacebarPress}"
|
||||
title="Back"
|
||||
aria-label="Back"
|
||||
>
|
||||
<span class="icon is-small">
|
||||
<fa-icon
|
||||
size="1.0em"
|
||||
class="has-text-grey"
|
||||
aria-hidden="true"
|
||||
.svg="${fasLeft}"
|
||||
></fa-icon>
|
||||
</span>
|
||||
</a>
|
||||
<a
|
||||
href="#"
|
||||
role="button"
|
||||
class="button narrow is-borderless"
|
||||
@click="${this.onGoForward}"
|
||||
@keyup="${clickOnSpacebarPress}"
|
||||
title="Forward"
|
||||
aria-label="Forward"
|
||||
>
|
||||
<span class="icon is-small">
|
||||
<fa-icon
|
||||
size="1.0em"
|
||||
class="has-text-grey"
|
||||
aria-hidden="true"
|
||||
.svg="${fasRight}"
|
||||
></fa-icon>
|
||||
</span>
|
||||
</a>
|
||||
<a
|
||||
href="#"
|
||||
role="button"
|
||||
class="button narrow is-borderless ${this.isLoading
|
||||
? "is-loading"
|
||||
: ""}"
|
||||
id="refresh"
|
||||
@click="${this.onRefresh}"
|
||||
@keyup="${clickOnSpacebarPress}"
|
||||
title="Reload"
|
||||
aria-label="Reload"
|
||||
>
|
||||
<span class="icon is-small">
|
||||
${!this.isLoading
|
||||
? html`
|
||||
<fa-icon
|
||||
size="1.0em"
|
||||
class="has-text-grey"
|
||||
aria-hidden="true"
|
||||
.svg="${fasRefresh}"
|
||||
></fa-icon>
|
||||
`
|
||||
: ""}
|
||||
</span>
|
||||
</a>`;
|
||||
}
|
||||
|
||||
renderLocationBar() {
|
||||
if (this.embed === "replayonly" || this.embed == "replay-with-info") {
|
||||
return "";
|
||||
}
|
||||
|
||||
const dateStr = tsToDate(this.ts).toLocaleString();
|
||||
|
||||
const isReplay = !!this.tabData.url;
|
||||
|
||||
const showFavIcon = isReplay && this.favIconUrl;
|
||||
@@ -1129,92 +1212,7 @@ class Item extends LitElement {
|
||||
>
|
||||
<nav class="replay-bar" aria-label="replay">
|
||||
<div class="field has-addons">
|
||||
${this.browsable
|
||||
? html` <a
|
||||
href="#"
|
||||
role="button"
|
||||
class="button narrow is-borderless is-hidden-mobile ${!isReplay
|
||||
? "grey-disabled"
|
||||
: ""}"
|
||||
@click="${this.onShowPages}"
|
||||
@keyup="${clickOnSpacebarPress}"
|
||||
?disabled="${!isReplay}"
|
||||
title="Browse Contents"
|
||||
aria-label="Browse Contents"
|
||||
aria-controls="contents"
|
||||
>
|
||||
<span class="icon is-small">
|
||||
<fa-icon
|
||||
size="1.0em"
|
||||
class="has-text-grey"
|
||||
aria-hidden="true"
|
||||
.svg="${farListAlt}"
|
||||
></fa-icon>
|
||||
</span>
|
||||
</a>`
|
||||
: ""}
|
||||
<a
|
||||
href="#"
|
||||
role="button"
|
||||
class="button narrow is-borderless"
|
||||
@click="${this.onGoBack}"
|
||||
@keyup="${clickOnSpacebarPress}"
|
||||
title="Back"
|
||||
aria-label="Back"
|
||||
>
|
||||
<span class="icon is-small">
|
||||
<fa-icon
|
||||
size="1.0em"
|
||||
class="has-text-grey"
|
||||
aria-hidden="true"
|
||||
.svg="${fasLeft}"
|
||||
></fa-icon>
|
||||
</span>
|
||||
</a>
|
||||
<a
|
||||
href="#"
|
||||
role="button"
|
||||
class="button narrow is-borderless"
|
||||
@click="${this.onGoForward}"
|
||||
@keyup="${clickOnSpacebarPress}"
|
||||
title="Forward"
|
||||
aria-label="Forward"
|
||||
>
|
||||
<span class="icon is-small">
|
||||
<fa-icon
|
||||
size="1.0em"
|
||||
class="has-text-grey"
|
||||
aria-hidden="true"
|
||||
.svg="${fasRight}"
|
||||
></fa-icon>
|
||||
</span>
|
||||
</a>
|
||||
<a
|
||||
href="#"
|
||||
role="button"
|
||||
class="button narrow is-borderless ${this.isLoading
|
||||
? "is-loading"
|
||||
: ""}"
|
||||
id="refresh"
|
||||
@click="${this.onRefresh}"
|
||||
@keyup="${clickOnSpacebarPress}"
|
||||
title="Reload"
|
||||
aria-label="Reload"
|
||||
>
|
||||
<span class="icon is-small">
|
||||
${!this.isLoading
|
||||
? html`
|
||||
<fa-icon
|
||||
size="1.0em"
|
||||
class="has-text-grey"
|
||||
aria-hidden="true"
|
||||
.svg="${fasRefresh}"
|
||||
></fa-icon>
|
||||
`
|
||||
: ""}
|
||||
</span>
|
||||
</a>
|
||||
${this.renderExtraToolbar()}
|
||||
${this.renderToolbarLeft()}
|
||||
<form @submit="${this.onSubmit}">
|
||||
<div
|
||||
class="control is-expanded ${showFavIcon ? "has-icons-left" : ""}"
|
||||
@@ -1236,58 +1234,106 @@ class Item extends LitElement {
|
||||
: html``}
|
||||
</div>
|
||||
</form>
|
||||
${this.renderToolbarRight()}
|
||||
</div>
|
||||
</nav>
|
||||
<p id="skip-replay-target" tabindex="-1" class="is-sr-only">Skipped</p>`;
|
||||
}
|
||||
|
||||
<div
|
||||
class="dropdown is-right ${this.menuActive ? "is-active" : ""}"
|
||||
@click="${() => (this.menuActive = false)}"
|
||||
protected renderToolbarRight() {
|
||||
const isReplay = !!this.tabData.url;
|
||||
|
||||
const dateStr = tsToDate(this.ts).toLocaleString();
|
||||
|
||||
return html` <div
|
||||
class="dropdown is-right ${this.menuActive ? "is-active" : ""}"
|
||||
@click="${() => (this.menuActive = false)}"
|
||||
>
|
||||
<a
|
||||
href="#"
|
||||
role="button"
|
||||
class="button narrow is-borderless is-hidden-touch"
|
||||
id="fullscreen"
|
||||
@click="${this.onFullscreenToggle}"
|
||||
@keyup="${clickOnSpacebarPress}"
|
||||
title="${this.isFullscreen ? "Exit Full Screen" : "Full Screen"}"
|
||||
aria-label="${this.isFullscreen ? "Exit Fullscreen" : "Fullscreen"}"
|
||||
>
|
||||
<span class="icon is-small">
|
||||
<fa-icon
|
||||
size="1.0em"
|
||||
class="has-text-grey"
|
||||
aria-hidden="true"
|
||||
.svg="${this.isFullscreen ? fasUnfullscreen : fasFullscreen}"
|
||||
></fa-icon>
|
||||
</span>
|
||||
</a>
|
||||
<div class="dropdown-trigger">
|
||||
<button
|
||||
class="button is-borderless"
|
||||
aria-haspopup="true"
|
||||
aria-controls="menu-dropdown"
|
||||
aria-expanded="${this.menuActive}"
|
||||
@click="${this.onMenu}"
|
||||
aria-label="more replay controls"
|
||||
>
|
||||
<span class="icon is-small">
|
||||
<fa-icon
|
||||
size="1.0em"
|
||||
class="has-text-grey"
|
||||
aria-hidden="true"
|
||||
.svg="${fasMenuV}"
|
||||
></fa-icon>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="dropdown-menu" id="menu-dropdown">
|
||||
<div class="dropdown-content">
|
||||
<a
|
||||
href="#"
|
||||
role="button"
|
||||
class="dropdown-item is-hidden-desktop"
|
||||
@click="${this.onFullscreenToggle}"
|
||||
@keyup="${clickOnSpacebarPress}"
|
||||
>
|
||||
<a
|
||||
href="#"
|
||||
role="button"
|
||||
class="button narrow is-borderless is-hidden-touch"
|
||||
id="fullscreen"
|
||||
@click="${this.onFullscreenToggle}"
|
||||
@keyup="${clickOnSpacebarPress}"
|
||||
title="${this.isFullscreen ? "Exit Full Screen" : "Full Screen"}"
|
||||
aria-label="${this.isFullscreen
|
||||
? "Exit Fullscreen"
|
||||
: "Fullscreen"}"
|
||||
>
|
||||
<span class="icon is-small">
|
||||
<fa-icon
|
||||
size="1.0em"
|
||||
class="has-text-grey"
|
||||
aria-hidden="true"
|
||||
.svg="${this.isFullscreen ? fasUnfullscreen : fasFullscreen}"
|
||||
></fa-icon>
|
||||
</span>
|
||||
</a>
|
||||
<div class="dropdown-trigger">
|
||||
<button
|
||||
class="button is-borderless"
|
||||
aria-haspopup="true"
|
||||
aria-controls="menu-dropdown"
|
||||
aria-expanded="${this.menuActive}"
|
||||
@click="${this.onMenu}"
|
||||
aria-label="more replay controls"
|
||||
<span class="icon is-small">
|
||||
<fa-icon
|
||||
size="1.0em"
|
||||
class="has-text-grey"
|
||||
aria-hidden="true"
|
||||
.svg="${this.isFullscreen ? fasUnfullscreen : fasFullscreen}"
|
||||
></fa-icon>
|
||||
</span>
|
||||
<span>Full Screen</span>
|
||||
</a>
|
||||
${this.browsable
|
||||
? html` <a
|
||||
href="#"
|
||||
role="button"
|
||||
class="dropdown-item is-hidden-tablet ${!isReplay
|
||||
? "grey-disabled"
|
||||
: ""}"
|
||||
@click="${this.onShowPages}"
|
||||
@keyup="${clickOnSpacebarPress}"
|
||||
>
|
||||
<span class="icon is-small">
|
||||
<fa-icon
|
||||
size="1.0em"
|
||||
class="has-text-grey"
|
||||
aria-hidden="true"
|
||||
.svg="${fasMenuV}"
|
||||
.svg="${farListAlt}"
|
||||
></fa-icon>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="dropdown-menu" id="menu-dropdown">
|
||||
<div class="dropdown-content">
|
||||
<span>Browse Contents</span>
|
||||
</a>`
|
||||
: ""}
|
||||
${this.clearable
|
||||
? html` <hr class="dropdown-divider is-hidden-desktop" />
|
||||
<a
|
||||
href="#"
|
||||
role="button"
|
||||
class="dropdown-item is-hidden-desktop"
|
||||
@click="${this.onFullscreenToggle}"
|
||||
class="dropdown-item"
|
||||
@click="${this.onPurgeCache}"
|
||||
@keyup="${clickOnSpacebarPress}"
|
||||
>
|
||||
<span class="icon is-small">
|
||||
@@ -1295,82 +1341,40 @@ class Item extends LitElement {
|
||||
size="1.0em"
|
||||
class="has-text-grey"
|
||||
aria-hidden="true"
|
||||
.svg="${this.isFullscreen
|
||||
? fasUnfullscreen
|
||||
: fasFullscreen}"
|
||||
.svg="${fasSync}"
|
||||
></fa-icon>
|
||||
</span>
|
||||
<span>Full Screen</span>
|
||||
</a>
|
||||
${this.browsable
|
||||
? html` <a
|
||||
href="#"
|
||||
role="button"
|
||||
class="dropdown-item is-hidden-tablet ${!isReplay
|
||||
? "grey-disabled"
|
||||
: ""}"
|
||||
@click="${this.onShowPages}"
|
||||
@keyup="${clickOnSpacebarPress}"
|
||||
>
|
||||
<span class="icon is-small">
|
||||
<fa-icon
|
||||
size="1.0em"
|
||||
class="has-text-grey"
|
||||
aria-hidden="true"
|
||||
.svg="${farListAlt}"
|
||||
></fa-icon>
|
||||
</span>
|
||||
<span>Browse Contents</span>
|
||||
</a>`
|
||||
: ""}
|
||||
${this.renderExtraToolbar()}
|
||||
${this.clearable
|
||||
? html` <hr class="dropdown-divider is-hidden-desktop" />
|
||||
<a
|
||||
href="#"
|
||||
role="button"
|
||||
class="dropdown-item"
|
||||
@click="${this.onPurgeCache}"
|
||||
@keyup="${clickOnSpacebarPress}"
|
||||
>
|
||||
<span class="icon is-small">
|
||||
<fa-icon
|
||||
size="1.0em"
|
||||
class="has-text-grey"
|
||||
aria-hidden="true"
|
||||
.svg="${fasSync}"
|
||||
></fa-icon>
|
||||
</span>
|
||||
<span>Purge Cache + Full Reload</span>
|
||||
</a>`
|
||||
: html``}
|
||||
${(!this.editable && this.sourceUrl?.startsWith("http://")) ||
|
||||
this.sourceUrl?.startsWith("https://")
|
||||
? html` <hr class="dropdown-divider" />
|
||||
<a
|
||||
href="${this.sourceUrl}"
|
||||
role="button"
|
||||
class="dropdown-item"
|
||||
@keyup="${clickOnSpacebarPress}"
|
||||
>
|
||||
<span class="icon is-small">
|
||||
<fa-icon
|
||||
size="1.0em"
|
||||
class="has-text-grey"
|
||||
aria-hidden="true"
|
||||
.svg="${fasDownload}"
|
||||
></fa-icon>
|
||||
</span>
|
||||
<span>Download Archive</span>
|
||||
</a>`
|
||||
: html``}
|
||||
${dateStr
|
||||
? html` <hr class="dropdown-divider is-hidden-desktop" />
|
||||
<div class="dropdown-item info is-hidden-tablet">
|
||||
<span class="menu-head">Capture Date</span>${dateStr}
|
||||
</div>`
|
||||
: ""}
|
||||
<span>Purge Cache + Full Reload</span>
|
||||
</a>`
|
||||
: html``}
|
||||
${(!this.editable && this.sourceUrl?.startsWith("http://")) ||
|
||||
this.sourceUrl?.startsWith("https://")
|
||||
? html` <hr class="dropdown-divider" />
|
||||
<a
|
||||
href="${this.sourceUrl}"
|
||||
role="button"
|
||||
class="dropdown-item"
|
||||
@keyup="${clickOnSpacebarPress}"
|
||||
>
|
||||
<span class="icon is-small">
|
||||
<fa-icon
|
||||
size="1.0em"
|
||||
class="has-text-grey"
|
||||
aria-hidden="true"
|
||||
.svg="${fasDownload}"
|
||||
></fa-icon>
|
||||
</span>
|
||||
<span>Download Archive</span>
|
||||
</a>`
|
||||
: html``}
|
||||
${dateStr
|
||||
? html` <hr class="dropdown-divider is-hidden-desktop" />
|
||||
<div class="dropdown-item info is-hidden-tablet">
|
||||
<span class="menu-head">Capture Date</span>${dateStr}
|
||||
</div>`
|
||||
: ""}
|
||||
${!this.editable
|
||||
? html` <a
|
||||
href="#"
|
||||
role="button"
|
||||
class="dropdown-item"
|
||||
@@ -1385,28 +1389,26 @@ class Item extends LitElement {
|
||||
</span>
|
||||
<span>Archive Info</span>
|
||||
</a>
|
||||
<hr class="dropdown-divider" />
|
||||
<a
|
||||
href="#"
|
||||
role="button"
|
||||
class="dropdown-item"
|
||||
@click="${this.onAbout}"
|
||||
>
|
||||
<fa-icon
|
||||
class="has-text-grey"
|
||||
size="1.0rem"
|
||||
aria-hidden="true"
|
||||
.svg=${rwpIcon}
|
||||
></fa-icon>
|
||||
<span> About ${this.appName}</span>
|
||||
<span class="menu-version">(${this.appVersion})</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<hr class="dropdown-divider" />`
|
||||
: ``}
|
||||
<a
|
||||
href="#"
|
||||
role="button"
|
||||
class="dropdown-item"
|
||||
@click="${this.onAbout}"
|
||||
>
|
||||
<fa-icon
|
||||
class="has-text-grey"
|
||||
size="1.0rem"
|
||||
aria-hidden="true"
|
||||
.svg=${rwpIcon}
|
||||
></fa-icon>
|
||||
<span> About ${this.appName}</span>
|
||||
<span class="menu-version">(${this.appVersion})</span>
|
||||
</a>
|
||||
</div>
|
||||
</nav>
|
||||
<p id="skip-replay-target" tabindex="-1" class="is-sr-only">Skipped</p>`;
|
||||
</div>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
private renderTimestamp() {
|
||||
@@ -1506,10 +1508,6 @@ class Item extends LitElement {
|
||||
></wr-item-info>`;
|
||||
}
|
||||
|
||||
protected renderExtraToolbar(/*isDropdown = false*/): "" | TemplateResult<1> {
|
||||
return "";
|
||||
}
|
||||
|
||||
// @ts-expect-error [// TODO: Fix this the next time the file is edited.] - TS7006 - Parameter 'isSidebar' implicitly has an 'any' type.
|
||||
renderItemTabs(isSidebar) {
|
||||
const isStory = this.hasStory && this.tabData.view === "story";
|
||||
@@ -1650,6 +1648,9 @@ class Item extends LitElement {
|
||||
this.showSidebar = false;
|
||||
this.updateTabData({ url: "", ts: "" });
|
||||
}
|
||||
if (!this.browsable) {
|
||||
this.showSidebar = false;
|
||||
}
|
||||
}
|
||||
|
||||
// @ts-expect-error [// TODO: Fix this the next time the file is edited.] - TS7006 - Parameter 'event' implicitly has an 'any' type.
|
||||
|
||||
+15
-6
@@ -55,12 +55,11 @@ class Replay extends LitElement {
|
||||
// TODO: Fix this the next time the file is edited.
|
||||
// eslint-disable-next-line @typescript-eslint/promise-function-async
|
||||
navigator.serviceWorker.addEventListener("message", (event) =>
|
||||
this.handleAuthMessage(event),
|
||||
this.handleSWMessage(event),
|
||||
);
|
||||
}
|
||||
|
||||
// @ts-expect-error [// TODO: Fix this the next time the file is edited.] - TS7006 - Parameter 'event' implicitly has an 'any' type.
|
||||
async handleAuthMessage(event) {
|
||||
async handleSWMessage(event: MessageEvent) {
|
||||
if (
|
||||
event.data.type === "authneeded" &&
|
||||
this.collInfo &&
|
||||
@@ -90,6 +89,8 @@ class Replay extends LitElement {
|
||||
} else {
|
||||
this.showAuth = true;
|
||||
}
|
||||
} else if (event.data.type) {
|
||||
window.parent.postMessage(event.data);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -211,6 +212,10 @@ class Replay extends LitElement {
|
||||
}
|
||||
} else if (event.data.wb_type === "title") {
|
||||
this.title = event.data.title;
|
||||
} else {
|
||||
const passEvent = { type: event.data.wb_type, ...event.data };
|
||||
delete passEvent.wb_type;
|
||||
window.parent.postMessage(passEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -272,9 +277,13 @@ class Replay extends LitElement {
|
||||
}
|
||||
|
||||
if (iframeWin) {
|
||||
iframeWin.addEventListener("beforeunload", () => {
|
||||
this.setLoading();
|
||||
});
|
||||
try {
|
||||
iframeWin.addEventListener("beforeunload", () => {
|
||||
this.setLoading();
|
||||
});
|
||||
} catch (e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+14
-39
@@ -4,76 +4,60 @@ import rwpLogo from "~assets/brand/replaywebpage-icon-color.svg";
|
||||
|
||||
// ===========================================================================
|
||||
export class SWManager {
|
||||
name: string;
|
||||
scope: string;
|
||||
appName: string;
|
||||
requireSubdomainIframe: boolean;
|
||||
|
||||
errorMsg: string | null = null;
|
||||
|
||||
constructor({
|
||||
name = "sw.js",
|
||||
scope = "./",
|
||||
appName = "ReplayWeb.page",
|
||||
requireSubdomainIframe = false,
|
||||
} = {}) {
|
||||
// @ts-expect-error - TS2339 - Property 'name' does not exist on type 'SWManager'.
|
||||
this.name = name;
|
||||
// @ts-expect-error - TS2339 - Property 'scope' does not exist on type 'SWManager'.
|
||||
this.scope = scope;
|
||||
// @ts-expect-error - TS2339 - Property 'appName' does not exist on type 'SWManager'.
|
||||
this.appName = appName;
|
||||
// @ts-expect-error - TS2339 - Property 'requireSubdomainIframe' does not exist on type 'SWManager'.
|
||||
this.requireSubdomainIframe = requireSubdomainIframe;
|
||||
|
||||
// @ts-expect-error - TS2339 - Property 'errorMsg' does not exist on type 'SWManager'.
|
||||
this.errorMsg = null;
|
||||
}
|
||||
|
||||
// @ts-expect-error [// TODO: Fix this the next time the file is edited.] - TS7006 - Parameter 'newAppName' implicitly has an 'any' type.
|
||||
setAppName(newAppName) {
|
||||
// @ts-expect-error - TS2339 - Property 'appName' does not exist on type 'SWManager'.
|
||||
setAppName(newAppName: string) {
|
||||
this.appName = newAppName;
|
||||
}
|
||||
|
||||
// TODO: Fix this the next time the file is edited.
|
||||
// eslint-disable-next-line @typescript-eslint/promise-function-async
|
||||
register() {
|
||||
async register(): Promise<void> {
|
||||
// @ts-expect-error [// TODO: Fix this the next time the file is edited.] - TS7034 - Variable 'resolve' implicitly has type 'any' in some locations where its type cannot be determined. | TS7034 - Variable 'reject' implicitly has type 'any' in some locations where its type cannot be determined.
|
||||
let resolve, reject;
|
||||
|
||||
const p = new Promise((res, rej) => {
|
||||
const p = new Promise<void>((res, rej) => {
|
||||
resolve = res;
|
||||
reject = rej;
|
||||
});
|
||||
|
||||
// @ts-expect-error - TS2339 - Property 'errorMsg' does not exist on type 'SWManager'.
|
||||
this.errorMsg = this.getSWErrorMsg();
|
||||
|
||||
// @ts-expect-error - TS2339 - Property 'errorMsg' does not exist on type 'SWManager'.
|
||||
if (this.errorMsg) {
|
||||
// @ts-expect-error - TS2339 - Property 'errorMsg' does not exist on type 'SWManager'.
|
||||
console.error(this.errorMsg);
|
||||
// @ts-expect-error - TS2339 - Property 'errorMsg' does not exist on type 'SWManager'.
|
||||
reject(this.errorMsg);
|
||||
reject!(this.errorMsg);
|
||||
}
|
||||
|
||||
// @ts-expect-error [// TODO: Fix this the next time the file is edited.] - TS7006 - Parameter 'error' implicitly has an 'any' type.
|
||||
const handleError = (error) => {
|
||||
console.error("Error during service worker registration:", error);
|
||||
// @ts-expect-error - TS2339 - Property 'errorMsg' does not exist on type 'SWManager'.
|
||||
this.errorMsg = this.getCrossOriginIframeMsg();
|
||||
// @ts-expect-error - TS2339 - Property 'errorMsg' does not exist on type 'SWManager'.
|
||||
if (!this.errorMsg) {
|
||||
// @ts-expect-error - TS2339 - Property 'errorMsg' does not exist on type 'SWManager'.
|
||||
this.errorMsg = `${
|
||||
// @ts-expect-error - TS2339 - Property 'appName' does not exist on type 'SWManager'.
|
||||
this.appName
|
||||
} could not be loaded due to the following error:\n${error.toString()}`;
|
||||
}
|
||||
|
||||
// @ts-expect-error - TS2339 - Property 'errorMsg' does not exist on type 'SWManager'.
|
||||
reject(this.errorMsg);
|
||||
reject!(this.errorMsg);
|
||||
};
|
||||
|
||||
// @ts-expect-error - TS2339 - Property 'scope' does not exist on type 'SWManager'. | TS2339 - Property 'name' does not exist on type 'SWManager'.
|
||||
// TODO: Fix this the next time the file is edited.
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
||||
register(this.scope + this.name, {
|
||||
// @ts-expect-error - TS2339 - Property 'scope' does not exist on type 'SWManager'.
|
||||
registrationOptions: { scope: this.scope },
|
||||
registered() {
|
||||
console.log("Service worker is registered");
|
||||
@@ -118,9 +102,7 @@ export class SWManager {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||
if (navigator.serviceWorker) {
|
||||
// must be loaded from a cross-origin (eg. subdomain)
|
||||
// @ts-expect-error - TS2339 - Property 'requireSubdomainIframe' does not exist on type 'SWManager'.
|
||||
if (this.requireSubdomainIframe && !this.isCrossOriginIframe()) {
|
||||
// @ts-expect-error - TS2339 - Property 'appName' does not exist on type 'SWManager'.
|
||||
return `Sorry, due to security settings, this ${this.appName} embed only be viewed within a subdomain iframe.`;
|
||||
}
|
||||
|
||||
@@ -135,12 +117,7 @@ export class SWManager {
|
||||
|
||||
if (!window.isSecureContext) {
|
||||
return `
|
||||
Sorry, the ${
|
||||
// @ts-expect-error - TS2339 - Property 'appName' does not exist on type 'SWManager'.
|
||||
this.appName
|
||||
} system must be loaded from an HTTPS URL (or localhost), but was loaded from: ${
|
||||
window.location.host
|
||||
}.
|
||||
Sorry, the ${this.appName} system must be loaded from an HTTPS URL (or localhost), but was loaded from: ${window.location.host}.
|
||||
Please try loading this page from an HTTPS URL`;
|
||||
}
|
||||
|
||||
@@ -149,13 +126,11 @@ export class SWManager {
|
||||
return "Sorry, Service Workers are disabled in Firefox in Private Mode. Please try loading this page in regular mode instead.";
|
||||
}
|
||||
|
||||
// @ts-expect-error - TS2339 - Property 'appName' does not exist on type 'SWManager'.
|
||||
return `Sorry, ${this.appName} won't work in this browser as Service Workers are not supported in this window.
|
||||
Please try a different browser.`;
|
||||
}
|
||||
|
||||
renderErrorReport(override?: string) {
|
||||
// @ts-expect-error - TS2339 - Property 'errorMsg' does not exist on type 'SWManager'.
|
||||
renderErrorReport(override = "") {
|
||||
const msg = this.errorMsg || override;
|
||||
|
||||
if (!msg) {
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@ export type URLResource = {
|
||||
export type Page = URLResource;
|
||||
|
||||
export type ItemType = {
|
||||
filename: string;
|
||||
filename?: string;
|
||||
sourceUrl: string;
|
||||
replayPrefix: string;
|
||||
apiPrefix: string;
|
||||
|
||||
Reference in New Issue
Block a user