diff --git a/src/argo-archive-list.ts b/src/argo-archive-list.ts index 3dcb8db..09737c5 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,10 +59,6 @@ export class ArgoArchiveList extends LitElement { height: 100%; } - .card-container { - padding: 0 1rem; - } - img.favicon { width: 20px !important; height: 20px !important; diff --git a/src/ext/bg.ts b/src/ext/bg.ts index 172af1a..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 = {}; @@ -26,6 +30,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,75 +61,18 @@ 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")) { + if ( + !port.sender || + port.sender.url !== chrome.runtime.getURL("sidepanel.html") + ) { return; } @@ -134,6 +84,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; @@ -165,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; } @@ -227,7 +185,29 @@ function sidepanelHandler(port) { } }); } +// =========================================================================== +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 +219,25 @@ 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)); + 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, + ); } }); @@ -328,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; @@ -384,7 +377,10 @@ async function startRecorder(tabId, opts) { } let err = null; - + // @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" }); + } const { waitForTabUpdate } = opts; // @ts-expect-error - TS2339 - Property 'running' does not exist on type 'BrowserRecorder'. @@ -432,29 +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:")) + ); } -// =========================================================================== -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. 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 f807b8d..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"; } @@ -424,6 +425,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 +438,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", }; } @@ -937,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"; @@ -955,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); @@ -969,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 = { @@ -993,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 b926743..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 } 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,6 +8,8 @@ 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 { getLocalOption, // removeLocalOption, @@ -15,8 +17,8 @@ import { } from "./localstorage"; import { BEHAVIOR_WAIT_LOAD, + BEHAVIOR_RUNNING, // BEHAVIOR_READY_START, - // BEHAVIOR_RUNNING, // BEHAVIOR_PAUSED, // BEHAVIOR_DONE, } from "./consts"; @@ -24,6 +26,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"; import { CollectionLoader } from "@webrecorder/wabac/swlib"; import WebTorrent from "webtorrent"; @@ -31,54 +34,151 @@ 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; + } + + .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; + } + .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)); + } + `, + ]; + private archiveList!: ArgoArchiveList; 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 '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 '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; } @@ -94,6 +194,7 @@ class ArgoViewer extends LitElement { waitingForStart: { type: Boolean }, replayUrl: { type: String }, + pageTitle: { type: String }, pageUrl: { type: String }, pageTs: { type: Number }, @@ -107,6 +208,22 @@ class ArgoViewer extends LitElement { }; } + // @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 ""; + } + private async onDownload() { const selectedPages = this.archiveList?.getSelectedPages?.() || []; if (!selectedPages.length) { @@ -232,7 +349,7 @@ class ArgoViewer extends LitElement { } firstUpdated() { - this.archiveList = document.getElementById( + this.archiveList = this.shadowRoot?.getElementById( "archive-list", ) as ArgoArchiveList; @@ -240,30 +357,32 @@ class ArgoViewer extends LitElement { this.registerMessages(); } - registerMessages() { - // @ts-expect-error - TS2339 - Property 'port' does not exist on type 'RecPopup'. - 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) { - // @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" }); + registerMessages() { + // @ts-expect-error - TS2339 - Property 'port' does not exist on type 'ArgoViewer'. + this.port = chrome.runtime.connect({ name: "sidepanel-port" }); + + this.updateTabInfo(); - // @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); }); @@ -271,78 +390,94 @@ 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 "update": + this.updateTabInfo(); + break; case "status": - // @ts-expect-error - TS2339 - Property 'recording' does not exist on type 'RecPopup'. + // @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 '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.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 '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; @@ -350,16 +485,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") || @@ -367,16 +502,16 @@ 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(); } @@ -384,15 +519,15 @@ class ArgoViewer extends LitElement { 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:")); } } @@ -405,7 +540,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(); @@ -414,72 +549,272 @@ 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 '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`
+ 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 'recording' does not exist on type 'RecPopup'. - !this.recording + // @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`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 + 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` + Status +

+ 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` Status +
+

Can't archive this page.

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

Archiving will start after the page reloads...

`; + } + + return html` Status +
+

${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 - - - - download - - - - share - - ` - : html` - - pause - Pause Archiving - - ` - } + ?disabled=${this.actionButtonDisabled || + // @ts-expect-error - TS2339 - Property 'canRecord' does not exist on type 'ArgoViewer'. + !this.canRecord} + @click=${this.onStart} + > + public + Resume Archiving + + + download + + + + share + + ` + : html` + + pause + Pause Archiving + + ` + } - - settings - + + settings + +
`; } diff --git a/src/sw/downloader.ts b/src/sw/downloader.ts index d7e1ae3..6fbbb28 100644 --- a/src/sw/downloader.ts +++ b/src/sw/downloader.ts @@ -650,7 +650,9 @@ class Downloader { data.method = resource.method; } - return `${getSurt(resource.url)} ${resource.timestamp} ${JSON.stringify(data)}\n`; + return `${getSurt(resource.url)} ${resource.timestamp} ${JSON.stringify( + data, + )}\n`; } *generateCDX() { @@ -1057,7 +1059,9 @@ class Downloader { }; const urlParsed = new URL(url); - const statusline = `${method} ${url.slice(urlParsed.origin.length)} HTTP/1.1`; + const statusline = `${method} ${url.slice( + urlParsed.origin.length, + )} HTTP/1.1`; const reqRecord = WARCRecord.create( { diff --git a/src/sw/ipfsutils.ts b/src/sw/ipfsutils.ts index 3dc8f8f..908a3b9 100644 --- a/src/sw/ipfsutils.ts +++ b/src/sw/ipfsutils.ts @@ -511,7 +511,11 @@ function getReplayHtml(waczPath: string, replayOpts: ReplayOpts = {}) { ${ 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 74a8710..050b80d 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -62,3 +62,29 @@ 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) + "..."; +} diff --git a/static/sidepanel.html b/static/sidepanel.html index 8f32024..394f34b 100644 --- a/static/sidepanel.html +++ b/static/sidepanel.html @@ -19,43 +19,8 @@ --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; + + --md-linear-progress-track-height: 8px; } @@ -63,38 +28,13 @@ -
- - search - -
- - - - - My Archives - My Shared Archives - - -
-
- -
-
- -
-
- - \ No newline at end of file +