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 */
|
/* eslint-env node */
|
||||||
|
/** @type { import("eslint").Linter.Config } */
|
||||||
module.exports = {
|
module.exports = {
|
||||||
env: {
|
env: {
|
||||||
browser: true,
|
browser: true,
|
||||||
@@ -19,7 +20,7 @@ module.exports = {
|
|||||||
rules: {
|
rules: {
|
||||||
"no-restricted-globals": [2, "event", "error"],
|
"no-restricted-globals": [2, "event", "error"],
|
||||||
"linebreak-style": ["error", "unix"],
|
"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
|
## CHANGES
|
||||||
|
|
||||||
v1.8.11
|
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
|
- 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
|
- 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
|
- Dependencies: Update to electron 25.5.1, ruffle 2023-06-14
|
||||||
|
|
||||||
v1.7.15
|
v1.7.15
|
||||||
@@ -149,7 +151,7 @@ v1.7.4
|
|||||||
v1.7.3
|
v1.7.3
|
||||||
|
|
||||||
- Fidelity: Misc fidelity improvements via latest wombat + wabac.js
|
- 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
|
- Loading: Fix occasional loading issues with multiple embeds loading on the same page
|
||||||
|
|
||||||
v1.7.2
|
v1.7.2
|
||||||
@@ -292,7 +294,7 @@ v1.5.2
|
|||||||
|
|
||||||
v1.5.1
|
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: Allow custom service worker init path on app init (or none)
|
||||||
- Library usage: Ensure page title reflects current app
|
- 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.
|
- 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
|
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)
|
- 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)
|
- Customization: Support for automated redirect to live page on not found (via embed options)
|
||||||
- UI: Updated page not found message
|
- UI: Updated page not found message
|
||||||
|
|||||||
+38
-37
@@ -1,5 +1,5 @@
|
|||||||
import { LitElement, html, css } from "lit";
|
import { LitElement, html, css, type TemplateResult } from "lit";
|
||||||
import { property } from "lit/decorators.js";
|
import { customElement, property } from "lit/decorators.js";
|
||||||
import { ifDefined } from "lit/directives/if-defined.js";
|
import { ifDefined } from "lit/directives/if-defined.js";
|
||||||
import {
|
import {
|
||||||
wrapCss,
|
wrapCss,
|
||||||
@@ -16,9 +16,11 @@ import { SWManager } from "./swmanager";
|
|||||||
import "./item";
|
import "./item";
|
||||||
import "./item-index";
|
import "./item-index";
|
||||||
import "./chooser";
|
import "./chooser";
|
||||||
|
import { LoadInfo } from "./item";
|
||||||
|
|
||||||
// ===========================================================================
|
// ===========================================================================
|
||||||
class ReplayWebApp extends LitElement {
|
@customElement("replay-app-main")
|
||||||
|
export class ReplayWebApp extends LitElement {
|
||||||
@property({ type: Boolean })
|
@property({ type: Boolean })
|
||||||
inited = false;
|
inited = false;
|
||||||
|
|
||||||
@@ -41,10 +43,10 @@ class ReplayWebApp extends LitElement {
|
|||||||
collTitle: string | null = null;
|
collTitle: string | null = null;
|
||||||
|
|
||||||
@property({ type: Object })
|
@property({ type: Object })
|
||||||
loadInfo: any = null;
|
loadInfo: LoadInfo | null = null;
|
||||||
|
|
||||||
@property({ type: String })
|
@property({ type: String })
|
||||||
embed: any = null;
|
embed: string | null = null;
|
||||||
|
|
||||||
@property({ type: String })
|
@property({ type: String })
|
||||||
collPageUrl = "";
|
collPageUrl = "";
|
||||||
@@ -56,13 +58,13 @@ class ReplayWebApp extends LitElement {
|
|||||||
pageReplay = false;
|
pageReplay = false;
|
||||||
|
|
||||||
@property({ type: String })
|
@property({ type: String })
|
||||||
source: any = null;
|
source: string | null = null;
|
||||||
|
|
||||||
@property({ type: Boolean })
|
@property({ type: Boolean })
|
||||||
skipRuffle = false;
|
skipRuffle = false;
|
||||||
|
|
||||||
@property({ type: Object })
|
@property({ type: Object })
|
||||||
swErrorMsg: any = null;
|
swErrorMsg: TemplateResult<1> | "" | null = null;
|
||||||
|
|
||||||
private swName?: string;
|
private swName?: string;
|
||||||
private swmanager: SWManager | null;
|
private swmanager: SWManager | null;
|
||||||
@@ -70,7 +72,6 @@ class ReplayWebApp extends LitElement {
|
|||||||
|
|
||||||
private droppedFile: File | null = null;
|
private droppedFile: File | null = null;
|
||||||
|
|
||||||
// eslint-disable-next-line no-undef
|
|
||||||
constructor(swName = __SW_NAME__) {
|
constructor(swName = __SW_NAME__) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
@@ -105,7 +106,7 @@ class ReplayWebApp extends LitElement {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private maybeStartFileDrop = (dragEvent) => {
|
private maybeStartFileDrop = (dragEvent: DragEvent) => {
|
||||||
if (this.sourceUrl) {
|
if (this.sourceUrl) {
|
||||||
// A source is already loaded. Don't allow dropping a file.
|
// A source is already loaded. Don't allow dropping a file.
|
||||||
return;
|
return;
|
||||||
@@ -372,7 +373,7 @@ class ReplayWebApp extends LitElement {
|
|||||||
-->
|
-->
|
||||||
<a
|
<a
|
||||||
href="?terms"
|
href="?terms"
|
||||||
@click="${(e) => {
|
@click="${(e: Event) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
this.showAbout = true;
|
this.showAbout = true;
|
||||||
}}"
|
}}"
|
||||||
@@ -385,7 +386,7 @@ class ReplayWebApp extends LitElement {
|
|||||||
return html` <wr-item
|
return html` <wr-item
|
||||||
.loadInfo="${this.loadInfo}"
|
.loadInfo="${this.loadInfo}"
|
||||||
sourceUrl="${this.sourceUrl || ""}"
|
sourceUrl="${this.sourceUrl || ""}"
|
||||||
embed="${this.embed}"
|
embed="${ifDefined(this.embed === null ? undefined : this.embed)}"
|
||||||
appName="${this.appName}"
|
appName="${this.appName}"
|
||||||
swName="${ifDefined(this.swName)}"
|
swName="${ifDefined(this.swName)}"
|
||||||
.appLogo="${this.mainLogo}"
|
.appLogo="${this.mainLogo}"
|
||||||
@@ -452,12 +453,11 @@ class ReplayWebApp extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.swmanager = new SWManager({ name, appName: this.appName });
|
this.swmanager = new SWManager({ name, appName: this.appName });
|
||||||
this.swmanager
|
this.swmanager.register().catch(
|
||||||
.register()
|
() =>
|
||||||
.catch(
|
// @ts-expect-error - TS2554 - Expected 2 arguments, but got 1.
|
||||||
() =>
|
(this.swErrorMsg = this.swmanager?.renderErrorReport(this.mainLogo)),
|
||||||
(this.swErrorMsg = this.swmanager?.renderErrorReport(this.mainLogo)),
|
);
|
||||||
);
|
|
||||||
|
|
||||||
window.addEventListener("popstate", () => {
|
window.addEventListener("popstate", () => {
|
||||||
this.initRoute();
|
this.initRoute();
|
||||||
@@ -534,16 +534,21 @@ class ReplayWebApp extends LitElement {
|
|||||||
this.pageParams = new URLSearchParams(window.location.search);
|
this.pageParams = new URLSearchParams(window.location.search);
|
||||||
|
|
||||||
// Google Drive
|
// 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) {
|
if (state) {
|
||||||
try {
|
try {
|
||||||
state = JSON.parse(state);
|
const parsedState: State = JSON.parse(state);
|
||||||
if (
|
if (
|
||||||
state.ids instanceof Array &&
|
parsedState.ids instanceof Array &&
|
||||||
state.userId &&
|
parsedState.userId &&
|
||||||
state.action === "open"
|
parsedState.action === "open"
|
||||||
) {
|
) {
|
||||||
this.pageParams.set("source", "googledrive://" + state.ids[0]);
|
this.pageParams.set("source", "googledrive://" + parsedState.ids[0]);
|
||||||
this.pageParams.delete("state");
|
this.pageParams.delete("state");
|
||||||
window.location.search = this.pageParams.toString();
|
window.location.search = this.pageParams.toString();
|
||||||
return;
|
return;
|
||||||
@@ -581,7 +586,7 @@ class ReplayWebApp extends LitElement {
|
|||||||
|
|
||||||
if (this.pageParams.get("config")) {
|
if (this.pageParams.get("config")) {
|
||||||
try {
|
try {
|
||||||
this.loadInfo.extraConfig = JSON.parse(
|
this.loadInfo!.extraConfig = JSON.parse(
|
||||||
this.pageParams.get("config") || "",
|
this.pageParams.get("config") || "",
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -590,35 +595,35 @@ class ReplayWebApp extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this.pageParams.get("baseUrlSourcePrefix")) {
|
if (this.pageParams.get("baseUrlSourcePrefix")) {
|
||||||
this.loadInfo.extraConfig = this.loadInfo.extraConfig || {};
|
this.loadInfo!.extraConfig = this.loadInfo!.extraConfig || {};
|
||||||
this.loadInfo.extraConfig.baseUrlSourcePrefix = this.pageParams.get(
|
this.loadInfo!.extraConfig.baseUrlSourcePrefix = this.pageParams.get(
|
||||||
"baseUrlSourcePrefix",
|
"baseUrlSourcePrefix",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.pageParams.get("basePageUrl")) {
|
if (this.pageParams.get("basePageUrl")) {
|
||||||
this.loadInfo.extraConfig = this.loadInfo.extraConfig || {};
|
this.loadInfo!.extraConfig = this.loadInfo!.extraConfig || {};
|
||||||
this.loadInfo.extraConfig.baseUrl = this.pageParams.get("basePageUrl");
|
this.loadInfo!.extraConfig.baseUrl = this.pageParams.get("basePageUrl");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.pageParams.get("customColl")) {
|
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") {
|
if (this.pageParams.get("noWebWorker") === "1") {
|
||||||
this.loadInfo.noWebWorker = true;
|
this.loadInfo!.noWebWorker = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.pageParams.get("noCache") === "1") {
|
if (this.pageParams.get("noCache") === "1") {
|
||||||
this.loadInfo.noCache = true;
|
this.loadInfo!.noCache = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.pageParams.get("hideOffscreen") === "1") {
|
if (this.pageParams.get("hideOffscreen") === "1") {
|
||||||
this.loadInfo.hideOffscreen = true;
|
this.loadInfo!.hideOffscreen = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.pageParams.get("loading") === "eager") {
|
if (this.pageParams.get("loading") === "eager") {
|
||||||
this.loadInfo.loadEager = true;
|
this.loadInfo!.loadEager = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.pageParams.get("swName")) {
|
if (this.pageParams.get("swName")) {
|
||||||
@@ -791,7 +796,3 @@ class ReplayWebApp extends LitElement {
|
|||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
customElements.define("replay-app-main", ReplayWebApp);
|
|
||||||
|
|
||||||
export { ReplayWebApp };
|
|
||||||
|
|||||||
@@ -2,47 +2,50 @@ import { LitElement, html, css } from "lit";
|
|||||||
import { IS_APP, wrapCss } from "./misc";
|
import { IS_APP, wrapCss } from "./misc";
|
||||||
|
|
||||||
import fasUpload from "@fortawesome/fontawesome-free/svgs/solid/upload.svg";
|
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 {
|
@customElement("wr-chooser")
|
||||||
constructor() {
|
export class Chooser extends LitElement {
|
||||||
super();
|
@property({ type: String })
|
||||||
|
fileDisplayName = "";
|
||||||
|
|
||||||
this.fileDisplayName = "";
|
@property({ attribute: false })
|
||||||
this.file = null;
|
file: FileWithPath | null = null;
|
||||||
this.droppedFile = 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;
|
@property({ type: Object })
|
||||||
|
showOpenFilePickerOptions = {
|
||||||
this.showOpenFilePickerOptions = {
|
types: [
|
||||||
types: [
|
{
|
||||||
{
|
description: "WARC, WACZ, HAR and WBN Files",
|
||||||
description: "WARC, WACZ, HAR and WBN Files",
|
accept: {
|
||||||
accept: {
|
"application/warc": [".warc", ".gz"],
|
||||||
"application/warc": [".warc", ".gz"],
|
"application/har": [".har"],
|
||||||
"application/har": [".har"],
|
"application/wacz": [".wacz"],
|
||||||
"application/wacz": [".wacz"],
|
"application/wbn": [".wbn"],
|
||||||
"application/wbn": [".wbn"],
|
"application/json": [".json"],
|
||||||
"application/json": [".json"],
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
],
|
},
|
||||||
};
|
],
|
||||||
}
|
};
|
||||||
|
|
||||||
static get properties() {
|
@property({ type: Boolean })
|
||||||
return {
|
newFullImport = false;
|
||||||
fileDisplayName: { type: String },
|
|
||||||
/** @type File */
|
@property({ type: Boolean })
|
||||||
droppedFile: { attribute: false },
|
noHead = false;
|
||||||
newFullImport: { type: Boolean },
|
|
||||||
noHead: { type: Boolean },
|
fileHandle?: FileSystemFileHandle;
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
updated(changedProperties) {
|
updated(changedProperties) {
|
||||||
if (changedProperties.has("droppedFile") && this.droppedFile) {
|
if (changedProperties.has("droppedFile") && this.droppedFile) {
|
||||||
@@ -56,11 +59,12 @@ class Chooser extends LitElement {
|
|||||||
.map(Object.values)
|
.map(Object.values)
|
||||||
.flat(2);
|
.flat(2);
|
||||||
|
|
||||||
const fileHasAllowedExtension = allowedFileExtensions.some((extension) =>
|
const fileHasAllowedExtension = allowedFileExtensions.some(
|
||||||
this.droppedFile.name.endsWith(extension),
|
(extension) => this.droppedFile?.name.endsWith(extension),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (fileHasAllowedExtension) {
|
if (fileHasAllowedExtension) {
|
||||||
|
if (this.droppedFile === null) return;
|
||||||
this.setFile(this.droppedFile);
|
this.setFile(this.droppedFile);
|
||||||
this.dispatchEvent(
|
this.dispatchEvent(
|
||||||
new CustomEvent("did-drop-file", { bubbles: true, composed: true }),
|
new CustomEvent("did-drop-file", { bubbles: true, composed: true }),
|
||||||
@@ -76,10 +80,10 @@ class Chooser extends LitElement {
|
|||||||
this.setFile(event.currentTarget.files[0]);
|
this.setFile(event.currentTarget.files[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
setFile(file) {
|
setFile(file: FileWithPath) {
|
||||||
this.file = file;
|
this.file = file;
|
||||||
// file.path only available in electron app
|
// 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() {
|
async onChooseNativeFile() {
|
||||||
@@ -90,9 +94,11 @@ class Chooser extends LitElement {
|
|||||||
const [fileHandle] = await window.showOpenFilePicker(
|
const [fileHandle] = await window.showOpenFilePicker(
|
||||||
this.showOpenFilePickerOptions,
|
this.showOpenFilePickerOptions,
|
||||||
);
|
);
|
||||||
|
|
||||||
this.fileHandle = fileHandle;
|
this.fileHandle = fileHandle;
|
||||||
|
|
||||||
this.file = await fileHandle.getFile();
|
this.file = (await fileHandle.getFile()) as FileWithPath;
|
||||||
|
|
||||||
this.fileDisplayName = "file://" + fileHandle.name;
|
this.fileDisplayName = "file://" + fileHandle.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,18 +109,32 @@ class Chooser extends LitElement {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
onStartLoad(event) {
|
onStartLoad(event?: Event) {
|
||||||
if (event) {
|
if (event) {
|
||||||
event.preventDefault();
|
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) {
|
if (this.file) {
|
||||||
loadInfo.isFile = true;
|
loadInfo.isFile = true;
|
||||||
// file.path only available in electron app
|
// file.path only available in electron app
|
||||||
if (this.file.path) {
|
if (this.file.path) {
|
||||||
// eslint-disable-next-line no-undef
|
|
||||||
loadInfo.loadUrl = "file2://" + this.file.path;
|
loadInfo.loadUrl = "file2://" + this.file.path;
|
||||||
loadInfo.noCache = true;
|
loadInfo.noCache = true;
|
||||||
} else if (this.fileHandle) {
|
} else if (this.fileHandle) {
|
||||||
@@ -130,8 +150,6 @@ class Chooser extends LitElement {
|
|||||||
loadInfo.name = this.fileDisplayName;
|
loadInfo.name = this.fileDisplayName;
|
||||||
}
|
}
|
||||||
|
|
||||||
loadInfo.newFullImport = this.newFullImport;
|
|
||||||
|
|
||||||
this.dispatchEvent(
|
this.dispatchEvent(
|
||||||
new CustomEvent("load-start", {
|
new CustomEvent("load-start", {
|
||||||
bubbles: true,
|
bubbles: true,
|
||||||
@@ -152,6 +170,7 @@ class Chooser extends LitElement {
|
|||||||
this.fileDisplayName.startsWith("file://")
|
this.fileDisplayName.startsWith("file://")
|
||||||
) {
|
) {
|
||||||
this.file = null;
|
this.file = null;
|
||||||
|
|
||||||
this.fileDisplayName = "";
|
this.fileDisplayName = "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -280,7 +299,3 @@ class Chooser extends LitElement {
|
|||||||
</section>`;
|
</section>`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
customElements.define("wr-chooser", Chooser);
|
|
||||||
|
|
||||||
export { Chooser };
|
|
||||||
@@ -9,4 +9,4 @@ const replayApp = new ElectronReplayApp({
|
|||||||
profileName: "replaywebpage",
|
profileName: "replaywebpage",
|
||||||
});
|
});
|
||||||
|
|
||||||
replayApp.init(true);
|
replayApp.init();
|
||||||
|
|||||||
@@ -11,6 +11,11 @@ const dbs = {};
|
|||||||
|
|
||||||
const loader = new CollectionLoader();
|
const loader = new CollectionLoader();
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {string} name
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
async function getColl(name) {
|
async function getColl(name) {
|
||||||
if (!dbs[name]) {
|
if (!dbs[name]) {
|
||||||
dbs[name] = await loader.loadColl(name);
|
dbs[name] = await loader.loadColl(name);
|
||||||
@@ -20,11 +25,24 @@ async function getColl(name) {
|
|||||||
return dbs[name];
|
return dbs[name];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} name
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
async function getDB(name) {
|
async function getDB(name) {
|
||||||
const coll = await getColl(name);
|
const coll = await getColl(name);
|
||||||
return coll.store;
|
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) {
|
async function getResponse(event, request, coll, ts, channel) {
|
||||||
const db = await getDB(coll);
|
const db = await getDB(coll);
|
||||||
|
|
||||||
|
|||||||
+48
-19
@@ -26,7 +26,9 @@ import log from "electron-log";
|
|||||||
import mime from "mime-types";
|
import mime from "mime-types";
|
||||||
import url from "url";
|
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;
|
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;
|
global.fetch = fetch;
|
||||||
|
|
||||||
const STATIC_PREFIX = "http://localhost:5471/";
|
const STATIC_PREFIX = "http://localhost:5471/";
|
||||||
@@ -39,27 +41,43 @@ const URL_RX = /([^/]+)\/([\d]+)(?:\w\w_)?\/(.*)$/;
|
|||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
class ElectronReplayApp {
|
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 = "" } = {}) {
|
constructor({ staticPath = "./", profileName = "" } = {}) {
|
||||||
this.pluginPath = "";
|
|
||||||
|
|
||||||
this.appPath = app.getAppPath();
|
|
||||||
|
|
||||||
this.projPath = path.join(this.appPath, "../");
|
|
||||||
|
|
||||||
this.staticContentPath = staticPath;
|
this.staticContentPath = staticPath;
|
||||||
|
|
||||||
this.profileName = profileName;
|
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() {
|
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
|
// 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.
|
// dock icon is clicked and there are no other windows open.
|
||||||
if (BrowserWindow.getAllWindows().length === 0) {
|
if (BrowserWindow.getAllWindows().length === 0) {
|
||||||
@@ -153,6 +171,7 @@ class ElectronReplayApp {
|
|||||||
|
|
||||||
checkUpdates() {
|
checkUpdates() {
|
||||||
autoUpdater.logger = log;
|
autoUpdater.logger = log;
|
||||||
|
// @ts-expect-error - TS2339 - Property 'transports' does not exist on type 'Logger'.
|
||||||
autoUpdater.logger.transports.file.level = "info";
|
autoUpdater.logger.transports.file.level = "info";
|
||||||
autoUpdater.checkForUpdatesAndNotify();
|
autoUpdater.checkForUpdatesAndNotify();
|
||||||
}
|
}
|
||||||
@@ -332,6 +351,15 @@ class ElectronReplayApp {
|
|||||||
callback({ statusCode, headers, data });
|
callback({ statusCode, headers, data });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {string} url
|
||||||
|
* @param {(props: {
|
||||||
|
* statusCode: number;
|
||||||
|
* headers: Record<string, string>;
|
||||||
|
* data: unknown;
|
||||||
|
* }) => void} callback
|
||||||
|
*/
|
||||||
notFound(url, callback) {
|
notFound(url, callback) {
|
||||||
console.log("not found: " + url);
|
console.log("not found: " + url);
|
||||||
const data = this._bufferToStream(
|
const data = this._bufferToStream(
|
||||||
@@ -449,6 +477,7 @@ class ElectronReplayApp {
|
|||||||
const theWindow = new BrowserWindow({
|
const theWindow = new BrowserWindow({
|
||||||
width: this.screenSize.width,
|
width: this.screenSize.width,
|
||||||
height: this.screenSize.height,
|
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,
|
isMaximized: true,
|
||||||
show: false,
|
show: false,
|
||||||
webPreferences: this.mainWindowWebPreferences,
|
webPreferences: this.mainWindowWebPreferences,
|
||||||
|
|||||||
@@ -6,36 +6,26 @@ import fasDownload from "@fortawesome/fontawesome-free/svgs/solid/download.svg";
|
|||||||
|
|
||||||
import { clickOnSpacebarPress } from "./misc";
|
import { clickOnSpacebarPress } from "./misc";
|
||||||
|
|
||||||
import { LitElement, html, css } from "lit";
|
import { LitElement, html, css, nothing } from "lit";
|
||||||
import { tsToDate } from "./pageutils";
|
import { tsToDate } from "./pageutils";
|
||||||
import prettyBytes from "pretty-bytes";
|
import prettyBytes from "pretty-bytes";
|
||||||
|
import { property } from "lit/decorators.js";
|
||||||
|
import type { Item as ItemType } from "./types";
|
||||||
|
|
||||||
// ===========================================================================
|
// ===========================================================================
|
||||||
export class RWPEmbedReceipt extends LitElement {
|
export class RWPEmbedReceipt extends LitElement {
|
||||||
constructor() {
|
@property({ type: Object }) collInfo: ItemType | null = null;
|
||||||
super();
|
@property({ type: Object }) appLogo = null;
|
||||||
this.collInfo = null;
|
@property({ type: String }) ts: string | null = null;
|
||||||
this.appLogo = null;
|
@property({ type: String }) url: string | null = null;
|
||||||
this.ts = null;
|
|
||||||
this.url = null;
|
|
||||||
this.active = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@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() {
|
get renderRoot() {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
static get properties() {
|
|
||||||
return {
|
|
||||||
collInfo: { type: Object },
|
|
||||||
appLogo: { type: Object },
|
|
||||||
url: { type: String },
|
|
||||||
ts: { type: String },
|
|
||||||
|
|
||||||
active: { type: Boolean },
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static get embedStyles() {
|
static get embedStyles() {
|
||||||
return css`
|
return css`
|
||||||
rwp-embed-receipt {
|
rwp-embed-receipt {
|
||||||
@@ -182,19 +172,17 @@ export class RWPEmbedReceipt extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let {
|
const {
|
||||||
numValid,
|
numValid = 0,
|
||||||
numInvalid,
|
numInvalid = 0,
|
||||||
domain,
|
domain,
|
||||||
certFingerprint,
|
certFingerprint,
|
||||||
datapackageHash,
|
datapackageHash,
|
||||||
publicKey,
|
publicKey,
|
||||||
software,
|
software,
|
||||||
} = this.collInfo.verify || {};
|
} = this.collInfo?.verify || {};
|
||||||
numValid = numValid || 0;
|
|
||||||
numInvalid = numInvalid || 0;
|
|
||||||
|
|
||||||
const sourceUrl = this.collInfo.sourceUrl;
|
const sourceUrl = this.collInfo?.sourceUrl;
|
||||||
|
|
||||||
const certFingerprintUrl = certFingerprint
|
const certFingerprintUrl = certFingerprint
|
||||||
? `https://crt.sh/?q=${certFingerprint}`
|
? `https://crt.sh/?q=${certFingerprint}`
|
||||||
@@ -251,25 +239,35 @@ export class RWPEmbedReceipt extends LitElement {
|
|||||||
>replayweb.page</a
|
>replayweb.page</a
|
||||||
>.
|
>.
|
||||||
</p>
|
</p>
|
||||||
<a
|
${sourceUrl
|
||||||
href="${sourceUrl}"
|
? html`
|
||||||
class="button is-primary mt-4"
|
<a
|
||||||
@keyup="${clickOnSpacebarPress}"
|
href="${sourceUrl}"
|
||||||
>
|
class="button is-primary mt-4"
|
||||||
<span class="icon is-small">
|
@keyup="${clickOnSpacebarPress}"
|
||||||
<fa-icon
|
>
|
||||||
size="1.0em"
|
<span class="icon is-small">
|
||||||
aria-hidden="true"
|
<fa-icon
|
||||||
.svg="${fasDownload}"
|
size="1.0em"
|
||||||
></fa-icon>
|
aria-hidden="true"
|
||||||
</span>
|
.svg="${fasDownload}"
|
||||||
<span>Download Archive</span>
|
></fa-icon>
|
||||||
</a>
|
</span>
|
||||||
<hr class="dropdown-divider mt-4" />
|
<span>Download Archive</span>
|
||||||
|
</a>
|
||||||
|
<hr class="dropdown-divider mt-4" />
|
||||||
|
`
|
||||||
|
: nothing}
|
||||||
<h2 class="mt-4">Technical Information</h2>
|
<h2 class="mt-4">Technical Information</h2>
|
||||||
<div class="embed-info-drop-statscontainer mb-4">
|
<div class="embed-info-drop-statscontainer mb-4">
|
||||||
<h3>Original URL:</h3>
|
${this.url
|
||||||
<p><a target="_blank" href="${this.url}">${this.url}</a></p>
|
? html`
|
||||||
|
<h3>Original URL:</h3>
|
||||||
|
<p>
|
||||||
|
<a target="_blank" href="${this.url}">${this.url}</a>
|
||||||
|
</p>
|
||||||
|
`
|
||||||
|
: nothing}
|
||||||
<h3 class="mt-2">Archived On:</h3>
|
<h3 class="mt-2">Archived On:</h3>
|
||||||
<p>${dateStr}</p>
|
<p>${dateStr}</p>
|
||||||
${domain
|
${domain
|
||||||
@@ -301,8 +299,12 @@ export class RWPEmbedReceipt extends LitElement {
|
|||||||
: html` <p>Not Available</p> `}
|
: html` <p>Not Available</p> `}
|
||||||
<h3 class="mt-2">Package Hash:</h3>
|
<h3 class="mt-2">Package Hash:</h3>
|
||||||
<p class="show-hash">${datapackageHash}</p>
|
<p class="show-hash">${datapackageHash}</p>
|
||||||
<h3 class="mt-2">Size</h3>
|
${this.collInfo?.size != null
|
||||||
<p>${prettyBytes(Number(this.collInfo.size || 0))}</p>
|
? html`
|
||||||
|
<h3 class="mt-2">Size</h3>
|
||||||
|
<p>${prettyBytes(Number(this.collInfo.size || 0))}</p>
|
||||||
|
`
|
||||||
|
: nothing}
|
||||||
</div>
|
</div>
|
||||||
${sourceUrl ? html`` : ""}
|
${sourceUrl ? html`` : ""}
|
||||||
<p
|
<p
|
||||||
@@ -314,13 +316,16 @@ export class RWPEmbedReceipt extends LitElement {
|
|||||||
class="has-text-black"
|
class="has-text-black"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
href="https://github.com/webrecorder/replayweb.page"
|
href="https://github.com/webrecorder/replayweb.page"
|
||||||
>
|
>${this.appLogo
|
||||||
<fa-icon
|
? html`
|
||||||
class="menu-logo mr-1"
|
<fa-icon
|
||||||
size="1.0rem"
|
class="menu-logo mr-1"
|
||||||
aria-hidden="true"
|
size="1.0rem"
|
||||||
.svg=${this.appLogo}
|
aria-hidden="true"
|
||||||
></fa-icon>
|
.svg=${this.appLogo}
|
||||||
|
></fa-icon>
|
||||||
|
`
|
||||||
|
: nothing}
|
||||||
Powered by ReplayWeb.page
|
Powered by ReplayWeb.page
|
||||||
</a>
|
</a>
|
||||||
</span>
|
</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 { ifDefined } from "lit/directives/if-defined.js";
|
||||||
|
|
||||||
import { wrapCss, rwpLogo } from "./misc";
|
import { wrapCss, rwpLogo } from "./misc";
|
||||||
import { SWManager } from "./swmanager";
|
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/";
|
const DEFAULT_REPLAY_BASE = "https://replayweb.page/";
|
||||||
|
|
||||||
// ===========================================================================
|
// ===========================================================================
|
||||||
class Embed extends LitElement {
|
class Embed extends LitElement {
|
||||||
constructor() {
|
@property({ type: String }) url = "";
|
||||||
super();
|
@property({ type: String }) ts = "";
|
||||||
this.replaybase = "./replay/";
|
@property({ type: String }) query = "";
|
||||||
this.replayfile = defaultReplayFile;
|
|
||||||
// eslint-disable-next-line no-undef
|
@property({ type: String }) source;
|
||||||
this.swName = __SW_NAME__;
|
@property({ type: String }) src;
|
||||||
this.mainElementName = "replay-app-main";
|
|
||||||
this.appName = "ReplayWeb.page";
|
@property({ type: String }) view = "replay";
|
||||||
this.view = "replay";
|
@property({ type: String }) embed: string | null = null;
|
||||||
this.ts = "";
|
|
||||||
this.url = "";
|
@property({ type: String }) replaybase = "./replay/";
|
||||||
this.query = "";
|
@property({ type: String }) swName = __SW_NAME__;
|
||||||
this.config = "";
|
|
||||||
this.customConfig = null;
|
@property({ type: String }) title!: string;
|
||||||
this.coll = "";
|
|
||||||
this.paramString = null;
|
@property({ type: String }) coll = "";
|
||||||
this.deepLink = false;
|
@property({ type: String }) config = "";
|
||||||
this.newWindowBase = "";
|
|
||||||
this.inited = false;
|
@property({ type: Boolean }) inited = false;
|
||||||
this.embed = null;
|
|
||||||
this.reloadCount = 0;
|
@property({ type: String }) paramString: string | null = null;
|
||||||
this.sandbox = false;
|
@property({ type: String }) hashString: string | undefined;
|
||||||
this.noWebWorker = false;
|
|
||||||
this.noCache = false;
|
@property({ type: Boolean }) deepLink = false;
|
||||||
// deprecated;
|
@property({ type: Boolean }) sandbox = false;
|
||||||
this.noSandbox = null;
|
@property({ type: Boolean }) noSandbox: boolean | null = null;
|
||||||
this.logo = rwpLogo;
|
@property({ type: Boolean }) noWebWorker = false;
|
||||||
this.loading = "";
|
@property({ type: Boolean }) noCache = false;
|
||||||
this.useRuffle = 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) {
|
static setDefaultReplayFile(replayfile) {
|
||||||
defaultReplayFile = 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() {
|
async doRegister() {
|
||||||
const replaybaseURL = new URL(this.replaybase, window.location.href);
|
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
|
// likely safari < 16, don't use web workers due to issues with split storage state
|
||||||
if (
|
if (
|
||||||
|
// @ts-expect-error - TS2339 - Property 'GestureEvent' does not exist on type 'Window & typeof globalThis'.
|
||||||
window.GestureEvent !== undefined &&
|
window.GestureEvent !== undefined &&
|
||||||
window.SharedWorker === undefined
|
window.SharedWorker === undefined
|
||||||
) {
|
) {
|
||||||
@@ -184,15 +166,19 @@ class Embed extends LitElement {
|
|||||||
const qs = new URLSearchParams(window.location.hash.slice(1));
|
const qs = new URLSearchParams(window.location.hash.slice(1));
|
||||||
|
|
||||||
if (qs.has("url")) {
|
if (qs.has("url")) {
|
||||||
|
// @ts-expect-error - TS2339 - Property 'url' does not exist on type 'Embed'.
|
||||||
this.url = qs.get("url");
|
this.url = qs.get("url");
|
||||||
}
|
}
|
||||||
if (qs.has("ts")) {
|
if (qs.has("ts")) {
|
||||||
|
// @ts-expect-error - TS2339 - Property 'ts' does not exist on type 'Embed'.
|
||||||
this.ts = qs.get("ts");
|
this.ts = qs.get("ts");
|
||||||
}
|
}
|
||||||
if (qs.has("query")) {
|
if (qs.has("query")) {
|
||||||
|
// @ts-expect-error - TS2339 - Property 'query' does not exist on type 'Embed'.
|
||||||
this.query = qs.get("query");
|
this.query = qs.get("query");
|
||||||
}
|
}
|
||||||
if (qs.has("view")) {
|
if (qs.has("view")) {
|
||||||
|
// @ts-expect-error - TS2339 - Property 'view' does not exist on type 'Embed'.
|
||||||
this.view = qs.get("view");
|
this.view = qs.get("view");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -203,6 +189,7 @@ class Embed extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this.config) {
|
if (this.config) {
|
||||||
|
// @ts-expect-error - TS2339 - Property 'customConfig' does not exist on type 'Embed'. | TS2339 - Property 'config' does not exist on type 'Embed'.
|
||||||
const config = { ...this.customConfig, ...JSON.parse(this.config) };
|
const config = { ...this.customConfig, ...JSON.parse(this.config) };
|
||||||
return JSON.stringify(config);
|
return JSON.stringify(config);
|
||||||
} else {
|
} else {
|
||||||
@@ -229,7 +216,20 @@ class Embed extends LitElement {
|
|||||||
|
|
||||||
const config = this.mergeConfigs();
|
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,
|
source,
|
||||||
customColl: this.coll,
|
customColl: this.coll,
|
||||||
config,
|
config,
|
||||||
@@ -258,7 +258,6 @@ class Embed extends LitElement {
|
|||||||
params.loading = "eager";
|
params.loading = "eager";
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line no-undef
|
|
||||||
if (this.swName !== __SW_NAME__) {
|
if (this.swName !== __SW_NAME__) {
|
||||||
params.swName = this.swName;
|
params.swName = this.swName;
|
||||||
}
|
}
|
||||||
@@ -267,7 +266,10 @@ class Embed extends LitElement {
|
|||||||
params.ruffle = "1";
|
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({
|
this.hashString = new URLSearchParams({
|
||||||
url: this.url,
|
url: this.url,
|
||||||
@@ -317,7 +319,8 @@ class Embed extends LitElement {
|
|||||||
allow-popups allow-popups-to-escape-sandbox allow-presentation allow-scripts\
|
allow-popups allow-popups-to-escape-sandbox allow-presentation allow-scripts\
|
||||||
allow-same-origin allow-forms"
|
allow-same-origin allow-forms"
|
||||||
: undefined,
|
: 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}"
|
@load="${this.onLoad}"
|
||||||
src="${this.replaybase}${this.replayfile}?${this
|
src="${this.replaybase}${this.replayfile}?${this
|
||||||
.paramString}#${this.hashString}"
|
.paramString}#${this.hashString}"
|
||||||
@@ -7,9 +7,13 @@ import fabGoogleDrive from "@fortawesome/fontawesome-free/svgs/brands/google-dri
|
|||||||
class GDrive extends LitElement {
|
class GDrive extends LitElement {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
|
// @ts-expect-error - TS2339 - Property 'state' does not exist on type 'GDrive'.
|
||||||
this.state = "trypublic";
|
this.state = "trypublic";
|
||||||
|
// @ts-expect-error - TS2339 - Property 'sourceUrl' does not exist on type 'GDrive'.
|
||||||
this.sourceUrl = "";
|
this.sourceUrl = "";
|
||||||
|
// @ts-expect-error - TS2339 - Property 'scriptLoaded' does not exist on type 'GDrive'.
|
||||||
this.scriptLoaded = false;
|
this.scriptLoaded = false;
|
||||||
|
// @ts-expect-error - TS2339 - Property 'error' does not exist on type 'GDrive'.
|
||||||
this.error = false;
|
this.error = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -24,10 +28,13 @@ class GDrive extends LitElement {
|
|||||||
|
|
||||||
updated(changedProperties) {
|
updated(changedProperties) {
|
||||||
if (changedProperties.has("sourceUrl")) {
|
if (changedProperties.has("sourceUrl")) {
|
||||||
|
// @ts-expect-error - TS2339 - Property 'error' does not exist on type 'GDrive'.
|
||||||
this.error = false;
|
this.error = false;
|
||||||
|
// @ts-expect-error - TS2339 - Property 'state' does not exist on type 'GDrive'.
|
||||||
this.state = "trypublic";
|
this.state = "trypublic";
|
||||||
this.tryPublicAccess().then((result) => {
|
this.tryPublicAccess().then((result) => {
|
||||||
if (!result) {
|
if (!result) {
|
||||||
|
// @ts-expect-error - TS2339 - Property 'state' does not exist on type 'GDrive'.
|
||||||
this.state = "tryauto";
|
this.state = "tryauto";
|
||||||
this.requestUpdate();
|
this.requestUpdate();
|
||||||
}
|
}
|
||||||
@@ -37,17 +44,19 @@ class GDrive extends LitElement {
|
|||||||
|
|
||||||
async tryPublicAccess() {
|
async tryPublicAccess() {
|
||||||
try {
|
try {
|
||||||
|
// @ts-expect-error - TS2339 - Property 'sourceUrl' does not exist on type 'GDrive'.
|
||||||
const sourceUrl = this.sourceUrl;
|
const sourceUrl = this.sourceUrl;
|
||||||
const fileId = sourceUrl.slice("googledrive://".length);
|
const fileId = sourceUrl.slice("googledrive://".length);
|
||||||
// eslint-disable-next-line no-undef
|
|
||||||
const publicCheckUrl = `${__HELPER_PROXY__}/g/${fileId}`;
|
const publicCheckUrl = `${__HELPER_PROXY__}/g/${fileId}`;
|
||||||
|
|
||||||
let resp = null;
|
let resp = null;
|
||||||
try {
|
try {
|
||||||
|
// @ts-expect-error - TS2322 - Type 'Response' is not assignable to type 'null'.
|
||||||
resp = await fetch(publicCheckUrl);
|
resp = await fetch(publicCheckUrl);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
// @ts-expect-error - TS2531 - Object is possibly 'null'.
|
||||||
const json = await resp.json();
|
const json = await resp.json();
|
||||||
if (!json.url || !json.name || !json.size) {
|
if (!json.url || !json.name || !json.size) {
|
||||||
return false;
|
return false;
|
||||||
@@ -63,8 +72,10 @@ class GDrive extends LitElement {
|
|||||||
try {
|
try {
|
||||||
const abort = new AbortController();
|
const abort = new AbortController();
|
||||||
const signal = abort.signal;
|
const signal = abort.signal;
|
||||||
|
// @ts-expect-error - TS2322 - Type 'Response' is not assignable to type 'null'.
|
||||||
resp = await fetch(publicUrl, { signal });
|
resp = await fetch(publicUrl, { signal });
|
||||||
abort.abort();
|
abort.abort();
|
||||||
|
// @ts-expect-error - TS2531 - Object is possibly 'null'.
|
||||||
if (resp.status != 200) {
|
if (resp.status != 200) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -88,10 +99,13 @@ class GDrive extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onLoad() {
|
onLoad() {
|
||||||
|
// @ts-expect-error - TS2339 - Property 'scriptLoaded' does not exist on type 'GDrive'.
|
||||||
this.scriptLoaded = true;
|
this.scriptLoaded = true;
|
||||||
this.gauth("none", (response) => {
|
this.gauth("none", (response) => {
|
||||||
if (response.error) {
|
if (response.error) {
|
||||||
|
// @ts-expect-error - TS2339 - Property 'state' does not exist on type 'GDrive'.
|
||||||
if (this.state !== "implicitonly") {
|
if (this.state !== "implicitonly") {
|
||||||
|
// @ts-expect-error - TS2339 - Property 'state' does not exist on type 'GDrive'.
|
||||||
this.state = "trymanual";
|
this.state = "trymanual";
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -109,6 +123,7 @@ class GDrive extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async authed(response) {
|
async authed(response) {
|
||||||
|
// @ts-expect-error - TS2339 - Property 'sourceUrl' does not exist on type 'GDrive'.
|
||||||
const sourceUrl = this.sourceUrl;
|
const sourceUrl = this.sourceUrl;
|
||||||
const fileId = sourceUrl.slice("googledrive://".length);
|
const fileId = sourceUrl.slice("googledrive://".length);
|
||||||
const metadataUrl = `https://www.googleapis.com/drive/v3/files/${fileId}`;
|
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) {
|
if (resp.status === 404 || resp.status == 403) {
|
||||||
|
// @ts-expect-error - TS2339 - Property 'state' does not exist on type 'GDrive'.
|
||||||
if (this.state !== "implicitonly") {
|
if (this.state !== "implicitonly") {
|
||||||
|
// @ts-expect-error - TS2339 - Property 'state' does not exist on type 'GDrive'.
|
||||||
this.state = "trymanual";
|
this.state = "trymanual";
|
||||||
}
|
}
|
||||||
|
// @ts-expect-error - TS2339 - Property 'error' does not exist on type 'GDrive'.
|
||||||
this.error = true;
|
this.error = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @ts-expect-error - TS2339 - Property 'error' does not exist on type 'GDrive'.
|
||||||
this.error = false;
|
this.error = false;
|
||||||
|
|
||||||
const metadata = await resp.json();
|
const metadata = await resp.json();
|
||||||
@@ -147,38 +166,48 @@ class GDrive extends LitElement {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
return html` ${this.script()}
|
return html` ${this.script()}
|
||||||
${this.state !== "trymanual"
|
${
|
||||||
? html` <p>Connecting to Google Drive...</p> `
|
// @ts-expect-error - TS2339 - Property 'state' does not exist on type 'GDrive'.
|
||||||
: html`
|
this.state !== "trymanual"
|
||||||
${this.error
|
? html` <p>Connecting to Google Drive...</p> `
|
||||||
? html`
|
: html`
|
||||||
<div class="error has-text-danger">
|
${
|
||||||
<p>
|
// @ts-expect-error - TS2339 - Property 'error' does not exist on type 'GDrive'.
|
||||||
${this.reauth
|
this.error
|
||||||
? "Some resources are loaded on demand from Google Drive, which requires reauthorization."
|
? html`
|
||||||
: "Could not access this file with the current Google Drive account."}
|
<div class="error has-text-danger">
|
||||||
</p>
|
<p>
|
||||||
<p>
|
${
|
||||||
If you have multiple Google Drive accounts, be sure to
|
// @ts-expect-error - TS2339 - Property 'reauth' does not exist on type 'GDrive'.
|
||||||
select the correct one.
|
this.reauth
|
||||||
</p>
|
? "Some resources are loaded on demand from Google Drive, which requires reauthorization."
|
||||||
</div>
|
: "Could not access this file with the current Google Drive account."
|
||||||
<br />
|
}
|
||||||
`
|
</p>
|
||||||
: ""}
|
<p>
|
||||||
<button
|
If you have multiple Google Drive accounts, be sure to
|
||||||
class="button is-warning is-rounded"
|
select the correct one.
|
||||||
@click="${this.onClickAuth}"
|
</p>
|
||||||
>
|
</div>
|
||||||
<span class="icon"
|
<br />
|
||||||
><fa-icon .svg="${fabGoogleDrive}"></fa-icon
|
`
|
||||||
></span>
|
: ""
|
||||||
<span>Authorize Google Drive</span>
|
}
|
||||||
</button>
|
<button
|
||||||
`}`;
|
class="button is-warning is-rounded"
|
||||||
|
@click="${this.onClickAuth}"
|
||||||
|
>
|
||||||
|
<span class="icon"
|
||||||
|
><fa-icon .svg="${fabGoogleDrive}"></fa-icon
|
||||||
|
></span>
|
||||||
|
<span>Authorize Google Drive</span>
|
||||||
|
</button>
|
||||||
|
`
|
||||||
|
}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
script() {
|
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) {
|
if (this.state === "trypublic" || this.scriptLoaded) {
|
||||||
return html``;
|
return html``;
|
||||||
}
|
}
|
||||||
@@ -189,10 +218,11 @@ class GDrive extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
gauth(prompt, callback) {
|
gauth(prompt, callback) {
|
||||||
|
// @ts-expect-error - TS2339 - Property 'gapi' does not exist on type 'Window & typeof globalThis'.
|
||||||
self.gapi.load("auth2", () => {
|
self.gapi.load("auth2", () => {
|
||||||
|
// @ts-expect-error - TS2339 - Property 'gapi' does not exist on type 'Window & typeof globalThis'.
|
||||||
self.gapi.auth2.authorize(
|
self.gapi.auth2.authorize(
|
||||||
{
|
{
|
||||||
// eslint-disable-next-line no-undef
|
|
||||||
client_id: __GDRIVE_CLIENT_ID__,
|
client_id: __GDRIVE_CLIENT_ID__,
|
||||||
scope: "https://www.googleapis.com/auth/drive.file",
|
scope: "https://www.googleapis.com/auth/drive.file",
|
||||||
response_type: "token",
|
response_type: "token",
|
||||||
Vendored
+12
-1
@@ -1,2 +1,13 @@
|
|||||||
declare module "*.svg";
|
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 = "";
|
query = "";
|
||||||
|
|
||||||
@property({ type: Array })
|
@property({ type: Array })
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO fixme
|
||||||
filteredItems: any[] = [];
|
filteredItems: any[] = [];
|
||||||
|
|
||||||
@property({ type: Array })
|
@property({ type: Array })
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO fixme
|
||||||
sortedItems: any[] | null = null;
|
sortedItems: any[] | null = null;
|
||||||
|
|
||||||
@property({ type: Boolean })
|
@property({ type: Boolean })
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO fixme
|
||||||
hideHeader: any = null;
|
hideHeader: any = null;
|
||||||
|
|
||||||
@property({ type: String })
|
@property({ type: String })
|
||||||
@@ -35,6 +38,7 @@ class ItemIndex extends LitElement {
|
|||||||
headerName = "Loaded Archives";
|
headerName = "Loaded Archives";
|
||||||
|
|
||||||
@state()
|
@state()
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO fixme
|
||||||
private _deleting: any = {};
|
private _deleting: any = {};
|
||||||
|
|
||||||
private typeFilter = "";
|
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 fasAngleRight from "@fortawesome/fontawesome-free/svgs/solid/angle-right.svg";
|
||||||
import fasCaretDown from "@fortawesome/fontawesome-free/svgs/solid/caret-down.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 Split from "split.js";
|
||||||
|
|
||||||
import type { Item as ItemInfo } from "./types";
|
import type { Item as ItemInfo } from "./types";
|
||||||
import type { Replay } from "./replay";
|
import type { Replay } from "./replay";
|
||||||
|
import { ifDefined } from "lit/directives/if-defined.js";
|
||||||
|
|
||||||
import "./item-info";
|
import "./item-info";
|
||||||
|
|
||||||
const RWP_SCHEME = "search://";
|
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 {
|
class Item extends LitElement {
|
||||||
@property({ type: Boolean })
|
@property({ type: Boolean })
|
||||||
@@ -67,7 +87,7 @@ class Item extends LitElement {
|
|||||||
sourceUrl: string | null = null;
|
sourceUrl: string | null = null;
|
||||||
|
|
||||||
@property({ type: Object, attribute: false })
|
@property({ type: Object, attribute: false })
|
||||||
loadInfo: any;
|
loadInfo: LoadInfo | null = null;
|
||||||
|
|
||||||
@property({ type: Boolean })
|
@property({ type: Boolean })
|
||||||
showSidebar: boolean | null = null;
|
showSidebar: boolean | null = null;
|
||||||
@@ -142,9 +162,9 @@ class Item extends LitElement {
|
|||||||
autoUpdateInterval = 10;
|
autoUpdateInterval = 10;
|
||||||
|
|
||||||
@property({ type: String })
|
@property({ type: String })
|
||||||
swName: any = null;
|
swName: string | null = null;
|
||||||
|
|
||||||
private splitter: any = null;
|
private splitter: Split.Instance | null = null;
|
||||||
|
|
||||||
private _replaceLoc = false;
|
private _replaceLoc = false;
|
||||||
private _locUpdateNeeded = false;
|
private _locUpdateNeeded = false;
|
||||||
@@ -224,7 +244,7 @@ class Item extends LitElement {
|
|||||||
this.updateTabData({ multiTs: json.timestamps });
|
this.updateTabData({ multiTs: json.timestamps });
|
||||||
}
|
}
|
||||||
|
|
||||||
willUpdate(changedProperties: Map<string, any>) {
|
willUpdate(changedProperties: Map<string, Record<string, unknown>>) {
|
||||||
if (changedProperties.has("tabData") && this.tabData) {
|
if (changedProperties.has("tabData") && this.tabData) {
|
||||||
// Format tab data from URL query params
|
// Format tab data from URL query params
|
||||||
const tabData = {};
|
const tabData = {};
|
||||||
@@ -266,7 +286,9 @@ class Item extends LitElement {
|
|||||||
if (!this.itemInfo || !this.itemInfo.coll) {
|
if (!this.itemInfo || !this.itemInfo.coll) {
|
||||||
return;
|
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) {
|
if (!this.tabData.url) {
|
||||||
this.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) {
|
} else if (this.splitter) {
|
||||||
try {
|
try {
|
||||||
@@ -850,6 +872,7 @@ class Item extends LitElement {
|
|||||||
|
|
||||||
if (!isReplay && this.tabData && this.tabData.view) {
|
if (!isReplay && this.tabData && this.tabData.view) {
|
||||||
const detail = {
|
const detail = {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO fixme
|
||||||
title: (this.tabLabels as any)[this.tabData.view],
|
title: (this.tabLabels as any)[this.tabData.view],
|
||||||
replayTitle: false,
|
replayTitle: false,
|
||||||
};
|
};
|
||||||
@@ -866,7 +889,7 @@ class Item extends LitElement {
|
|||||||
return html` <wr-loader
|
return html` <wr-loader
|
||||||
.loadInfo="${this.loadInfo}"
|
.loadInfo="${this.loadInfo}"
|
||||||
embed="${this.embed || ""}"
|
embed="${this.embed || ""}"
|
||||||
swName="${this.swName}"
|
swName="${ifDefined(this.swName === null ? undefined : this.swName)}"
|
||||||
.coll="${this.item}"
|
.coll="${this.item}"
|
||||||
sourceUrl="${this.sourceUrl || ""}"
|
sourceUrl="${this.sourceUrl || ""}"
|
||||||
@coll-loaded=${this.onItemLoaded}
|
@coll-loaded=${this.onItemLoaded}
|
||||||
@@ -891,7 +914,7 @@ class Item extends LitElement {
|
|||||||
: isReplay
|
: isReplay
|
||||||
? "is-hidden"
|
? "is-hidden"
|
||||||
: "full-pages"}"
|
: "full-pages"}"
|
||||||
role="${(isSidebar ? "complementary" : "") as any}"
|
role="${ifDefined(isSidebar ? "complementary" : undefined)}"
|
||||||
aria-label="${isSidebar ? "Browse Contents" : ""}"
|
aria-label="${isSidebar ? "Browse Contents" : ""}"
|
||||||
>
|
>
|
||||||
${this.renderTabHeader(isSidebar)}
|
${this.renderTabHeader(isSidebar)}
|
||||||
@@ -961,9 +984,9 @@ class Item extends LitElement {
|
|||||||
href="#story"
|
href="#story"
|
||||||
class="is-size-6"
|
class="is-size-6"
|
||||||
aria-label="Story"
|
aria-label="Story"
|
||||||
aria-current="${(this.tabData.view === "story"
|
aria-current="${ifDefined(
|
||||||
? "location"
|
this.tabData.view === "story" ? "location" : undefined,
|
||||||
: "") as any}"
|
)}"
|
||||||
>
|
>
|
||||||
<span class="icon"
|
<span class="icon"
|
||||||
><fa-icon
|
><fa-icon
|
||||||
@@ -987,9 +1010,9 @@ class Item extends LitElement {
|
|||||||
href="#pages"
|
href="#pages"
|
||||||
class="is-size-6"
|
class="is-size-6"
|
||||||
aria-label="Pages"
|
aria-label="Pages"
|
||||||
aria-current="${(this.tabData.view === "pages"
|
aria-current="${ifDefined(
|
||||||
? "location"
|
this.tabData.view === "pages" ? "location" : undefined,
|
||||||
: "") as any}"
|
)}"
|
||||||
>
|
>
|
||||||
<span class="icon"
|
<span class="icon"
|
||||||
><fa-icon
|
><fa-icon
|
||||||
@@ -1012,9 +1035,9 @@ class Item extends LitElement {
|
|||||||
href="#resources"
|
href="#resources"
|
||||||
class="is-size-6"
|
class="is-size-6"
|
||||||
aria-label="URLs"
|
aria-label="URLs"
|
||||||
aria-current="${(this.tabData.view === "resources"
|
aria-current="${ifDefined(
|
||||||
? "location"
|
this.tabData.view === "resources" ? "location" : undefined,
|
||||||
: "") as any}"
|
)}"
|
||||||
>
|
>
|
||||||
<span class="icon"
|
<span class="icon"
|
||||||
><fa-icon
|
><fa-icon
|
||||||
@@ -1513,7 +1536,7 @@ class Item extends LitElement {
|
|||||||
id="story"
|
id="story"
|
||||||
.isSidebar="${isSidebar}"
|
.isSidebar="${isSidebar}"
|
||||||
class="${isStory ? "" : "is-hidden"} ${isSidebar ? "sidebar" : ""}"
|
class="${isStory ? "" : "is-hidden"} ${isSidebar ? "sidebar" : ""}"
|
||||||
role="${(isSidebar ? "" : "main") as any}"
|
role="${ifDefined(isSidebar ? undefined : "main")}"
|
||||||
>
|
>
|
||||||
</wr-coll-story>`
|
</wr-coll-story>`
|
||||||
: ""}
|
: ""}
|
||||||
@@ -1530,7 +1553,7 @@ class Item extends LitElement {
|
|||||||
class="is-paddingless ${isResources ? "" : "is-hidden"} ${isSidebar
|
class="is-paddingless ${isResources ? "" : "is-hidden"} ${isSidebar
|
||||||
? "sidebar"
|
? "sidebar"
|
||||||
: ""}"
|
: ""}"
|
||||||
role="${(isSidebar ? "" : "main") as any}"
|
role="${ifDefined(isSidebar ? undefined : "main")}"
|
||||||
>
|
>
|
||||||
</wr-coll-resources>`
|
</wr-coll-resources>`
|
||||||
: ""}
|
: ""}
|
||||||
@@ -1548,7 +1571,7 @@ class Item extends LitElement {
|
|||||||
id="pages"
|
id="pages"
|
||||||
@coll-update="${this.onItemUpdate}"
|
@coll-update="${this.onItemUpdate}"
|
||||||
class="${isPages ? "" : "is-hidden"} ${isSidebar ? "sidebar" : ""}"
|
class="${isPages ? "" : "is-hidden"} ${isSidebar ? "sidebar" : ""}"
|
||||||
role="${(isSidebar ? "" : "main") as any}"
|
role="${ifDefined(isSidebar ? undefined : "main")}"
|
||||||
>
|
>
|
||||||
</wr-page-view>`
|
</wr-page-view>`
|
||||||
: ""}
|
: ""}
|
||||||
@@ -1738,6 +1761,7 @@ class Item extends LitElement {
|
|||||||
|
|
||||||
_stringToParams(value) {
|
_stringToParams(value) {
|
||||||
const q = new URLSearchParams(value.slice(RWP_SCHEME.length));
|
const q = new URLSearchParams(value.slice(RWP_SCHEME.length));
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO fixme
|
||||||
const data: any = {};
|
const data: any = {};
|
||||||
data.url = "";
|
data.url = "";
|
||||||
data.ts = "";
|
data.ts = "";
|
||||||
@@ -1757,7 +1781,7 @@ class Item extends LitElement {
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
_paramsToString(value) {
|
_paramsToString(value: Record<string, unknown>) {
|
||||||
const q = new URLSearchParams();
|
const q = new URLSearchParams();
|
||||||
|
|
||||||
for (const param of [
|
for (const param of [
|
||||||
@@ -1768,14 +1792,14 @@ class Item extends LitElement {
|
|||||||
"urlSearchType",
|
"urlSearchType",
|
||||||
]) {
|
]) {
|
||||||
if (param in value) {
|
if (param in value) {
|
||||||
q.set(param, value[param]);
|
q.set(param, String(value[param]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return q.toString();
|
return q.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
onRefresh(event, replayOnly = false) {
|
onRefresh(event: Event | null, replayOnly = false) {
|
||||||
if (event) {
|
if (event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,52 +4,36 @@ import { wrapCss } from "./misc";
|
|||||||
import prettyBytes from "pretty-bytes";
|
import prettyBytes from "pretty-bytes";
|
||||||
|
|
||||||
import { parseURLSchemeHostPath } from "./pageutils";
|
import { parseURLSchemeHostPath } from "./pageutils";
|
||||||
|
import { property } from "lit/decorators.js";
|
||||||
|
import { LoadInfo } from "./item";
|
||||||
|
|
||||||
// ===========================================================================
|
// ===========================================================================
|
||||||
class Loader extends LitElement {
|
class Loader extends LitElement {
|
||||||
constructor() {
|
@property({ type: String }) sourceUrl?: string;
|
||||||
super();
|
@property({ type: Object }) loadInfo: LoadInfo | null = null;
|
||||||
this.progress = 0;
|
@property({ type: String }) state = "waiting";
|
||||||
this.total = 0;
|
@property({ type: Number }) progress = 0;
|
||||||
this.percent = 0;
|
@property({ type: Number }) percent = 0;
|
||||||
this.coll = "";
|
@property({ type: Number }) currentSize = 0;
|
||||||
this.state = "waiting";
|
@property({ type: Number }) totalSize = 0;
|
||||||
this.loadInfo = null;
|
@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;
|
pingInterval: number | NodeJS.Timer = 0;
|
||||||
this.totalSize = 0;
|
fileHandle: FileSystemHandle | null = null;
|
||||||
|
noWebWorker = false;
|
||||||
|
worker?: Worker | null;
|
||||||
|
|
||||||
this.tryFileHandle = !!window.showOpenFilePicker;
|
// Google Drive
|
||||||
|
_gdWait?: Promise<LoadInfo>;
|
||||||
this.fileHandle = null;
|
_gdResolve!: (value: LoadInfo | PromiseLike<LoadInfo>) => void;
|
||||||
|
|
||||||
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 },
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
firstUpdated() {
|
firstUpdated() {
|
||||||
this.initMessages();
|
this.initMessages();
|
||||||
@@ -57,17 +41,17 @@ class Loader extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
initMessages() {
|
initMessages() {
|
||||||
this.noWebWorker = this.loadInfo && this.loadInfo.noWebWorker;
|
this.noWebWorker = Boolean(this.loadInfo && this.loadInfo.noWebWorker);
|
||||||
|
|
||||||
if (!this.noWebWorker) {
|
if (!this.noWebWorker) {
|
||||||
// eslint-disable-next-line no-undef
|
this.worker = new Worker(this.swName!);
|
||||||
this.worker = new Worker(this.swName);
|
|
||||||
} else {
|
} else {
|
||||||
if (!navigator.serviceWorker) {
|
if (!navigator.serviceWorker) {
|
||||||
return;
|
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) => {
|
this.worker.addEventListener("message", (event) => {
|
||||||
@@ -110,7 +94,7 @@ class Loader extends LitElement {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (!this.noWebWorker) {
|
if (!this.noWebWorker) {
|
||||||
this.worker.terminate();
|
this.worker?.terminate();
|
||||||
} else {
|
} else {
|
||||||
if (this.pingInterval) {
|
if (this.pingInterval) {
|
||||||
clearInterval(this.pingInterval);
|
clearInterval(this.pingInterval);
|
||||||
@@ -125,7 +109,7 @@ class Loader extends LitElement {
|
|||||||
|
|
||||||
async doLoad() {
|
async doLoad() {
|
||||||
let sourceUrl = this.sourceUrl;
|
let sourceUrl = this.sourceUrl;
|
||||||
let source = null;
|
let source: LoadInfo | null = null;
|
||||||
|
|
||||||
this.percent = this.currentSize = this.totalSize = 0;
|
this.percent = this.currentSize = this.totalSize = 0;
|
||||||
|
|
||||||
@@ -145,7 +129,7 @@ class Loader extends LitElement {
|
|||||||
switch (scheme) {
|
switch (scheme) {
|
||||||
case "googledrive":
|
case "googledrive":
|
||||||
this.state = "googledrive";
|
this.state = "googledrive";
|
||||||
source = await this.googledriveInit();
|
source = (await this.googledriveInit()) ?? null;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "s3":
|
case "s3":
|
||||||
@@ -170,7 +154,7 @@ You can select a file to upload from the main page by clicking the 'Choose File.
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case "proxy":
|
case "proxy":
|
||||||
sourceUrl = "proxy:" + sourceUrl.slice("proxy://".length);
|
sourceUrl = "proxy:" + sourceUrl!.slice("proxy://".length);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} 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";
|
this.state = "started";
|
||||||
|
|
||||||
let type = undefined;
|
let type = undefined;
|
||||||
let extraConfig = undefined;
|
let extraConfig: LoadInfo["extraConfig"] = undefined;
|
||||||
|
|
||||||
if (this.loadInfo) {
|
if (this.loadInfo) {
|
||||||
source.newFullImport = this.loadInfo.newFullImport;
|
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?
|
// todo: too special case?
|
||||||
if (
|
if (
|
||||||
sourceUrl.startsWith("proxy:") &&
|
sourceUrl!.startsWith("proxy:") &&
|
||||||
extraConfig &&
|
extraConfig &&
|
||||||
extraConfig.recording
|
extraConfig.recording
|
||||||
) {
|
) {
|
||||||
|
// @ts-expect-error - TS2322 - Type '"recordingproxy"' is not assignable to type 'undefined'.
|
||||||
type = "recordingproxy";
|
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) {
|
if (!navigator.serviceWorker.controller) {
|
||||||
await new Promise((resolve) => {
|
await new Promise((resolve) => {
|
||||||
navigator.serviceWorker.addEventListener("controllerchange", () =>
|
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(),
|
resolve(),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@@ -225,11 +211,13 @@ You can select a file to upload from the main page by clicking the 'Choose File.
|
|||||||
if (!this.noWebWorker) {
|
if (!this.noWebWorker) {
|
||||||
this.worker.postMessage(msg);
|
this.worker.postMessage(msg);
|
||||||
} else {
|
} else {
|
||||||
|
// @ts-expect-error - TS2531 - Object is possibly 'null'.
|
||||||
navigator.serviceWorker.controller.postMessage(msg);
|
navigator.serviceWorker.controller.postMessage(msg);
|
||||||
|
|
||||||
// ping service worker with messages to avoid shutdown while loading
|
// ping service worker with messages to avoid shutdown while loading
|
||||||
// (mostly for Firefox)
|
// (mostly for Firefox)
|
||||||
this.pingInterval = setInterval(() => {
|
this.pingInterval = setInterval(() => {
|
||||||
|
// @ts-expect-error - TS2531 - Object is possibly 'null'.
|
||||||
navigator.serviceWorker.controller.postMessage({ msg_type: "ping" });
|
navigator.serviceWorker.controller.postMessage({ msg_type: "ping" });
|
||||||
}, 15000);
|
}, 15000);
|
||||||
}
|
}
|
||||||
@@ -350,7 +338,7 @@ You can select a file to upload from the main page by clicking the 'Choose File.
|
|||||||
switch (this.state) {
|
switch (this.state) {
|
||||||
case "googledrive":
|
case "googledrive":
|
||||||
return html`<wr-gdrive
|
return html`<wr-gdrive
|
||||||
.sourceUrl=${this.sourceUrl}
|
.sourceUrl=${this.sourceUrl!}
|
||||||
@load-ready=${this.onLoadReady}
|
@load-ready=${this.onLoadReady}
|
||||||
></wr-gdrive>`;
|
></wr-gdrive>`;
|
||||||
|
|
||||||
@@ -363,10 +351,15 @@ You can select a file to upload from the main page by clicking the 'Choose File.
|
|||||||
max="100"
|
max="100"
|
||||||
></progress>
|
></progress>
|
||||||
<label class="progress-label" for="progress">${this.percent}%</label>
|
<label class="progress-label" for="progress">${this.percent}%</label>
|
||||||
|
|
||||||
${this.currentSize && this.totalSize
|
${this.currentSize && this.totalSize
|
||||||
? html` <div class="loaded-prog">
|
? html` <div class="loaded-prog">
|
||||||
Loaded <b>${prettyBytes(this.currentSize)}</b> of
|
Loaded
|
||||||
|
<b>${prettyBytes(this.currentSize)}</b>
|
||||||
|
of
|
||||||
|
|
||||||
<b>${prettyBytes(this.totalSize)}</b>
|
<b>${prettyBytes(this.totalSize)}</b>
|
||||||
|
|
||||||
${this.extraMsg &&
|
${this.extraMsg &&
|
||||||
html` <p class="extra-msg">(${this.extraMsg})</p> `}
|
html` <p class="extra-msg">(${this.extraMsg})</p> `}
|
||||||
</div>`
|
</div>`
|
||||||
@@ -417,7 +410,10 @@ You can select a file to upload from the main page by clicking the 'Choose File.
|
|||||||
}
|
}
|
||||||
|
|
||||||
async onAskPermission() {
|
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") {
|
if (result === "granted") {
|
||||||
this.doLoad();
|
this.doLoad();
|
||||||
}
|
}
|
||||||
@@ -4,6 +4,7 @@ import { LitElement, html, css, unsafeCSS } from "lit";
|
|||||||
import { unsafeSVG } from "lit/directives/unsafe-svg.js";
|
import { unsafeSVG } from "lit/directives/unsafe-svg.js";
|
||||||
import { styleMap } from "lit/directives/style-map.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 allCssRaw from "../assets/main.scss";
|
||||||
|
|
||||||
import rwpLogo from "../assets/logo.svg";
|
import rwpLogo from "../assets/logo.svg";
|
||||||
@@ -18,11 +19,12 @@ function wrapCss(custom) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const IS_APP =
|
const IS_APP =
|
||||||
|
// @ts-expect-error - TS2339 - Property 'IS_APP' does not exist on type 'Window & typeof globalThis'.
|
||||||
window.IS_APP ||
|
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.electron && window.electron.IS_APP) ||
|
||||||
window.matchMedia("(display-mode: standalone)").matches;
|
window.matchMedia("(display-mode: standalone)").matches;
|
||||||
|
|
||||||
// eslint-disable-next-line no-undef
|
|
||||||
const VERSION = __VERSION__;
|
const VERSION = __VERSION__;
|
||||||
|
|
||||||
// ===========================================================================
|
// ===========================================================================
|
||||||
@@ -39,8 +41,11 @@ function clickOnSpacebarPress(event) {
|
|||||||
class FaIcon extends LitElement {
|
class FaIcon extends LitElement {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
|
// @ts-expect-error - TS2339 - Property 'size' does not exist on type 'FaIcon'.
|
||||||
this.size = "1.1em";
|
this.size = "1.1em";
|
||||||
|
// @ts-expect-error - TS2339 - Property 'width' does not exist on type 'FaIcon'.
|
||||||
this.width = null;
|
this.width = null;
|
||||||
|
// @ts-expect-error - TS2339 - Property 'height' does not exist on type 'FaIcon'.
|
||||||
this.height = null;
|
this.height = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,26 +75,39 @@ class FaIcon extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
// @ts-expect-error - TS2339 - Property 'svg' does not exist on type 'FaIcon'.
|
||||||
if (!this.svg) {
|
if (!this.svg) {
|
||||||
return html``;
|
return html``;
|
||||||
}
|
}
|
||||||
|
|
||||||
const styles = {};
|
const styles = {};
|
||||||
|
|
||||||
|
// @ts-expect-error - TS2339 - Property 'size' does not exist on type 'FaIcon'.
|
||||||
if (this.size) {
|
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;
|
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;
|
styles.height = this.size;
|
||||||
} else {
|
} else {
|
||||||
|
// @ts-expect-error - TS2339 - Property 'width' does not exist on type 'FaIcon'.
|
||||||
if (this.width) {
|
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;
|
styles.width = this.width;
|
||||||
}
|
}
|
||||||
|
// @ts-expect-error - TS2339 - Property 'height' does not exist on type 'FaIcon'.
|
||||||
if (this.height) {
|
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;
|
styles.height = this.height;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return html`<svg style="${styleMap(styles)}">
|
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>`;
|
</svg>`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -98,6 +116,7 @@ class FaIcon extends LitElement {
|
|||||||
class AnimLogo extends FaIcon {
|
class AnimLogo extends FaIcon {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
|
// @ts-expect-error - TS2339 - Property 'svg' does not exist on type 'AnimLogo'.
|
||||||
this.svg = rwpLogo;
|
this.svg = rwpLogo;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -155,7 +174,9 @@ class WrModal extends LitElement {
|
|||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this.title = "";
|
this.title = "";
|
||||||
|
// @ts-expect-error - TS2339 - Property 'bgClass' does not exist on type 'WrModal'.
|
||||||
this.bgClass = "";
|
this.bgClass = "";
|
||||||
|
// @ts-expect-error - TS2339 - Property 'noBgClose' does not exist on type 'WrModal'.
|
||||||
this.noBgClose = false;
|
this.noBgClose = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,10 +209,18 @@ class WrModal extends LitElement {
|
|||||||
return html` <div class="modal is-active">
|
return html` <div class="modal is-active">
|
||||||
<div
|
<div
|
||||||
class="modal-background"
|
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>
|
||||||
<div class="modal-card">
|
<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>
|
<p class="modal-card-title is-3">${this.title}</p>
|
||||||
<button
|
<button
|
||||||
class="delete"
|
class="delete"
|
||||||
+2
-1
@@ -18,6 +18,7 @@ class PageEntry extends LitElement {
|
|||||||
textSnippet: string | null = "";
|
textSnippet: string | null = "";
|
||||||
|
|
||||||
@property({ type: Object })
|
@property({ type: Object })
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO fixme
|
||||||
page: any = null;
|
page: any = null;
|
||||||
|
|
||||||
@property({ type: String })
|
@property({ type: String })
|
||||||
@@ -77,7 +78,7 @@ class PageEntry extends LitElement {
|
|||||||
width: 100%;
|
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 {
|
.columns {
|
||||||
margin-top: calc(-0.75rem + 2px);
|
margin-top: calc(-0.75rem + 2px);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,21 +20,26 @@ import type { PageEntry } from "./pageentry";
|
|||||||
// ===========================================================================
|
// ===========================================================================
|
||||||
class Pages extends LitElement {
|
class Pages extends LitElement {
|
||||||
@property({ type: Array })
|
@property({ type: Array })
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO fixme
|
||||||
filteredPages: any[] = [];
|
filteredPages: any[] = [];
|
||||||
|
|
||||||
@property({ type: Array })
|
@property({ type: Array })
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO fixme
|
||||||
sortedPages: any[] = [];
|
sortedPages: any[] = [];
|
||||||
|
|
||||||
@property({ type: String })
|
@property({ type: String })
|
||||||
query = "";
|
query = "";
|
||||||
|
|
||||||
@property()
|
@property()
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO fixme
|
||||||
flex: any = null;
|
flex: any = null;
|
||||||
|
|
||||||
@property()
|
@property()
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO fixme
|
||||||
textPages: any = null;
|
textPages: any = null;
|
||||||
|
|
||||||
@property()
|
@property()
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO fixme
|
||||||
newQuery: any = null;
|
newQuery: any = null;
|
||||||
|
|
||||||
@property({ type: Boolean })
|
@property({ type: Boolean })
|
||||||
@@ -83,15 +88,19 @@ class Pages extends LitElement {
|
|||||||
ts = "";
|
ts = "";
|
||||||
|
|
||||||
@property({ type: Boolean })
|
@property({ type: Boolean })
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO fixme
|
||||||
editing: any = false;
|
editing: any = false;
|
||||||
|
|
||||||
@property({ type: Object })
|
@property({ type: Object })
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO fixme
|
||||||
toDeletePages: any = null;
|
toDeletePages: any = null;
|
||||||
|
|
||||||
@property({ type: Object })
|
@property({ type: Object })
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO fixme
|
||||||
toDeletePage: any = null;
|
toDeletePage: any = null;
|
||||||
|
|
||||||
@property({ type: Object })
|
@property({ type: Object })
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO fixme
|
||||||
collInfo: any;
|
collInfo: any;
|
||||||
|
|
||||||
@property({ type: Boolean })
|
@property({ type: Boolean })
|
||||||
@@ -100,6 +109,7 @@ class Pages extends LitElement {
|
|||||||
@property({ type: String })
|
@property({ type: String })
|
||||||
defaultKey = "";
|
defaultKey = "";
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO fixme
|
||||||
private _ival: any;
|
private _ival: any;
|
||||||
|
|
||||||
static get sortKeys() {
|
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>) {
|
async updated(changedProperties: Map<string, any>) {
|
||||||
if (changedProperties.has("collInfo")) {
|
if (changedProperties.has("collInfo")) {
|
||||||
this.updateTextSearch();
|
this.updateTextSearch();
|
||||||
@@ -154,7 +165,9 @@ class Pages extends LitElement {
|
|||||||
}
|
}
|
||||||
const sorter = this.renderRoot.querySelector("wr-sorter") as Sorter;
|
const sorter = this.renderRoot.querySelector("wr-sorter") as Sorter;
|
||||||
if (sorter) {
|
if (sorter) {
|
||||||
|
// @ts-expect-error - TS2339 - Property 'sortKey' does not exist on type 'Sorter'.
|
||||||
sorter.sortKey = this.sortKey;
|
sorter.sortKey = this.sortKey;
|
||||||
|
// @ts-expect-error - TS2339 - Property 'sortDesc' does not exist on type 'Sorter'.
|
||||||
sorter.sortDesc = this.sortDesc;
|
sorter.sortDesc = this.sortDesc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -168,6 +181,7 @@ class Pages extends LitElement {
|
|||||||
block: "nearest",
|
block: "nearest",
|
||||||
inline: "nearest",
|
inline: "nearest",
|
||||||
};
|
};
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO fixme
|
||||||
setTimeout(() => selected.scrollIntoView(opts as any), 100);
|
setTimeout(() => selected.scrollIntoView(opts as any), 100);
|
||||||
}
|
}
|
||||||
//}
|
//}
|
||||||
@@ -175,6 +189,7 @@ class Pages extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onChangeQuery(event: Event) {
|
onChangeQuery(event: Event) {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO fixme
|
||||||
this.newQuery = (event.currentTarget as any).value;
|
this.newQuery = (event.currentTarget as any).value;
|
||||||
//this.loading = true;
|
//this.loading = true;
|
||||||
if (this._ival) {
|
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[] = [];
|
const lines: any[] = [];
|
||||||
|
|
||||||
for await (const line of ndjson(resp.body!.getReader())) {
|
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;
|
collInfo: Item | Record<string, never> | null = null;
|
||||||
|
|
||||||
@property({ type: String })
|
@property({ type: String })
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO fixme
|
||||||
sourceUrl: any = null;
|
sourceUrl: any = null;
|
||||||
|
|
||||||
// external url set from parent
|
// external url set from parent
|
||||||
@@ -33,12 +34,14 @@ class Replay extends LitElement {
|
|||||||
title = "";
|
title = "";
|
||||||
|
|
||||||
@property({ type: String })
|
@property({ type: String })
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO fixme
|
||||||
iframeUrl: any = null;
|
iframeUrl: any = null;
|
||||||
|
|
||||||
@property({ type: Boolean })
|
@property({ type: Boolean })
|
||||||
showAuth = false;
|
showAuth = false;
|
||||||
|
|
||||||
@property({ type: Object })
|
@property({ type: Object })
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO fixme
|
||||||
authFileHandle: any = null;
|
authFileHandle: any = null;
|
||||||
|
|
||||||
private reauthWait: null | Promise<void> = 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");
|
const iframe = this.renderRoot.querySelector("iframe");
|
||||||
|
|
||||||
if (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");
|
const iframe = this.renderRoot.querySelector("iframe");
|
||||||
|
|
||||||
if (iframe && event.source === iframe.contentWindow) {
|
if (iframe && event.source === iframe.contentWindow) {
|
||||||
@@ -237,6 +242,7 @@ class Replay extends LitElement {
|
|||||||
!iframe.contentDocument ||
|
!iframe.contentDocument ||
|
||||||
!iframe.contentWindow ||
|
!iframe.contentWindow ||
|
||||||
(iframe.contentDocument.readyState === "complete" &&
|
(iframe.contentDocument.readyState === "complete" &&
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO fixme
|
||||||
!(iframe.contentWindow as Window & { _WBWombat: any })._WBWombat)
|
!(iframe.contentWindow as Window & { _WBWombat: any })._WBWombat)
|
||||||
) {
|
) {
|
||||||
this.clearLoading(iframe && iframe.contentWindow);
|
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 };
|
||||||
+88
-20
@@ -13,18 +13,26 @@ class Story extends LitElement {
|
|||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
|
// @ts-expect-error - TS2339 - Property 'collInfo' does not exist on type 'Story'.
|
||||||
this.collInfo = null;
|
this.collInfo = null;
|
||||||
|
|
||||||
|
// @ts-expect-error - TS2339 - Property 'curatedPageMap' does not exist on type 'Story'.
|
||||||
this.curatedPageMap = {};
|
this.curatedPageMap = {};
|
||||||
|
|
||||||
|
// @ts-expect-error - TS2339 - Property 'currList' does not exist on type 'Story'.
|
||||||
this.currList = 0;
|
this.currList = 0;
|
||||||
|
|
||||||
|
// @ts-expect-error - TS2339 - Property 'active' does not exist on type 'Story'.
|
||||||
this.active = false;
|
this.active = false;
|
||||||
|
|
||||||
|
// @ts-expect-error - TS2339 - Property 'lastST' does not exist on type 'Story'.
|
||||||
this.lastST = 0;
|
this.lastST = 0;
|
||||||
|
// @ts-expect-error - TS2339 - Property 'clickTime' does not exist on type 'Story'.
|
||||||
this.clickTime = 0;
|
this.clickTime = 0;
|
||||||
|
|
||||||
|
// @ts-expect-error - TS2339 - Property 'isSidebar' does not exist on type 'Story'.
|
||||||
this.isSidebar = false;
|
this.isSidebar = false;
|
||||||
|
// @ts-expect-error - TS2339 - Property 'splitDirection' does not exist on type 'Story'.
|
||||||
this.splitDirection = false;
|
this.splitDirection = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,17 +52,21 @@ class Story extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
recalcSplitter(width) {
|
recalcSplitter(width) {
|
||||||
|
// @ts-expect-error - TS2339 - Property 'splitDirection' does not exist on type 'Story'.
|
||||||
this.splitDirection =
|
this.splitDirection =
|
||||||
|
// @ts-expect-error - TS2339 - Property 'isSidebar' does not exist on type 'Story'.
|
||||||
this.isSidebar || width < 769 ? "vertical" : "horizontal";
|
this.isSidebar || width < 769 ? "vertical" : "horizontal";
|
||||||
}
|
}
|
||||||
|
|
||||||
firstUpdated() {
|
firstUpdated() {
|
||||||
this.recalcSplitter(document.documentElement.clientWidth);
|
this.recalcSplitter(document.documentElement.clientWidth);
|
||||||
|
|
||||||
|
// @ts-expect-error - TS2339 - Property 'obs' does not exist on type 'Story'.
|
||||||
this.obs = new ResizeObserver((entries /*, observer*/) => {
|
this.obs = new ResizeObserver((entries /*, observer*/) => {
|
||||||
this.recalcSplitter(entries[0].contentRect.width);
|
this.recalcSplitter(entries[0].contentRect.width);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// @ts-expect-error - TS2339 - Property 'obs' does not exist on type 'Story'.
|
||||||
this.obs.observe(this);
|
this.obs.observe(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,8 +86,10 @@ class Story extends LitElement {
|
|||||||
this.configureSplitter();
|
this.configureSplitter();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @ts-expect-error - TS2339 - Property 'active' does not exist on type 'Story'.
|
||||||
if (changedProperties.has("currList") && this.active) {
|
if (changedProperties.has("currList") && this.active) {
|
||||||
this.sendChangeEvent({
|
this.sendChangeEvent({
|
||||||
|
// @ts-expect-error - TS2339 - Property 'currList' does not exist on type 'Story'.
|
||||||
currList: this.currList,
|
currList: this.currList,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -85,39 +99,50 @@ class Story extends LitElement {
|
|||||||
const sidebar = this.renderRoot.querySelector(".sidebar");
|
const sidebar = this.renderRoot.querySelector(".sidebar");
|
||||||
const content = this.renderRoot.querySelector(".main-content");
|
const content = this.renderRoot.querySelector(".main-content");
|
||||||
|
|
||||||
|
// @ts-expect-error - TS2339 - Property 'splitter' does not exist on type 'Story'.
|
||||||
if (this.splitter) {
|
if (this.splitter) {
|
||||||
try {
|
try {
|
||||||
|
// @ts-expect-error - TS2339 - Property 'splitter' does not exist on type 'Story'.
|
||||||
this.splitter.destroy();
|
this.splitter.destroy();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// ignore splitter destory err
|
// ignore splitter destory err
|
||||||
}
|
}
|
||||||
|
// @ts-expect-error - TS2339 - Property 'splitter' does not exist on type 'Story'.
|
||||||
this.splitter = null;
|
this.splitter = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @ts-expect-error - TS2339 - Property 'splitter' does not exist on type 'Story'.
|
||||||
if (sidebar && content && !this.splitter) {
|
if (sidebar && content && !this.splitter) {
|
||||||
const opts = {
|
const opts = {
|
||||||
sizes: [20, 80],
|
sizes: [20, 80],
|
||||||
|
|
||||||
gutterSize: 4,
|
gutterSize: 4,
|
||||||
|
|
||||||
|
// @ts-expect-error - TS2339 - Property 'splitDirection' does not exist on type 'Story'.
|
||||||
direction: this.splitDirection,
|
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);
|
this.splitter = Split([sidebar, content], opts);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async doLoadCurated() {
|
async doLoadCurated() {
|
||||||
|
// @ts-expect-error - TS2339 - Property 'curatedPageMap' does not exist on type 'Story'.
|
||||||
this.curatedPageMap = {};
|
this.curatedPageMap = {};
|
||||||
|
|
||||||
const pageMap = {};
|
const pageMap = {};
|
||||||
|
|
||||||
|
// @ts-expect-error - TS2339 - Property 'collInfo' does not exist on type 'Story'.
|
||||||
for (const page of this.collInfo.pages) {
|
for (const page of this.collInfo.pages) {
|
||||||
pageMap[page.id] = page;
|
pageMap[page.id] = page;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @ts-expect-error - TS2339 - Property 'collInfo' does not exist on type 'Story'.
|
||||||
for (const curated of this.collInfo.curatedPages) {
|
for (const curated of this.collInfo.curatedPages) {
|
||||||
|
// @ts-expect-error - TS2339 - Property 'curatedPageMap' does not exist on type 'Story'.
|
||||||
if (!this.curatedPageMap[curated.list]) {
|
if (!this.curatedPageMap[curated.list]) {
|
||||||
|
// @ts-expect-error - TS2339 - Property 'curatedPageMap' does not exist on type 'Story'.
|
||||||
this.curatedPageMap[curated.list] = [];
|
this.curatedPageMap[curated.list] = [];
|
||||||
}
|
}
|
||||||
const page = curated;
|
const page = curated;
|
||||||
@@ -135,6 +160,7 @@ class Story extends LitElement {
|
|||||||
const title = page.title || page.url;
|
const title = page.title || page.url;
|
||||||
const desc = curated.desc;
|
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 });
|
this.curatedPageMap[curated.list].push({ url, ts, title, desc });
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -249,15 +275,23 @@ class Story extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
// @ts-expect-error - TS2339 - Property 'currList' does not exist on type 'Story'.
|
||||||
const currListNum = this.currList;
|
const currListNum = this.currList;
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
<div
|
<div
|
||||||
class="is-sr-only"
|
class="is-sr-only"
|
||||||
role="heading"
|
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>
|
||||||
<div class="columns">
|
<div class="columns">
|
||||||
<div class="column sidebar is-one-fifth">
|
<div class="column sidebar is-one-fifth">
|
||||||
@@ -271,21 +305,29 @@ class Story extends LitElement {
|
|||||||
? "is-active"
|
? "is-active"
|
||||||
: ""} menu-label is-size-4"
|
: ""} menu-label is-size-4"
|
||||||
@click=${this.onClickScroll}
|
@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">
|
<ul class="menu-list">
|
||||||
${this.collInfo.lists.map(
|
${
|
||||||
(list) =>
|
// @ts-expect-error - TS2339 - Property 'collInfo' does not exist on type 'Story'.
|
||||||
html` <li>
|
this.collInfo.lists.map(
|
||||||
<a
|
(list) =>
|
||||||
@click=${this.onClickScroll}
|
html` <li>
|
||||||
href="#list-${list.id}"
|
<a
|
||||||
data-list="${list.id}"
|
@click=${this.onClickScroll}
|
||||||
class="${currListNum === list.id ? "is-active" : ""}"
|
href="#list-${list.id}"
|
||||||
>${list.title}</a
|
data-list="${list.id}"
|
||||||
>
|
class="${currListNum === list.id
|
||||||
</li>`,
|
? "is-active"
|
||||||
)}
|
: ""}"
|
||||||
|
>${list.title}</a
|
||||||
|
>
|
||||||
|
</li>`,
|
||||||
|
)
|
||||||
|
}
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
@@ -293,8 +335,17 @@ class Story extends LitElement {
|
|||||||
</div>
|
</div>
|
||||||
<div @scroll=${this.onScroll} class="column main-content main-scroll">
|
<div @scroll=${this.onScroll} class="column main-content main-scroll">
|
||||||
<section id="list-0" class="desc">
|
<section id="list-0" class="desc">
|
||||||
<h2 class="has-text-centered title is-3">${this.collInfo.title}</h2>
|
<h2 class="has-text-centered title is-3">
|
||||||
${this.collInfo.desc ? unsafeHTML(marked(this.collInfo.desc)) : ""}
|
${
|
||||||
|
// @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>
|
</section>
|
||||||
${this.renderLists()}
|
${this.renderLists()}
|
||||||
</div>
|
</div>
|
||||||
@@ -303,6 +354,7 @@ class Story extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderLists() {
|
renderLists() {
|
||||||
|
// @ts-expect-error - TS2339 - Property 'collInfo' does not exist on type 'Story'.
|
||||||
return html` ${this.collInfo.lists.map(
|
return html` ${this.collInfo.lists.map(
|
||||||
(list) => html`
|
(list) => html`
|
||||||
<article id="list-${list.id}">
|
<article id="list-${list.id}">
|
||||||
@@ -311,9 +363,13 @@ class Story extends LitElement {
|
|||||||
<h3>${list.title}</h3>
|
<h3>${list.title}</h3>
|
||||||
<p>${list.desc}</p>
|
<p>${list.desc}</p>
|
||||||
<ol>
|
<ol>
|
||||||
${this.curatedPageMap[list.id]
|
${
|
||||||
? this.curatedPageMap[list.id].map((p) => this.renderCPage(p))
|
// @ts-expect-error - TS2339 - Property 'curatedPageMap' does not exist on type 'Story'.
|
||||||
: html``}
|
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>
|
</ol>
|
||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
@@ -361,6 +417,7 @@ class Story extends LitElement {
|
|||||||
onClickScroll(event) {
|
onClickScroll(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
//this.pageView = false;
|
//this.pageView = false;
|
||||||
|
// @ts-expect-error - TS2339 - Property 'currList' does not exist on type 'Story'.
|
||||||
this.currList = Number(event.currentTarget.getAttribute("data-list"));
|
this.currList = Number(event.currentTarget.getAttribute("data-list"));
|
||||||
this.scrollToList();
|
this.scrollToList();
|
||||||
return false;
|
return false;
|
||||||
@@ -368,12 +425,16 @@ class Story extends LitElement {
|
|||||||
|
|
||||||
scrollToList() {
|
scrollToList() {
|
||||||
// lists are 1 based, 0 is header, 1 is first list
|
// 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) {
|
if (this.currList > this.collInfo.lists.length) {
|
||||||
|
// @ts-expect-error - TS2339 - Property 'currList' does not exist on type 'Story'.
|
||||||
this.currList = 0;
|
this.currList = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const opts = { behavior: "smooth", block: "nearest", inline: "nearest" };
|
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();
|
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);
|
const curr = this.renderRoot.getElementById("list-" + this.currList);
|
||||||
if (curr) {
|
if (curr) {
|
||||||
curr.scrollIntoView(opts);
|
curr.scrollIntoView(opts);
|
||||||
@@ -382,6 +443,7 @@ class Story extends LitElement {
|
|||||||
|
|
||||||
onScroll(event) {
|
onScroll(event) {
|
||||||
const scrollable = event.currentTarget;
|
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);
|
const curr = this.renderRoot.getElementById("list-" + this.currList);
|
||||||
|
|
||||||
if (!curr) {
|
if (!curr) {
|
||||||
@@ -392,6 +454,7 @@ class Story extends LitElement {
|
|||||||
const target = scrollable.offsetTop;
|
const target = scrollable.offsetTop;
|
||||||
const currST = scrollable.scrollTop;
|
const currST = scrollable.scrollTop;
|
||||||
|
|
||||||
|
// @ts-expect-error - TS2339 - Property 'lastST' does not exist on type 'Story'.
|
||||||
if (currST > this.lastST) {
|
if (currST > this.lastST) {
|
||||||
while (
|
while (
|
||||||
next.nextElementSibling &&
|
next.nextElementSibling &&
|
||||||
@@ -407,22 +470,27 @@ class Story extends LitElement {
|
|||||||
next = next.previousElementSibling;
|
next = next.previousElementSibling;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// @ts-expect-error - TS2339 - Property 'lastST' does not exist on type 'Story'.
|
||||||
this.lastST = currST;
|
this.lastST = currST;
|
||||||
if (next && next != curr) {
|
if (next && next != curr) {
|
||||||
if (next.id.startsWith("list-")) {
|
if (next.id.startsWith("list-")) {
|
||||||
|
// @ts-expect-error - TS2339 - Property 'currList' does not exist on type 'Story'.
|
||||||
this.currList = Number(next.id.slice(5));
|
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) {
|
if (new Date().getTime() - this.clickTime < 1000) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const sel = this.renderRoot.querySelector(
|
const sel = this.renderRoot.querySelector(
|
||||||
|
// @ts-expect-error - TS2339 - Property 'currList' does not exist on type 'Story'.
|
||||||
`a[data-list="${this.currList}"]`,
|
`a[data-list="${this.currList}"]`,
|
||||||
);
|
);
|
||||||
if (sel) {
|
if (sel) {
|
||||||
const opts = { behavior: "smooth", block: "nearest", inline: "nearest" };
|
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);
|
sel.scrollIntoView(opts);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -9,15 +9,21 @@ export class SWManager {
|
|||||||
appName = "ReplayWeb.page",
|
appName = "ReplayWeb.page",
|
||||||
requireSubdomainIframe = false,
|
requireSubdomainIframe = false,
|
||||||
} = {}) {
|
} = {}) {
|
||||||
|
// @ts-expect-error - TS2339 - Property 'name' does not exist on type 'SWManager'.
|
||||||
this.name = name;
|
this.name = name;
|
||||||
|
// @ts-expect-error - TS2339 - Property 'scope' does not exist on type 'SWManager'.
|
||||||
this.scope = scope;
|
this.scope = scope;
|
||||||
|
// @ts-expect-error - TS2339 - Property 'appName' does not exist on type 'SWManager'.
|
||||||
this.appName = appName;
|
this.appName = appName;
|
||||||
|
// @ts-expect-error - TS2339 - Property 'requireSubdomainIframe' does not exist on type 'SWManager'.
|
||||||
this.requireSubdomainIframe = requireSubdomainIframe;
|
this.requireSubdomainIframe = requireSubdomainIframe;
|
||||||
|
|
||||||
|
// @ts-expect-error - TS2339 - Property 'errorMsg' does not exist on type 'SWManager'.
|
||||||
this.errorMsg = null;
|
this.errorMsg = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
setAppName(newAppName) {
|
setAppName(newAppName) {
|
||||||
|
// @ts-expect-error - TS2339 - Property 'appName' does not exist on type 'SWManager'.
|
||||||
this.appName = newAppName;
|
this.appName = newAppName;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -29,26 +35,37 @@ export class SWManager {
|
|||||||
reject = rej;
|
reject = rej;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// @ts-expect-error - TS2339 - Property 'errorMsg' does not exist on type 'SWManager'.
|
||||||
this.errorMsg = this.getSWErrorMsg();
|
this.errorMsg = this.getSWErrorMsg();
|
||||||
|
|
||||||
|
// @ts-expect-error - TS2339 - Property 'errorMsg' does not exist on type 'SWManager'.
|
||||||
if (this.errorMsg) {
|
if (this.errorMsg) {
|
||||||
|
// @ts-expect-error - TS2339 - Property 'errorMsg' does not exist on type 'SWManager'.
|
||||||
console.error(this.errorMsg);
|
console.error(this.errorMsg);
|
||||||
|
// @ts-expect-error - TS2339 - Property 'errorMsg' does not exist on type 'SWManager'.
|
||||||
reject(this.errorMsg);
|
reject(this.errorMsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleError = (error) => {
|
const handleError = (error) => {
|
||||||
console.error("Error during service worker registration:", 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();
|
this.errorMsg = this.getCrossOriginIframeMsg();
|
||||||
|
// @ts-expect-error - TS2339 - Property 'errorMsg' does not exist on type 'SWManager'.
|
||||||
if (!this.errorMsg) {
|
if (!this.errorMsg) {
|
||||||
|
// @ts-expect-error - TS2339 - Property 'errorMsg' does not exist on type 'SWManager'.
|
||||||
this.errorMsg = `${
|
this.errorMsg = `${
|
||||||
|
// @ts-expect-error - TS2339 - Property 'appName' does not exist on type 'SWManager'.
|
||||||
this.appName
|
this.appName
|
||||||
} could not be loaded due to the following error:\n${error.toString()}`;
|
} could not be loaded due to the following error:\n${error.toString()}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @ts-expect-error - TS2339 - Property 'errorMsg' does not exist on type 'SWManager'.
|
||||||
reject(this.errorMsg);
|
reject(this.errorMsg);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// @ts-expect-error - TS2339 - Property 'scope' does not exist on type 'SWManager'. | TS2339 - Property 'name' does not exist on type 'SWManager'.
|
||||||
register(this.scope + this.name, {
|
register(this.scope + this.name, {
|
||||||
|
// @ts-expect-error - TS2339 - Property 'scope' does not exist on type 'SWManager'.
|
||||||
registrationOptions: { scope: this.scope },
|
registrationOptions: { scope: this.scope },
|
||||||
registered() {
|
registered() {
|
||||||
console.log("Service worker is registered");
|
console.log("Service worker is registered");
|
||||||
@@ -80,6 +97,7 @@ export class SWManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
// @ts-expect-error - TS2531 - Object is possibly 'null'.
|
||||||
return window.top.location.href === "";
|
return window.top.location.href === "";
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return true;
|
return true;
|
||||||
@@ -89,7 +107,9 @@ export class SWManager {
|
|||||||
getSWErrorMsg() {
|
getSWErrorMsg() {
|
||||||
if (navigator.serviceWorker) {
|
if (navigator.serviceWorker) {
|
||||||
// must be loaded from a cross-origin (eg. subdomain)
|
// 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()) {
|
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.`;
|
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) {
|
if (!window.isSecureContext) {
|
||||||
return `
|
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`;
|
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.";
|
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.
|
return `Sorry, ${this.appName} won't work in this browser as Service Workers are not supported in this window.
|
||||||
Please try a different browser.`;
|
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;
|
const msg = this.errorMsg || override;
|
||||||
|
|
||||||
if (!msg) {
|
if (!msg) {
|
||||||
+5
-1
@@ -8,6 +8,8 @@ export interface Item {
|
|||||||
* Archived Item ID
|
* Archived Item ID
|
||||||
*/
|
*/
|
||||||
coll?: string;
|
coll?: string;
|
||||||
|
// TODO(emma) is `id` the same as `coll`? should they be merged?
|
||||||
|
id?: string;
|
||||||
name?: string;
|
name?: string;
|
||||||
title?: string;
|
title?: string;
|
||||||
loadUrl?: string;
|
loadUrl?: string;
|
||||||
@@ -24,9 +26,11 @@ export interface Item {
|
|||||||
software?: string;
|
software?: string;
|
||||||
};
|
};
|
||||||
onDemand?: boolean;
|
onDemand?: boolean;
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO fixme
|
||||||
pages?: any[];
|
pages?: any[];
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO fixme
|
||||||
lists?: any[];
|
lists?: any[];
|
||||||
ctime?: string;
|
ctime?: string;
|
||||||
totalSize?: unknown;
|
totalSize?: unknown;
|
||||||
size?: unknown;
|
size?: number | string;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,24 +58,37 @@ class URLResources extends LitElement {
|
|||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
|
// @ts-expect-error - TS2339 - Property 'collInfo' does not exist on type 'URLResources'.
|
||||||
this.collInfo = null;
|
this.collInfo = null;
|
||||||
|
// @ts-expect-error - TS2339 - Property 'isSidebar' does not exist on type 'URLResources'.
|
||||||
this.isSidebar = false;
|
this.isSidebar = false;
|
||||||
|
|
||||||
|
// @ts-expect-error - TS2339 - Property 'currMime' does not exist on type 'URLResources'.
|
||||||
this.currMime = "";
|
this.currMime = "";
|
||||||
|
// @ts-expect-error - TS2339 - Property 'query' does not exist on type 'URLResources'.
|
||||||
this.query = "";
|
this.query = "";
|
||||||
|
// @ts-expect-error - TS2339 - Property 'urlSearchType' does not exist on type 'URLResources'.
|
||||||
this.urlSearchType = "";
|
this.urlSearchType = "";
|
||||||
|
|
||||||
|
// @ts-expect-error - TS2339 - Property 'filteredResults' does not exist on type 'URLResources'.
|
||||||
this.filteredResults = [];
|
this.filteredResults = [];
|
||||||
|
// @ts-expect-error - TS2339 - Property 'sortedResults' does not exist on type 'URLResources'.
|
||||||
this.sortedResults = [];
|
this.sortedResults = [];
|
||||||
|
|
||||||
|
// @ts-expect-error - TS2339 - Property 'results' does not exist on type 'URLResources'.
|
||||||
this.results = [];
|
this.results = [];
|
||||||
|
|
||||||
|
// @ts-expect-error - TS2339 - Property 'newQuery' does not exist on type 'URLResources'.
|
||||||
this.newQuery = null;
|
this.newQuery = null;
|
||||||
|
|
||||||
|
// @ts-expect-error - TS2339 - Property 'tryMore' does not exist on type 'URLResources'.
|
||||||
this.tryMore = false;
|
this.tryMore = false;
|
||||||
|
// @ts-expect-error - TS2339 - Property 'loading' does not exist on type 'URLResources'.
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
|
|
||||||
|
// @ts-expect-error - TS2339 - Property 'sortKey' does not exist on type 'URLResources'.
|
||||||
this.sortKey = "url";
|
this.sortKey = "url";
|
||||||
|
// @ts-expect-error - TS2339 - Property 'sortDesc' does not exist on type 'URLResources'.
|
||||||
this.sortDesc = false;
|
this.sortDesc = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,14 +109,19 @@ class URLResources extends LitElement {
|
|||||||
|
|
||||||
firstUpdated() {
|
firstUpdated() {
|
||||||
//this.doLoadResources();
|
//this.doLoadResources();
|
||||||
|
// @ts-expect-error - TS2339 - Property 'urlSearchType' does not exist on type 'URLResources'.
|
||||||
if (this.urlSearchType === "") {
|
if (this.urlSearchType === "") {
|
||||||
|
// @ts-expect-error - TS2339 - Property 'urlSearchType' does not exist on type 'URLResources'.
|
||||||
this.urlSearchType = "prefix";
|
this.urlSearchType = "prefix";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_timedUpdate() {
|
_timedUpdate() {
|
||||||
|
// @ts-expect-error - TS2339 - Property 'newQuery' does not exist on type 'URLResources'.
|
||||||
if (this.newQuery !== null) {
|
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;
|
this.query = this.newQuery;
|
||||||
|
// @ts-expect-error - TS2339 - Property 'newQuery' does not exist on type 'URLResources'.
|
||||||
this.newQuery = null;
|
this.newQuery = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -116,8 +134,11 @@ class URLResources extends LitElement {
|
|||||||
) {
|
) {
|
||||||
this.doLoadResources();
|
this.doLoadResources();
|
||||||
const data = {
|
const data = {
|
||||||
|
// @ts-expect-error - TS2339 - Property 'query' does not exist on type 'URLResources'.
|
||||||
query: this.query,
|
query: this.query,
|
||||||
|
// @ts-expect-error - TS2339 - Property 'urlSearchType' does not exist on type 'URLResources'.
|
||||||
urlSearchType: this.urlSearchType,
|
urlSearchType: this.urlSearchType,
|
||||||
|
// @ts-expect-error - TS2339 - Property 'currMime' does not exist on type 'URLResources'.
|
||||||
currMime: this.currMime,
|
currMime: this.currMime,
|
||||||
};
|
};
|
||||||
const replaceLoc =
|
const replaceLoc =
|
||||||
@@ -136,16 +157,21 @@ class URLResources extends LitElement {
|
|||||||
async doLoadResources(isMore = false) {
|
async doLoadResources(isMore = false) {
|
||||||
const count = 100;
|
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)) {
|
if (isMore && (!this.tryMore || !this.results.length)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @ts-expect-error - TS2339 - Property 'loading' does not exist on type 'URLResources'.
|
||||||
if (this.loading) {
|
if (this.loading) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @ts-expect-error - TS2339 - Property 'loading' does not exist on type 'URLResources'.
|
||||||
this.loading = true;
|
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 : "";
|
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;
|
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://
|
// 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;
|
url = "https://" + url;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @ts-expect-error - TS2339 - Property 'currMime' does not exist on type 'URLResources'.
|
||||||
const mime = this.currMime;
|
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({
|
const params = new URLSearchParams({
|
||||||
mime,
|
mime,
|
||||||
url,
|
url,
|
||||||
@@ -163,50 +191,66 @@ class URLResources extends LitElement {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (isMore) {
|
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];
|
const last = this.results[this.results.length - 1];
|
||||||
params.set("fromMime", last.mime);
|
params.set("fromMime", last.mime);
|
||||||
params.set("fromUrl", last.url);
|
params.set("fromUrl", last.url);
|
||||||
params.set("fromStatus", last.status);
|
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());
|
params.set("fromTs", new Date(last.date).getTime());
|
||||||
}
|
}
|
||||||
|
|
||||||
let resp = await fetch(
|
let resp = await fetch(
|
||||||
|
// @ts-expect-error - TS2339 - Property 'collInfo' does not exist on type 'URLResources'.
|
||||||
`${this.collInfo.apiPrefix}/urls?${params.toString()}`,
|
`${this.collInfo.apiPrefix}/urls?${params.toString()}`,
|
||||||
);
|
);
|
||||||
resp = await resp.json();
|
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;
|
this.results = isMore ? this.results.concat(resp.urls) : resp.urls;
|
||||||
// can be more than count if multiple mimes
|
// 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.tryMore = resp.urls.length >= count;
|
||||||
this.filter();
|
this.filter();
|
||||||
|
|
||||||
|
// @ts-expect-error - TS2339 - Property 'loading' does not exist on type 'URLResources'.
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
onChangeTypeSearch(event) {
|
onChangeTypeSearch(event) {
|
||||||
|
// @ts-expect-error - TS2339 - Property 'currMime' does not exist on type 'URLResources'.
|
||||||
this.currMime = event.currentTarget.value;
|
this.currMime = event.currentTarget.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
onChangeQuery(event) {
|
onChangeQuery(event) {
|
||||||
|
// @ts-expect-error - TS2339 - Property 'newQuery' does not exist on type 'URLResources'.
|
||||||
this.newQuery = event.currentTarget.value;
|
this.newQuery = event.currentTarget.value;
|
||||||
|
// @ts-expect-error - TS2339 - Property '_ival' does not exist on type 'URLResources'.
|
||||||
if (this._ival) {
|
if (this._ival) {
|
||||||
|
// @ts-expect-error - TS2339 - Property '_ival' does not exist on type 'URLResources'.
|
||||||
window.clearTimeout(this._ival);
|
window.clearTimeout(this._ival);
|
||||||
}
|
}
|
||||||
|
// @ts-expect-error - TS2339 - Property '_ival' does not exist on type 'URLResources'.
|
||||||
this._ival = window.setTimeout(() => this._timedUpdate(), 250);
|
this._ival = window.setTimeout(() => this._timedUpdate(), 250);
|
||||||
}
|
}
|
||||||
|
|
||||||
onClickUrlType(event) {
|
onClickUrlType(event) {
|
||||||
|
// @ts-expect-error - TS2339 - Property 'urlSearchType' does not exist on type 'URLResources'.
|
||||||
this.urlSearchType = event.currentTarget.value;
|
this.urlSearchType = event.currentTarget.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
filter() {
|
filter() {
|
||||||
const filteredResults = [];
|
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 : "";
|
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) {
|
for (const result of this.results) {
|
||||||
if (!filterText || result.url.indexOf(filterText) >= 0) {
|
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);
|
filteredResults.push(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @ts-expect-error - TS2339 - Property 'filteredResults' does not exist on type 'URLResources'.
|
||||||
this.filteredResults = filteredResults;
|
this.filteredResults = filteredResults;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -214,6 +258,7 @@ class URLResources extends LitElement {
|
|||||||
const element = event.currentTarget;
|
const element = event.currentTarget;
|
||||||
const diff =
|
const diff =
|
||||||
element.scrollHeight - element.scrollTop - element.clientHeight;
|
element.scrollHeight - element.scrollTop - element.clientHeight;
|
||||||
|
// @ts-expect-error - TS2339 - Property 'tryMore' does not exist on type 'URLResources'.
|
||||||
if (this.tryMore && diff < 40) {
|
if (this.tryMore && diff < 40) {
|
||||||
this.doLoadResources(true);
|
this.doLoadResources(true);
|
||||||
}
|
}
|
||||||
@@ -320,15 +365,25 @@ class URLResources extends LitElement {
|
|||||||
return html`
|
return html`
|
||||||
<div
|
<div
|
||||||
role="heading"
|
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"
|
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>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
role="heading"
|
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"
|
class="is-sr-only"
|
||||||
>
|
>
|
||||||
Search and Filter
|
Search and Filter
|
||||||
@@ -343,7 +398,10 @@ class URLResources extends LitElement {
|
|||||||
(filter) => html`
|
(filter) => html`
|
||||||
<option
|
<option
|
||||||
value="${filter.filter}"
|
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}
|
${filter.name}
|
||||||
</option>
|
</option>
|
||||||
@@ -353,15 +411,19 @@ class URLResources extends LitElement {
|
|||||||
</div>
|
</div>
|
||||||
<div class="field flex-auto">
|
<div class="field flex-auto">
|
||||||
<div
|
<div
|
||||||
class="control has-icons-left ${this.loading
|
class="control has-icons-left ${
|
||||||
? "is-loading"
|
// @ts-expect-error - TS2339 - Property 'loading' does not exist on type 'URLResources'.
|
||||||
: ""}"
|
this.loading ? "is-loading" : ""
|
||||||
|
}"
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
class="input"
|
class="input"
|
||||||
@input="${this.onChangeQuery}"
|
@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"
|
placeholder="Enter URL to Search"
|
||||||
/>
|
/>
|
||||||
<span class="icon is-left"
|
<span class="icon is-left"
|
||||||
@@ -378,7 +440,10 @@ class URLResources extends LitElement {
|
|||||||
type="radio"
|
type="radio"
|
||||||
name="urltype"
|
name="urltype"
|
||||||
value="contains"
|
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}"
|
@click="${this.onClickUrlType}"
|
||||||
/> Contains</label
|
/> Contains</label
|
||||||
>
|
>
|
||||||
@@ -387,7 +452,10 @@ class URLResources extends LitElement {
|
|||||||
type="radio"
|
type="radio"
|
||||||
name="urltype"
|
name="urltype"
|
||||||
value="prefix"
|
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}"
|
@click="${this.onClickUrlType}"
|
||||||
/> Prefix</label
|
/> Prefix</label
|
||||||
>
|
>
|
||||||
@@ -396,7 +464,10 @@ class URLResources extends LitElement {
|
|||||||
type="radio"
|
type="radio"
|
||||||
name="urltype"
|
name="urltype"
|
||||||
value="exact"
|
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}"
|
@click="${this.onClickUrlType}"
|
||||||
/> Exact</label
|
/> Exact</label
|
||||||
>
|
>
|
||||||
@@ -406,7 +477,11 @@ class URLResources extends LitElement {
|
|||||||
is-pulled-right
|
is-pulled-right
|
||||||
aria-live="polite"
|
aria-live="polite"
|
||||||
aria-atomic="true"
|
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>
|
||||||
</div>
|
</div>
|
||||||
@@ -415,10 +490,19 @@ class URLResources extends LitElement {
|
|||||||
<div class="sort-header is-hidden-tablet">
|
<div class="sort-header is-hidden-tablet">
|
||||||
<wr-sorter
|
<wr-sorter
|
||||||
id="urls"
|
id="urls"
|
||||||
.sortKey="${this.sortKey}"
|
.sortKey="${
|
||||||
.sortDesc="${this.sortDesc}"
|
// @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}"
|
.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}"
|
@sort-changed="${this.onSortChanged}"
|
||||||
>
|
>
|
||||||
</wr-sorter>
|
</wr-sorter>
|
||||||
@@ -426,7 +510,10 @@ class URLResources extends LitElement {
|
|||||||
|
|
||||||
<div
|
<div
|
||||||
role="heading"
|
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"
|
id="results-heading"
|
||||||
class="is-sr-only"
|
class="is-sr-only"
|
||||||
>
|
>
|
||||||
@@ -443,11 +530,15 @@ class URLResources extends LitElement {
|
|||||||
@click="${this.onSort}"
|
@click="${this.onSort}"
|
||||||
@keyup="${clickOnSpacebarPress}"
|
@keyup="${clickOnSpacebarPress}"
|
||||||
data-key="url"
|
data-key="url"
|
||||||
class="${this.sortKey === "url"
|
class="${
|
||||||
? this.sortDesc
|
// @ts-expect-error - TS2339 - Property 'sortKey' does not exist on type 'URLResources'.
|
||||||
? "desc"
|
this.sortKey === "url"
|
||||||
: "asc"
|
? // @ts-expect-error - TS2339 - Property 'sortDesc' does not exist on type 'URLResources'.
|
||||||
: ""}"
|
this.sortDesc
|
||||||
|
? "desc"
|
||||||
|
: "asc"
|
||||||
|
: ""
|
||||||
|
}"
|
||||||
>URL</a
|
>URL</a
|
||||||
>
|
>
|
||||||
</th>
|
</th>
|
||||||
@@ -458,11 +549,15 @@ class URLResources extends LitElement {
|
|||||||
@click="${this.onSort}"
|
@click="${this.onSort}"
|
||||||
@keyup="${clickOnSpacebarPress}"
|
@keyup="${clickOnSpacebarPress}"
|
||||||
data-key="ts"
|
data-key="ts"
|
||||||
class="${this.sortKey === "ts"
|
class="${
|
||||||
? this.sortDesc
|
// @ts-expect-error - TS2339 - Property 'sortKey' does not exist on type 'URLResources'.
|
||||||
? "desc"
|
this.sortKey === "ts"
|
||||||
: "asc"
|
? // @ts-expect-error - TS2339 - Property 'sortDesc' does not exist on type 'URLResources'.
|
||||||
: ""}"
|
this.sortDesc
|
||||||
|
? "desc"
|
||||||
|
: "asc"
|
||||||
|
: ""
|
||||||
|
}"
|
||||||
>Date</a
|
>Date</a
|
||||||
>
|
>
|
||||||
</th>
|
</th>
|
||||||
@@ -473,11 +568,15 @@ class URLResources extends LitElement {
|
|||||||
@click="${this.onSort}"
|
@click="${this.onSort}"
|
||||||
@keyup="${clickOnSpacebarPress}"
|
@keyup="${clickOnSpacebarPress}"
|
||||||
data-key="mime"
|
data-key="mime"
|
||||||
class="${this.sortKey === "mime"
|
class="${
|
||||||
? this.sortDesc
|
// @ts-expect-error - TS2339 - Property 'sortKey' does not exist on type 'URLResources'.
|
||||||
? "desc"
|
this.sortKey === "mime"
|
||||||
: "asc"
|
? // @ts-expect-error - TS2339 - Property 'sortDesc' does not exist on type 'URLResources'.
|
||||||
: ""}"
|
this.sortDesc
|
||||||
|
? "desc"
|
||||||
|
: "asc"
|
||||||
|
: ""
|
||||||
|
}"
|
||||||
>Mime Type</a
|
>Mime Type</a
|
||||||
>
|
>
|
||||||
</th>
|
</th>
|
||||||
@@ -488,11 +587,15 @@ class URLResources extends LitElement {
|
|||||||
@click="${this.onSort}"
|
@click="${this.onSort}"
|
||||||
@keyup="${clickOnSpacebarPress}"
|
@keyup="${clickOnSpacebarPress}"
|
||||||
data-key="status"
|
data-key="status"
|
||||||
class="${this.sortKey === "status"
|
class="${
|
||||||
? this.sortDesc
|
// @ts-expect-error - TS2339 - Property 'sortKey' does not exist on type 'URLResources'.
|
||||||
? "desc"
|
this.sortKey === "status"
|
||||||
: "asc"
|
? // @ts-expect-error - TS2339 - Property 'sortDesc' does not exist on type 'URLResources'.
|
||||||
: ""}"
|
this.sortDesc
|
||||||
|
? "desc"
|
||||||
|
: "asc"
|
||||||
|
: ""
|
||||||
|
}"
|
||||||
>Status</a
|
>Status</a
|
||||||
>
|
>
|
||||||
</th>
|
</th>
|
||||||
@@ -500,45 +603,53 @@ class URLResources extends LitElement {
|
|||||||
</thead>
|
</thead>
|
||||||
|
|
||||||
<tbody class="main-scroll" @scroll="${this.onScroll}">
|
<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'.
|
||||||
(result) => html`
|
this.sortedResults.length
|
||||||
<tr class="columns result">
|
? // @ts-expect-error - TS2339 - Property 'sortedResults' does not exist on type 'URLResources'.
|
||||||
<td class="column col-url is-6">
|
this.sortedResults.map(
|
||||||
<p class="minihead is-hidden-tablet">URL</p>
|
(result) => html`
|
||||||
<a
|
<tr class="columns result">
|
||||||
@click="${this.onReplay}"
|
<td class="column col-url is-6">
|
||||||
data-url="${result.url}"
|
<p class="minihead is-hidden-tablet">URL</p>
|
||||||
data-ts="${result.ts}"
|
<a
|
||||||
href="${getReplayLink(
|
@click="${this.onReplay}"
|
||||||
"resources",
|
data-url="${result.url}"
|
||||||
result.url,
|
data-ts="${result.ts}"
|
||||||
result.ts,
|
href="${getReplayLink(
|
||||||
)}"
|
"resources",
|
||||||
>
|
result.url,
|
||||||
<keyword-mark keywords="${this.query}"
|
result.ts,
|
||||||
>${result.url}</keyword-mark
|
)}"
|
||||||
>
|
>
|
||||||
</a>
|
<keyword-mark
|
||||||
</td>
|
keywords="${
|
||||||
<td class="column col-ts is-2">
|
// @ts-expect-error - TS2339 - Property 'query' does not exist on type 'URLResources'.
|
||||||
<p class="minihead is-hidden-tablet">Date</p>
|
this.query
|
||||||
${new Date(result.date).toLocaleString()}
|
}"
|
||||||
</td>
|
>${result.url}</keyword-mark
|
||||||
<td class="column col-mime is-3">
|
>
|
||||||
<p class="minihead is-hidden-tablet">Mime Type</p>
|
</a>
|
||||||
${result.mime}
|
</td>
|
||||||
</td>
|
<td class="column col-ts is-2">
|
||||||
<td class="column col-status is-1">
|
<p class="minihead is-hidden-tablet">Date</p>
|
||||||
<p class="minihead is-hidden-tablet">Status</p>
|
${new Date(result.date).toLocaleString()}
|
||||||
${result.status}
|
</td>
|
||||||
</td>
|
<td class="column col-mime is-3">
|
||||||
</tr>
|
<p class="minihead is-hidden-tablet">Mime Type</p>
|
||||||
`,
|
${result.mime}
|
||||||
)
|
</td>
|
||||||
: html`<tr class="section">
|
<td class="column col-status is-1">
|
||||||
<td colspan="4"><i>No Results Found.</i></td>
|
<p class="minihead is-hidden-tablet">Status</p>
|
||||||
</tr>`}
|
${result.status}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
`,
|
||||||
|
)
|
||||||
|
: html`<tr class="section">
|
||||||
|
<td colspan="4"><i>No Results Found.</i></td>
|
||||||
|
</tr>`
|
||||||
|
}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
`;
|
`;
|
||||||
@@ -548,17 +659,24 @@ class URLResources extends LitElement {
|
|||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
const key = event.currentTarget.getAttribute("data-key");
|
const key = event.currentTarget.getAttribute("data-key");
|
||||||
|
// @ts-expect-error - TS2339 - Property 'sortKey' does not exist on type 'URLResources'.
|
||||||
if (key === this.sortKey) {
|
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;
|
this.sortDesc = !this.sortDesc;
|
||||||
} else {
|
} else {
|
||||||
|
// @ts-expect-error - TS2339 - Property 'sortDesc' does not exist on type 'URLResources'.
|
||||||
this.sortDesc = false;
|
this.sortDesc = false;
|
||||||
|
// @ts-expect-error - TS2339 - Property 'sortKey' does not exist on type 'URLResources'.
|
||||||
this.sortKey = key;
|
this.sortKey = key;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onSortChanged(event) {
|
onSortChanged(event) {
|
||||||
|
// @ts-expect-error - TS2339 - Property 'sortedResults' does not exist on type 'URLResources'.
|
||||||
this.sortedResults = event.detail.sortedData;
|
this.sortedResults = event.detail.sortedData;
|
||||||
|
// @ts-expect-error - TS2339 - Property 'sortKey' does not exist on type 'URLResources'.
|
||||||
this.sortKey = event.detail.sortKey;
|
this.sortKey = event.detail.sortKey;
|
||||||
|
// @ts-expect-error - TS2339 - Property 'sortDesc' does not exist on type 'URLResources'.
|
||||||
this.sortDesc = event.detail.sortDesc;
|
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"
|
"no-invalid-css": "off"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"skipLibCheck": true
|
||||||
},
|
},
|
||||||
"include": ["src/**/*.ts"]
|
"include": ["src/**/*.ts", "src/**/*.js"]
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user