From 79d65ec3d9036430b01115adcab435242733b11c Mon Sep 17 00:00:00 2001 From: Juan Date: Fri, 9 May 2025 11:52:29 -0500 Subject: [PATCH 1/5] new html layout --- src/argo-archive-list.ts | 6 +- src/sidepanel.ts | 445 ++++++++++++++++++++++++++++++--------- static/sidepanel.html | 71 +------ 3 files changed, 347 insertions(+), 175 deletions(-) diff --git a/src/argo-archive-list.ts b/src/argo-archive-list.ts index 855ee38..3a024a4 100644 --- a/src/argo-archive-list.ts +++ b/src/argo-archive-list.ts @@ -21,6 +21,9 @@ export class ArgoArchiveList extends LitElement { padding: 0; overflow: visible; } + .card-container { + padding: 0 1rem; + } md-elevated-card > details { border-radius: inherit; @@ -56,9 +59,6 @@ export class ArgoArchiveList extends LitElement { height: 100%; } - .card-container { - padding: 0 1rem; - } img.favicon { width: 20px !important; diff --git a/src/sidepanel.ts b/src/sidepanel.ts index 42e9dbd..fde00cb 100644 --- a/src/sidepanel.ts +++ b/src/sidepanel.ts @@ -1,11 +1,14 @@ import "@material/web/all.js"; import { styles as typescaleStyles } from "@material/web/typography/md-typescale-styles.js"; -import { LitElement, html } from "lit"; +import { LitElement, html, css, CSSResultGroup } from "lit"; import { unsafeSVG } from "lit/directives/unsafe-svg.js"; import "./argo-archive-list"; import "@material/web/textfield/outlined-text-field.js"; import "@material/web/icon/icon.js"; + +import wrRec from "./assets/icons/recLogo.svg"; + import { getLocalOption, // removeLocalOption, @@ -13,8 +16,8 @@ import { } from "./localstorage"; import { BEHAVIOR_WAIT_LOAD, + BEHAVIOR_RUNNING, // BEHAVIOR_READY_START, - // BEHAVIOR_RUNNING, // BEHAVIOR_PAUSED, // BEHAVIOR_DONE, } from "./consts"; @@ -26,53 +29,112 @@ import "@material/web/divider/divider.js"; document.adoptedStyleSheets.push(typescaleStyles.styleSheet!); class ArgoViewer extends LitElement { + + static styles: CSSResultGroup = [ + typescaleStyles as unknown as CSSResultGroup, + css` + + md-tabs { + background-color: white; + } + + .search-container { + margin: 16px 12px; + height: 32px; + background: #ece7f8; + border-radius: 9999px; + display: flex; + align-items: center; + overflow: hidden; + } + + .search-field { + width: 100%; + --md-filled-text-field-container-color: transparent; + --md-ref-shape-corner-radius: 9999px; + overflow: hidden; + } + + + .search-field::part(container), + .search-field::part(hover-overlay), + .search-field::part(focus-overlay) { + border-radius: 9999px; + } + + .search-field::part(input-area) { + padding: 0; + } + + .search-field md-icon, + .search-field input::placeholder { + color: #6b6b6b; + }, + + md-elevated-card { + display: block; + margin: 1rem 0; + padding: 0; + overflow: visible; + } + .card-container { + padding: 0 1rem; + } + + .summary { + background: transparent !important; + padding: 0.75rem 1rem; + } + ` + ]; + constructor() { super(); - // @ts-expect-error - TS2339 - Property 'collections' does not exist on type 'RecPopup'. + // @ts-expect-error - TS2339 - Property 'collections' does not exist on type 'ArgoViewer'. this.collections = []; - // @ts-expect-error - TS2339 - Property 'collTitle' does not exist on type 'RecPopup'. + // @ts-expect-error - TS2339 - Property 'collTitle' does not exist on type 'ArgoViewer'. this.collTitle = ""; - // @ts-expect-error - TS2339 - Property 'collId' does not exist on type 'RecPopup'. + // @ts-expect-error - TS2339 - Property 'collId' does not exist on type 'ArgoViewer'. this.collId = ""; - // @ts-expect-error - TS2339 - Property 'tabId' does not exist on type 'RecPopup'. + // @ts-expect-error - TS2339 - Property 'tabId' does not exist on type 'ArgoViewer'. this.tabId = 0; - // @ts-expect-error - TS2339 - Property 'recording' does not exist on type 'RecPopup'. + // @ts-expect-error - TS2339 - Property 'recording' does not exist on type 'ArgoViewer'. this.recording = false; - // @ts-expect-error - TS2339 - Property 'status' does not exist on type 'RecPopup'. + // @ts-expect-error - TS2339 - Property 'status' does not exist on type 'ArgoViewer'. this.status = null; - // @ts-expect-error - TS2339 - Property 'port' does not exist on type 'RecPopup'. + // @ts-expect-error - TS2339 - Property 'port' does not exist on type 'ArgoViewer'. this.port = null; - // @ts-expect-error - TS2339 - Property 'pageUrl' does not exist on type 'RecPopup'. + // @ts-expect-error - TS2339 - Property 'pageUrl' does not exist on type 'ArgoViewer'. this.pageUrl = ""; - // @ts-expect-error - TS2339 - Property 'pageTs' does not exist on type 'RecPopup'. + // @ts-expect-error - TS2339 - Property 'pageTs' does not exist on type 'ArgoViewer'. this.pageTs = 0; - // @ts-expect-error - TS2339 - Property 'replayUrl' does not exist on type 'RecPopup'. + // @ts-expect-error - TS2339 - Property 'replayUrl' does not exist on type 'ArgoViewer'. this.replayUrl = ""; - // @ts-expect-error - TS2339 - Property 'canRecord' does not exist on type 'RecPopup'. + // @ts-expect-error - TS2339 - Property 'canRecord' does not exist on type 'ArgoViewer'. this.canRecord = false; - // @ts-expect-error - TS2339 - Property 'failureMsg' does not exist on type 'RecPopup'. + // @ts-expect-error - TS2339 - Property 'failureMsg' does not exist on type 'ArgoViewer'. this.failureMsg = null; - // @ts-expect-error - TS2339 - Property 'collDrop' does not exist on type 'RecPopup'. + // @ts-expect-error - TS2339 - Property 'collDrop' does not exist on type 'ArgoViewer'. this.collDrop = ""; - // @ts-expect-error - TS2339 - Property 'allowCreate' does not exist on type 'RecPopup'. + // @ts-expect-error - TS2339 - Property 'allowCreate' does not exist on type 'ArgoViewer'. this.allowCreate = true; - // @ts-expect-error - TS2339 - Property 'waitingForStart' does not exist on type 'RecPopup'. + // @ts-expect-error - TS2339 - Property 'waitingForStart' does not exist on type 'ArgoViewer'. this.waitingForStart = false; - // @ts-expect-error - TS2339 - Property 'waitingForStop' does not exist on type 'RecPopup'. + // @ts-expect-error - TS2339 - Property 'waitingForStop' does not exist on type 'ArgoViewer'. this.waitingForStop = false; - // @ts-expect-error - TS2339 - Property 'behaviorState' does not exist on type 'RecPopup'. + // @ts-expect-error - TS2339 - Property 'behaviorState' does not exist on type 'ArgoViewer'. this.behaviorState = BEHAVIOR_WAIT_LOAD; - // @ts-expect-error - TS2339 - Property 'behaviorMsg' does not exist on type 'RecPopup'. + // @ts-expect-error - TS2339 - Property 'behaviorMsg' does not exist on type 'ArgoViewer'. this.behaviorMsg = ""; - // @ts-expect-error - TS2339 - Property 'autorun' does not exist on type 'RecPopup'. + // @ts-expect-error - TS2339 - Property 'autorun' does not exist on type 'ArgoViewer'. this.autorun = false; } @@ -99,6 +161,22 @@ class ArgoViewer extends LitElement { behaviorMsg: { type: String }, autorun: { type: Boolean }, }; + } + + // @ts-expect-error - TS7006 - Parameter 'match' implicitly has an 'any' type. + findTitleFor(match) { + if (!match) { + return ""; + } + // @ts-expect-error - TS2339 - Property 'collections' does not exist on type 'ArgoViewer'. + for (const coll of this.collections) { + // @ts-expect-error - TS2339 - Property 'collId' does not exist on type 'ArgoViewer'. + if (coll.id === this.collId) { + return coll.title; + } + } + + return ""; } firstUpdated() { @@ -106,29 +184,29 @@ class ArgoViewer extends LitElement { } registerMessages() { - // @ts-expect-error - TS2339 - Property 'port' does not exist on type 'RecPopup'. + // @ts-expect-error - TS2339 - Property 'port' does not exist on type 'ArgoViewer'. this.port = chrome.runtime.connect({ name: "sidepanel-port" }); // @ts-expect-error - TS7006 - Parameter 'tabs' implicitly has an 'any' type. chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => { if (tabs.length) { - // @ts-expect-error - TS2339 - Property 'tabId' does not exist on type 'RecPopup'. + // @ts-expect-error - TS2339 - Property 'tabId' does not exist on type 'ArgoViewer'. this.tabId = tabs[0].id; - // @ts-expect-error - TS2339 - Property 'pageUrl' does not exist on type 'RecPopup'. + // @ts-expect-error - TS2339 - Property 'pageUrl' does not exist on type 'ArgoViewer'. this.pageUrl = tabs[0].url; - // @ts-expect-error - TS2339 - Property 'tabId' does not exist on type 'RecPopup'. | TS7006 - Parameter 'result' implicitly has an 'any' type. + // @ts-expect-error - TS2339 - Property 'tabId' does not exist on type 'ArgoViewer'. | TS7006 - Parameter 'result' implicitly has an 'any' type. chrome.action.getTitle({ tabId: this.tabId }, (result) => { - // @ts-expect-error - TS2339 - Property 'recording' does not exist on type 'RecPopup'. + // @ts-expect-error - TS2339 - Property 'recording' does not exist on type 'ArgoViewer'. this.recording = result.indexOf("Recording:") >= 0; }); - // @ts-expect-error - TS2339 - Property 'tabId' does not exist on type 'RecPopup'. + // @ts-expect-error - TS2339 - Property 'tabId' does not exist on type 'ArgoViewer'. this.sendMessage({ tabId: this.tabId, type: "startUpdates" }); } }); // this.sendMessage({ type: "getPages" }); - // @ts-expect-error - TS2339 - Property 'port' does not exist on type 'RecPopup'. + // @ts-expect-error - TS2339 - Property 'port' does not exist on type 'ArgoViewer'. this.port.onMessage.addListener((message) => { this.onMessage(message); }); @@ -136,78 +214,78 @@ class ArgoViewer extends LitElement { // @ts-expect-error - TS7006 - Parameter 'message' implicitly has an 'any' type. sendMessage(message) { - // @ts-expect-error - TS2339 - Property 'port' does not exist on type 'RecPopup'. + // @ts-expect-error - TS2339 - Property 'port' does not exist on type 'ArgoViewer'. this.port.postMessage(message); } // @ts-expect-error - TS7006 - Parameter 'message' implicitly has an 'any' type. async onMessage(message) { switch (message.type) { case "status": - // @ts-expect-error - TS2339 - Property 'recording' does not exist on type 'RecPopup'. + // @ts-expect-error - TS2339 - Property 'recording' does not exist on type 'ArgoViewer'. this.recording = message.recording; - // @ts-expect-error - TS2339 - Property 'waitingForStart' does not exist on type 'RecPopup'. + // @ts-expect-error - TS2339 - Property 'waitingForStart' does not exist on type 'ArgoViewer'. if (this.waitingForStart && message.firstPageStarted) { - // @ts-expect-error - TS2339 - Property 'waitingForStart' does not exist on type 'RecPopup'. + // @ts-expect-error - TS2339 - Property 'waitingForStart' does not exist on type 'ArgoViewer'. this.waitingForStart = false; } - // @ts-expect-error - TS2339 - Property 'waitingForStop' does not exist on type 'RecPopup'. + // @ts-expect-error - TS2339 - Property 'waitingForStop' does not exist on type 'ArgoViewer'. if (this.waitingForStop && !message.recording && !message.stopping) { - // @ts-expect-error - TS2339 - Property 'waitingForStop' does not exist on type 'RecPopup'. + // @ts-expect-error - TS2339 - Property 'waitingForStop' does not exist on type 'ArgoViewer'. this.waitingForStop = false; } - // @ts-expect-error - TS2339 - Property 'status' does not exist on type 'RecPopup'. + // @ts-expect-error - TS2339 - Property 'status' does not exist on type 'ArgoViewer'. this.status = message; - // @ts-expect-error - TS2339 - Property 'behaviorState' does not exist on type 'RecPopup'. + // @ts-expect-error - TS2339 - Property 'behaviorState' does not exist on type 'ArgoViewer'. this.behaviorState = message.behaviorState; - // @ts-expect-error - TS2339 - Property 'behaviorMsg' does not exist on type 'RecPopup'. + // @ts-expect-error - TS2339 - Property 'behaviorMsg' does not exist on type 'ArgoViewer'. this.behaviorMsg = message.behaviorData?.msg || "Starting..."; - // @ts-expect-error - TS2339 - Property 'behaviorResults' does not exist on type 'RecPopup'. + // @ts-expect-error - TS2339 - Property 'behaviorResults' does not exist on type 'ArgoViewer'. this.behaviorResults = message.behaviorData?.state; - // @ts-expect-error - TS2339 - Property 'autorun' does not exist on type 'RecPopup'. + // @ts-expect-error - TS2339 - Property 'autorun' does not exist on type 'ArgoViewer'. this.autorun = message.autorun; if (message.pageUrl) { - // @ts-expect-error - TS2339 - Property 'pageUrl' does not exist on type 'RecPopup'. + // @ts-expect-error - TS2339 - Property 'pageUrl' does not exist on type 'ArgoViewer'. this.pageUrl = message.pageUrl; } if (message.pageTs) { - // @ts-expect-error - TS2339 - Property 'pageTs' does not exist on type 'RecPopup'. + // @ts-expect-error - TS2339 - Property 'pageTs' does not exist on type 'ArgoViewer'. this.pageTs = message.pageTs; } - // @ts-expect-error - TS2339 - Property 'failureMsg' does not exist on type 'RecPopup'. + // @ts-expect-error - TS2339 - Property 'failureMsg' does not exist on type 'ArgoViewer'. this.failureMsg = message.failureMsg; - // @ts-expect-error - TS2339 - Property 'collId' does not exist on type 'RecPopup'. + // @ts-expect-error - TS2339 - Property 'collId' does not exist on type 'ArgoViewer'. if (this.collId !== message.collId) { - // @ts-expect-error - TS2339 - Property 'collId' does not exist on type 'RecPopup'. + // @ts-expect-error - TS2339 - Property 'collId' does not exist on type 'ArgoViewer'. this.collId = message.collId; - // @ts-expect-error - TS2339 - Property 'collTitle' does not exist on type 'RecPopup'. | TS2339 - Property 'collId' does not exist on type 'RecPopup'. + // @ts-expect-error - TS2339 - Property 'collTitle' does not exist on type 'ArgoViewer'. | TS2339 - Property 'collId' does not exist on type 'ArgoViewer'. this.collTitle = this.findTitleFor(this.collId); - // @ts-expect-error - TS2339 - Property 'tabId' does not exist on type 'RecPopup'. | TS2339 - Property 'collId' does not exist on type 'RecPopup'. + // @ts-expect-error - TS2339 - Property 'tabId' does not exist on type 'ArgoViewer'. | TS2339 - Property 'collId' does not exist on type 'ArgoViewer'. await setLocalOption(`${this.tabId}-collId`, this.collId); } break; case "collections": - // @ts-expect-error - TS2339 - Property 'collections' does not exist on type 'RecPopup'. + // @ts-expect-error - TS2339 - Property 'collections' does not exist on type 'ArgoViewer'. this.collections = message.collections; - // @ts-expect-error - TS2339 - Property 'collId' does not exist on type 'RecPopup'. | TS2339 - Property 'tabId' does not exist on type 'RecPopup'. + // @ts-expect-error - TS2339 - Property 'collId' does not exist on type 'ArgoViewer'. | TS2339 - Property 'tabId' does not exist on type 'ArgoViewer'. this.collId = await getLocalOption(`${this.tabId}-collId`); - // @ts-expect-error - TS2339 - Property 'collTitle' does not exist on type 'RecPopup'. + // @ts-expect-error - TS2339 - Property 'collTitle' does not exist on type 'ArgoViewer'. this.collTitle = ""; - // @ts-expect-error - TS2339 - Property 'collId' does not exist on type 'RecPopup'. + // @ts-expect-error - TS2339 - Property 'collId' does not exist on type 'ArgoViewer'. if (this.collId) { - // @ts-expect-error - TS2339 - Property 'collTitle' does not exist on type 'RecPopup'. | TS2339 - Property 'collId' does not exist on type 'RecPopup'. + // @ts-expect-error - TS2339 - Property 'collTitle' does not exist on type 'ArgoViewer'. | TS2339 - Property 'collId' does not exist on type 'ArgoViewer'. this.collTitle = this.findTitleFor(this.collId); } // may no longer be valid, try default id - // @ts-expect-error - TS2339 - Property 'collTitle' does not exist on type 'RecPopup'. + // @ts-expect-error - TS2339 - Property 'collTitle' does not exist on type 'ArgoViewer'. if (!this.collTitle) { - // @ts-expect-error - TS2339 - Property 'collId' does not exist on type 'RecPopup'. + // @ts-expect-error - TS2339 - Property 'collId' does not exist on type 'ArgoViewer'. this.collId = message.collId; - // @ts-expect-error - TS2339 - Property 'collTitle' does not exist on type 'RecPopup'. | TS2339 - Property 'collId' does not exist on type 'RecPopup'. + // @ts-expect-error - TS2339 - Property 'collTitle' does not exist on type 'ArgoViewer'. | TS2339 - Property 'collId' does not exist on type 'ArgoViewer'. this.collTitle = this.findTitleFor(this.collId); } - // @ts-expect-error - TS2339 - Property 'collTitle' does not exist on type 'RecPopup'. + // @ts-expect-error - TS2339 - Property 'collTitle' does not exist on type 'ArgoViewer'. if (!this.collTitle) { - // @ts-expect-error - TS2339 - Property 'collTitle' does not exist on type 'RecPopup'. + // @ts-expect-error - TS2339 - Property 'collTitle' does not exist on type 'ArgoViewer'. this.collTitle = "[No Title]"; } break; @@ -215,16 +293,16 @@ class ArgoViewer extends LitElement { } get actionButtonDisabled() { - // @ts-expect-error - TS2339 - Property 'recording' does not exist on type 'RecPopup'. | TS2339 - Property 'waitingForStart' does not exist on type 'RecPopup'. | TS2339 - Property 'waitingForStop' does not exist on type 'RecPopup'. + // @ts-expect-error - TS2339 - Property 'recording' does not exist on type 'ArgoViewer'. | TS2339 - Property 'waitingForStart' does not exist on type 'ArgoViewer'. | TS2339 - Property 'waitingForStop' does not exist on type 'ArgoViewer'. return !this.recording ? this.waitingForStart : this.waitingForStop; } // @ts-expect-error - TS7006 - Parameter 'changedProperties' implicitly has an 'any' type. updated(changedProperties) { if ( - // @ts-expect-error - TS2339 - Property 'pageUrl' does not exist on type 'RecPopup'. + // @ts-expect-error - TS2339 - Property 'pageUrl' does not exist on type 'ArgoViewer'. this.pageUrl && - // @ts-expect-error - TS2339 - Property 'pageTs' does not exist on type 'RecPopup'. + // @ts-expect-error - TS2339 - Property 'pageTs' does not exist on type 'ArgoViewer'. this.pageTs && (changedProperties.has("pageUrl") || changedProperties.has("pageTs") || @@ -232,29 +310,29 @@ class ArgoViewer extends LitElement { changedProperties.has("collId")) ) { const params = new URLSearchParams(); - // @ts-expect-error - TS2339 - Property 'pageUrl' does not exist on type 'RecPopup'. + // @ts-expect-error - TS2339 - Property 'pageUrl' does not exist on type 'ArgoViewer'. params.set("url", this.pageUrl); params.set( "ts", - // @ts-expect-error - TS2339 - Property 'pageTs' does not exist on type 'RecPopup'. + // @ts-expect-error - TS2339 - Property 'pageTs' does not exist on type 'ArgoViewer'. new Date(this.pageTs).toISOString().replace(/[-:TZ.]/g, ""), ); params.set("view", "pages"); - // @ts-expect-error - TS2339 - Property 'replayUrl' does not exist on type 'RecPopup'. + // @ts-expect-error - TS2339 - Property 'replayUrl' does not exist on type 'ArgoViewer'. this.replayUrl = this.getCollPage() + "#" + params.toString(); } if (changedProperties.has("pageUrl") || changedProperties.has("failureMsg")) { - // @ts-expect-error - TS2339 - Property 'canRecord' does not exist on type 'RecPopup'. + // @ts-expect-error - TS2339 - Property 'canRecord' does not exist on type 'ArgoViewer'. this.canRecord = - // @ts-expect-error - TS2339 - Property 'pageUrl' does not exist on type 'RecPopup'. + // @ts-expect-error - TS2339 - Property 'pageUrl' does not exist on type 'ArgoViewer'. this.pageUrl && - // @ts-expect-error - TS2339 - Property 'pageUrl' does not exist on type 'RecPopup'. + // @ts-expect-error - TS2339 - Property 'pageUrl' does not exist on type 'ArgoViewer'. (this.pageUrl === "about:blank" || - // @ts-expect-error - TS2339 - Property 'pageUrl' does not exist on type 'RecPopup'. + // @ts-expect-error - TS2339 - Property 'pageUrl' does not exist on type 'ArgoViewer'. this.pageUrl.startsWith("http:") || - // @ts-expect-error - TS2339 - Property 'pageUrl' does not exist on type 'RecPopup'. + // @ts-expect-error - TS2339 - Property 'pageUrl' does not exist on type 'ArgoViewer'. this.pageUrl.startsWith("https:")); } } @@ -267,7 +345,7 @@ class ArgoViewer extends LitElement { getCollPage() { const sourceParams = new URLSearchParams(); - // @ts-expect-error - TS2339 - Property 'collId' does not exist on type 'RecPopup'. + // @ts-expect-error - TS2339 - Property 'collId' does not exist on type 'ArgoViewer'. sourceParams.set("source", "local://" + this.collId); return this.getHomePage() + "?" + sourceParams.toString(); @@ -276,62 +354,219 @@ class ArgoViewer extends LitElement { onStart() { this.sendMessage({ type: "startRecording", - // @ts-expect-error - TS2339 - Property 'collId' does not exist on type 'RecPopup'. + // @ts-expect-error - TS2339 - Property 'collId' does not exist on type 'ArgoViewer'. collId: this.collId, - // @ts-expect-error - TS2339 - Property 'pageUrl' does not exist on type 'RecPopup'. + // @ts-expect-error - TS2339 - Property 'pageUrl' does not exist on type 'ArgoViewer'. url: this.pageUrl, - // @ts-expect-error - TS2339 - Property 'autorun' does not exist on type 'RecPopup'. + // @ts-expect-error - TS2339 - Property 'autorun' does not exist on type 'ArgoViewer'. autorun: this.autorun, }); - // @ts-expect-error - TS2339 - Property 'waitingForStart' does not exist on type 'RecPopup'. + // @ts-expect-error - TS2339 - Property 'waitingForStart' does not exist on type 'ArgoViewer'. this.waitingForStart = true; - // @ts-expect-error - TS2339 - Property 'waitingForStop' does not exist on type 'RecPopup'. + // @ts-expect-error - TS2339 - Property 'waitingForStop' does not exist on type 'ArgoViewer'. this.waitingForStop = false; } onStop() { this.sendMessage({ type: "stopRecording" }); - // @ts-expect-error - TS2339 - Property 'waitingForStart' does not exist on type 'RecPopup'. + // @ts-expect-error - TS2339 - Property 'waitingForStart' does not exist on type 'ArgoViewer'. this.waitingForStart = false; - // @ts-expect-error - TS2339 - Property 'waitingForStop' does not exist on type 'RecPopup'. + // @ts-expect-error - TS2339 - Property 'waitingForStop' does not exist on type 'ArgoViewer'. this.waitingForStop = true; } - render() { + + get notRecordingMessage() { + return "Not Archiving this Tab"; + } + + renderStatusCard() { return html` - -
+
+ +
+ ${this.renderStatus()} +
+
+
+ `; + } + + + renderStatus() { + // @ts-expect-error - TS2339 - Property 'behaviorState' does not exist on type 'ArgoViewer'. + if (this.behaviorState === BEHAVIOR_RUNNING) { + return html`Auto Recording, ${ - // @ts-expect-error - TS2339 - Property 'recording' does not exist on type 'RecPopup'. - !this.recording + // @ts-expect-error - TS2339 - Property 'behaviorMsg' does not exist on type 'ArgoViewer'. + this.behaviorMsg + }`; + } + + // @ts-expect-error - TS2339 - Property 'recording' does not exist on type 'ArgoViewer'. + if (this.recording) { + return html`${ + // @ts-expect-error - TS2339 - Property 'waitingForStop' does not exist on type 'ArgoViewer'. + this.waitingForStop ? "Finishing " : "" + } + Archiving: ${ + // @ts-expect-error - TS2339 - Property 'status' does not exist on type 'ArgoViewer'. | TS2339 - Property 'status' does not exist on type 'ArgoViewer'. + this.status?.numPending ? html` - - public - Resume Archiving - - ` - : html` - ${ + // @ts-expect-error - TS2339 - Property 'status' does not exist on type 'ArgoViewer'. + this.status.numPending + } + URLs + pending${ + // @ts-expect-error - TS2339 - Property 'waitingForStop' does not exist on type 'ArgoViewer'. + this.waitingForStop + ? "." + : ", please wait before loading a new page." + } - pause - Pause Archiving - ` - } + : html` Idle, Continue Browsing` + }`; + } + + // @ts-expect-error - TS2339 - Property 'failureMsg' does not exist on type 'ArgoViewer'. + if (this.failureMsg) { + return html` +
+

+ Sorry, there was an error starting archiving on this page. Please + try again or try a different page. +

+

+ Error Details: + ${ + // @ts-expect-error - TS2339 - Property 'failureMsg' does not exist on type 'ArgoViewer'. + this.failureMsg + } +

+

+ If the error persists, check the + Common Errors and Issues + page in the guide for known issues and possible solutions. +

+
+ `; + } + + // @ts-expect-error - TS2339 - Property 'canRecord' does not exist on type 'ArgoViewer'. + if (!this.canRecord) { + // @ts-expect-error - TS2339 - Property 'pageUrl' does not exist on type 'ArgoViewer'. | TS2339 - Property 'pageUrl' does not exist on type 'ArgoViewer'. + if (this.pageUrl?.startsWith(this.extRoot)) { + return html` +

+ This page is part of the extension. You can view existing archived + items from here. To start a new archiving session, click the + Start Archiving button and enter + a new URL. +

+ `; + } + + return html`Can't archive this page.`; + } + + // @ts-expect-error - TS2339 - Property 'waitingForStart' does not exist on type 'ArgoViewer'. + if (this.waitingForStart) { + return html`Archiving will start after the page reloads...`; + } + + return html`${this.notRecordingMessage}`; + } + + renderSearch() { + return html` +
+ + search + +
+ `; + } + + renderTabs() { + return html` + + My Archives + My Shared Archives + + +
+
+ +
+
+ +
+
+ `; + } + + render() { + return html` + ${this.renderSearch()} + ${this.renderStatusCard()} + ${this.renderTabs()} +
+ +
+ ${ + // @ts-expect-error - TS2339 - Property 'recording' does not exist on type 'ArgoViewer'. + !this.recording + ? html` + + public + Resume Archiving + + ` + : html` + + pause + Pause Archiving + + ` + } - - settings - + + settings + +
`; } diff --git a/static/sidepanel.html b/static/sidepanel.html index ed57b29..8cfed38 100644 --- a/static/sidepanel.html +++ b/static/sidepanel.html @@ -19,81 +19,18 @@ --md-sys-color-background: white; --md-sys-color-surface-container: white; --md-elevated-card-container-color: white; - } - - md-tabs { - background-color: white; - } - - .search-container { - margin: 16px 12px; - height: 32px; - background: #ece7f8; - border-radius: 9999px; - display: flex; - align-items: center; - overflow: hidden; - } - - .search-field { - width: 100%; - --md-filled-text-field-container-color: transparent; - --md-ref-shape-corner-radius: 9999px; - overflow: hidden; - } - - - .search-field::part(container), - .search-field::part(hover-overlay), - .search-field::part(focus-overlay) { - border-radius: 9999px; - } - - .search-field::part(input-area) { - padding: 0; - } - - .search-field md-icon, - .search-field input::placeholder { - color: #6b6b6b; + } -
- - search - -
- - - - - My Archives - My Shared Archives - - -
-
- -
-
- -
-
- - \ No newline at end of file + From 3e7964b295c736e57ba567c8cc9c046aebf65d36 Mon Sep 17 00:00:00 2001 From: Juan Date: Wed, 14 May 2025 12:09:07 -0500 Subject: [PATCH 2/5] status card and status update on tab change --- src/ext/bg.ts | 119 ++++++++++--------------------- src/recorder.ts | 6 ++ src/sidepanel.ts | 162 +++++++++++++++++++++++++++++++++--------- src/utils.ts | 27 +++++++ static/sidepanel.html | 5 +- 5 files changed, 203 insertions(+), 116 deletions(-) diff --git a/src/ext/bg.ts b/src/ext/bg.ts index 172af1a..deb510f 100644 --- a/src/ext/bg.ts +++ b/src/ext/bg.ts @@ -26,6 +26,9 @@ const collLoader = new CollectionLoader(); const disabledCSPTabs = new Set(); +// @ts-expect-error - TS7034 - Variable 'sidepanelPort' implicitly has type 'any' in some locations where its type cannot be determined. +let sidepanelPort = null; + // =========================================================================== function main() { @@ -54,72 +57,13 @@ chrome.sidePanel // @ts-expect-error - TS7006 - Parameter 'port' implicitly has an 'any' type. chrome.runtime.onConnect.addListener((port) => { switch (port.name) { - case "popup-port": - popupHandler(port); - break; case "sidepanel-port": sidepanelHandler(port); break; } }); -// @ts-expect-error - TS7006 - Parameter 'port' implicitly has an 'any' type. -function popupHandler(port) { - if (!port.sender || port.sender.url !== chrome.runtime.getURL("popup.html")) { - return; - } - - // @ts-expect-error - TS7034 - Variable 'tabId' implicitly has type 'any' in some locations where its type cannot be determined. - let tabId = null; - - // @ts-expect-error - TS7006 - Parameter 'message' implicitly has an 'any' type. - port.onMessage.addListener(async (message) => { - switch (message.type) { - case "startUpdates": - tabId = message.tabId; - if (self.recorders[tabId]) { - // @ts-expect-error - TS2339 - Property 'port' does not exist on type 'BrowserRecorder'. - self.recorders[tabId].port = port; - self.recorders[tabId].doUpdateStatus(); - } - port.postMessage(await listAllMsg(collLoader)); - break; - - case "startRecording": { - const { collId, autorun } = message; - // @ts-expect-error - TS2554 - Expected 2 arguments, but got 3. - startRecorder(tabId, { collId, port, autorun }, message.url); - break; - } - - case "stopRecording": - // @ts-expect-error - TS7005 - Variable 'tabId' implicitly has an 'any' type. - stopRecorder(tabId); - break; - - case "toggleBehaviors": - // @ts-expect-error - TS7005 - Variable 'tabId' implicitly has an 'any' type. - toggleBehaviors(tabId); - break; - - case "newColl": { - const { name } = await collLoader.initNewColl({ title: message.title }); - defaultCollId = name; - port.postMessage(await listAllMsg(collLoader, { defaultCollId })); - await setLocalOption("defaultCollId", defaultCollId); - break; - } - } - }); - port.onDisconnect.addListener(() => { - // @ts-expect-error - TS2538 - Type 'null' cannot be used as an index type. - if (self.recorders[tabId]) { - // @ts-expect-error - TS2538 - Type 'null' cannot be used as an index type. - self.recorders[tabId].port = null; - } - }); -} // @ts-expect-error - TS7006 - Parameter 'port' implicitly has an 'any' type. function sidepanelHandler(port) { if (!port.sender || port.sender.url !== chrome.runtime.getURL("sidepanel.html")) { @@ -134,6 +78,7 @@ function sidepanelHandler(port) { switch (message.type) { case "startUpdates": tabId = message.tabId; + sidepanelPort = port; if (self.recorders[tabId]) { // @ts-expect-error - TS2339 - Property 'port' does not exist on type 'BrowserRecorder'. self.recorders[tabId].port = port; @@ -226,8 +171,32 @@ function sidepanelHandler(port) { self.recorders[tabId].port = null; } }); + + } +// =========================================================================== +chrome.runtime.onMessage.addListener( + // @ts-expect-error - TS7006 - Parameter 'message' implicitly has an 'any' type. + (message /*sender, sendResponse*/) => { + console.log("onMessage", message); + switch (message.msg) { + case "startNew": + (async () => { + newRecUrl = message.url; + newRecCollId = message.collId; + autorun = message.autorun; + defaultCollId = await getLocalOption("defaultCollId"); + chrome.tabs.create({ url: "about:blank" }); + })(); + break; + case "disableCSP": + disableCSPForTab(message.tabId); + break; + } + return true; + }, +); // =========================================================================== // @ts-expect-error - TS7006 - Parameter 'tab' implicitly has an 'any' type. | TS7006 - Parameter 'reason' implicitly has an 'any' type. chrome.debugger.onDetach.addListener((tab, reason) => { @@ -239,16 +208,20 @@ chrome.debugger.onDetach.addListener((tab, reason) => { // @ts-expect-error - TS7006 - Parameter 'tab' implicitly has an 'any' type. chrome.tabs.onActivated.addListener(async ({ tabId }) => { + + // @ts-expect-error - TS7034 - Variable 'err' implicitly has type 'any' in some locations where its type cannot be determined. + if (sidepanelPort) { + sidepanelPort.postMessage({ type: "update" }); + } if (!isRecordingEnabled) return; // @ts-expect-error - chrome doesn't have type definitions const tab = await new Promise((resolve) => chrome.tabs.get(tabId, resolve)); if (!isValidUrl(tab.url)) return; - if (!self.recorders[tabId]) { // @ts-expect-error - TS2554 - Expected 2 arguments, but got 3. - startRecorder(tabId, { collId: defaultCollId, port: null, autorun }, tab.url); + await startRecorder(tabId, { collId: defaultCollId, port: null, autorun }, tab.url); } }); @@ -384,9 +357,13 @@ async function startRecorder(tabId, opts) { } let err = null; - + // @ts-expect-error - TS7034 - Variable 'err' implicitly has type 'any' in some locations where its type cannot be determined. + if (sidepanelPort) { + sidepanelPort.postMessage({ type: "update" }); + } const { waitForTabUpdate } = opts; + // @ts-expect-error - TS2339 - Property 'running' does not exist on type 'BrowserRecorder'. if (!waitForTabUpdate && !self.recorders[tabId].running) { try { @@ -435,25 +412,7 @@ function isValidUrl(url) { return url && (url === "about:blank" || url.startsWith("https:") || url.startsWith("http:")); } -// =========================================================================== -chrome.runtime.onMessage.addListener( - // @ts-expect-error - TS7006 - Parameter 'message' implicitly has an 'any' type. - async (message /*sender, sendResponse*/) => { - switch (message.msg) { - case "startNew": - newRecUrl = message.url; - newRecCollId = message.collId; - autorun = message.autorun; - defaultCollId = await getLocalOption("defaultCollId"); - chrome.tabs.create({ url: "about:blank" }); - break; - case "disableCSP": - disableCSPForTab(message.tabId); - break; - } - }, -); // =========================================================================== // @ts-expect-error - TS7006 - Parameter 'tabId' implicitly has an 'any' type. diff --git a/src/recorder.ts b/src/recorder.ts index f807b8d..d0cfd5b 100644 --- a/src/recorder.ts +++ b/src/recorder.ts @@ -424,6 +424,10 @@ class Recorder { // @ts-expect-error - TS2339 - Property 'numPending' does not exist on type 'Recorder'. numPending: this.numPending, // @ts-expect-error - TS2339 - Property 'pageInfo' does not exist on type 'Recorder'. + favIconUrl: this.pageInfo.favIconUrl, + // @ts-expect-error - TS2339 - Property 'pageInfo' does not exist on type 'Recorder'. + pageTitle: this.pageInfo.title, + // @ts-expect-error - TS2339 - Property 'pageInfo' does not exist on type 'Recorder'. pageUrl: this.pageInfo.url, // @ts-expect-error - TS2339 - Property 'pageInfo' does not exist on type 'Recorder'. pageTs: this.pageInfo.ts, @@ -433,6 +437,8 @@ class Recorder { collId: this.collId, // @ts-expect-error - TS2339 - Property 'stopping' does not exist on type 'Recorder'. stopping: this.stopping, + // @ts-expect-error - TS2339 - Property 'tabId' does not exist on type 'Recorder'. + tabId: this.tabId, type: "status", }; } diff --git a/src/sidepanel.ts b/src/sidepanel.ts index fde00cb..e37e1fd 100644 --- a/src/sidepanel.ts +++ b/src/sidepanel.ts @@ -25,6 +25,7 @@ import { import "@material/web/button/filled-button.js"; import "@material/web/button/outlined-button.js"; import "@material/web/divider/divider.js"; +import { mapIntegerToRange, truncateString } from "./utils"; document.adoptedStyleSheets.push(typescaleStyles.styleSheet!); @@ -85,6 +86,42 @@ class ArgoViewer extends LitElement { background: transparent !important; padding: 0.75rem 1rem; } + .status-current-page { + display: flex; + flex-direction: column; + align-items: start; + justify-content: space-between; + } + + .status-title { + font-size: 12px; + font-weight: 500; + color: #6b6b6b; + margin-bottom: 4px; + } + + .status-ready { + font-size: 11px; + font-weight: 500; + color: #6b6b6b; + margin-bottom: 4px; + } + + .status-page-title { + font-size: 14px; + font-weight: 500; + color: #000; + margin-bottom: 8px; + } + + img.favicon { + width: 20px !important; + height: 20px !important; + flex: 0 0 auto; + object-fit: cover; + border-radius: 4px; + filter: drop-shadow(0 0 1px rgba(0, 0, 0, 0.6)); + } ` ]; @@ -108,6 +145,10 @@ class ArgoViewer extends LitElement { // @ts-expect-error - TS2339 - Property 'port' does not exist on type 'ArgoViewer'. this.port = null; + // @ts-expect-error - TS2339 - Property 'favIconUrl' does not exist on type 'ArgoViewer'. + this.favIconUrl = ""; + // @ts-expect-error - TS2339 - Property 'pageTitle' does not exist on type 'ArgoViewer'. + this.pageTitle = ""; // @ts-expect-error - TS2339 - Property 'pageUrl' does not exist on type 'ArgoViewer'. this.pageUrl = ""; // @ts-expect-error - TS2339 - Property 'pageTs' does not exist on type 'ArgoViewer'. @@ -150,6 +191,7 @@ class ArgoViewer extends LitElement { waitingForStart: { type: Boolean }, replayUrl: { type: String }, + pageTitle: { type: String }, pageUrl: { type: String }, pageTs: { type: Number }, @@ -183,9 +225,7 @@ class ArgoViewer extends LitElement { this.registerMessages(); } - registerMessages() { - // @ts-expect-error - TS2339 - Property 'port' does not exist on type 'ArgoViewer'. - this.port = chrome.runtime.connect({ name: "sidepanel-port" }); + updateTabInfo() { // @ts-expect-error - TS7006 - Parameter 'tabs' implicitly has an 'any' type. chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => { if (tabs.length) { @@ -198,13 +238,17 @@ class ArgoViewer extends LitElement { // @ts-expect-error - TS2339 - Property 'recording' does not exist on type 'ArgoViewer'. this.recording = result.indexOf("Recording:") >= 0; }); - // @ts-expect-error - TS2339 - Property 'tabId' does not exist on type 'ArgoViewer'. this.sendMessage({ tabId: this.tabId, type: "startUpdates" }); } }); + } + + registerMessages() { + // @ts-expect-error - TS2339 - Property 'port' does not exist on type 'ArgoViewer'. + this.port = chrome.runtime.connect({ name: "sidepanel-port" }); - // this.sendMessage({ type: "getPages" }); + this.updateTabInfo(); // @ts-expect-error - TS2339 - Property 'port' does not exist on type 'ArgoViewer'. this.port.onMessage.addListener((message) => { @@ -220,7 +264,14 @@ class ArgoViewer extends LitElement { // @ts-expect-error - TS7006 - Parameter 'message' implicitly has an 'any' type. async onMessage(message) { switch (message.type) { + case "update": + this.updateTabInfo(); + break; case "status": + // @ts-expect-error - TS2339 - Property 'tabId' does not exist on type 'ArgoViewer'. + if (this.tabId !== message.tabId) { + return; + } // @ts-expect-error - TS2339 - Property 'recording' does not exist on type 'ArgoViewer'. this.recording = message.recording; // @ts-expect-error - TS2339 - Property 'waitingForStart' does not exist on type 'ArgoViewer'. @@ -243,6 +294,15 @@ class ArgoViewer extends LitElement { this.behaviorResults = message.behaviorData?.state; // @ts-expect-error - TS2339 - Property 'autorun' does not exist on type 'ArgoViewer'. this.autorun = message.autorun; + + if (message.favIconUrl) { + // @ts-expect-error - TS2339 - Property 'favIconUrl' does not exist on type 'ArgoViewer'. + this.favIconUrl = message.favIconUrl; + } + if (message.pageTitle) { + // @ts-expect-error - TS2339 - Property 'pageTitle' does not exist on type 'ArgoViewer'. + this.pageTitle = message.pageTitle; + } if (message.pageUrl) { // @ts-expect-error - TS2339 - Property 'pageUrl' does not exist on type 'ArgoViewer'. this.pageUrl = message.pageUrl; @@ -406,37 +466,59 @@ class ArgoViewer extends LitElement { // @ts-expect-error - TS2339 - Property 'recording' does not exist on type 'ArgoViewer'. if (this.recording) { - return html`${ - // @ts-expect-error - TS2339 - Property 'waitingForStop' does not exist on type 'ArgoViewer'. - this.waitingForStop ? "Finishing " : "" - } - Archiving: ${ + return html`
+ Current page + ${ + // @ts-expect-error - TS2339 - Property 'favIconUrl' does not exist on type 'ArgoViewer'. + this.favIconUrl || + // @ts-expect-error - TS2339 - Property 'pageUrl' does not exist on type 'ArgoViewer'. + this.pageTitle ? html` +
+ Favicon + ${ + //@ts-expect-error - TS2339 - Property 'pageTitle' does not exist on type 'ArgoViewer'. + truncateString(this.pageTitle) + } +
+ ` : "" + } + Status + ${ + // @ts-expect-error - TS2339 - Property 'status' does not exist on type 'ArgoViewer'. + this.status?.numPending ? html` + + ` : "" + } + ${ // @ts-expect-error - TS2339 - Property 'status' does not exist on type 'ArgoViewer'. | TS2339 - Property 'status' does not exist on type 'ArgoViewer'. - this.status?.numPending - ? html` - ${ - // @ts-expect-error - TS2339 - Property 'status' does not exist on type 'ArgoViewer'. - this.status.numPending - } - URLs - pending${ - // @ts-expect-error - TS2339 - Property 'waitingForStop' does not exist on type 'ArgoViewer'. - this.waitingForStop - ? "." - : ", please wait before loading a new page." - } - ` - : html` Idle, Continue Browsing` - }`; + !this.status?.numPending + ? html`All resources archived` : "" + }
`; } // @ts-expect-error - TS2339 - Property 'failureMsg' does not exist on type 'ArgoViewer'. if (this.failureMsg) { return html` + Status

Sorry, there was an error starting archiving on this page. Please @@ -469,6 +551,7 @@ class ArgoViewer extends LitElement { // @ts-expect-error - TS2339 - Property 'pageUrl' does not exist on type 'ArgoViewer'. | TS2339 - Property 'pageUrl' does not exist on type 'ArgoViewer'. if (this.pageUrl?.startsWith(this.extRoot)) { return html` + Status

This page is part of the extension. You can view existing archived items from here. To start a new archiving session, click the @@ -478,15 +561,24 @@ class ArgoViewer extends LitElement { `; } - return html`Can't archive this page.`; + return html` + Status +
+

Can't archive this page.

`; } // @ts-expect-error - TS2339 - Property 'waitingForStart' does not exist on type 'ArgoViewer'. if (this.waitingForStart) { - return html`Archiving will start after the page reloads...`; + return html` + Status +
+

Archiving will start after the page reloads...

`; } - return html`${this.notRecordingMessage}`; + return html` + Status +
+

${this.notRecordingMessage}

`; } renderSearch() { @@ -511,7 +603,7 @@ class ArgoViewer extends LitElement { My Shared Archives -
+
@@ -527,7 +619,7 @@ class ArgoViewer extends LitElement { ${this.renderSearch()} ${this.renderStatusCard()} ${this.renderTabs()} -
+
${ diff --git a/src/utils.ts b/src/utils.ts index 74a8710..0f6500d 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -62,3 +62,30 @@ export async function listAllMsg(collLoader, { defaultCollId = null } = {}) { return msg; } + + +export function mapIntegerToRange(integer: number) { + // Calculate distance from 0 (use absolute value for negative numbers) + const distance = Math.abs(integer); + + // Use our calculated decay constant for appropriate distribution + const decayConstant = 0.014505; + + // Calculate result using exponential decay + const result = 0.1 + 0.9 * Math.exp(-decayConstant * distance); + + // Ensure the result is between 0.1 and 1 + return Math.max(0.1, Math.min(1, result)); +} + +export function truncateString(str: string) { + const maxLength = 100; + // If string is shorter than or equal to maxLength, return it as is + if (str.length <= maxLength) { + return str; + } + + // Otherwise, truncate to maxLength - 3 characters and add "..." + // This ensures the total length (including "...") doesn't exceed maxLength + return str.substring(0, maxLength - 3) + "..."; +} \ No newline at end of file diff --git a/static/sidepanel.html b/static/sidepanel.html index 8cfed38..a8e35bd 100644 --- a/static/sidepanel.html +++ b/static/sidepanel.html @@ -20,6 +20,7 @@ --md-sys-color-surface-container: white; --md-elevated-card-container-color: white; + --md-linear-progress-track-height: 8px; } @@ -28,9 +29,11 @@ From abac8742620a0eb896ece07688dc2400da714651 Mon Sep 17 00:00:00 2001 From: Juan Date: Wed, 14 May 2025 12:15:18 -0500 Subject: [PATCH 3/5] ts comment fix --- src/ext/bg.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ext/bg.ts b/src/ext/bg.ts index deb510f..658f01e 100644 --- a/src/ext/bg.ts +++ b/src/ext/bg.ts @@ -357,7 +357,7 @@ async function startRecorder(tabId, opts) { } let err = null; - // @ts-expect-error - TS7034 - Variable 'err' implicitly has type 'any' in some locations where its type cannot be determined. + // @ts-expect-error - TS7034 - Variable 'sidepanelPort' implicitly has type 'any' in some locations where its type cannot be determined. if (sidepanelPort) { sidepanelPort.postMessage({ type: "update" }); } From 67116b0f4fe76a6badc1824f1cf1d8b97e6c5746 Mon Sep 17 00:00:00 2001 From: Juan Date: Wed, 14 May 2025 13:56:46 -0500 Subject: [PATCH 4/5] fix element selection --- src/sidepanel.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sidepanel.ts b/src/sidepanel.ts index 57275eb..bd95d44 100644 --- a/src/sidepanel.ts +++ b/src/sidepanel.ts @@ -352,7 +352,7 @@ class ArgoViewer extends LitElement { } firstUpdated() { - this.archiveList = document.getElementById( + this.archiveList = this.shadowRoot?.getElementById( "archive-list", ) as ArgoArchiveList; From e4932b1fae002b4eb25e26e16160e33754d507b3 Mon Sep 17 00:00:00 2001 From: Juan Date: Wed, 14 May 2025 15:52:38 -0500 Subject: [PATCH 5/5] prettier/format command --- src/argo-archive-list.ts | 1 - src/ext/bg.ts | 80 ++++++++++------ src/ext/browser-recorder.ts | 12 ++- src/recorder.ts | 59 +++++++----- src/sidepanel.ts | 177 +++++++++++++++++++----------------- src/sw/downloader.ts | 8 +- src/sw/ipfsutils.ts | 6 +- src/sw/recproxy.ts | 19 +++- src/utils.ts | 3 +- 9 files changed, 219 insertions(+), 146 deletions(-) diff --git a/src/argo-archive-list.ts b/src/argo-archive-list.ts index bc4a602..09737c5 100644 --- a/src/argo-archive-list.ts +++ b/src/argo-archive-list.ts @@ -59,7 +59,6 @@ export class ArgoArchiveList extends LitElement { height: 100%; } - img.favicon { width: 20px !important; height: 20px !important; diff --git a/src/ext/bg.ts b/src/ext/bg.ts index 658f01e..3e2ade9 100644 --- a/src/ext/bg.ts +++ b/src/ext/bg.ts @@ -4,7 +4,11 @@ import { CollectionLoader } from "@webrecorder/wabac/swlib"; import { listAllMsg } from "../utils"; -import { getLocalOption, removeLocalOption, setLocalOption } from "../localstorage"; +import { + getLocalOption, + removeLocalOption, + setLocalOption, +} from "../localstorage"; // =========================================================================== self.recorders = {}; @@ -63,10 +67,12 @@ chrome.runtime.onConnect.addListener((port) => { } }); - // @ts-expect-error - TS7006 - Parameter 'port' implicitly has an 'any' type. function sidepanelHandler(port) { - if (!port.sender || port.sender.url !== chrome.runtime.getURL("sidepanel.html")) { + if ( + !port.sender || + port.sender.url !== chrome.runtime.getURL("sidepanel.html") + ) { return; } @@ -110,22 +116,29 @@ function sidepanelHandler(port) { autorun = message.autorun; // @ts-expect-error - tabs doesn't have type definitions - chrome.tabs.query({ active: true, currentWindow: true }, async (tabs) => { - for (const tab of tabs) { - if (!isValidUrl(tab.url)) continue; - - // @ts-expect-error - TS2554 - Expected 2 arguments, but got 3. - await startRecorder(tab.id, { collId: defaultCollId, port: null, autorun }, tab.url); - } - - port.postMessage({ - type: "status", - recording: true, - autorun, - // @ts-expect-error - defaultCollId implicitly has an 'any' type. - collId: defaultCollId, - }); - }); + chrome.tabs.query( + { active: true, currentWindow: true }, + async (tabs) => { + for (const tab of tabs) { + if (!isValidUrl(tab.url)) continue; + + // @ts-expect-error - TS2554 - Expected 2 arguments, but got 3. + await startRecorder( + tab.id, + { collId: defaultCollId, port: null, autorun }, + tab.url, + ); + } + + port.postMessage({ + type: "status", + recording: true, + autorun, + // @ts-expect-error - defaultCollId implicitly has an 'any' type. + collId: defaultCollId, + }); + }, + ); break; } @@ -171,8 +184,6 @@ function sidepanelHandler(port) { self.recorders[tabId].port = null; } }); - - } // =========================================================================== chrome.runtime.onMessage.addListener( @@ -208,7 +219,6 @@ chrome.debugger.onDetach.addListener((tab, reason) => { // @ts-expect-error - TS7006 - Parameter 'tab' implicitly has an 'any' type. chrome.tabs.onActivated.addListener(async ({ tabId }) => { - // @ts-expect-error - TS7034 - Variable 'err' implicitly has type 'any' in some locations where its type cannot be determined. if (sidepanelPort) { sidepanelPort.postMessage({ type: "update" }); @@ -216,12 +226,18 @@ chrome.tabs.onActivated.addListener(async ({ tabId }) => { if (!isRecordingEnabled) return; // @ts-expect-error - chrome doesn't have type definitions - const tab = await new Promise((resolve) => chrome.tabs.get(tabId, resolve)); + const tab = await new Promise((resolve) => + chrome.tabs.get(tabId, resolve), + ); if (!isValidUrl(tab.url)) return; if (!self.recorders[tabId]) { // @ts-expect-error - TS2554 - Expected 2 arguments, but got 3. - await startRecorder(tabId, { collId: defaultCollId, port: null, autorun }, tab.url); + await startRecorder( + tabId, + { collId: defaultCollId, port: null, autorun }, + tab.url, + ); } }); @@ -301,7 +317,11 @@ chrome.tabs.onUpdated.addListener((tabId, changeInfo) => { } } } else if (changeInfo.url) { - if (isRecordingEnabled && isValidUrl(changeInfo.url) && !self.recorders[tabId]) { + if ( + isRecordingEnabled && + isValidUrl(changeInfo.url) && + !self.recorders[tabId] + ) { // @ts-expect-error - TS2554 - Expected 2 arguments, but got 3. startRecorder(tabId, { collId: defaultCollId, autorun }, changeInfo.url); return; @@ -363,7 +383,6 @@ async function startRecorder(tabId, opts) { } const { waitForTabUpdate } = opts; - // @ts-expect-error - TS2339 - Property 'running' does not exist on type 'BrowserRecorder'. if (!waitForTabUpdate && !self.recorders[tabId].running) { try { @@ -409,11 +428,14 @@ function isRecording(tabId) { // =========================================================================== // @ts-expect-error - TS7006 - Parameter 'url' implicitly has an 'any' type. function isValidUrl(url) { - return url && (url === "about:blank" || url.startsWith("https:") || url.startsWith("http:")); + return ( + url && + (url === "about:blank" || + url.startsWith("https:") || + url.startsWith("http:")) + ); } - - // =========================================================================== // @ts-expect-error - TS7006 - Parameter 'tabId' implicitly has an 'any' type. async function disableCSPForTab(tabId) { diff --git a/src/ext/browser-recorder.ts b/src/ext/browser-recorder.ts index 45cad0a..abaab74 100644 --- a/src/ext/browser-recorder.ts +++ b/src/ext/browser-recorder.ts @@ -125,7 +125,9 @@ class BrowserRecorder extends Recorder { } if (numOtherRecorders > 0) { - console.log(`closing session, not detaching, ${numOtherRecorders} other recording tab(s) left`); + console.log( + `closing session, not detaching, ${numOtherRecorders} other recording tab(s) left`, + ); return this.sessionClose([]); } else { console.log("detaching debugger, already tabs stopped"); @@ -234,7 +236,9 @@ class BrowserRecorder extends Recorder { this.doUpdateStatus(); } catch (msg) { // @ts-expect-error - TS2339 - Property 'failureMsg' does not exist on type 'BrowserRecorder'. - this.failureMsg = chrome.runtime.lastError ? chrome.runtime.lastError.message : msg; + this.failureMsg = chrome.runtime.lastError + ? chrome.runtime.lastError.message + : msg; this.doUpdateStatus(); throw msg; } @@ -371,7 +375,9 @@ class BrowserRecorder extends Recorder { prr.resolve(res); } else { // @ts-expect-error - TS7005 - Variable 'prr' implicitly has an 'any' type. - prr.reject(chrome.runtime.lastError ? chrome.runtime.lastError.message : ""); + prr.reject( + chrome.runtime.lastError ? chrome.runtime.lastError.message : "", + ); } }; diff --git a/src/recorder.ts b/src/recorder.ts index d0cfd5b..f6c0fb0 100644 --- a/src/recorder.ts +++ b/src/recorder.ts @@ -160,7 +160,8 @@ class Recorder { this.archiveCookies = (await getLocalOption("archiveCookies")) === "1"; this.archiveStorage = (await getLocalOption("archiveStorage")) === "1"; this.archiveFlash = (await getLocalOption("archiveFlash")) === "1"; - this.archiveScreenshots = (await getLocalOption("archiveScreenshots")) === "1"; + this.archiveScreenshots = + (await getLocalOption("archiveScreenshots")) === "1"; this.archivePDF = (await getLocalOption("archivePDF")) === "1"; } @@ -943,13 +944,13 @@ class Recorder { // eslint-disable-next-line @typescript-eslint/no-explicit-any async savePDF(pageInfo: any) { // @ts-expect-error: ignore param - await this.send("Emulation.setEmulatedMedia", {type: "screen"}); + await this.send("Emulation.setEmulatedMedia", { type: "screen" }); // @ts-expect-error: ignore param - const resp = await this.send("Page.printToPDF", {printBackground: true}); + const resp = await this.send("Page.printToPDF", { printBackground: true }); // @ts-expect-error: ignore param - await this.send("Emulation.setEmulatedMedia", {type: ""}); + await this.send("Emulation.setEmulatedMedia", { type: "" }); const payload = Buffer.from(resp.data, "base64"); const mime = "application/pdf"; @@ -961,10 +962,13 @@ class Recorder { statusText: "OK", pageId: pageInfo.id, mime, - respHeaders: {"Content-Type": mime, "Content-Length": payload.length + ""}, + respHeaders: { + "Content-Type": mime, + "Content-Length": payload.length + "", + }, reqHeaders: {}, payload, - extraOpts: {resource: true}, + extraOpts: { resource: true }, }; console.log("pdf", payload.length); @@ -975,21 +979,25 @@ class Recorder { // eslint-disable-next-line @typescript-eslint/no-explicit-any async saveScreenshot(pageInfo: any) { - // View Screenshot const width = 1920; const height = 1080; // @ts-expect-error: ignore param - await this.send("Emulation.setDeviceMetricsOverride", {width, height, deviceScaleFactor: 0, mobile: false}); + await this.send("Emulation.setDeviceMetricsOverride", { + width, + height, + deviceScaleFactor: 0, + mobile: false, + }); // @ts-expect-error: ignore param - const resp = await this.send("Page.captureScreenshot", {format: "png"}); + const resp = await this.send("Page.captureScreenshot", { format: "png" }); const payload = Buffer.from(resp.data, "base64"); - const blob = new Blob([payload], {type: "image/png"}); + const blob = new Blob([payload], { type: "image/png" }); await this.send("Emulation.clearDeviceMetricsOverride"); - + const mime = "image/png"; const fullData = { @@ -999,35 +1007,44 @@ class Recorder { statusText: "OK", pageId: pageInfo.id, mime, - respHeaders: {"Content-Type": mime, "Content-Length": payload.length + ""}, + respHeaders: { + "Content-Type": mime, + "Content-Length": payload.length + "", + }, reqHeaders: {}, payload, - extraOpts: {resource: true}, + extraOpts: { resource: true }, }; const thumbWidth = 640; const thumbHeight = 360; - const bitmap = await self.createImageBitmap(blob, {resizeWidth: thumbWidth, resizeHeight: thumbHeight}); - + const bitmap = await self.createImageBitmap(blob, { + resizeWidth: thumbWidth, + resizeHeight: thumbHeight, + }); + const canvas = new OffscreenCanvas(thumbWidth, thumbWidth); const context = canvas.getContext("bitmaprenderer")!; context.transferFromImageBitmap(bitmap); - const resizedBlob = await canvas.convertToBlob({type: "image/png"}); + const resizedBlob = await canvas.convertToBlob({ type: "image/png" }); const thumbPayload = new Uint8Array(await resizedBlob.arrayBuffer()); - const thumbData = {...fullData, + const thumbData = { + ...fullData, url: "urn:thumbnail:" + pageInfo.url, - respHeaders: {"Content-Type": mime, "Content-Length": thumbPayload.length + ""}, - payload: thumbPayload + respHeaders: { + "Content-Type": mime, + "Content-Length": thumbPayload.length + "", + }, + payload: thumbPayload, }; - + // @ts-expect-error - TS2339 - Property '_doAddResource' does not exist on type 'Recorder'. await this._doAddResource(fullData); - // @ts-expect-error - TS2339 - Property '_doAddResource' does not exist on type 'Recorder'. await this._doAddResource(thumbData); } diff --git a/src/sidepanel.ts b/src/sidepanel.ts index bd95d44..f07e787 100644 --- a/src/sidepanel.ts +++ b/src/sidepanel.ts @@ -1,6 +1,6 @@ import "@material/web/all.js"; import { styles as typescaleStyles } from "@material/web/typography/md-typescale-styles.js"; -import { LitElement, html, css, CSSResultGroup } from "lit"; +import { LitElement, html, css, CSSResultGroup } from "lit"; import { unsafeSVG } from "lit/directives/unsafe-svg.js"; import "./argo-archive-list"; import "@material/web/textfield/outlined-text-field.js"; @@ -8,7 +8,6 @@ import "@material/web/icon/icon.js"; import { ArgoArchiveList } from "./argo-archive-list"; import { Downloader } from "./sw/downloader"; - import wrRec from "./assets/icons/recLogo.svg"; import { @@ -35,17 +34,15 @@ document.adoptedStyleSheets.push(typescaleStyles.styleSheet!); const collLoader = new CollectionLoader(); class ArgoViewer extends LitElement { - static styles: CSSResultGroup = [ typescaleStyles as unknown as CSSResultGroup, css` - md-tabs { - background-color: white; + background-color: white; } .search-container { - margin: 16px 12px; + margin: 16px 12px; height: 32px; background: #ece7f8; border-radius: 9999px; @@ -58,10 +55,9 @@ class ArgoViewer extends LitElement { width: 100%; --md-filled-text-field-container-color: transparent; --md-ref-shape-corner-radius: 9999px; - overflow: hidden; + overflow: hidden; } - .search-field::part(container), .search-field::part(hover-overlay), .search-field::part(focus-overlay) { @@ -75,8 +71,9 @@ class ArgoViewer extends LitElement { .search-field md-icon, .search-field input::placeholder { color: #6b6b6b; - }, + } + , md-elevated-card { display: block; margin: 1rem 0; @@ -127,7 +124,7 @@ class ArgoViewer extends LitElement { border-radius: 4px; filter: drop-shadow(0 0 1px rgba(0, 0, 0, 0.6)); } - ` + `, ]; private archiveList!: ArgoArchiveList; @@ -209,8 +206,8 @@ class ArgoViewer extends LitElement { behaviorMsg: { type: String }, autorun: { type: Boolean }, }; - } - + } + // @ts-expect-error - TS7006 - Parameter 'match' implicitly has an 'any' type. findTitleFor(match) { if (!match) { @@ -581,14 +578,11 @@ class ArgoViewer extends LitElement { return html`
-
- ${this.renderStatus()} -
+
${this.renderStatus()}
`; } - renderStatus() { // @ts-expect-error - TS2339 - Property 'behaviorState' does not exist on type 'ArgoViewer'. @@ -610,47 +604,59 @@ class ArgoViewer extends LitElement { // @ts-expect-error - TS2339 - Property 'favIconUrl' does not exist on type 'ArgoViewer'. this.favIconUrl || // @ts-expect-error - TS2339 - Property 'pageUrl' does not exist on type 'ArgoViewer'. - this.pageTitle ? html` -
- Favicon - ${ - //@ts-expect-error - TS2339 - Property 'pageTitle' does not exist on type 'ArgoViewer'. - truncateString(this.pageTitle) - } -
- ` : "" + this.pageTitle + ? html` +
+ Favicon + ${ + //@ts-expect-error - TS2339 - Property 'pageTitle' does not exist on type 'ArgoViewer'. + truncateString(this.pageTitle) + } +
+ ` + : "" } Status ${ // @ts-expect-error - TS2339 - Property 'status' does not exist on type 'ArgoViewer'. - this.status?.numPending ? html` - - ` : "" + value=${mapIntegerToRange( + // @ts-expect-error - TS2339 - Property 'status' does not exist on type 'ArgoViewer'. + this.status?.numPending || 0, + )} + style="--md-sys-color-primary: #7b1fa2; width: 100%; margin-bottom: 0.5rem;" + > + ` + : "" } ${ // @ts-expect-error - TS2339 - Property 'status' does not exist on type 'ArgoViewer'. | TS2339 - Property 'status' does not exist on type 'ArgoViewer'. !this.status?.numPending - ? html`All resources archived` : "" - }
`; + ? html`All resources archived` + : "" + } +
`; } // @ts-expect-error - TS2339 - Property 'failureMsg' does not exist on type 'ArgoViewer'. @@ -699,24 +705,21 @@ class ArgoViewer extends LitElement { `; } - return html` - Status -
+ return html` Status +

Can't archive this page.

`; } // @ts-expect-error - TS2339 - Property 'waitingForStart' does not exist on type 'ArgoViewer'. if (this.waitingForStart) { - return html` - Status -
+ return html` Status +

Archiving will start after the page reloads...

`; } - return html` - Status -
-

${this.notRecordingMessage}

`; + return html` Status +
+

${this.notRecordingMessage}

`; } renderSearch() { @@ -737,11 +740,18 @@ class ArgoViewer extends LitElement { renderTabs() { return html` - My Archives - My Shared Archives + My Archives + My Shared Archives -
+
@@ -754,39 +764,40 @@ class ArgoViewer extends LitElement { render() { return html` - ${this.renderSearch()} - ${this.renderStatusCard()} - ${this.renderTabs()} + ${this.renderSearch()} ${this.renderStatusCard()} ${this.renderTabs()}
-
+
${ // @ts-expect-error - TS2339 - Property 'recording' does not exist on type 'ArgoViewer'. !this.recording ? html` - - public - Resume Archiving - - - download - - - - share - + !this.canRecord} + @click=${this.onStart} + > + public + Resume Archiving + + + download + + + + share + ` : html` ${ showEmbed ? ` - ` + ` : ` ` } diff --git a/src/sw/recproxy.ts b/src/sw/recproxy.ts index 3e86acb..415fd69 100644 --- a/src/sw/recproxy.ts +++ b/src/sw/recproxy.ts @@ -97,7 +97,11 @@ export class RecProxy extends ArchiveDB { return await (this.db! as any).get("rec", "numPending"); } - override async getResource(request: ArchiveRequest, prefix: string, event: FetchEvent) { + override async getResource( + request: ArchiveRequest, + prefix: string, + event: FetchEvent, + ) { if (!this.isRecording) { return await super.getResource(request, prefix, event); } @@ -224,7 +228,13 @@ export class RecProxy extends ArchiveDB { } } - isPage(url: string, request: Request, status: number, referrer: string, mod: string) { + isPage( + url: string, + request: Request, + status: number, + referrer: string, + mod: string, + ) { if (!this.isNew) { return false; } @@ -259,7 +269,9 @@ export class RecProxy extends ArchiveDB { if (!pageId) { return; } - const page = await this.db!.get("pages", pageId) as ExtPageEntry | undefined; + const page = (await this.db!.get("pages", pageId)) as + | ExtPageEntry + | undefined; if (!page) { return; } @@ -311,7 +323,6 @@ export class RecordingCollections extends SWCollections { } break; - default: return await super._handleMessage(event); } diff --git a/src/utils.ts b/src/utils.ts index 0f6500d..050b80d 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -63,7 +63,6 @@ export async function listAllMsg(collLoader, { defaultCollId = null } = {}) { return msg; } - export function mapIntegerToRange(integer: number) { // Calculate distance from 0 (use absolute value for negative numbers) const distance = Math.abs(integer); @@ -88,4 +87,4 @@ export function truncateString(str: string) { // Otherwise, truncate to maxLength - 3 characters and add "..." // This ensures the total length (including "...") doesn't exceed maxLength return str.substring(0, maxLength - 3) + "..."; -} \ No newline at end of file +}