Typescript migration part 2 (#261)
Converts everything to typescript, adding `@ts-expect-error`s where necessary. Also makes some progress converting elements to use decorators, but we're not fully there yet — I think it'll make sense to continue to do that in future PRs, rather than doing it all in one go, just so that we can keep up with the dev branch.
This commit is contained in:
+3
-2
@@ -1,4 +1,5 @@
|
||||
/* eslint-env node */
|
||||
/** @type { import("eslint").Linter.Config } */
|
||||
module.exports = {
|
||||
env: {
|
||||
browser: true,
|
||||
@@ -19,7 +20,7 @@ module.exports = {
|
||||
rules: {
|
||||
"no-restricted-globals": [2, "event", "error"],
|
||||
"linebreak-style": ["error", "unix"],
|
||||
"@typescript-eslint/no-explicit-any": "warn",
|
||||
},
|
||||
ignorePatterns: ["ruffle/**/*", "build/**/*"],
|
||||
ignorePatterns: ["ruffle/**/*", "build/**/*", "/sw.js", "/ui.js"],
|
||||
reportUnusedDisableDirectives: true,
|
||||
};
|
||||
|
||||
Vendored
+8
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"dbaeumer.vscode-eslint",
|
||||
"esbenp.prettier-vscode",
|
||||
"runem.lit-plugin",
|
||||
"streetsidesoftware.code-spell-checker"
|
||||
]
|
||||
}
|
||||
Vendored
+63
@@ -0,0 +1,63 @@
|
||||
{
|
||||
"cSpell.languageSettings": [
|
||||
{
|
||||
"languageId": "typescript",
|
||||
"allowCompoundWords": true,
|
||||
"dictionaries": ["typescript", "node", "html", "fonts", "css"]
|
||||
},
|
||||
{
|
||||
"languageId": "javascript",
|
||||
"allowCompoundWords": true,
|
||||
"dictionaries": ["typescript", "node", "html", "fonts", "css"]
|
||||
},
|
||||
{
|
||||
"languageId": "markdown",
|
||||
"allowCompoundWords": true,
|
||||
"dictionaries": ["typescript", "node", "html", "fonts", "css"]
|
||||
}
|
||||
],
|
||||
"cSpell.words": [
|
||||
"authed",
|
||||
"browsertrix",
|
||||
"Bulma",
|
||||
"canonicalization",
|
||||
"cdxj",
|
||||
"Collec",
|
||||
"colls",
|
||||
"electronuserland",
|
||||
"flexsearch",
|
||||
"gapi",
|
||||
"gauth",
|
||||
"gdrive",
|
||||
"iframes",
|
||||
"indexeddb",
|
||||
"inited",
|
||||
"ipfs",
|
||||
"ival",
|
||||
"kiwix",
|
||||
"ndjson",
|
||||
"pmarsceill",
|
||||
"popd",
|
||||
"pushd",
|
||||
"pywb",
|
||||
"reauth",
|
||||
"recalc",
|
||||
"replaybase",
|
||||
"replayweb.page",
|
||||
"sesh",
|
||||
"Strs",
|
||||
"surt",
|
||||
"svgs",
|
||||
"swmanager",
|
||||
"swonly",
|
||||
"Unfullscreen",
|
||||
"unrewriting",
|
||||
"wabac",
|
||||
"WACZ",
|
||||
"WARC",
|
||||
"warcio",
|
||||
"webrecorder",
|
||||
"wrlogo"
|
||||
],
|
||||
"cSpell.ignorePaths": ["node_modules", ".git", "*.lock", "package.json"]
|
||||
}
|
||||
+6
-4
@@ -1,3 +1,5 @@
|
||||
<!-- cSpell:ignoreRegExp @\w+ -->
|
||||
|
||||
## CHANGES
|
||||
|
||||
v1.8.11
|
||||
@@ -72,7 +74,7 @@ v1.8.0
|
||||
|
||||
- UI: Add 'Show All Pages' option to show non-seed pages that are previously only available via search
|
||||
- Embeds: add 'swName' option to allow customizing 'sw.js' to a different filename
|
||||
- Dependencies: Update to wabac.js 2.16.1 -- varioues loading improvements related to surt
|
||||
- Dependencies: Update to wabac.js 2.16.1 -- various loading improvements related to surt
|
||||
- Dependencies: Update to electron 25.5.1, ruffle 2023-06-14
|
||||
|
||||
v1.7.15
|
||||
@@ -149,7 +151,7 @@ v1.7.4
|
||||
v1.7.3
|
||||
|
||||
- Fidelity: Misc fidelity improvements via latest wombat + wabac.js
|
||||
- Dependecies: wabac.js 2.13.8, wombat 3.3.11, auto-js-ipfs 1.5.1
|
||||
- Dependencies: wabac.js 2.13.8, wombat 3.3.11, auto-js-ipfs 1.5.1
|
||||
- Loading: Fix occasional loading issues with multiple embeds loading on the same page
|
||||
|
||||
v1.7.2
|
||||
@@ -292,7 +294,7 @@ v1.5.2
|
||||
|
||||
v1.5.1
|
||||
|
||||
- Library usage: Simplfy download options in editable mode, add warc/1.0 download opt (for archiveweb.page)
|
||||
- Library usage: Simplify download options in editable mode, add warc/1.0 download opt (for archiveweb.page)
|
||||
- Library usage: Allow custom service worker init path on app init (or none)
|
||||
- Library usage: Ensure page title reflects current app
|
||||
- UI: Refresh UI after half second while waiting for service worker to load, instead of every 5.
|
||||
@@ -338,7 +340,7 @@ v1.4.4
|
||||
|
||||
v1.4.3
|
||||
|
||||
- Loading: Various fixes to index loading for compessed WACZ index
|
||||
- Loading: Various fixes to index loading for compressed WACZ index
|
||||
- Fidelity: Fix edge-case POST-to-get conversion - binary, empty and text/plain POST payloads now handled same way here (via wabac.js/warcio.js) as in other tools (pywb, cdxj-indexer)
|
||||
- Customization: Support for automated redirect to live page on not found (via embed options)
|
||||
- UI: Updated page not found message
|
||||
|
||||
+35
-34
@@ -1,5 +1,5 @@
|
||||
import { LitElement, html, css } from "lit";
|
||||
import { property } from "lit/decorators.js";
|
||||
import { LitElement, html, css, type TemplateResult } from "lit";
|
||||
import { customElement, property } from "lit/decorators.js";
|
||||
import { ifDefined } from "lit/directives/if-defined.js";
|
||||
import {
|
||||
wrapCss,
|
||||
@@ -16,9 +16,11 @@ import { SWManager } from "./swmanager";
|
||||
import "./item";
|
||||
import "./item-index";
|
||||
import "./chooser";
|
||||
import { LoadInfo } from "./item";
|
||||
|
||||
// ===========================================================================
|
||||
class ReplayWebApp extends LitElement {
|
||||
@customElement("replay-app-main")
|
||||
export class ReplayWebApp extends LitElement {
|
||||
@property({ type: Boolean })
|
||||
inited = false;
|
||||
|
||||
@@ -41,10 +43,10 @@ class ReplayWebApp extends LitElement {
|
||||
collTitle: string | null = null;
|
||||
|
||||
@property({ type: Object })
|
||||
loadInfo: any = null;
|
||||
loadInfo: LoadInfo | null = null;
|
||||
|
||||
@property({ type: String })
|
||||
embed: any = null;
|
||||
embed: string | null = null;
|
||||
|
||||
@property({ type: String })
|
||||
collPageUrl = "";
|
||||
@@ -56,13 +58,13 @@ class ReplayWebApp extends LitElement {
|
||||
pageReplay = false;
|
||||
|
||||
@property({ type: String })
|
||||
source: any = null;
|
||||
source: string | null = null;
|
||||
|
||||
@property({ type: Boolean })
|
||||
skipRuffle = false;
|
||||
|
||||
@property({ type: Object })
|
||||
swErrorMsg: any = null;
|
||||
swErrorMsg: TemplateResult<1> | "" | null = null;
|
||||
|
||||
private swName?: string;
|
||||
private swmanager: SWManager | null;
|
||||
@@ -70,7 +72,6 @@ class ReplayWebApp extends LitElement {
|
||||
|
||||
private droppedFile: File | null = null;
|
||||
|
||||
// eslint-disable-next-line no-undef
|
||||
constructor(swName = __SW_NAME__) {
|
||||
super();
|
||||
|
||||
@@ -105,7 +106,7 @@ class ReplayWebApp extends LitElement {
|
||||
});
|
||||
}
|
||||
|
||||
private maybeStartFileDrop = (dragEvent) => {
|
||||
private maybeStartFileDrop = (dragEvent: DragEvent) => {
|
||||
if (this.sourceUrl) {
|
||||
// A source is already loaded. Don't allow dropping a file.
|
||||
return;
|
||||
@@ -372,7 +373,7 @@ class ReplayWebApp extends LitElement {
|
||||
-->
|
||||
<a
|
||||
href="?terms"
|
||||
@click="${(e) => {
|
||||
@click="${(e: Event) => {
|
||||
e.preventDefault();
|
||||
this.showAbout = true;
|
||||
}}"
|
||||
@@ -385,7 +386,7 @@ class ReplayWebApp extends LitElement {
|
||||
return html` <wr-item
|
||||
.loadInfo="${this.loadInfo}"
|
||||
sourceUrl="${this.sourceUrl || ""}"
|
||||
embed="${this.embed}"
|
||||
embed="${ifDefined(this.embed === null ? undefined : this.embed)}"
|
||||
appName="${this.appName}"
|
||||
swName="${ifDefined(this.swName)}"
|
||||
.appLogo="${this.mainLogo}"
|
||||
@@ -452,10 +453,9 @@ class ReplayWebApp extends LitElement {
|
||||
}
|
||||
|
||||
this.swmanager = new SWManager({ name, appName: this.appName });
|
||||
this.swmanager
|
||||
.register()
|
||||
.catch(
|
||||
this.swmanager.register().catch(
|
||||
() =>
|
||||
// @ts-expect-error - TS2554 - Expected 2 arguments, but got 1.
|
||||
(this.swErrorMsg = this.swmanager?.renderErrorReport(this.mainLogo)),
|
||||
);
|
||||
|
||||
@@ -534,16 +534,21 @@ class ReplayWebApp extends LitElement {
|
||||
this.pageParams = new URLSearchParams(window.location.search);
|
||||
|
||||
// Google Drive
|
||||
let state: any = this.pageParams.get("state");
|
||||
const state = this.pageParams.get("state");
|
||||
type State = {
|
||||
ids?: string[];
|
||||
userId?: string;
|
||||
action?: string;
|
||||
};
|
||||
if (state) {
|
||||
try {
|
||||
state = JSON.parse(state);
|
||||
const parsedState: State = JSON.parse(state);
|
||||
if (
|
||||
state.ids instanceof Array &&
|
||||
state.userId &&
|
||||
state.action === "open"
|
||||
parsedState.ids instanceof Array &&
|
||||
parsedState.userId &&
|
||||
parsedState.action === "open"
|
||||
) {
|
||||
this.pageParams.set("source", "googledrive://" + state.ids[0]);
|
||||
this.pageParams.set("source", "googledrive://" + parsedState.ids[0]);
|
||||
this.pageParams.delete("state");
|
||||
window.location.search = this.pageParams.toString();
|
||||
return;
|
||||
@@ -581,7 +586,7 @@ class ReplayWebApp extends LitElement {
|
||||
|
||||
if (this.pageParams.get("config")) {
|
||||
try {
|
||||
this.loadInfo.extraConfig = JSON.parse(
|
||||
this.loadInfo!.extraConfig = JSON.parse(
|
||||
this.pageParams.get("config") || "",
|
||||
);
|
||||
} catch (e) {
|
||||
@@ -590,35 +595,35 @@ class ReplayWebApp extends LitElement {
|
||||
}
|
||||
|
||||
if (this.pageParams.get("baseUrlSourcePrefix")) {
|
||||
this.loadInfo.extraConfig = this.loadInfo.extraConfig || {};
|
||||
this.loadInfo.extraConfig.baseUrlSourcePrefix = this.pageParams.get(
|
||||
this.loadInfo!.extraConfig = this.loadInfo!.extraConfig || {};
|
||||
this.loadInfo!.extraConfig.baseUrlSourcePrefix = this.pageParams.get(
|
||||
"baseUrlSourcePrefix",
|
||||
);
|
||||
}
|
||||
|
||||
if (this.pageParams.get("basePageUrl")) {
|
||||
this.loadInfo.extraConfig = this.loadInfo.extraConfig || {};
|
||||
this.loadInfo.extraConfig.baseUrl = this.pageParams.get("basePageUrl");
|
||||
this.loadInfo!.extraConfig = this.loadInfo!.extraConfig || {};
|
||||
this.loadInfo!.extraConfig.baseUrl = this.pageParams.get("basePageUrl");
|
||||
}
|
||||
|
||||
if (this.pageParams.get("customColl")) {
|
||||
this.loadInfo.customColl = this.pageParams.get("customColl");
|
||||
this.loadInfo!.customColl = this.pageParams.get("customColl");
|
||||
}
|
||||
|
||||
if (this.pageParams.get("noWebWorker") === "1") {
|
||||
this.loadInfo.noWebWorker = true;
|
||||
this.loadInfo!.noWebWorker = true;
|
||||
}
|
||||
|
||||
if (this.pageParams.get("noCache") === "1") {
|
||||
this.loadInfo.noCache = true;
|
||||
this.loadInfo!.noCache = true;
|
||||
}
|
||||
|
||||
if (this.pageParams.get("hideOffscreen") === "1") {
|
||||
this.loadInfo.hideOffscreen = true;
|
||||
this.loadInfo!.hideOffscreen = true;
|
||||
}
|
||||
|
||||
if (this.pageParams.get("loading") === "eager") {
|
||||
this.loadInfo.loadEager = true;
|
||||
this.loadInfo!.loadEager = true;
|
||||
}
|
||||
|
||||
if (this.pageParams.get("swName")) {
|
||||
@@ -791,7 +796,3 @@ class ReplayWebApp extends LitElement {
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define("replay-app-main", ReplayWebApp);
|
||||
|
||||
export { ReplayWebApp };
|
||||
|
||||
@@ -2,23 +2,29 @@ import { LitElement, html, css } from "lit";
|
||||
import { IS_APP, wrapCss } from "./misc";
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
class Chooser extends LitElement {
|
||||
constructor() {
|
||||
super();
|
||||
@customElement("wr-chooser")
|
||||
export class Chooser extends LitElement {
|
||||
@property({ type: String })
|
||||
fileDisplayName = "";
|
||||
|
||||
this.fileDisplayName = "";
|
||||
this.file = null;
|
||||
this.droppedFile = null;
|
||||
@property({ attribute: false })
|
||||
file: FileWithPath | null = null;
|
||||
|
||||
this.hasNativeFS = !!window.showOpenFilePicker && !IS_APP;
|
||||
@property({ attribute: false })
|
||||
droppedFile: FileWithPath | null = null;
|
||||
|
||||
this.newFullImport = false;
|
||||
@property({ type: Boolean })
|
||||
hasNativeFS = !!window.showOpenFilePicker && !IS_APP;
|
||||
|
||||
this.noHead = false;
|
||||
|
||||
this.showOpenFilePickerOptions = {
|
||||
@property({ type: Object })
|
||||
showOpenFilePickerOptions = {
|
||||
types: [
|
||||
{
|
||||
description: "WARC, WACZ, HAR and WBN Files",
|
||||
@@ -32,17 +38,14 @@ class Chooser extends LitElement {
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
return {
|
||||
fileDisplayName: { type: String },
|
||||
/** @type File */
|
||||
droppedFile: { attribute: false },
|
||||
newFullImport: { type: Boolean },
|
||||
noHead: { type: Boolean },
|
||||
};
|
||||
}
|
||||
@property({ type: Boolean })
|
||||
newFullImport = false;
|
||||
|
||||
@property({ type: Boolean })
|
||||
noHead = false;
|
||||
|
||||
fileHandle?: FileSystemFileHandle;
|
||||
|
||||
updated(changedProperties) {
|
||||
if (changedProperties.has("droppedFile") && this.droppedFile) {
|
||||
@@ -56,11 +59,12 @@ class Chooser extends LitElement {
|
||||
.map(Object.values)
|
||||
.flat(2);
|
||||
|
||||
const fileHasAllowedExtension = allowedFileExtensions.some((extension) =>
|
||||
this.droppedFile.name.endsWith(extension),
|
||||
const fileHasAllowedExtension = allowedFileExtensions.some(
|
||||
(extension) => this.droppedFile?.name.endsWith(extension),
|
||||
);
|
||||
|
||||
if (fileHasAllowedExtension) {
|
||||
if (this.droppedFile === null) return;
|
||||
this.setFile(this.droppedFile);
|
||||
this.dispatchEvent(
|
||||
new CustomEvent("did-drop-file", { bubbles: true, composed: true }),
|
||||
@@ -76,10 +80,10 @@ class Chooser extends LitElement {
|
||||
this.setFile(event.currentTarget.files[0]);
|
||||
}
|
||||
|
||||
setFile(file) {
|
||||
setFile(file: FileWithPath) {
|
||||
this.file = file;
|
||||
// file.path only available in electron app
|
||||
this.fileDisplayName = "file://" + (this.file.path || this.file.name);
|
||||
this.fileDisplayName = "file://" + (file.path || file.name);
|
||||
}
|
||||
|
||||
async onChooseNativeFile() {
|
||||
@@ -90,9 +94,11 @@ class Chooser extends LitElement {
|
||||
const [fileHandle] = await window.showOpenFilePicker(
|
||||
this.showOpenFilePickerOptions,
|
||||
);
|
||||
|
||||
this.fileHandle = fileHandle;
|
||||
|
||||
this.file = await fileHandle.getFile();
|
||||
this.file = (await fileHandle.getFile()) as FileWithPath;
|
||||
|
||||
this.fileDisplayName = "file://" + fileHandle.name;
|
||||
}
|
||||
|
||||
@@ -103,18 +109,32 @@ class Chooser extends LitElement {
|
||||
);
|
||||
}
|
||||
|
||||
onStartLoad(event) {
|
||||
onStartLoad(event?: Event) {
|
||||
if (event) {
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
const loadInfo = { sourceUrl: this.fileDisplayName };
|
||||
type LoadInfo = {
|
||||
sourceUrl: string;
|
||||
isFile?: boolean;
|
||||
loadUrl?: string;
|
||||
noCache?: boolean;
|
||||
extra?: { fileHandle: FileSystemFileHandle };
|
||||
blob?: Blob;
|
||||
size?: number;
|
||||
name?: string;
|
||||
newFullImport: boolean;
|
||||
};
|
||||
|
||||
const loadInfo: LoadInfo = {
|
||||
sourceUrl: this.fileDisplayName,
|
||||
newFullImport: this.newFullImport,
|
||||
};
|
||||
|
||||
if (this.file) {
|
||||
loadInfo.isFile = true;
|
||||
// file.path only available in electron app
|
||||
if (this.file.path) {
|
||||
// eslint-disable-next-line no-undef
|
||||
loadInfo.loadUrl = "file2://" + this.file.path;
|
||||
loadInfo.noCache = true;
|
||||
} else if (this.fileHandle) {
|
||||
@@ -130,8 +150,6 @@ class Chooser extends LitElement {
|
||||
loadInfo.name = this.fileDisplayName;
|
||||
}
|
||||
|
||||
loadInfo.newFullImport = this.newFullImport;
|
||||
|
||||
this.dispatchEvent(
|
||||
new CustomEvent("load-start", {
|
||||
bubbles: true,
|
||||
@@ -152,6 +170,7 @@ class Chooser extends LitElement {
|
||||
this.fileDisplayName.startsWith("file://")
|
||||
) {
|
||||
this.file = null;
|
||||
|
||||
this.fileDisplayName = "";
|
||||
}
|
||||
}
|
||||
@@ -280,7 +299,3 @@ class Chooser extends LitElement {
|
||||
</section>`;
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define("wr-chooser", Chooser);
|
||||
|
||||
export { Chooser };
|
||||
@@ -9,4 +9,4 @@ const replayApp = new ElectronReplayApp({
|
||||
profileName: "replaywebpage",
|
||||
});
|
||||
|
||||
replayApp.init(true);
|
||||
replayApp.init();
|
||||
|
||||
@@ -11,6 +11,11 @@ const dbs = {};
|
||||
|
||||
const loader = new CollectionLoader();
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string} name
|
||||
* @returns
|
||||
*/
|
||||
async function getColl(name) {
|
||||
if (!dbs[name]) {
|
||||
dbs[name] = await loader.loadColl(name);
|
||||
@@ -20,11 +25,24 @@ async function getColl(name) {
|
||||
return dbs[name];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} name
|
||||
* @returns
|
||||
*/
|
||||
async function getDB(name) {
|
||||
const coll = await getColl(name);
|
||||
return coll.store;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {import("electron").IpcRendererEvent} event
|
||||
* @param {*} request
|
||||
* @param {*} coll
|
||||
* @param {*} ts
|
||||
* @param {*} channel
|
||||
* @returns
|
||||
*/
|
||||
async function getResponse(event, request, coll, ts, channel) {
|
||||
const db = await getDB(coll);
|
||||
|
||||
|
||||
+48
-19
@@ -26,7 +26,9 @@ import log from "electron-log";
|
||||
import mime from "mime-types";
|
||||
import url from "url";
|
||||
|
||||
// @ts-expect-error - TS2322 - Type 'typeof Headers' is not assignable to type '{ new (init?: HeadersInit | undefined): Headers; prototype: Headers; }'.
|
||||
global.Headers = Headers;
|
||||
// @ts-expect-error - TS2322 - Type '(url: RequestInfo, init?: RequestInit | undefined) => Promise<Response>' is not assignable to type '(input: RequestInfo, init?: RequestInit | undefined) => Promise<Response>'.
|
||||
global.fetch = fetch;
|
||||
|
||||
const STATIC_PREFIX = "http://localhost:5471/";
|
||||
@@ -39,27 +41,43 @@ const URL_RX = /([^/]+)\/([\d]+)(?:\w\w_)?\/(.*)$/;
|
||||
|
||||
// ============================================================================
|
||||
class ElectronReplayApp {
|
||||
/**
|
||||
* @type {string}
|
||||
*/
|
||||
pluginPath = "";
|
||||
|
||||
appPath = app.getAppPath();
|
||||
|
||||
projPath = path.join(this.appPath, "../");
|
||||
|
||||
staticContentPath = "./";
|
||||
|
||||
profileName = "";
|
||||
|
||||
proxyColl = null;
|
||||
|
||||
proxyTS = null;
|
||||
|
||||
/**
|
||||
* @type {BrowserWindow | null}
|
||||
*/
|
||||
mainWindow = null;
|
||||
|
||||
/**
|
||||
* @type {string | null}
|
||||
*/
|
||||
openNextFile = null;
|
||||
|
||||
screenSize = { width: 1024, height: 768 };
|
||||
|
||||
/**
|
||||
* @type {string | null}
|
||||
*/
|
||||
origUA = null;
|
||||
|
||||
constructor({ staticPath = "./", profileName = "" } = {}) {
|
||||
this.pluginPath = "";
|
||||
|
||||
this.appPath = app.getAppPath();
|
||||
|
||||
this.projPath = path.join(this.appPath, "../");
|
||||
|
||||
this.staticContentPath = staticPath;
|
||||
|
||||
this.profileName = profileName;
|
||||
|
||||
this.proxyColl = null;
|
||||
this.proxyTS = null;
|
||||
|
||||
this.mainWindow = null;
|
||||
|
||||
this.openNextFile = null;
|
||||
|
||||
this.screenSize = { width: 1024, height: 768 };
|
||||
|
||||
this.origUA = null;
|
||||
}
|
||||
|
||||
get mainWindowWebPreferences() {
|
||||
@@ -132,7 +150,7 @@ class ElectronReplayApp {
|
||||
});
|
||||
});
|
||||
|
||||
app.on("activate", function () {
|
||||
app.on("activate", () => {
|
||||
// On macOS it's common to re-create a window in the app when the
|
||||
// dock icon is clicked and there are no other windows open.
|
||||
if (BrowserWindow.getAllWindows().length === 0) {
|
||||
@@ -153,6 +171,7 @@ class ElectronReplayApp {
|
||||
|
||||
checkUpdates() {
|
||||
autoUpdater.logger = log;
|
||||
// @ts-expect-error - TS2339 - Property 'transports' does not exist on type 'Logger'.
|
||||
autoUpdater.logger.transports.file.level = "info";
|
||||
autoUpdater.checkForUpdatesAndNotify();
|
||||
}
|
||||
@@ -332,6 +351,15 @@ class ElectronReplayApp {
|
||||
callback({ statusCode, headers, data });
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string} url
|
||||
* @param {(props: {
|
||||
* statusCode: number;
|
||||
* headers: Record<string, string>;
|
||||
* data: unknown;
|
||||
* }) => void} callback
|
||||
*/
|
||||
notFound(url, callback) {
|
||||
console.log("not found: " + url);
|
||||
const data = this._bufferToStream(
|
||||
@@ -449,6 +477,7 @@ class ElectronReplayApp {
|
||||
const theWindow = new BrowserWindow({
|
||||
width: this.screenSize.width,
|
||||
height: this.screenSize.height,
|
||||
// @ts-expect-error - TS2345 - Argument of type '{ width: any; height: any; isMaximized: boolean; show: false; webPreferences: { plugins: boolean; preload: string; nativeWindowOpen: boolean; contextIsolation: boolean; enableRemoteModule: boolean; sandbox: boolean; nodeIntegration: boolean; }; }' is not assignable to parameter of type 'BrowserWindowConstructorOptions'.
|
||||
isMaximized: true,
|
||||
show: false,
|
||||
webPreferences: this.mainWindowWebPreferences,
|
||||
|
||||
@@ -6,36 +6,26 @@ import fasDownload from "@fortawesome/fontawesome-free/svgs/solid/download.svg";
|
||||
|
||||
import { clickOnSpacebarPress } from "./misc";
|
||||
|
||||
import { LitElement, html, css } from "lit";
|
||||
import { LitElement, html, css, nothing } from "lit";
|
||||
import { tsToDate } from "./pageutils";
|
||||
import prettyBytes from "pretty-bytes";
|
||||
import { property } from "lit/decorators.js";
|
||||
import type { Item as ItemType } from "./types";
|
||||
|
||||
// ===========================================================================
|
||||
export class RWPEmbedReceipt extends LitElement {
|
||||
constructor() {
|
||||
super();
|
||||
this.collInfo = null;
|
||||
this.appLogo = null;
|
||||
this.ts = null;
|
||||
this.url = null;
|
||||
this.active = false;
|
||||
}
|
||||
@property({ type: Object }) collInfo: ItemType | null = null;
|
||||
@property({ type: Object }) appLogo = null;
|
||||
@property({ type: String }) ts: string | null = null;
|
||||
@property({ type: String }) url: string | null = null;
|
||||
|
||||
@property({ type: Boolean }) active = false;
|
||||
|
||||
// @ts-expect-error - TS2611 - 'renderRoot' is defined as a property in class 'LitElement', but is overridden here in 'RWPEmbedReceipt' as an accessor.
|
||||
get renderRoot() {
|
||||
return this;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
return {
|
||||
collInfo: { type: Object },
|
||||
appLogo: { type: Object },
|
||||
url: { type: String },
|
||||
ts: { type: String },
|
||||
|
||||
active: { type: Boolean },
|
||||
};
|
||||
}
|
||||
|
||||
static get embedStyles() {
|
||||
return css`
|
||||
rwp-embed-receipt {
|
||||
@@ -182,19 +172,17 @@ export class RWPEmbedReceipt extends LitElement {
|
||||
}
|
||||
|
||||
render() {
|
||||
let {
|
||||
numValid,
|
||||
numInvalid,
|
||||
const {
|
||||
numValid = 0,
|
||||
numInvalid = 0,
|
||||
domain,
|
||||
certFingerprint,
|
||||
datapackageHash,
|
||||
publicKey,
|
||||
software,
|
||||
} = this.collInfo.verify || {};
|
||||
numValid = numValid || 0;
|
||||
numInvalid = numInvalid || 0;
|
||||
} = this.collInfo?.verify || {};
|
||||
|
||||
const sourceUrl = this.collInfo.sourceUrl;
|
||||
const sourceUrl = this.collInfo?.sourceUrl;
|
||||
|
||||
const certFingerprintUrl = certFingerprint
|
||||
? `https://crt.sh/?q=${certFingerprint}`
|
||||
@@ -251,6 +239,8 @@ export class RWPEmbedReceipt extends LitElement {
|
||||
>replayweb.page</a
|
||||
>.
|
||||
</p>
|
||||
${sourceUrl
|
||||
? html`
|
||||
<a
|
||||
href="${sourceUrl}"
|
||||
class="button is-primary mt-4"
|
||||
@@ -266,10 +256,18 @@ export class RWPEmbedReceipt extends LitElement {
|
||||
<span>Download Archive</span>
|
||||
</a>
|
||||
<hr class="dropdown-divider mt-4" />
|
||||
`
|
||||
: nothing}
|
||||
<h2 class="mt-4">Technical Information</h2>
|
||||
<div class="embed-info-drop-statscontainer mb-4">
|
||||
${this.url
|
||||
? html`
|
||||
<h3>Original URL:</h3>
|
||||
<p><a target="_blank" href="${this.url}">${this.url}</a></p>
|
||||
<p>
|
||||
<a target="_blank" href="${this.url}">${this.url}</a>
|
||||
</p>
|
||||
`
|
||||
: nothing}
|
||||
<h3 class="mt-2">Archived On:</h3>
|
||||
<p>${dateStr}</p>
|
||||
${domain
|
||||
@@ -301,8 +299,12 @@ export class RWPEmbedReceipt extends LitElement {
|
||||
: html` <p>Not Available</p> `}
|
||||
<h3 class="mt-2">Package Hash:</h3>
|
||||
<p class="show-hash">${datapackageHash}</p>
|
||||
${this.collInfo?.size != null
|
||||
? html`
|
||||
<h3 class="mt-2">Size</h3>
|
||||
<p>${prettyBytes(Number(this.collInfo.size || 0))}</p>
|
||||
`
|
||||
: nothing}
|
||||
</div>
|
||||
${sourceUrl ? html`` : ""}
|
||||
<p
|
||||
@@ -314,13 +316,16 @@ export class RWPEmbedReceipt extends LitElement {
|
||||
class="has-text-black"
|
||||
target="_blank"
|
||||
href="https://github.com/webrecorder/replayweb.page"
|
||||
>
|
||||
>${this.appLogo
|
||||
? html`
|
||||
<fa-icon
|
||||
class="menu-logo mr-1"
|
||||
size="1.0rem"
|
||||
aria-hidden="true"
|
||||
.svg=${this.appLogo}
|
||||
></fa-icon>
|
||||
`
|
||||
: nothing}
|
||||
Powered by ReplayWeb.page
|
||||
</a>
|
||||
</span>
|
||||
+84
-81
@@ -1,96 +1,77 @@
|
||||
import { LitElement, html, css } from "lit";
|
||||
import { LitElement, html, css, TemplateResult } from "lit";
|
||||
import { ifDefined } from "lit/directives/if-defined.js";
|
||||
|
||||
import { wrapCss, rwpLogo } from "./misc";
|
||||
import { SWManager } from "./swmanager";
|
||||
import { property } from "lit/decorators.js";
|
||||
|
||||
var scriptSrc = document.currentScript && document.currentScript.src;
|
||||
const scriptSrc =
|
||||
document.currentScript && (document.currentScript as HTMLScriptElement).src;
|
||||
|
||||
var defaultReplayFile = "";
|
||||
let defaultReplayFile = "";
|
||||
|
||||
const DEFAULT_REPLAY_BASE = "https://replayweb.page/";
|
||||
|
||||
// ===========================================================================
|
||||
class Embed extends LitElement {
|
||||
constructor() {
|
||||
super();
|
||||
this.replaybase = "./replay/";
|
||||
this.replayfile = defaultReplayFile;
|
||||
// eslint-disable-next-line no-undef
|
||||
this.swName = __SW_NAME__;
|
||||
this.mainElementName = "replay-app-main";
|
||||
this.appName = "ReplayWeb.page";
|
||||
this.view = "replay";
|
||||
this.ts = "";
|
||||
this.url = "";
|
||||
this.query = "";
|
||||
this.config = "";
|
||||
this.customConfig = null;
|
||||
this.coll = "";
|
||||
this.paramString = null;
|
||||
this.deepLink = false;
|
||||
this.newWindowBase = "";
|
||||
this.inited = false;
|
||||
this.embed = null;
|
||||
this.reloadCount = 0;
|
||||
this.sandbox = false;
|
||||
this.noWebWorker = false;
|
||||
this.noCache = false;
|
||||
// deprecated;
|
||||
this.noSandbox = null;
|
||||
this.logo = rwpLogo;
|
||||
this.loading = "";
|
||||
this.useRuffle = false;
|
||||
}
|
||||
@property({ type: String }) url = "";
|
||||
@property({ type: String }) ts = "";
|
||||
@property({ type: String }) query = "";
|
||||
|
||||
@property({ type: String }) source;
|
||||
@property({ type: String }) src;
|
||||
|
||||
@property({ type: String }) view = "replay";
|
||||
@property({ type: String }) embed: string | null = null;
|
||||
|
||||
@property({ type: String }) replaybase = "./replay/";
|
||||
@property({ type: String }) swName = __SW_NAME__;
|
||||
|
||||
@property({ type: String }) title!: string;
|
||||
|
||||
@property({ type: String }) coll = "";
|
||||
@property({ type: String }) config = "";
|
||||
|
||||
@property({ type: Boolean }) inited = false;
|
||||
|
||||
@property({ type: String }) paramString: string | null = null;
|
||||
@property({ type: String }) hashString: string | undefined;
|
||||
|
||||
@property({ type: Boolean }) deepLink = false;
|
||||
@property({ type: Boolean }) sandbox = false;
|
||||
@property({ type: Boolean }) noSandbox: boolean | null = null;
|
||||
@property({ type: Boolean }) noWebWorker = false;
|
||||
@property({ type: Boolean }) noCache = false;
|
||||
@property({ type: Boolean }) hideOffscreen: boolean | undefined;
|
||||
|
||||
@property({ type: String }) newWindowBase = "";
|
||||
|
||||
@property({ type: String }) errorMessage:
|
||||
| ""
|
||||
| TemplateResult<1>
|
||||
| string
|
||||
| undefined;
|
||||
|
||||
@property({ type: Boolean }) requireSubdomainIframe;
|
||||
|
||||
@property({ type: String }) loading = "";
|
||||
|
||||
@property({ type: Boolean }) useRuffle = false;
|
||||
|
||||
replayfile = defaultReplayFile;
|
||||
mainElementName = "replay-app-main";
|
||||
appName = "ReplayWeb.page";
|
||||
customConfig = null;
|
||||
reloadCount = 0;
|
||||
logo = rwpLogo;
|
||||
|
||||
isCrossOrigin: boolean | undefined;
|
||||
swmanager: SWManager | undefined;
|
||||
|
||||
static setDefaultReplayFile(replayfile) {
|
||||
defaultReplayFile = replayfile;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
return {
|
||||
url: { type: String },
|
||||
ts: { type: String },
|
||||
query: { type: String },
|
||||
|
||||
source: { type: String },
|
||||
src: { type: String },
|
||||
|
||||
view: { type: String },
|
||||
embed: { type: String },
|
||||
|
||||
replaybase: { type: String },
|
||||
swName: { type: String },
|
||||
|
||||
title: { type: String },
|
||||
|
||||
coll: { type: String },
|
||||
config: { type: String },
|
||||
|
||||
inited: { type: Boolean },
|
||||
|
||||
paramString: { type: String },
|
||||
hashString: { type: String },
|
||||
|
||||
deepLink: { type: Boolean },
|
||||
sandbox: { type: Boolean },
|
||||
noSandbox: { type: Boolean },
|
||||
noWebWorker: { type: Boolean },
|
||||
noCache: { type: Boolean },
|
||||
hideOffscreen: { type: Boolean },
|
||||
|
||||
newWindowBase: { type: String },
|
||||
|
||||
errorMessage: { type: String },
|
||||
|
||||
requireSubdomainIframe: { type: Boolean },
|
||||
|
||||
loading: { type: String },
|
||||
|
||||
useRuffle: { type: Boolean },
|
||||
};
|
||||
}
|
||||
|
||||
async doRegister() {
|
||||
const replaybaseURL = new URL(this.replaybase, window.location.href);
|
||||
|
||||
@@ -168,6 +149,7 @@ class Embed extends LitElement {
|
||||
|
||||
// likely safari < 16, don't use web workers due to issues with split storage state
|
||||
if (
|
||||
// @ts-expect-error - TS2339 - Property 'GestureEvent' does not exist on type 'Window & typeof globalThis'.
|
||||
window.GestureEvent !== undefined &&
|
||||
window.SharedWorker === undefined
|
||||
) {
|
||||
@@ -184,15 +166,19 @@ class Embed extends LitElement {
|
||||
const qs = new URLSearchParams(window.location.hash.slice(1));
|
||||
|
||||
if (qs.has("url")) {
|
||||
// @ts-expect-error - TS2339 - Property 'url' does not exist on type 'Embed'.
|
||||
this.url = qs.get("url");
|
||||
}
|
||||
if (qs.has("ts")) {
|
||||
// @ts-expect-error - TS2339 - Property 'ts' does not exist on type 'Embed'.
|
||||
this.ts = qs.get("ts");
|
||||
}
|
||||
if (qs.has("query")) {
|
||||
// @ts-expect-error - TS2339 - Property 'query' does not exist on type 'Embed'.
|
||||
this.query = qs.get("query");
|
||||
}
|
||||
if (qs.has("view")) {
|
||||
// @ts-expect-error - TS2339 - Property 'view' does not exist on type 'Embed'.
|
||||
this.view = qs.get("view");
|
||||
}
|
||||
}
|
||||
@@ -203,6 +189,7 @@ class Embed extends LitElement {
|
||||
}
|
||||
|
||||
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 {
|
||||
@@ -229,7 +216,20 @@ class Embed extends LitElement {
|
||||
|
||||
const config = this.mergeConfigs();
|
||||
|
||||
const params = {
|
||||
const params: {
|
||||
source: URL;
|
||||
customColl: string;
|
||||
config: string;
|
||||
basePageUrl: string;
|
||||
baseUrlSourcePrefix: string;
|
||||
embed: string;
|
||||
noWebWorker?: "1";
|
||||
noCache?: "1";
|
||||
hideOffscreen?: "1";
|
||||
loading?: "eager";
|
||||
swName?: string;
|
||||
ruffle?: "1";
|
||||
} = {
|
||||
source,
|
||||
customColl: this.coll,
|
||||
config,
|
||||
@@ -258,7 +258,6 @@ class Embed extends LitElement {
|
||||
params.loading = "eager";
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-undef
|
||||
if (this.swName !== __SW_NAME__) {
|
||||
params.swName = this.swName;
|
||||
}
|
||||
@@ -267,7 +266,10 @@ class Embed extends LitElement {
|
||||
params.ruffle = "1";
|
||||
}
|
||||
|
||||
this.paramString = new URLSearchParams(params).toString();
|
||||
this.paramString = new URLSearchParams(
|
||||
// Converting to unknown here so that we can ignore the URL -> string conversion necessary for the types to work out
|
||||
params as unknown as Record<string, string>,
|
||||
).toString();
|
||||
|
||||
this.hashString = new URLSearchParams({
|
||||
url: this.url,
|
||||
@@ -317,7 +319,8 @@ class Embed extends LitElement {
|
||||
allow-popups allow-popups-to-escape-sandbox allow-presentation allow-scripts\
|
||||
allow-same-origin allow-forms"
|
||||
: undefined,
|
||||
)}"
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- the typedef for the `sandbox` attribute here is incorrect, it doesn't support multiple values
|
||||
) as any}"
|
||||
@load="${this.onLoad}"
|
||||
src="${this.replaybase}${this.replayfile}?${this
|
||||
.paramString}#${this.hashString}"
|
||||
@@ -7,9 +7,13 @@ import fabGoogleDrive from "@fortawesome/fontawesome-free/svgs/brands/google-dri
|
||||
class GDrive extends LitElement {
|
||||
constructor() {
|
||||
super();
|
||||
// @ts-expect-error - TS2339 - Property 'state' does not exist on type 'GDrive'.
|
||||
this.state = "trypublic";
|
||||
// @ts-expect-error - TS2339 - Property 'sourceUrl' does not exist on type 'GDrive'.
|
||||
this.sourceUrl = "";
|
||||
// @ts-expect-error - TS2339 - Property 'scriptLoaded' does not exist on type 'GDrive'.
|
||||
this.scriptLoaded = false;
|
||||
// @ts-expect-error - TS2339 - Property 'error' does not exist on type 'GDrive'.
|
||||
this.error = false;
|
||||
}
|
||||
|
||||
@@ -24,10 +28,13 @@ class GDrive extends LitElement {
|
||||
|
||||
updated(changedProperties) {
|
||||
if (changedProperties.has("sourceUrl")) {
|
||||
// @ts-expect-error - TS2339 - Property 'error' does not exist on type 'GDrive'.
|
||||
this.error = false;
|
||||
// @ts-expect-error - TS2339 - Property 'state' does not exist on type 'GDrive'.
|
||||
this.state = "trypublic";
|
||||
this.tryPublicAccess().then((result) => {
|
||||
if (!result) {
|
||||
// @ts-expect-error - TS2339 - Property 'state' does not exist on type 'GDrive'.
|
||||
this.state = "tryauto";
|
||||
this.requestUpdate();
|
||||
}
|
||||
@@ -37,17 +44,19 @@ class GDrive extends LitElement {
|
||||
|
||||
async tryPublicAccess() {
|
||||
try {
|
||||
// @ts-expect-error - TS2339 - Property 'sourceUrl' does not exist on type 'GDrive'.
|
||||
const sourceUrl = this.sourceUrl;
|
||||
const fileId = sourceUrl.slice("googledrive://".length);
|
||||
// eslint-disable-next-line no-undef
|
||||
const publicCheckUrl = `${__HELPER_PROXY__}/g/${fileId}`;
|
||||
|
||||
let resp = null;
|
||||
try {
|
||||
// @ts-expect-error - TS2322 - Type 'Response' is not assignable to type 'null'.
|
||||
resp = await fetch(publicCheckUrl);
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
// @ts-expect-error - TS2531 - Object is possibly 'null'.
|
||||
const json = await resp.json();
|
||||
if (!json.url || !json.name || !json.size) {
|
||||
return false;
|
||||
@@ -63,8 +72,10 @@ class GDrive extends LitElement {
|
||||
try {
|
||||
const abort = new AbortController();
|
||||
const signal = abort.signal;
|
||||
// @ts-expect-error - TS2322 - Type 'Response' is not assignable to type 'null'.
|
||||
resp = await fetch(publicUrl, { signal });
|
||||
abort.abort();
|
||||
// @ts-expect-error - TS2531 - Object is possibly 'null'.
|
||||
if (resp.status != 200) {
|
||||
return false;
|
||||
}
|
||||
@@ -88,10 +99,13 @@ class GDrive extends LitElement {
|
||||
}
|
||||
|
||||
onLoad() {
|
||||
// @ts-expect-error - TS2339 - Property 'scriptLoaded' does not exist on type 'GDrive'.
|
||||
this.scriptLoaded = true;
|
||||
this.gauth("none", (response) => {
|
||||
if (response.error) {
|
||||
// @ts-expect-error - TS2339 - Property 'state' does not exist on type 'GDrive'.
|
||||
if (this.state !== "implicitonly") {
|
||||
// @ts-expect-error - TS2339 - Property 'state' does not exist on type 'GDrive'.
|
||||
this.state = "trymanual";
|
||||
}
|
||||
} else {
|
||||
@@ -109,6 +123,7 @@ class GDrive extends LitElement {
|
||||
}
|
||||
|
||||
async authed(response) {
|
||||
// @ts-expect-error - TS2339 - Property 'sourceUrl' does not exist on type 'GDrive'.
|
||||
const sourceUrl = this.sourceUrl;
|
||||
const fileId = sourceUrl.slice("googledrive://".length);
|
||||
const metadataUrl = `https://www.googleapis.com/drive/v3/files/${fileId}`;
|
||||
@@ -121,13 +136,17 @@ class GDrive extends LitElement {
|
||||
);
|
||||
|
||||
if (resp.status === 404 || resp.status == 403) {
|
||||
// @ts-expect-error - TS2339 - Property 'state' does not exist on type 'GDrive'.
|
||||
if (this.state !== "implicitonly") {
|
||||
// @ts-expect-error - TS2339 - Property 'state' does not exist on type 'GDrive'.
|
||||
this.state = "trymanual";
|
||||
}
|
||||
// @ts-expect-error - TS2339 - Property 'error' does not exist on type 'GDrive'.
|
||||
this.error = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// @ts-expect-error - TS2339 - Property 'error' does not exist on type 'GDrive'.
|
||||
this.error = false;
|
||||
|
||||
const metadata = await resp.json();
|
||||
@@ -147,16 +166,23 @@ class GDrive extends LitElement {
|
||||
|
||||
render() {
|
||||
return html` ${this.script()}
|
||||
${this.state !== "trymanual"
|
||||
${
|
||||
// @ts-expect-error - TS2339 - Property 'state' does not exist on type 'GDrive'.
|
||||
this.state !== "trymanual"
|
||||
? html` <p>Connecting to Google Drive...</p> `
|
||||
: html`
|
||||
${this.error
|
||||
${
|
||||
// @ts-expect-error - TS2339 - Property 'error' does not exist on type 'GDrive'.
|
||||
this.error
|
||||
? html`
|
||||
<div class="error has-text-danger">
|
||||
<p>
|
||||
${this.reauth
|
||||
${
|
||||
// @ts-expect-error - TS2339 - Property 'reauth' does not exist on type 'GDrive'.
|
||||
this.reauth
|
||||
? "Some resources are loaded on demand from Google Drive, which requires reauthorization."
|
||||
: "Could not access this file with the current Google Drive account."}
|
||||
: "Could not access this file with the current Google Drive account."
|
||||
}
|
||||
</p>
|
||||
<p>
|
||||
If you have multiple Google Drive accounts, be sure to
|
||||
@@ -165,7 +191,8 @@ class GDrive extends LitElement {
|
||||
</div>
|
||||
<br />
|
||||
`
|
||||
: ""}
|
||||
: ""
|
||||
}
|
||||
<button
|
||||
class="button is-warning is-rounded"
|
||||
@click="${this.onClickAuth}"
|
||||
@@ -175,10 +202,12 @@ class GDrive extends LitElement {
|
||||
></span>
|
||||
<span>Authorize Google Drive</span>
|
||||
</button>
|
||||
`}`;
|
||||
`
|
||||
}`;
|
||||
}
|
||||
|
||||
script() {
|
||||
// @ts-expect-error - TS2339 - Property 'state' does not exist on type 'GDrive'. | TS2339 - Property 'scriptLoaded' does not exist on type 'GDrive'.
|
||||
if (this.state === "trypublic" || this.scriptLoaded) {
|
||||
return html``;
|
||||
}
|
||||
@@ -189,10 +218,11 @@ class GDrive extends LitElement {
|
||||
}
|
||||
|
||||
gauth(prompt, callback) {
|
||||
// @ts-expect-error - TS2339 - Property 'gapi' does not exist on type 'Window & typeof globalThis'.
|
||||
self.gapi.load("auth2", () => {
|
||||
// @ts-expect-error - TS2339 - Property 'gapi' does not exist on type 'Window & typeof globalThis'.
|
||||
self.gapi.auth2.authorize(
|
||||
{
|
||||
// eslint-disable-next-line no-undef
|
||||
client_id: __GDRIVE_CLIENT_ID__,
|
||||
scope: "https://www.googleapis.com/auth/drive.file",
|
||||
response_type: "token",
|
||||
Vendored
+12
-1
@@ -1,2 +1,13 @@
|
||||
declare module "*.svg";
|
||||
declare let __SW_NAME__: string;
|
||||
declare const __SW_NAME__: string;
|
||||
declare const __HELPER_PROXY__: string;
|
||||
declare const __GDRIVE_CLIENT_ID__: string;
|
||||
declare const __VERSION__: string;
|
||||
|
||||
// showOpenFilePicker doesn't yet exist in Typescript's DOM lib
|
||||
// see https://developer.mozilla.org/en-US/docs/Web/API/Window/showOpenFilePicker for details
|
||||
interface Window {
|
||||
showOpenFilePicker: (options?: {
|
||||
types: { description: string; accept: Record<string, string[]> }[];
|
||||
}) => Promise<[FileSystemFileHandle]>;
|
||||
}
|
||||
|
||||
@@ -20,12 +20,15 @@ class ItemIndex extends LitElement {
|
||||
query = "";
|
||||
|
||||
@property({ type: Array })
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO fixme
|
||||
filteredItems: any[] = [];
|
||||
|
||||
@property({ type: Array })
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO fixme
|
||||
sortedItems: any[] | null = null;
|
||||
|
||||
@property({ type: Boolean })
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO fixme
|
||||
hideHeader: any = null;
|
||||
|
||||
@property({ type: String })
|
||||
@@ -35,6 +38,7 @@ class ItemIndex extends LitElement {
|
||||
headerName = "Loaded Archives";
|
||||
|
||||
@state()
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO fixme
|
||||
private _deleting: any = {};
|
||||
|
||||
private typeFilter = "";
|
||||
|
||||
+48
-24
@@ -48,16 +48,36 @@ import fasAngleLeft from "@fortawesome/fontawesome-free/svgs/solid/angle-left.sv
|
||||
import fasAngleRight from "@fortawesome/fontawesome-free/svgs/solid/angle-right.svg";
|
||||
import fasCaretDown from "@fortawesome/fontawesome-free/svgs/solid/caret-down.svg";
|
||||
|
||||
import { RWPEmbedReceipt } from "./embed-receipt.js";
|
||||
import { RWPEmbedReceipt } from "./embed-receipt";
|
||||
import Split from "split.js";
|
||||
|
||||
import type { Item as ItemInfo } from "./types";
|
||||
import type { Replay } from "./replay";
|
||||
import { ifDefined } from "lit/directives/if-defined.js";
|
||||
|
||||
import "./item-info";
|
||||
|
||||
const RWP_SCHEME = "search://";
|
||||
|
||||
export type LoadInfo = {
|
||||
extraConfig?: {
|
||||
baseUrlSourcePrefix?: unknown;
|
||||
baseUrl?: unknown;
|
||||
headers?: unknown;
|
||||
recording?: unknown;
|
||||
};
|
||||
customColl?: string | null;
|
||||
noWebWorker?: boolean;
|
||||
noCache?: boolean;
|
||||
hideOffscreen?: boolean;
|
||||
loadEager?: boolean;
|
||||
sourceUrl?: string;
|
||||
loadUrl?: string;
|
||||
swError?: string;
|
||||
newFullImport?: unknown;
|
||||
name?: string;
|
||||
};
|
||||
|
||||
// ===========================================================================
|
||||
class Item extends LitElement {
|
||||
@property({ type: Boolean })
|
||||
@@ -67,7 +87,7 @@ class Item extends LitElement {
|
||||
sourceUrl: string | null = null;
|
||||
|
||||
@property({ type: Object, attribute: false })
|
||||
loadInfo: any;
|
||||
loadInfo: LoadInfo | null = null;
|
||||
|
||||
@property({ type: Boolean })
|
||||
showSidebar: boolean | null = null;
|
||||
@@ -142,9 +162,9 @@ class Item extends LitElement {
|
||||
autoUpdateInterval = 10;
|
||||
|
||||
@property({ type: String })
|
||||
swName: any = null;
|
||||
swName: string | null = null;
|
||||
|
||||
private splitter: any = null;
|
||||
private splitter: Split.Instance | null = null;
|
||||
|
||||
private _replaceLoc = false;
|
||||
private _locUpdateNeeded = false;
|
||||
@@ -224,7 +244,7 @@ class Item extends LitElement {
|
||||
this.updateTabData({ multiTs: json.timestamps });
|
||||
}
|
||||
|
||||
willUpdate(changedProperties: Map<string, any>) {
|
||||
willUpdate(changedProperties: Map<string, Record<string, unknown>>) {
|
||||
if (changedProperties.has("tabData") && this.tabData) {
|
||||
// Format tab data from URL query params
|
||||
const tabData = {};
|
||||
@@ -266,7 +286,9 @@ class Item extends LitElement {
|
||||
if (!this.itemInfo || !this.itemInfo.coll) {
|
||||
return;
|
||||
}
|
||||
const newHash = "#" + new URLSearchParams(this.tabData as any).toString();
|
||||
const newHash =
|
||||
"#" +
|
||||
new URLSearchParams(this.tabData as Record<string, string>).toString();
|
||||
|
||||
if (!this.tabData.url) {
|
||||
this.url =
|
||||
@@ -338,7 +360,7 @@ class Item extends LitElement {
|
||||
},
|
||||
};
|
||||
|
||||
this.splitter = Split([contents as any, replay], opts);
|
||||
this.splitter = Split([contents, replay], opts);
|
||||
}
|
||||
} else if (this.splitter) {
|
||||
try {
|
||||
@@ -850,6 +872,7 @@ class Item extends LitElement {
|
||||
|
||||
if (!isReplay && this.tabData && this.tabData.view) {
|
||||
const detail = {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO fixme
|
||||
title: (this.tabLabels as any)[this.tabData.view],
|
||||
replayTitle: false,
|
||||
};
|
||||
@@ -866,7 +889,7 @@ class Item extends LitElement {
|
||||
return html` <wr-loader
|
||||
.loadInfo="${this.loadInfo}"
|
||||
embed="${this.embed || ""}"
|
||||
swName="${this.swName}"
|
||||
swName="${ifDefined(this.swName === null ? undefined : this.swName)}"
|
||||
.coll="${this.item}"
|
||||
sourceUrl="${this.sourceUrl || ""}"
|
||||
@coll-loaded=${this.onItemLoaded}
|
||||
@@ -891,7 +914,7 @@ class Item extends LitElement {
|
||||
: isReplay
|
||||
? "is-hidden"
|
||||
: "full-pages"}"
|
||||
role="${(isSidebar ? "complementary" : "") as any}"
|
||||
role="${ifDefined(isSidebar ? "complementary" : undefined)}"
|
||||
aria-label="${isSidebar ? "Browse Contents" : ""}"
|
||||
>
|
||||
${this.renderTabHeader(isSidebar)}
|
||||
@@ -961,9 +984,9 @@ class Item extends LitElement {
|
||||
href="#story"
|
||||
class="is-size-6"
|
||||
aria-label="Story"
|
||||
aria-current="${(this.tabData.view === "story"
|
||||
? "location"
|
||||
: "") as any}"
|
||||
aria-current="${ifDefined(
|
||||
this.tabData.view === "story" ? "location" : undefined,
|
||||
)}"
|
||||
>
|
||||
<span class="icon"
|
||||
><fa-icon
|
||||
@@ -987,9 +1010,9 @@ class Item extends LitElement {
|
||||
href="#pages"
|
||||
class="is-size-6"
|
||||
aria-label="Pages"
|
||||
aria-current="${(this.tabData.view === "pages"
|
||||
? "location"
|
||||
: "") as any}"
|
||||
aria-current="${ifDefined(
|
||||
this.tabData.view === "pages" ? "location" : undefined,
|
||||
)}"
|
||||
>
|
||||
<span class="icon"
|
||||
><fa-icon
|
||||
@@ -1012,9 +1035,9 @@ class Item extends LitElement {
|
||||
href="#resources"
|
||||
class="is-size-6"
|
||||
aria-label="URLs"
|
||||
aria-current="${(this.tabData.view === "resources"
|
||||
? "location"
|
||||
: "") as any}"
|
||||
aria-current="${ifDefined(
|
||||
this.tabData.view === "resources" ? "location" : undefined,
|
||||
)}"
|
||||
>
|
||||
<span class="icon"
|
||||
><fa-icon
|
||||
@@ -1513,7 +1536,7 @@ class Item extends LitElement {
|
||||
id="story"
|
||||
.isSidebar="${isSidebar}"
|
||||
class="${isStory ? "" : "is-hidden"} ${isSidebar ? "sidebar" : ""}"
|
||||
role="${(isSidebar ? "" : "main") as any}"
|
||||
role="${ifDefined(isSidebar ? undefined : "main")}"
|
||||
>
|
||||
</wr-coll-story>`
|
||||
: ""}
|
||||
@@ -1530,7 +1553,7 @@ class Item extends LitElement {
|
||||
class="is-paddingless ${isResources ? "" : "is-hidden"} ${isSidebar
|
||||
? "sidebar"
|
||||
: ""}"
|
||||
role="${(isSidebar ? "" : "main") as any}"
|
||||
role="${ifDefined(isSidebar ? undefined : "main")}"
|
||||
>
|
||||
</wr-coll-resources>`
|
||||
: ""}
|
||||
@@ -1548,7 +1571,7 @@ class Item extends LitElement {
|
||||
id="pages"
|
||||
@coll-update="${this.onItemUpdate}"
|
||||
class="${isPages ? "" : "is-hidden"} ${isSidebar ? "sidebar" : ""}"
|
||||
role="${(isSidebar ? "" : "main") as any}"
|
||||
role="${ifDefined(isSidebar ? undefined : "main")}"
|
||||
>
|
||||
</wr-page-view>`
|
||||
: ""}
|
||||
@@ -1738,6 +1761,7 @@ class Item extends LitElement {
|
||||
|
||||
_stringToParams(value) {
|
||||
const q = new URLSearchParams(value.slice(RWP_SCHEME.length));
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO fixme
|
||||
const data: any = {};
|
||||
data.url = "";
|
||||
data.ts = "";
|
||||
@@ -1757,7 +1781,7 @@ class Item extends LitElement {
|
||||
return data;
|
||||
}
|
||||
|
||||
_paramsToString(value) {
|
||||
_paramsToString(value: Record<string, unknown>) {
|
||||
const q = new URLSearchParams();
|
||||
|
||||
for (const param of [
|
||||
@@ -1768,14 +1792,14 @@ class Item extends LitElement {
|
||||
"urlSearchType",
|
||||
]) {
|
||||
if (param in value) {
|
||||
q.set(param, value[param]);
|
||||
q.set(param, String(value[param]));
|
||||
}
|
||||
}
|
||||
|
||||
return q.toString();
|
||||
}
|
||||
|
||||
onRefresh(event, replayOnly = false) {
|
||||
onRefresh(event: Event | null, replayOnly = false) {
|
||||
if (event) {
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
@@ -4,52 +4,36 @@ import { wrapCss } from "./misc";
|
||||
import prettyBytes from "pretty-bytes";
|
||||
|
||||
import { parseURLSchemeHostPath } from "./pageutils";
|
||||
import { property } from "lit/decorators.js";
|
||||
import { LoadInfo } from "./item";
|
||||
|
||||
// ===========================================================================
|
||||
class Loader extends LitElement {
|
||||
constructor() {
|
||||
super();
|
||||
this.progress = 0;
|
||||
this.total = 0;
|
||||
this.percent = 0;
|
||||
this.coll = "";
|
||||
this.state = "waiting";
|
||||
this.loadInfo = null;
|
||||
@property({ type: String }) sourceUrl?: string;
|
||||
@property({ type: Object }) loadInfo: LoadInfo | null = null;
|
||||
@property({ type: String }) state = "waiting";
|
||||
@property({ type: Number }) progress = 0;
|
||||
@property({ type: Number }) percent = 0;
|
||||
@property({ type: Number }) currentSize = 0;
|
||||
@property({ type: Number }) totalSize = 0;
|
||||
@property({ type: String }) error?: string;
|
||||
@property({ type: Number }) total = 0;
|
||||
@property({ type: String }) status?: string;
|
||||
@property({ type: String }) coll = "";
|
||||
@property({ type: String }) embed?: string;
|
||||
@property({ type: Boolean }) tryFileHandle = !!window.showOpenFilePicker;
|
||||
@property({ type: Boolean }) errorAllowRetry = false;
|
||||
@property({ type: String }) extraMsg?: string;
|
||||
@property({ type: String }) swName?: string;
|
||||
|
||||
this.currentSize = 0;
|
||||
this.totalSize = 0;
|
||||
pingInterval: number | NodeJS.Timer = 0;
|
||||
fileHandle: FileSystemHandle | null = null;
|
||||
noWebWorker = false;
|
||||
worker?: Worker | null;
|
||||
|
||||
this.tryFileHandle = !!window.showOpenFilePicker;
|
||||
|
||||
this.fileHandle = null;
|
||||
|
||||
this.errorAllowRetry = false;
|
||||
|
||||
this.pingInterval = 0;
|
||||
|
||||
this.noWebWorker = false;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
return {
|
||||
sourceUrl: { type: String },
|
||||
loadInfo: { type: Object },
|
||||
state: { type: String },
|
||||
progress: { type: Number },
|
||||
percent: { type: Number },
|
||||
currentSize: { type: Number },
|
||||
totalSize: { type: Number },
|
||||
error: { type: String },
|
||||
total: { type: Number },
|
||||
status: { type: String },
|
||||
coll: { type: String },
|
||||
embed: { type: String },
|
||||
tryFileHandle: { type: Boolean },
|
||||
errorAllowRetry: { type: Boolean },
|
||||
extraMsg: { type: String },
|
||||
swName: { type: String },
|
||||
};
|
||||
}
|
||||
// Google Drive
|
||||
_gdWait?: Promise<LoadInfo>;
|
||||
_gdResolve!: (value: LoadInfo | PromiseLike<LoadInfo>) => void;
|
||||
|
||||
firstUpdated() {
|
||||
this.initMessages();
|
||||
@@ -57,17 +41,17 @@ class Loader extends LitElement {
|
||||
}
|
||||
|
||||
initMessages() {
|
||||
this.noWebWorker = this.loadInfo && this.loadInfo.noWebWorker;
|
||||
this.noWebWorker = Boolean(this.loadInfo && this.loadInfo.noWebWorker);
|
||||
|
||||
if (!this.noWebWorker) {
|
||||
// eslint-disable-next-line no-undef
|
||||
this.worker = new Worker(this.swName);
|
||||
this.worker = new Worker(this.swName!);
|
||||
} else {
|
||||
if (!navigator.serviceWorker) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.worker = navigator.serviceWorker;
|
||||
// TODO figure out if this is okay?
|
||||
this.worker = navigator.serviceWorker as unknown as Worker;
|
||||
}
|
||||
|
||||
this.worker.addEventListener("message", (event) => {
|
||||
@@ -110,7 +94,7 @@ class Loader extends LitElement {
|
||||
);
|
||||
|
||||
if (!this.noWebWorker) {
|
||||
this.worker.terminate();
|
||||
this.worker?.terminate();
|
||||
} else {
|
||||
if (this.pingInterval) {
|
||||
clearInterval(this.pingInterval);
|
||||
@@ -125,7 +109,7 @@ class Loader extends LitElement {
|
||||
|
||||
async doLoad() {
|
||||
let sourceUrl = this.sourceUrl;
|
||||
let source = null;
|
||||
let source: LoadInfo | null = null;
|
||||
|
||||
this.percent = this.currentSize = this.totalSize = 0;
|
||||
|
||||
@@ -145,7 +129,7 @@ class Loader extends LitElement {
|
||||
switch (scheme) {
|
||||
case "googledrive":
|
||||
this.state = "googledrive";
|
||||
source = await this.googledriveInit();
|
||||
source = (await this.googledriveInit()) ?? null;
|
||||
break;
|
||||
|
||||
case "s3":
|
||||
@@ -170,7 +154,7 @@ You can select a file to upload from the main page by clicking the 'Choose File.
|
||||
break;
|
||||
|
||||
case "proxy":
|
||||
sourceUrl = "proxy:" + sourceUrl.slice("proxy://".length);
|
||||
sourceUrl = "proxy:" + sourceUrl!.slice("proxy://".length);
|
||||
break;
|
||||
}
|
||||
} catch (e) {
|
||||
@@ -184,7 +168,7 @@ You can select a file to upload from the main page by clicking the 'Choose File.
|
||||
this.state = "started";
|
||||
|
||||
let type = undefined;
|
||||
let extraConfig = undefined;
|
||||
let extraConfig: LoadInfo["extraConfig"] = undefined;
|
||||
|
||||
if (this.loadInfo) {
|
||||
source.newFullImport = this.loadInfo.newFullImport;
|
||||
@@ -196,10 +180,11 @@ You can select a file to upload from the main page by clicking the 'Choose File.
|
||||
}
|
||||
// todo: too special case?
|
||||
if (
|
||||
sourceUrl.startsWith("proxy:") &&
|
||||
sourceUrl!.startsWith("proxy:") &&
|
||||
extraConfig &&
|
||||
extraConfig.recording
|
||||
) {
|
||||
// @ts-expect-error - TS2322 - Type '"recordingproxy"' is not assignable to type 'undefined'.
|
||||
type = "recordingproxy";
|
||||
}
|
||||
}
|
||||
@@ -216,6 +201,7 @@ You can select a file to upload from the main page by clicking the 'Choose File.
|
||||
if (!navigator.serviceWorker.controller) {
|
||||
await new Promise((resolve) => {
|
||||
navigator.serviceWorker.addEventListener("controllerchange", () =>
|
||||
// @ts-expect-error - TS2794 - Expected 1 arguments, but got 0. Did you forget to include 'void' in your type argument to 'Promise'?
|
||||
resolve(),
|
||||
);
|
||||
});
|
||||
@@ -225,11 +211,13 @@ You can select a file to upload from the main page by clicking the 'Choose File.
|
||||
if (!this.noWebWorker) {
|
||||
this.worker.postMessage(msg);
|
||||
} else {
|
||||
// @ts-expect-error - TS2531 - Object is possibly 'null'.
|
||||
navigator.serviceWorker.controller.postMessage(msg);
|
||||
|
||||
// ping service worker with messages to avoid shutdown while loading
|
||||
// (mostly for Firefox)
|
||||
this.pingInterval = setInterval(() => {
|
||||
// @ts-expect-error - TS2531 - Object is possibly 'null'.
|
||||
navigator.serviceWorker.controller.postMessage({ msg_type: "ping" });
|
||||
}, 15000);
|
||||
}
|
||||
@@ -350,7 +338,7 @@ You can select a file to upload from the main page by clicking the 'Choose File.
|
||||
switch (this.state) {
|
||||
case "googledrive":
|
||||
return html`<wr-gdrive
|
||||
.sourceUrl=${this.sourceUrl}
|
||||
.sourceUrl=${this.sourceUrl!}
|
||||
@load-ready=${this.onLoadReady}
|
||||
></wr-gdrive>`;
|
||||
|
||||
@@ -363,10 +351,15 @@ You can select a file to upload from the main page by clicking the 'Choose File.
|
||||
max="100"
|
||||
></progress>
|
||||
<label class="progress-label" for="progress">${this.percent}%</label>
|
||||
|
||||
${this.currentSize && this.totalSize
|
||||
? html` <div class="loaded-prog">
|
||||
Loaded <b>${prettyBytes(this.currentSize)}</b> of
|
||||
Loaded
|
||||
<b>${prettyBytes(this.currentSize)}</b>
|
||||
of
|
||||
|
||||
<b>${prettyBytes(this.totalSize)}</b>
|
||||
|
||||
${this.extraMsg &&
|
||||
html` <p class="extra-msg">(${this.extraMsg})</p> `}
|
||||
</div>`
|
||||
@@ -417,7 +410,10 @@ You can select a file to upload from the main page by clicking the 'Choose File.
|
||||
}
|
||||
|
||||
async onAskPermission() {
|
||||
const result = await this.fileHandle.requestPermission({ mode: "read" });
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const result = await (this.fileHandle as any)?.requestPermission({
|
||||
mode: "read",
|
||||
});
|
||||
if (result === "granted") {
|
||||
this.doLoad();
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import { LitElement, html, css, unsafeCSS } from "lit";
|
||||
import { unsafeSVG } from "lit/directives/unsafe-svg.js";
|
||||
import { styleMap } from "lit/directives/style-map.js";
|
||||
|
||||
// @ts-expect-error - TS2307 - Cannot find module '../assets/main.scss' or its corresponding type declarations.
|
||||
import allCssRaw from "../assets/main.scss";
|
||||
|
||||
import rwpLogo from "../assets/logo.svg";
|
||||
@@ -18,11 +19,12 @@ function wrapCss(custom) {
|
||||
}
|
||||
|
||||
const IS_APP =
|
||||
// @ts-expect-error - TS2339 - Property 'IS_APP' does not exist on type 'Window & typeof globalThis'.
|
||||
window.IS_APP ||
|
||||
// @ts-expect-error - TS2551 - Property 'electron' does not exist on type 'Window & typeof globalThis'. Did you mean 'Electron'? | TS2551 - Property 'electron' does not exist on type 'Window & typeof globalThis'. Did you mean 'Electron'?
|
||||
(window.electron && window.electron.IS_APP) ||
|
||||
window.matchMedia("(display-mode: standalone)").matches;
|
||||
|
||||
// eslint-disable-next-line no-undef
|
||||
const VERSION = __VERSION__;
|
||||
|
||||
// ===========================================================================
|
||||
@@ -39,8 +41,11 @@ function clickOnSpacebarPress(event) {
|
||||
class FaIcon extends LitElement {
|
||||
constructor() {
|
||||
super();
|
||||
// @ts-expect-error - TS2339 - Property 'size' does not exist on type 'FaIcon'.
|
||||
this.size = "1.1em";
|
||||
// @ts-expect-error - TS2339 - Property 'width' does not exist on type 'FaIcon'.
|
||||
this.width = null;
|
||||
// @ts-expect-error - TS2339 - Property 'height' does not exist on type 'FaIcon'.
|
||||
this.height = null;
|
||||
}
|
||||
|
||||
@@ -70,26 +75,39 @@ class FaIcon extends LitElement {
|
||||
}
|
||||
|
||||
render() {
|
||||
// @ts-expect-error - TS2339 - Property 'svg' does not exist on type 'FaIcon'.
|
||||
if (!this.svg) {
|
||||
return html``;
|
||||
}
|
||||
|
||||
const styles = {};
|
||||
|
||||
// @ts-expect-error - TS2339 - Property 'size' does not exist on type 'FaIcon'.
|
||||
if (this.size) {
|
||||
// @ts-expect-error - TS2339 - Property 'width' does not exist on type '{}'. | TS2339 - Property 'size' does not exist on type 'FaIcon'.
|
||||
styles.width = this.size;
|
||||
// @ts-expect-error - TS2339 - Property 'height' does not exist on type '{}'. | TS2339 - Property 'size' does not exist on type 'FaIcon'.
|
||||
styles.height = this.size;
|
||||
} else {
|
||||
// @ts-expect-error - TS2339 - Property 'width' does not exist on type 'FaIcon'.
|
||||
if (this.width) {
|
||||
// @ts-expect-error - TS2339 - Property 'width' does not exist on type '{}'. | TS2339 - Property 'width' does not exist on type 'FaIcon'.
|
||||
styles.width = this.width;
|
||||
}
|
||||
// @ts-expect-error - TS2339 - Property 'height' does not exist on type 'FaIcon'.
|
||||
if (this.height) {
|
||||
// @ts-expect-error - TS2339 - Property 'height' does not exist on type '{}'. | TS2339 - Property 'height' does not exist on type 'FaIcon'.
|
||||
styles.height = this.height;
|
||||
}
|
||||
}
|
||||
|
||||
return html`<svg style="${styleMap(styles)}">
|
||||
<g>${unsafeSVG(this.svg)}</g>
|
||||
<g>
|
||||
${
|
||||
// @ts-expect-error - TS2339 - Property 'svg' does not exist on type 'FaIcon'.
|
||||
unsafeSVG(this.svg)
|
||||
}
|
||||
</g>
|
||||
</svg>`;
|
||||
}
|
||||
}
|
||||
@@ -98,6 +116,7 @@ class FaIcon extends LitElement {
|
||||
class AnimLogo extends FaIcon {
|
||||
constructor() {
|
||||
super();
|
||||
// @ts-expect-error - TS2339 - Property 'svg' does not exist on type 'AnimLogo'.
|
||||
this.svg = rwpLogo;
|
||||
}
|
||||
|
||||
@@ -155,7 +174,9 @@ class WrModal extends LitElement {
|
||||
constructor() {
|
||||
super();
|
||||
this.title = "";
|
||||
// @ts-expect-error - TS2339 - Property 'bgClass' does not exist on type 'WrModal'.
|
||||
this.bgClass = "";
|
||||
// @ts-expect-error - TS2339 - Property 'noBgClose' does not exist on type 'WrModal'.
|
||||
this.noBgClose = false;
|
||||
}
|
||||
|
||||
@@ -188,10 +209,18 @@ class WrModal extends LitElement {
|
||||
return html` <div class="modal is-active">
|
||||
<div
|
||||
class="modal-background"
|
||||
@click="${() => !this.noBgClose && this.onClose()}"
|
||||
@click="${
|
||||
// @ts-expect-error - TS2339 - Property 'noBgClose' does not exist on type 'WrModal'.
|
||||
() => !this.noBgClose && this.onClose()
|
||||
}"
|
||||
></div>
|
||||
<div class="modal-card">
|
||||
<header class="modal-card-head ${this.bgClass}">
|
||||
<header
|
||||
class="modal-card-head ${
|
||||
// @ts-expect-error - TS2339 - Property 'bgClass' does not exist on type 'WrModal'.
|
||||
this.bgClass
|
||||
}"
|
||||
>
|
||||
<p class="modal-card-title is-3">${this.title}</p>
|
||||
<button
|
||||
class="delete"
|
||||
+2
-1
@@ -18,6 +18,7 @@ class PageEntry extends LitElement {
|
||||
textSnippet: string | null = "";
|
||||
|
||||
@property({ type: Object })
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO fixme
|
||||
page: any = null;
|
||||
|
||||
@property({ type: String })
|
||||
@@ -77,7 +78,7 @@ class PageEntry extends LitElement {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Overrde Bulma to add the tiniest margin, so the focus indicator isn't obscured */
|
||||
/* Override Bulma to add the tiniest margin, so the focus indicator isn't obscured */
|
||||
.columns {
|
||||
margin-top: calc(-0.75rem + 2px);
|
||||
}
|
||||
|
||||
@@ -20,21 +20,26 @@ import type { PageEntry } from "./pageentry";
|
||||
// ===========================================================================
|
||||
class Pages extends LitElement {
|
||||
@property({ type: Array })
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO fixme
|
||||
filteredPages: any[] = [];
|
||||
|
||||
@property({ type: Array })
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO fixme
|
||||
sortedPages: any[] = [];
|
||||
|
||||
@property({ type: String })
|
||||
query = "";
|
||||
|
||||
@property()
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO fixme
|
||||
flex: any = null;
|
||||
|
||||
@property()
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO fixme
|
||||
textPages: any = null;
|
||||
|
||||
@property()
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO fixme
|
||||
newQuery: any = null;
|
||||
|
||||
@property({ type: Boolean })
|
||||
@@ -83,15 +88,19 @@ class Pages extends LitElement {
|
||||
ts = "";
|
||||
|
||||
@property({ type: Boolean })
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO fixme
|
||||
editing: any = false;
|
||||
|
||||
@property({ type: Object })
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO fixme
|
||||
toDeletePages: any = null;
|
||||
|
||||
@property({ type: Object })
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO fixme
|
||||
toDeletePage: any = null;
|
||||
|
||||
@property({ type: Object })
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO fixme
|
||||
collInfo: any;
|
||||
|
||||
@property({ type: Boolean })
|
||||
@@ -100,6 +109,7 @@ class Pages extends LitElement {
|
||||
@property({ type: String })
|
||||
defaultKey = "";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO fixme
|
||||
private _ival: any;
|
||||
|
||||
static get sortKeys() {
|
||||
@@ -127,6 +137,7 @@ class Pages extends LitElement {
|
||||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO fixme
|
||||
async updated(changedProperties: Map<string, any>) {
|
||||
if (changedProperties.has("collInfo")) {
|
||||
this.updateTextSearch();
|
||||
@@ -154,7 +165,9 @@ class Pages extends LitElement {
|
||||
}
|
||||
const sorter = this.renderRoot.querySelector("wr-sorter") as Sorter;
|
||||
if (sorter) {
|
||||
// @ts-expect-error - TS2339 - Property 'sortKey' does not exist on type 'Sorter'.
|
||||
sorter.sortKey = this.sortKey;
|
||||
// @ts-expect-error - TS2339 - Property 'sortDesc' does not exist on type 'Sorter'.
|
||||
sorter.sortDesc = this.sortDesc;
|
||||
}
|
||||
}
|
||||
@@ -168,6 +181,7 @@ class Pages extends LitElement {
|
||||
block: "nearest",
|
||||
inline: "nearest",
|
||||
};
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO fixme
|
||||
setTimeout(() => selected.scrollIntoView(opts as any), 100);
|
||||
}
|
||||
//}
|
||||
@@ -175,6 +189,7 @@ class Pages extends LitElement {
|
||||
}
|
||||
|
||||
onChangeQuery(event: Event) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO fixme
|
||||
this.newQuery = (event.currentTarget as any).value;
|
||||
//this.loading = true;
|
||||
if (this._ival) {
|
||||
@@ -280,6 +295,7 @@ class Pages extends LitElement {
|
||||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO fixme
|
||||
const lines: any[] = [];
|
||||
|
||||
for await (const line of ndjson(resp.body!.getReader())) {
|
||||
|
||||
+8
-2
@@ -10,6 +10,7 @@ class Replay extends LitElement {
|
||||
collInfo: Item | Record<string, never> | null = null;
|
||||
|
||||
@property({ type: String })
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO fixme
|
||||
sourceUrl: any = null;
|
||||
|
||||
// external url set from parent
|
||||
@@ -33,12 +34,14 @@ class Replay extends LitElement {
|
||||
title = "";
|
||||
|
||||
@property({ type: String })
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO fixme
|
||||
iframeUrl: any = null;
|
||||
|
||||
@property({ type: Boolean })
|
||||
showAuth = false;
|
||||
|
||||
@property({ type: Object })
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO fixme
|
||||
authFileHandle: any = null;
|
||||
|
||||
private reauthWait: null | Promise<void> = null;
|
||||
@@ -161,7 +164,8 @@ class Replay extends LitElement {
|
||||
}
|
||||
}
|
||||
|
||||
setDisablePointer(disable) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO fixme
|
||||
setDisablePointer(disable: any) {
|
||||
const iframe = this.renderRoot.querySelector("iframe");
|
||||
|
||||
if (iframe) {
|
||||
@@ -169,7 +173,8 @@ class Replay extends LitElement {
|
||||
}
|
||||
}
|
||||
|
||||
onReplayMessage(event) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO fixme
|
||||
onReplayMessage(event: any) {
|
||||
const iframe = this.renderRoot.querySelector("iframe");
|
||||
|
||||
if (iframe && event.source === iframe.contentWindow) {
|
||||
@@ -237,6 +242,7 @@ class Replay extends LitElement {
|
||||
!iframe.contentDocument ||
|
||||
!iframe.contentWindow ||
|
||||
(iframe.contentDocument.readyState === "complete" &&
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO fixme
|
||||
!(iframe.contentWindow as Window & { _WBWombat: any })._WBWombat)
|
||||
) {
|
||||
this.clearLoading(iframe && iframe.contentWindow);
|
||||
|
||||
-153
@@ -1,153 +0,0 @@
|
||||
import { LitElement, html, css } from "lit";
|
||||
import { wrapCss } from "./misc";
|
||||
|
||||
import fasSortDown from "@fortawesome/fontawesome-free/svgs/solid/sort-down.svg";
|
||||
import fasSortUp from "@fortawesome/fontawesome-free/svgs/solid/sort-up.svg";
|
||||
// ===========================================================================
|
||||
/**
|
||||
* @typedef {{key: string;name: string;}[]} SortKeys
|
||||
* @prop {SortKeys} sortKeys
|
||||
*/
|
||||
class Sorter extends LitElement {
|
||||
constructor() {
|
||||
super();
|
||||
this.sortedData = [];
|
||||
this.data = [];
|
||||
|
||||
this.pageResults = 0;
|
||||
this.numResults = 0;
|
||||
|
||||
this.sortKey = null;
|
||||
this.sortDesc = null;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
return {
|
||||
id: { type: String },
|
||||
|
||||
pageResults: { type: Number },
|
||||
|
||||
data: { type: Array },
|
||||
sortedData: { type: Array },
|
||||
|
||||
sortKey: { type: String },
|
||||
sortDesc: { type: Boolean },
|
||||
};
|
||||
}
|
||||
|
||||
firstUpdated() {
|
||||
if (this.id) {
|
||||
const sortKey = localStorage.getItem(`${this.id}:sortKey`);
|
||||
if (sortKey !== null) {
|
||||
this.sortKey = sortKey;
|
||||
}
|
||||
const sortDesc = localStorage.getItem(`${this.id}:sortDesc`);
|
||||
if (sortDesc !== null) {
|
||||
this.sortDesc = sortDesc === "1";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
updated(changedProperties) {
|
||||
const keyChanged = changedProperties.has("sortKey");
|
||||
const descChanged = changedProperties.has("sortDesc");
|
||||
const dataChanged = changedProperties.has("data");
|
||||
|
||||
if (keyChanged && this.sortKey !== null) {
|
||||
localStorage.setItem(`${this.id}:sortKey`, this.sortKey);
|
||||
}
|
||||
|
||||
if (descChanged && this.sortDesc !== null) {
|
||||
localStorage.setItem(`${this.id}:sortDesc`, this.sortDesc ? "1" : "0");
|
||||
}
|
||||
|
||||
if (keyChanged || descChanged || dataChanged) {
|
||||
this.sortData();
|
||||
}
|
||||
}
|
||||
|
||||
sortData() {
|
||||
this.sortedData = [...this.data];
|
||||
this.numResults = this.pageResults;
|
||||
|
||||
if (this.sortKey === "") {
|
||||
if (this.sortDesc) {
|
||||
this.sortedData.reverse();
|
||||
}
|
||||
} else {
|
||||
this.sortedData.sort((first, second) => {
|
||||
if (first[this.sortKey] === second[this.sortKey]) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return this.sortDesc == first[this.sortKey] < second[this.sortKey]
|
||||
? 1
|
||||
: -1;
|
||||
});
|
||||
}
|
||||
|
||||
this.sendSortChanged();
|
||||
}
|
||||
|
||||
sendSortChanged() {
|
||||
const detail = {
|
||||
sortKey: this.sortKey,
|
||||
sortDesc: this.sortDesc,
|
||||
sortedData: this.numResults
|
||||
? this.sortedData.slice(0, this.numResults)
|
||||
: this.sortedData,
|
||||
};
|
||||
this.dispatchEvent(new CustomEvent("sort-changed", { detail }));
|
||||
}
|
||||
|
||||
getMore(more = 100) {
|
||||
if (this.pageResults && this.numResults >= this.sortedData.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.numResults += more;
|
||||
this.sendSortChanged();
|
||||
}
|
||||
|
||||
static get styles() {
|
||||
return wrapCss(css`
|
||||
:host {
|
||||
min-width: 100px;
|
||||
box-sizing: border-box !important;
|
||||
}
|
||||
button.button.is-small {
|
||||
border-radius: 4px;
|
||||
}
|
||||
`);
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`
|
||||
<div class="select is-small">
|
||||
<select id="sort-select" @change=${(e) =>
|
||||
(this.sortKey = e.currentTarget.value)}>
|
||||
${this.sortKeys.map(
|
||||
(sort) => html`
|
||||
<option value="${sort.key}" ?selected="${sort.key === this.sortKey}">
|
||||
Sort By: ${sort.name}
|
||||
</option>
|
||||
`,
|
||||
)}
|
||||
</select>
|
||||
</div>
|
||||
<button @click=${() =>
|
||||
(this.sortDesc = !this.sortDesc)} class="button is-small">
|
||||
<span>Order:</span>
|
||||
<span class="is-sr-only">${
|
||||
this.sortDesc ? "Ascending" : "Descending"
|
||||
}</span>
|
||||
<span class="icon"><fa-icon aria-hidden="true" .svg=${
|
||||
this.sortDesc ? fasSortUp : fasSortDown
|
||||
}></span>
|
||||
</button>`;
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define("wr-sorter", Sorter);
|
||||
|
||||
export { Sorter };
|
||||
+191
@@ -0,0 +1,191 @@
|
||||
import { LitElement, html, css } from "lit";
|
||||
import { wrapCss } from "./misc";
|
||||
|
||||
import fasSortDown from "@fortawesome/fontawesome-free/svgs/solid/sort-down.svg";
|
||||
import fasSortUp from "@fortawesome/fontawesome-free/svgs/solid/sort-up.svg";
|
||||
|
||||
// ===========================================================================
|
||||
class Sorter extends LitElement {
|
||||
constructor() {
|
||||
super();
|
||||
// @ts-expect-error - TS2551 - Property 'sortedData' does not exist on type 'Sorter'. Did you mean 'sortData'?
|
||||
this.sortedData = [];
|
||||
// @ts-expect-error - TS2339 - Property 'data' does not exist on type 'Sorter'.
|
||||
this.data = [];
|
||||
|
||||
// @ts-expect-error - TS2339 - Property 'pageResults' does not exist on type 'Sorter'.
|
||||
this.pageResults = 0;
|
||||
// @ts-expect-error - TS2339 - Property 'numResults' does not exist on type 'Sorter'.
|
||||
this.numResults = 0;
|
||||
|
||||
// @ts-expect-error - TS2339 - Property 'sortKey' does not exist on type 'Sorter'.
|
||||
this.sortKey = null;
|
||||
// @ts-expect-error - TS2339 - Property 'sortDesc' does not exist on type 'Sorter'.
|
||||
this.sortDesc = null;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
return {
|
||||
id: { type: String },
|
||||
|
||||
pageResults: { type: Number },
|
||||
|
||||
data: { type: Array },
|
||||
sortedData: { type: Array },
|
||||
|
||||
sortKey: { type: String },
|
||||
sortDesc: { type: Boolean },
|
||||
};
|
||||
}
|
||||
|
||||
firstUpdated() {
|
||||
if (this.id) {
|
||||
const sortKey = localStorage.getItem(`${this.id}:sortKey`);
|
||||
if (sortKey !== null) {
|
||||
// @ts-expect-error - TS2339 - Property 'sortKey' does not exist on type 'Sorter'.
|
||||
this.sortKey = sortKey;
|
||||
}
|
||||
const sortDesc = localStorage.getItem(`${this.id}:sortDesc`);
|
||||
if (sortDesc !== null) {
|
||||
// @ts-expect-error - TS2339 - Property 'sortDesc' does not exist on type 'Sorter'.
|
||||
this.sortDesc = sortDesc === "1";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
updated(changedProperties) {
|
||||
const keyChanged = changedProperties.has("sortKey");
|
||||
const descChanged = changedProperties.has("sortDesc");
|
||||
const dataChanged = changedProperties.has("data");
|
||||
|
||||
// @ts-expect-error - TS2339 - Property 'sortKey' does not exist on type 'Sorter'.
|
||||
if (keyChanged && this.sortKey !== null) {
|
||||
// @ts-expect-error - TS2339 - Property 'sortKey' does not exist on type 'Sorter'.
|
||||
localStorage.setItem(`${this.id}:sortKey`, this.sortKey);
|
||||
}
|
||||
|
||||
// @ts-expect-error - TS2339 - Property 'sortDesc' does not exist on type 'Sorter'.
|
||||
if (descChanged && this.sortDesc !== null) {
|
||||
// @ts-expect-error - TS2339 - Property 'sortDesc' does not exist on type 'Sorter'.
|
||||
localStorage.setItem(`${this.id}:sortDesc`, this.sortDesc ? "1" : "0");
|
||||
}
|
||||
|
||||
if (keyChanged || descChanged || dataChanged) {
|
||||
this.sortData();
|
||||
}
|
||||
}
|
||||
|
||||
sortData() {
|
||||
// @ts-expect-error - TS2551 - Property 'sortedData' does not exist on type 'Sorter'. Did you mean 'sortData'? | TS2339 - Property 'data' does not exist on type 'Sorter'.
|
||||
this.sortedData = [...this.data];
|
||||
// @ts-expect-error - TS2339 - Property 'numResults' does not exist on type 'Sorter'. | TS2339 - Property 'pageResults' does not exist on type 'Sorter'.
|
||||
this.numResults = this.pageResults;
|
||||
|
||||
// @ts-expect-error - TS2339 - Property 'sortKey' does not exist on type 'Sorter'.
|
||||
if (this.sortKey === "") {
|
||||
// @ts-expect-error - TS2339 - Property 'sortDesc' does not exist on type 'Sorter'.
|
||||
if (this.sortDesc) {
|
||||
// @ts-expect-error - TS2551 - Property 'sortedData' does not exist on type 'Sorter'. Did you mean 'sortData'?
|
||||
this.sortedData.reverse();
|
||||
}
|
||||
} else {
|
||||
// @ts-expect-error - TS2551 - Property 'sortedData' does not exist on type 'Sorter'. Did you mean 'sortData'?
|
||||
this.sortedData.sort((first, second) => {
|
||||
// @ts-expect-error - TS2339 - Property 'sortKey' does not exist on type 'Sorter'. | TS2339 - Property 'sortKey' does not exist on type 'Sorter'.
|
||||
if (first[this.sortKey] === second[this.sortKey]) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// @ts-expect-error - TS2339 - Property 'sortDesc' does not exist on type 'Sorter'. | TS2339 - Property 'sortKey' does not exist on type 'Sorter'. | TS2339 - Property 'sortKey' does not exist on type 'Sorter'.
|
||||
return this.sortDesc == first[this.sortKey] < second[this.sortKey]
|
||||
? 1
|
||||
: -1;
|
||||
});
|
||||
}
|
||||
|
||||
this.sendSortChanged();
|
||||
}
|
||||
|
||||
sendSortChanged() {
|
||||
const detail = {
|
||||
// @ts-expect-error - TS2339 - Property 'sortKey' does not exist on type 'Sorter'.
|
||||
sortKey: this.sortKey,
|
||||
// @ts-expect-error - TS2339 - Property 'sortDesc' does not exist on type 'Sorter'.
|
||||
sortDesc: this.sortDesc,
|
||||
// @ts-expect-error - TS2339 - Property 'numResults' does not exist on type 'Sorter'.
|
||||
sortedData: this.numResults
|
||||
? // @ts-expect-error - TS2551 - Property 'sortedData' does not exist on type 'Sorter'. Did you mean 'sortData'? | TS2339 - Property 'numResults' does not exist on type 'Sorter'.
|
||||
this.sortedData.slice(0, this.numResults)
|
||||
: // @ts-expect-error - TS2551 - Property 'sortedData' does not exist on type 'Sorter'. Did you mean 'sortData'?
|
||||
this.sortedData,
|
||||
};
|
||||
this.dispatchEvent(new CustomEvent("sort-changed", { detail }));
|
||||
}
|
||||
|
||||
getMore(more = 100) {
|
||||
// @ts-expect-error - TS2339 - Property 'pageResults' does not exist on type 'Sorter'. | TS2339 - Property 'numResults' does not exist on type 'Sorter'. | TS2551 - Property 'sortedData' does not exist on type 'Sorter'. Did you mean 'sortData'?
|
||||
if (this.pageResults && this.numResults >= this.sortedData.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
// @ts-expect-error - TS2339 - Property 'numResults' does not exist on type 'Sorter'.
|
||||
this.numResults += more;
|
||||
this.sendSortChanged();
|
||||
}
|
||||
|
||||
static get styles() {
|
||||
return wrapCss(css`
|
||||
:host {
|
||||
min-width: 100px;
|
||||
box-sizing: border-box !important;
|
||||
}
|
||||
button.button.is-small {
|
||||
border-radius: 4px;
|
||||
}
|
||||
`);
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`
|
||||
<div class="select is-small">
|
||||
<select id="sort-select" @change=${(e) =>
|
||||
// @ts-expect-error - TS2339 - Property 'sortKey' does not exist on type 'Sorter'.
|
||||
(this.sortKey = e.currentTarget.value)}>
|
||||
|
||||
${
|
||||
// @ts-expect-error - TS2339 - Property 'sortKeys' does not exist on type 'Sorter'.
|
||||
this.sortKeys.map(
|
||||
(sort) => html`
|
||||
<option
|
||||
value="${sort.key}"
|
||||
?selected="${
|
||||
// @ts-expect-error - TS2339 - Property 'sortKey' does not exist on type 'Sorter'.
|
||||
sort.key === this.sortKey
|
||||
}"
|
||||
>
|
||||
Sort By: ${sort.name}
|
||||
</option>
|
||||
`,
|
||||
)
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
<button @click=${() =>
|
||||
// @ts-expect-error - TS2339 - Property 'sortDesc' does not exist on type 'Sorter'. | TS2339 - Property 'sortDesc' does not exist on type 'Sorter'.
|
||||
(this.sortDesc = !this.sortDesc)} class="button is-small">
|
||||
<span>Order:</span>
|
||||
<span class="is-sr-only">${
|
||||
// @ts-expect-error - TS2339 - Property 'sortDesc' does not exist on type 'Sorter'.
|
||||
this.sortDesc ? "Ascending" : "Descending"
|
||||
}</span>
|
||||
<span class="icon"><fa-icon aria-hidden="true" .svg=${
|
||||
// @ts-expect-error - TS2339 - Property 'sortDesc' does not exist on type 'Sorter'.
|
||||
this.sortDesc ? fasSortUp : fasSortDown
|
||||
}></span>
|
||||
</button>`;
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define("wr-sorter", Sorter);
|
||||
|
||||
export { Sorter };
|
||||
+79
-11
@@ -13,18 +13,26 @@ class Story extends LitElement {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
// @ts-expect-error - TS2339 - Property 'collInfo' does not exist on type 'Story'.
|
||||
this.collInfo = null;
|
||||
|
||||
// @ts-expect-error - TS2339 - Property 'curatedPageMap' does not exist on type 'Story'.
|
||||
this.curatedPageMap = {};
|
||||
|
||||
// @ts-expect-error - TS2339 - Property 'currList' does not exist on type 'Story'.
|
||||
this.currList = 0;
|
||||
|
||||
// @ts-expect-error - TS2339 - Property 'active' does not exist on type 'Story'.
|
||||
this.active = false;
|
||||
|
||||
// @ts-expect-error - TS2339 - Property 'lastST' does not exist on type 'Story'.
|
||||
this.lastST = 0;
|
||||
// @ts-expect-error - TS2339 - Property 'clickTime' does not exist on type 'Story'.
|
||||
this.clickTime = 0;
|
||||
|
||||
// @ts-expect-error - TS2339 - Property 'isSidebar' does not exist on type 'Story'.
|
||||
this.isSidebar = false;
|
||||
// @ts-expect-error - TS2339 - Property 'splitDirection' does not exist on type 'Story'.
|
||||
this.splitDirection = false;
|
||||
}
|
||||
|
||||
@@ -44,17 +52,21 @@ class Story extends LitElement {
|
||||
}
|
||||
|
||||
recalcSplitter(width) {
|
||||
// @ts-expect-error - TS2339 - Property 'splitDirection' does not exist on type 'Story'.
|
||||
this.splitDirection =
|
||||
// @ts-expect-error - TS2339 - Property 'isSidebar' does not exist on type 'Story'.
|
||||
this.isSidebar || width < 769 ? "vertical" : "horizontal";
|
||||
}
|
||||
|
||||
firstUpdated() {
|
||||
this.recalcSplitter(document.documentElement.clientWidth);
|
||||
|
||||
// @ts-expect-error - TS2339 - Property 'obs' does not exist on type 'Story'.
|
||||
this.obs = new ResizeObserver((entries /*, observer*/) => {
|
||||
this.recalcSplitter(entries[0].contentRect.width);
|
||||
});
|
||||
|
||||
// @ts-expect-error - TS2339 - Property 'obs' does not exist on type 'Story'.
|
||||
this.obs.observe(this);
|
||||
}
|
||||
|
||||
@@ -74,8 +86,10 @@ class Story extends LitElement {
|
||||
this.configureSplitter();
|
||||
}
|
||||
|
||||
// @ts-expect-error - TS2339 - Property 'active' does not exist on type 'Story'.
|
||||
if (changedProperties.has("currList") && this.active) {
|
||||
this.sendChangeEvent({
|
||||
// @ts-expect-error - TS2339 - Property 'currList' does not exist on type 'Story'.
|
||||
currList: this.currList,
|
||||
});
|
||||
}
|
||||
@@ -85,39 +99,50 @@ class Story extends LitElement {
|
||||
const sidebar = this.renderRoot.querySelector(".sidebar");
|
||||
const content = this.renderRoot.querySelector(".main-content");
|
||||
|
||||
// @ts-expect-error - TS2339 - Property 'splitter' does not exist on type 'Story'.
|
||||
if (this.splitter) {
|
||||
try {
|
||||
// @ts-expect-error - TS2339 - Property 'splitter' does not exist on type 'Story'.
|
||||
this.splitter.destroy();
|
||||
} catch (e) {
|
||||
// ignore splitter destory err
|
||||
}
|
||||
// @ts-expect-error - TS2339 - Property 'splitter' does not exist on type 'Story'.
|
||||
this.splitter = null;
|
||||
}
|
||||
|
||||
// @ts-expect-error - TS2339 - Property 'splitter' does not exist on type 'Story'.
|
||||
if (sidebar && content && !this.splitter) {
|
||||
const opts = {
|
||||
sizes: [20, 80],
|
||||
|
||||
gutterSize: 4,
|
||||
|
||||
// @ts-expect-error - TS2339 - Property 'splitDirection' does not exist on type 'Story'.
|
||||
direction: this.splitDirection,
|
||||
};
|
||||
|
||||
// @ts-expect-error - TS2339 - Property 'splitter' does not exist on type 'Story'. | TS2322 - Type 'Element' is not assignable to type 'string | HTMLElement'. | TS2322 - Type 'Element' is not assignable to type 'string | HTMLElement'.
|
||||
this.splitter = Split([sidebar, content], opts);
|
||||
}
|
||||
}
|
||||
|
||||
async doLoadCurated() {
|
||||
// @ts-expect-error - TS2339 - Property 'curatedPageMap' does not exist on type 'Story'.
|
||||
this.curatedPageMap = {};
|
||||
|
||||
const pageMap = {};
|
||||
|
||||
// @ts-expect-error - TS2339 - Property 'collInfo' does not exist on type 'Story'.
|
||||
for (const page of this.collInfo.pages) {
|
||||
pageMap[page.id] = page;
|
||||
}
|
||||
|
||||
// @ts-expect-error - TS2339 - Property 'collInfo' does not exist on type 'Story'.
|
||||
for (const curated of this.collInfo.curatedPages) {
|
||||
// @ts-expect-error - TS2339 - Property 'curatedPageMap' does not exist on type 'Story'.
|
||||
if (!this.curatedPageMap[curated.list]) {
|
||||
// @ts-expect-error - TS2339 - Property 'curatedPageMap' does not exist on type 'Story'.
|
||||
this.curatedPageMap[curated.list] = [];
|
||||
}
|
||||
const page = curated;
|
||||
@@ -135,6 +160,7 @@ class Story extends LitElement {
|
||||
const title = page.title || page.url;
|
||||
const desc = curated.desc;
|
||||
|
||||
// @ts-expect-error - TS2339 - Property 'curatedPageMap' does not exist on type 'Story'.
|
||||
this.curatedPageMap[curated.list].push({ url, ts, title, desc });
|
||||
}
|
||||
|
||||
@@ -249,15 +275,23 @@ class Story extends LitElement {
|
||||
}
|
||||
|
||||
render() {
|
||||
// @ts-expect-error - TS2339 - Property 'currList' does not exist on type 'Story'.
|
||||
const currListNum = this.currList;
|
||||
|
||||
return html`
|
||||
<div
|
||||
class="is-sr-only"
|
||||
role="heading"
|
||||
aria-level="${this.isSidebar ? "2" : "1"}"
|
||||
aria-level="${
|
||||
// @ts-expect-error - TS2339 - Property 'isSidebar' does not exist on type 'Story'.
|
||||
this.isSidebar ? "2" : "1"
|
||||
}"
|
||||
>
|
||||
Story for ${this.collInfo.title}
|
||||
Story for
|
||||
${
|
||||
// @ts-expect-error - TS2339 - Property 'collInfo' does not exist on type 'Story'.
|
||||
this.collInfo.title
|
||||
}
|
||||
</div>
|
||||
<div class="columns">
|
||||
<div class="column sidebar is-one-fifth">
|
||||
@@ -271,21 +305,29 @@ class Story extends LitElement {
|
||||
? "is-active"
|
||||
: ""} menu-label is-size-4"
|
||||
@click=${this.onClickScroll}
|
||||
>${this.collInfo.title}</a
|
||||
>${
|
||||
// @ts-expect-error - TS2339 - Property 'collInfo' does not exist on type 'Story'.
|
||||
this.collInfo.title
|
||||
}</a
|
||||
>
|
||||
<ul class="menu-list">
|
||||
${this.collInfo.lists.map(
|
||||
${
|
||||
// @ts-expect-error - TS2339 - Property 'collInfo' does not exist on type 'Story'.
|
||||
this.collInfo.lists.map(
|
||||
(list) =>
|
||||
html` <li>
|
||||
<a
|
||||
@click=${this.onClickScroll}
|
||||
href="#list-${list.id}"
|
||||
data-list="${list.id}"
|
||||
class="${currListNum === list.id ? "is-active" : ""}"
|
||||
class="${currListNum === list.id
|
||||
? "is-active"
|
||||
: ""}"
|
||||
>${list.title}</a
|
||||
>
|
||||
</li>`,
|
||||
)}
|
||||
)
|
||||
}
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -293,8 +335,17 @@ class Story extends LitElement {
|
||||
</div>
|
||||
<div @scroll=${this.onScroll} class="column main-content main-scroll">
|
||||
<section id="list-0" class="desc">
|
||||
<h2 class="has-text-centered title is-3">${this.collInfo.title}</h2>
|
||||
${this.collInfo.desc ? unsafeHTML(marked(this.collInfo.desc)) : ""}
|
||||
<h2 class="has-text-centered title is-3">
|
||||
${
|
||||
// @ts-expect-error - TS2339 - Property 'collInfo' does not exist on type 'Story'.
|
||||
this.collInfo.title
|
||||
}
|
||||
</h2>
|
||||
|
||||
${
|
||||
// @ts-expect-error - TS2339 - Property 'collInfo' does not exist on type 'Story'. | TS2339 - Property 'collInfo' does not exist on type 'Story'.
|
||||
this.collInfo.desc ? unsafeHTML(marked(this.collInfo.desc)) : ""
|
||||
}
|
||||
</section>
|
||||
${this.renderLists()}
|
||||
</div>
|
||||
@@ -303,6 +354,7 @@ class Story extends LitElement {
|
||||
}
|
||||
|
||||
renderLists() {
|
||||
// @ts-expect-error - TS2339 - Property 'collInfo' does not exist on type 'Story'.
|
||||
return html` ${this.collInfo.lists.map(
|
||||
(list) => html`
|
||||
<article id="list-${list.id}">
|
||||
@@ -311,9 +363,13 @@ class Story extends LitElement {
|
||||
<h3>${list.title}</h3>
|
||||
<p>${list.desc}</p>
|
||||
<ol>
|
||||
${this.curatedPageMap[list.id]
|
||||
? this.curatedPageMap[list.id].map((p) => this.renderCPage(p))
|
||||
: html``}
|
||||
${
|
||||
// @ts-expect-error - TS2339 - Property 'curatedPageMap' does not exist on type 'Story'.
|
||||
this.curatedPageMap[list.id]
|
||||
? // @ts-expect-error - TS2339 - Property 'curatedPageMap' does not exist on type 'Story'.
|
||||
this.curatedPageMap[list.id].map((p) => this.renderCPage(p))
|
||||
: html``
|
||||
}
|
||||
</ol>
|
||||
</div>
|
||||
</article>
|
||||
@@ -361,6 +417,7 @@ class Story extends LitElement {
|
||||
onClickScroll(event) {
|
||||
event.preventDefault();
|
||||
//this.pageView = false;
|
||||
// @ts-expect-error - TS2339 - Property 'currList' does not exist on type 'Story'.
|
||||
this.currList = Number(event.currentTarget.getAttribute("data-list"));
|
||||
this.scrollToList();
|
||||
return false;
|
||||
@@ -368,12 +425,16 @@ class Story extends LitElement {
|
||||
|
||||
scrollToList() {
|
||||
// lists are 1 based, 0 is header, 1 is first list
|
||||
// @ts-expect-error - TS2339 - Property 'currList' does not exist on type 'Story'. | TS2339 - Property 'collInfo' does not exist on type 'Story'.
|
||||
if (this.currList > this.collInfo.lists.length) {
|
||||
// @ts-expect-error - TS2339 - Property 'currList' does not exist on type 'Story'.
|
||||
this.currList = 0;
|
||||
}
|
||||
|
||||
const opts = { behavior: "smooth", block: "nearest", inline: "nearest" };
|
||||
// @ts-expect-error - TS2339 - Property 'clickTime' does not exist on type 'Story'.
|
||||
this.clickTime = new Date().getTime();
|
||||
// @ts-expect-error - TS2339 - Property 'getElementById' does not exist on type 'HTMLElement | ShadowRoot'. | TS2339 - Property 'currList' does not exist on type 'Story'.
|
||||
const curr = this.renderRoot.getElementById("list-" + this.currList);
|
||||
if (curr) {
|
||||
curr.scrollIntoView(opts);
|
||||
@@ -382,6 +443,7 @@ class Story extends LitElement {
|
||||
|
||||
onScroll(event) {
|
||||
const scrollable = event.currentTarget;
|
||||
// @ts-expect-error - TS2339 - Property 'getElementById' does not exist on type 'HTMLElement | ShadowRoot'. | TS2339 - Property 'currList' does not exist on type 'Story'.
|
||||
const curr = this.renderRoot.getElementById("list-" + this.currList);
|
||||
|
||||
if (!curr) {
|
||||
@@ -392,6 +454,7 @@ class Story extends LitElement {
|
||||
const target = scrollable.offsetTop;
|
||||
const currST = scrollable.scrollTop;
|
||||
|
||||
// @ts-expect-error - TS2339 - Property 'lastST' does not exist on type 'Story'.
|
||||
if (currST > this.lastST) {
|
||||
while (
|
||||
next.nextElementSibling &&
|
||||
@@ -407,22 +470,27 @@ class Story extends LitElement {
|
||||
next = next.previousElementSibling;
|
||||
}
|
||||
}
|
||||
// @ts-expect-error - TS2339 - Property 'lastST' does not exist on type 'Story'.
|
||||
this.lastST = currST;
|
||||
if (next && next != curr) {
|
||||
if (next.id.startsWith("list-")) {
|
||||
// @ts-expect-error - TS2339 - Property 'currList' does not exist on type 'Story'.
|
||||
this.currList = Number(next.id.slice(5));
|
||||
}
|
||||
}
|
||||
|
||||
// @ts-expect-error - TS2339 - Property 'clickTime' does not exist on type 'Story'.
|
||||
if (new Date().getTime() - this.clickTime < 1000) {
|
||||
return;
|
||||
}
|
||||
|
||||
const sel = this.renderRoot.querySelector(
|
||||
// @ts-expect-error - TS2339 - Property 'currList' does not exist on type 'Story'.
|
||||
`a[data-list="${this.currList}"]`,
|
||||
);
|
||||
if (sel) {
|
||||
const opts = { behavior: "smooth", block: "nearest", inline: "nearest" };
|
||||
// @ts-expect-error - TS2345 - Argument of type '{ behavior: string; block: string; inline: string; }' is not assignable to parameter of type 'boolean | ScrollIntoViewOptions | undefined'.
|
||||
sel.scrollIntoView(opts);
|
||||
}
|
||||
}
|
||||
@@ -9,15 +9,21 @@ export class SWManager {
|
||||
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;
|
||||
}
|
||||
|
||||
setAppName(newAppName) {
|
||||
// @ts-expect-error - TS2339 - Property 'appName' does not exist on type 'SWManager'.
|
||||
this.appName = newAppName;
|
||||
}
|
||||
|
||||
@@ -29,26 +35,37 @@ export class SWManager {
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
};
|
||||
|
||||
// @ts-expect-error - TS2339 - Property 'scope' does not exist on type 'SWManager'. | TS2339 - Property 'name' does not exist on type 'SWManager'.
|
||||
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");
|
||||
@@ -80,6 +97,7 @@ export class SWManager {
|
||||
}
|
||||
|
||||
try {
|
||||
// @ts-expect-error - TS2531 - Object is possibly 'null'.
|
||||
return window.top.location.href === "";
|
||||
} catch (e) {
|
||||
return true;
|
||||
@@ -89,7 +107,9 @@ export class SWManager {
|
||||
getSWErrorMsg() {
|
||||
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.`;
|
||||
}
|
||||
|
||||
@@ -104,7 +124,12 @@ export class SWManager {
|
||||
|
||||
if (!window.isSecureContext) {
|
||||
return `
|
||||
Sorry, the ${this.appName} system must be loaded from an HTTPS URL (or localhost), but was loaded from: ${window.location.host}.
|
||||
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
|
||||
}.
|
||||
Please try loading this page from an HTTPS URL`;
|
||||
}
|
||||
|
||||
@@ -113,11 +138,13 @@ 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(logo, override) {
|
||||
renderErrorReport(logo: string, override?: string) {
|
||||
// @ts-expect-error - TS2339 - Property 'errorMsg' does not exist on type 'SWManager'.
|
||||
const msg = this.errorMsg || override;
|
||||
|
||||
if (!msg) {
|
||||
+5
-1
@@ -8,6 +8,8 @@ export interface Item {
|
||||
* Archived Item ID
|
||||
*/
|
||||
coll?: string;
|
||||
// TODO(emma) is `id` the same as `coll`? should they be merged?
|
||||
id?: string;
|
||||
name?: string;
|
||||
title?: string;
|
||||
loadUrl?: string;
|
||||
@@ -24,9 +26,11 @@ export interface Item {
|
||||
software?: string;
|
||||
};
|
||||
onDemand?: boolean;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO fixme
|
||||
pages?: any[];
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO fixme
|
||||
lists?: any[];
|
||||
ctime?: string;
|
||||
totalSize?: unknown;
|
||||
size?: unknown;
|
||||
size?: number | string;
|
||||
}
|
||||
|
||||
@@ -58,24 +58,37 @@ class URLResources extends LitElement {
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
// @ts-expect-error - TS2339 - Property 'collInfo' does not exist on type 'URLResources'.
|
||||
this.collInfo = null;
|
||||
// @ts-expect-error - TS2339 - Property 'isSidebar' does not exist on type 'URLResources'.
|
||||
this.isSidebar = false;
|
||||
|
||||
// @ts-expect-error - TS2339 - Property 'currMime' does not exist on type 'URLResources'.
|
||||
this.currMime = "";
|
||||
// @ts-expect-error - TS2339 - Property 'query' does not exist on type 'URLResources'.
|
||||
this.query = "";
|
||||
// @ts-expect-error - TS2339 - Property 'urlSearchType' does not exist on type 'URLResources'.
|
||||
this.urlSearchType = "";
|
||||
|
||||
// @ts-expect-error - TS2339 - Property 'filteredResults' does not exist on type 'URLResources'.
|
||||
this.filteredResults = [];
|
||||
// @ts-expect-error - TS2339 - Property 'sortedResults' does not exist on type 'URLResources'.
|
||||
this.sortedResults = [];
|
||||
|
||||
// @ts-expect-error - TS2339 - Property 'results' does not exist on type 'URLResources'.
|
||||
this.results = [];
|
||||
|
||||
// @ts-expect-error - TS2339 - Property 'newQuery' does not exist on type 'URLResources'.
|
||||
this.newQuery = null;
|
||||
|
||||
// @ts-expect-error - TS2339 - Property 'tryMore' does not exist on type 'URLResources'.
|
||||
this.tryMore = false;
|
||||
// @ts-expect-error - TS2339 - Property 'loading' does not exist on type 'URLResources'.
|
||||
this.loading = false;
|
||||
|
||||
// @ts-expect-error - TS2339 - Property 'sortKey' does not exist on type 'URLResources'.
|
||||
this.sortKey = "url";
|
||||
// @ts-expect-error - TS2339 - Property 'sortDesc' does not exist on type 'URLResources'.
|
||||
this.sortDesc = false;
|
||||
}
|
||||
|
||||
@@ -96,14 +109,19 @@ class URLResources extends LitElement {
|
||||
|
||||
firstUpdated() {
|
||||
//this.doLoadResources();
|
||||
// @ts-expect-error - TS2339 - Property 'urlSearchType' does not exist on type 'URLResources'.
|
||||
if (this.urlSearchType === "") {
|
||||
// @ts-expect-error - TS2339 - Property 'urlSearchType' does not exist on type 'URLResources'.
|
||||
this.urlSearchType = "prefix";
|
||||
}
|
||||
}
|
||||
|
||||
_timedUpdate() {
|
||||
// @ts-expect-error - TS2339 - Property 'newQuery' does not exist on type 'URLResources'.
|
||||
if (this.newQuery !== null) {
|
||||
// @ts-expect-error - TS2339 - Property 'query' does not exist on type 'URLResources'. | TS2339 - Property 'newQuery' does not exist on type 'URLResources'.
|
||||
this.query = this.newQuery;
|
||||
// @ts-expect-error - TS2339 - Property 'newQuery' does not exist on type 'URLResources'.
|
||||
this.newQuery = null;
|
||||
}
|
||||
}
|
||||
@@ -116,8 +134,11 @@ class URLResources extends LitElement {
|
||||
) {
|
||||
this.doLoadResources();
|
||||
const data = {
|
||||
// @ts-expect-error - TS2339 - Property 'query' does not exist on type 'URLResources'.
|
||||
query: this.query,
|
||||
// @ts-expect-error - TS2339 - Property 'urlSearchType' does not exist on type 'URLResources'.
|
||||
urlSearchType: this.urlSearchType,
|
||||
// @ts-expect-error - TS2339 - Property 'currMime' does not exist on type 'URLResources'.
|
||||
currMime: this.currMime,
|
||||
};
|
||||
const replaceLoc =
|
||||
@@ -136,16 +157,21 @@ class URLResources extends LitElement {
|
||||
async doLoadResources(isMore = false) {
|
||||
const count = 100;
|
||||
|
||||
// @ts-expect-error - TS2339 - Property 'tryMore' does not exist on type 'URLResources'. | TS2339 - Property 'results' does not exist on type 'URLResources'.
|
||||
if (isMore && (!this.tryMore || !this.results.length)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// @ts-expect-error - TS2339 - Property 'loading' does not exist on type 'URLResources'.
|
||||
if (this.loading) {
|
||||
return;
|
||||
}
|
||||
|
||||
// @ts-expect-error - TS2339 - Property 'loading' does not exist on type 'URLResources'.
|
||||
this.loading = true;
|
||||
// @ts-expect-error - TS2339 - Property 'urlSearchType' does not exist on type 'URLResources'. | TS2339 - Property 'query' does not exist on type 'URLResources'.
|
||||
let url = this.urlSearchType !== "contains" ? this.query : "";
|
||||
// @ts-expect-error - TS2339 - Property 'urlSearchType' does not exist on type 'URLResources'.
|
||||
const prefix = url && this.urlSearchType === "prefix" ? 1 : 0;
|
||||
|
||||
// optimization: if not starting with http, likely won't have a match here, so just add https://
|
||||
@@ -153,8 +179,10 @@ class URLResources extends LitElement {
|
||||
url = "https://" + url;
|
||||
}
|
||||
|
||||
// @ts-expect-error - TS2339 - Property 'currMime' does not exist on type 'URLResources'.
|
||||
const mime = this.currMime;
|
||||
|
||||
// @ts-expect-error - TS2345 - Argument of type '{ mime: any; url: any; prefix: number; count: number; }' is not assignable to parameter of type 'string | Record<string, string> | URLSearchParams | string[][] | undefined'.
|
||||
const params = new URLSearchParams({
|
||||
mime,
|
||||
url,
|
||||
@@ -163,50 +191,66 @@ class URLResources extends LitElement {
|
||||
});
|
||||
|
||||
if (isMore) {
|
||||
// @ts-expect-error - TS2339 - Property 'results' does not exist on type 'URLResources'. | TS2339 - Property 'results' does not exist on type 'URLResources'.
|
||||
const last = this.results[this.results.length - 1];
|
||||
params.set("fromMime", last.mime);
|
||||
params.set("fromUrl", last.url);
|
||||
params.set("fromStatus", last.status);
|
||||
// @ts-expect-error - TS2345 - Argument of type 'number' is not assignable to parameter of type 'string'.
|
||||
params.set("fromTs", new Date(last.date).getTime());
|
||||
}
|
||||
|
||||
let resp = await fetch(
|
||||
// @ts-expect-error - TS2339 - Property 'collInfo' does not exist on type 'URLResources'.
|
||||
`${this.collInfo.apiPrefix}/urls?${params.toString()}`,
|
||||
);
|
||||
resp = await resp.json();
|
||||
// @ts-expect-error - TS2339 - Property 'results' does not exist on type 'URLResources'. | TS2339 - Property 'results' does not exist on type 'URLResources'. | TS2551 - Property 'urls' does not exist on type 'Response'. Did you mean 'url'? | TS2551 - Property 'urls' does not exist on type 'Response'. Did you mean 'url'?
|
||||
this.results = isMore ? this.results.concat(resp.urls) : resp.urls;
|
||||
// can be more than count if multiple mimes
|
||||
// @ts-expect-error - TS2339 - Property 'tryMore' does not exist on type 'URLResources'. | TS2551 - Property 'urls' does not exist on type 'Response'. Did you mean 'url'?
|
||||
this.tryMore = resp.urls.length >= count;
|
||||
this.filter();
|
||||
|
||||
// @ts-expect-error - TS2339 - Property 'loading' does not exist on type 'URLResources'.
|
||||
this.loading = false;
|
||||
}
|
||||
|
||||
onChangeTypeSearch(event) {
|
||||
// @ts-expect-error - TS2339 - Property 'currMime' does not exist on type 'URLResources'.
|
||||
this.currMime = event.currentTarget.value;
|
||||
}
|
||||
|
||||
onChangeQuery(event) {
|
||||
// @ts-expect-error - TS2339 - Property 'newQuery' does not exist on type 'URLResources'.
|
||||
this.newQuery = event.currentTarget.value;
|
||||
// @ts-expect-error - TS2339 - Property '_ival' does not exist on type 'URLResources'.
|
||||
if (this._ival) {
|
||||
// @ts-expect-error - TS2339 - Property '_ival' does not exist on type 'URLResources'.
|
||||
window.clearTimeout(this._ival);
|
||||
}
|
||||
// @ts-expect-error - TS2339 - Property '_ival' does not exist on type 'URLResources'.
|
||||
this._ival = window.setTimeout(() => this._timedUpdate(), 250);
|
||||
}
|
||||
|
||||
onClickUrlType(event) {
|
||||
// @ts-expect-error - TS2339 - Property 'urlSearchType' does not exist on type 'URLResources'.
|
||||
this.urlSearchType = event.currentTarget.value;
|
||||
}
|
||||
|
||||
filter() {
|
||||
const filteredResults = [];
|
||||
// @ts-expect-error - TS2339 - Property 'urlSearchType' does not exist on type 'URLResources'. | TS2339 - Property 'query' does not exist on type 'URLResources'.
|
||||
const filterText = this.urlSearchType === "contains" ? this.query : "";
|
||||
// @ts-expect-error - TS2339 - Property 'results' does not exist on type 'URLResources'.
|
||||
for (const result of this.results) {
|
||||
if (!filterText || result.url.indexOf(filterText) >= 0) {
|
||||
// @ts-expect-error - TS2345 - Argument of type 'any' is not assignable to parameter of type 'never'.
|
||||
filteredResults.push(result);
|
||||
}
|
||||
}
|
||||
|
||||
// @ts-expect-error - TS2339 - Property 'filteredResults' does not exist on type 'URLResources'.
|
||||
this.filteredResults = filteredResults;
|
||||
}
|
||||
|
||||
@@ -214,6 +258,7 @@ class URLResources extends LitElement {
|
||||
const element = event.currentTarget;
|
||||
const diff =
|
||||
element.scrollHeight - element.scrollTop - element.clientHeight;
|
||||
// @ts-expect-error - TS2339 - Property 'tryMore' does not exist on type 'URLResources'.
|
||||
if (this.tryMore && diff < 40) {
|
||||
this.doLoadResources(true);
|
||||
}
|
||||
@@ -320,15 +365,25 @@ class URLResources extends LitElement {
|
||||
return html`
|
||||
<div
|
||||
role="heading"
|
||||
aria-level="${this.isSidebar ? "2" : "1"}"
|
||||
aria-level="${
|
||||
// @ts-expect-error - TS2339 - Property 'isSidebar' does not exist on type 'URLResources'.
|
||||
this.isSidebar ? "2" : "1"
|
||||
}"
|
||||
class="is-sr-only"
|
||||
>
|
||||
URLs in ${this.collInfo.title}
|
||||
URLs in
|
||||
${
|
||||
// @ts-expect-error - TS2339 - Property 'collInfo' does not exist on type 'URLResources'.
|
||||
this.collInfo.title
|
||||
}
|
||||
</div>
|
||||
|
||||
<div
|
||||
role="heading"
|
||||
aria-level="${this.isSidebar ? "3" : "2"}"
|
||||
aria-level="${
|
||||
// @ts-expect-error - TS2339 - Property 'isSidebar' does not exist on type 'URLResources'.
|
||||
this.isSidebar ? "3" : "2"
|
||||
}"
|
||||
class="is-sr-only"
|
||||
>
|
||||
Search and Filter
|
||||
@@ -343,7 +398,10 @@ class URLResources extends LitElement {
|
||||
(filter) => html`
|
||||
<option
|
||||
value="${filter.filter}"
|
||||
?selected="${filter.filter === this.currMime}"
|
||||
?selected="${
|
||||
// @ts-expect-error - TS2339 - Property 'currMime' does not exist on type 'URLResources'.
|
||||
filter.filter === this.currMime
|
||||
}"
|
||||
>
|
||||
${filter.name}
|
||||
</option>
|
||||
@@ -353,15 +411,19 @@ class URLResources extends LitElement {
|
||||
</div>
|
||||
<div class="field flex-auto">
|
||||
<div
|
||||
class="control has-icons-left ${this.loading
|
||||
? "is-loading"
|
||||
: ""}"
|
||||
class="control has-icons-left ${
|
||||
// @ts-expect-error - TS2339 - Property 'loading' does not exist on type 'URLResources'.
|
||||
this.loading ? "is-loading" : ""
|
||||
}"
|
||||
>
|
||||
<input
|
||||
type="text"
|
||||
class="input"
|
||||
@input="${this.onChangeQuery}"
|
||||
.value="${this.query}"
|
||||
.value="${
|
||||
// @ts-expect-error - TS2339 - Property 'query' does not exist on type 'URLResources'.
|
||||
this.query
|
||||
}"
|
||||
placeholder="Enter URL to Search"
|
||||
/>
|
||||
<span class="icon is-left"
|
||||
@@ -378,7 +440,10 @@ class URLResources extends LitElement {
|
||||
type="radio"
|
||||
name="urltype"
|
||||
value="contains"
|
||||
?checked="${this.urlSearchType === "contains"}"
|
||||
?checked="${
|
||||
// @ts-expect-error - TS2339 - Property 'urlSearchType' does not exist on type 'URLResources'.
|
||||
this.urlSearchType === "contains"
|
||||
}"
|
||||
@click="${this.onClickUrlType}"
|
||||
/> Contains</label
|
||||
>
|
||||
@@ -387,7 +452,10 @@ class URLResources extends LitElement {
|
||||
type="radio"
|
||||
name="urltype"
|
||||
value="prefix"
|
||||
?checked="${this.urlSearchType === "prefix"}"
|
||||
?checked="${
|
||||
// @ts-expect-error - TS2339 - Property 'urlSearchType' does not exist on type 'URLResources'.
|
||||
this.urlSearchType === "prefix"
|
||||
}"
|
||||
@click="${this.onClickUrlType}"
|
||||
/> Prefix</label
|
||||
>
|
||||
@@ -396,7 +464,10 @@ class URLResources extends LitElement {
|
||||
type="radio"
|
||||
name="urltype"
|
||||
value="exact"
|
||||
?checked="${this.urlSearchType === "exact"}"
|
||||
?checked="${
|
||||
// @ts-expect-error - TS2339 - Property 'urlSearchType' does not exist on type 'URLResources'.
|
||||
this.urlSearchType === "exact"
|
||||
}"
|
||||
@click="${this.onClickUrlType}"
|
||||
/> Exact</label
|
||||
>
|
||||
@@ -406,7 +477,11 @@ class URLResources extends LitElement {
|
||||
is-pulled-right
|
||||
aria-live="polite"
|
||||
aria-atomic="true"
|
||||
>${this.filteredResults.length} Result(s)</span
|
||||
>${
|
||||
// @ts-expect-error - TS2339 - Property 'filteredResults' does not exist on type 'URLResources'.
|
||||
this.filteredResults.length
|
||||
}
|
||||
Result(s)</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
@@ -415,10 +490,19 @@ class URLResources extends LitElement {
|
||||
<div class="sort-header is-hidden-tablet">
|
||||
<wr-sorter
|
||||
id="urls"
|
||||
.sortKey="${this.sortKey}"
|
||||
.sortDesc="${this.sortDesc}"
|
||||
.sortKey="${
|
||||
// @ts-expect-error - TS2339 - Property 'sortKey' does not exist on type 'URLResources'.
|
||||
this.sortKey
|
||||
}"
|
||||
.sortDesc="${
|
||||
// @ts-expect-error - TS2339 - Property 'sortDesc' does not exist on type 'URLResources'.
|
||||
this.sortDesc
|
||||
}"
|
||||
.sortKeys="${URLResources.sortKeys}"
|
||||
.data="${this.filteredResults}"
|
||||
.data="${
|
||||
// @ts-expect-error - TS2339 - Property 'filteredResults' does not exist on type 'URLResources'.
|
||||
this.filteredResults
|
||||
}"
|
||||
@sort-changed="${this.onSortChanged}"
|
||||
>
|
||||
</wr-sorter>
|
||||
@@ -426,7 +510,10 @@ class URLResources extends LitElement {
|
||||
|
||||
<div
|
||||
role="heading"
|
||||
aria-level="${this.isSidebar ? "3" : "2"}"
|
||||
aria-level="${
|
||||
// @ts-expect-error - TS2339 - Property 'isSidebar' does not exist on type 'URLResources'.
|
||||
this.isSidebar ? "3" : "2"
|
||||
}"
|
||||
id="results-heading"
|
||||
class="is-sr-only"
|
||||
>
|
||||
@@ -443,11 +530,15 @@ class URLResources extends LitElement {
|
||||
@click="${this.onSort}"
|
||||
@keyup="${clickOnSpacebarPress}"
|
||||
data-key="url"
|
||||
class="${this.sortKey === "url"
|
||||
? this.sortDesc
|
||||
class="${
|
||||
// @ts-expect-error - TS2339 - Property 'sortKey' does not exist on type 'URLResources'.
|
||||
this.sortKey === "url"
|
||||
? // @ts-expect-error - TS2339 - Property 'sortDesc' does not exist on type 'URLResources'.
|
||||
this.sortDesc
|
||||
? "desc"
|
||||
: "asc"
|
||||
: ""}"
|
||||
: ""
|
||||
}"
|
||||
>URL</a
|
||||
>
|
||||
</th>
|
||||
@@ -458,11 +549,15 @@ class URLResources extends LitElement {
|
||||
@click="${this.onSort}"
|
||||
@keyup="${clickOnSpacebarPress}"
|
||||
data-key="ts"
|
||||
class="${this.sortKey === "ts"
|
||||
? this.sortDesc
|
||||
class="${
|
||||
// @ts-expect-error - TS2339 - Property 'sortKey' does not exist on type 'URLResources'.
|
||||
this.sortKey === "ts"
|
||||
? // @ts-expect-error - TS2339 - Property 'sortDesc' does not exist on type 'URLResources'.
|
||||
this.sortDesc
|
||||
? "desc"
|
||||
: "asc"
|
||||
: ""}"
|
||||
: ""
|
||||
}"
|
||||
>Date</a
|
||||
>
|
||||
</th>
|
||||
@@ -473,11 +568,15 @@ class URLResources extends LitElement {
|
||||
@click="${this.onSort}"
|
||||
@keyup="${clickOnSpacebarPress}"
|
||||
data-key="mime"
|
||||
class="${this.sortKey === "mime"
|
||||
? this.sortDesc
|
||||
class="${
|
||||
// @ts-expect-error - TS2339 - Property 'sortKey' does not exist on type 'URLResources'.
|
||||
this.sortKey === "mime"
|
||||
? // @ts-expect-error - TS2339 - Property 'sortDesc' does not exist on type 'URLResources'.
|
||||
this.sortDesc
|
||||
? "desc"
|
||||
: "asc"
|
||||
: ""}"
|
||||
: ""
|
||||
}"
|
||||
>Mime Type</a
|
||||
>
|
||||
</th>
|
||||
@@ -488,11 +587,15 @@ class URLResources extends LitElement {
|
||||
@click="${this.onSort}"
|
||||
@keyup="${clickOnSpacebarPress}"
|
||||
data-key="status"
|
||||
class="${this.sortKey === "status"
|
||||
? this.sortDesc
|
||||
class="${
|
||||
// @ts-expect-error - TS2339 - Property 'sortKey' does not exist on type 'URLResources'.
|
||||
this.sortKey === "status"
|
||||
? // @ts-expect-error - TS2339 - Property 'sortDesc' does not exist on type 'URLResources'.
|
||||
this.sortDesc
|
||||
? "desc"
|
||||
: "asc"
|
||||
: ""}"
|
||||
: ""
|
||||
}"
|
||||
>Status</a
|
||||
>
|
||||
</th>
|
||||
@@ -500,8 +603,11 @@ class URLResources extends LitElement {
|
||||
</thead>
|
||||
|
||||
<tbody class="main-scroll" @scroll="${this.onScroll}">
|
||||
${this.sortedResults.length
|
||||
? this.sortedResults.map(
|
||||
${
|
||||
// @ts-expect-error - TS2339 - Property 'sortedResults' does not exist on type 'URLResources'.
|
||||
this.sortedResults.length
|
||||
? // @ts-expect-error - TS2339 - Property 'sortedResults' does not exist on type 'URLResources'.
|
||||
this.sortedResults.map(
|
||||
(result) => html`
|
||||
<tr class="columns result">
|
||||
<td class="column col-url is-6">
|
||||
@@ -516,7 +622,11 @@ class URLResources extends LitElement {
|
||||
result.ts,
|
||||
)}"
|
||||
>
|
||||
<keyword-mark keywords="${this.query}"
|
||||
<keyword-mark
|
||||
keywords="${
|
||||
// @ts-expect-error - TS2339 - Property 'query' does not exist on type 'URLResources'.
|
||||
this.query
|
||||
}"
|
||||
>${result.url}</keyword-mark
|
||||
>
|
||||
</a>
|
||||
@@ -538,7 +648,8 @@ class URLResources extends LitElement {
|
||||
)
|
||||
: html`<tr class="section">
|
||||
<td colspan="4"><i>No Results Found.</i></td>
|
||||
</tr>`}
|
||||
</tr>`
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
`;
|
||||
@@ -548,17 +659,24 @@ class URLResources extends LitElement {
|
||||
event.preventDefault();
|
||||
|
||||
const key = event.currentTarget.getAttribute("data-key");
|
||||
// @ts-expect-error - TS2339 - Property 'sortKey' does not exist on type 'URLResources'.
|
||||
if (key === this.sortKey) {
|
||||
// @ts-expect-error - TS2339 - Property 'sortDesc' does not exist on type 'URLResources'. | TS2339 - Property 'sortDesc' does not exist on type 'URLResources'.
|
||||
this.sortDesc = !this.sortDesc;
|
||||
} else {
|
||||
// @ts-expect-error - TS2339 - Property 'sortDesc' does not exist on type 'URLResources'.
|
||||
this.sortDesc = false;
|
||||
// @ts-expect-error - TS2339 - Property 'sortKey' does not exist on type 'URLResources'.
|
||||
this.sortKey = key;
|
||||
}
|
||||
}
|
||||
|
||||
onSortChanged(event) {
|
||||
// @ts-expect-error - TS2339 - Property 'sortedResults' does not exist on type 'URLResources'.
|
||||
this.sortedResults = event.detail.sortedData;
|
||||
// @ts-expect-error - TS2339 - Property 'sortKey' does not exist on type 'URLResources'.
|
||||
this.sortKey = event.detail.sortKey;
|
||||
// @ts-expect-error - TS2339 - Property 'sortDesc' does not exist on type 'URLResources'.
|
||||
this.sortDesc = event.detail.sortDesc;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
export function assertNonNullish<T>(
|
||||
item: T,
|
||||
itemName: string,
|
||||
): asserts item is NonNullable<T> {
|
||||
if (item == null) {
|
||||
throw new Error(
|
||||
`Variable \`${itemName}\` was expected to be defined, but found value ${item} instead`,
|
||||
);
|
||||
}
|
||||
}
|
||||
+3
-2
@@ -31,7 +31,8 @@
|
||||
"no-invalid-css": "off"
|
||||
}
|
||||
}
|
||||
]
|
||||
],
|
||||
"skipLibCheck": true
|
||||
},
|
||||
"include": ["src/**/*.ts"]
|
||||
"include": ["src/**/*.ts", "src/**/*.js"]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user