diff --git a/.gitignore b/.gitignore index 4fc3fa5..a429f1d 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ **/node_modules .DS_Store dist +.export-include \ No newline at end of file diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..a0d7b8f --- /dev/null +++ b/.prettierrc @@ -0,0 +1,7 @@ +{ + "useTabs": false, + "tabWidth": 2, + "semi": true, + "singleQuote": false, + "printWidth": 120 +} diff --git a/package.json b/package.json index f148364..f635b88 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "author": "Webrecorder Software", "license": "AGPL-3.0-or-later", "dependencies": { + "@material/web": "^2.3.0", "@fortawesome/fontawesome-free": "^5.13.0", "@ipld/car": "^5.3.2", "@ipld/unixfs": "^3.0.0", diff --git a/src/argo-archive-list.ts b/src/argo-archive-list.ts new file mode 100644 index 0000000..c36101e --- /dev/null +++ b/src/argo-archive-list.ts @@ -0,0 +1,223 @@ +import { LitElement, html, css, CSSResultGroup } from "lit"; +import { customElement, state } from "lit/decorators.js"; +import { styles as typescaleStyles } from "@material/web/typography/md-typescale-styles.js"; + +import "@material/web/list/list.js"; +import "@material/web/list/list-item.js"; +import "@material/web/checkbox/checkbox.js"; +import "@material/web/icon/icon.js"; +import "@material/web/labs/card/elevated-card.js"; + +import { getLocalOption } from "./localstorage"; + +@customElement("argo-archive-list") +export class ArgoArchiveList extends LitElement { + static styles: CSSResultGroup = [ + typescaleStyles as unknown as CSSResultGroup, + css` + md-elevated-card { + display: block; + margin: 1rem 0; + padding: 0; + overflow: visible; + } + + md-elevated-card > details { + border-radius: inherit; + overflow: hidden; + margin: 0; + background: transparent; + } + + md-elevated-card > details summary { + background: transparent !important; + padding: 0.75rem 1rem; + } + + md-elevated-card > details md-list { + background: transparent; + padding: 0 0rem 0rem; + } + + md-list-item { + --md-list-item-top-space: 0px; + --md-list-item-bottom-space: 0px; + + --md-list-item-leading-space: 0px; + --md-list-item-trailing-space: 12px; + + --md-list-item-one-line-container-height: 0px; + } + + .leading-group { + display: flex; + gap: 0px; + align-items: center; + height: 100%; + } + + .card-container { + padding: 0 1rem; + } + + 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)); + } + + summary { + display: flex; + align-items: center; + gap: 0.5rem; + padding: 0.75rem 1rem; + cursor: pointer; + user-select: none; + } + summary::-webkit-details-marker { + display: none; + } + + summary md-icon.arrow-right, + summary md-icon.arrow-down { + display: none; + } + details:not([open]) summary md-icon.arrow-right { + display: block; + } + details[open] summary md-icon.arrow-down { + display: block; + } + + .title-url { + display: flex; + align-items: center; + gap: 0.5rem; + width: 100%; + overflow: hidden; + white-space: nowrap; + } + .title-text { + flex: 1; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + .base-url { + flex-shrink: 0; + text-decoration: none; + } + `, + ]; + + @state() private pages: Array<{ ts: string; url: string; title?: string; favIconUrl?: string }> = []; + @state() private collId = ""; + + async connectedCallback() { + super.connectedCallback(); + this.collId = (await getLocalOption("defaultCollId")) || ""; + const port = chrome.runtime.connect({ name: "sidepanel-port" }); + // @ts-expect-error - TS7006 - Parameter 'msg' implicitly has an 'any' type. + port.onMessage.addListener((msg) => { + if (msg.type === "pages") this.pages = msg.pages || []; + }); + port.postMessage({ type: "getPages" }); + } + + render() { + if (!this.pages.length) { + return html`

No archives yet.

`; + } + + const groups = this.pages.reduce( + (acc, page) => { + const key = this._formatDate(new Date(Number(page.ts))); + (acc[key] ||= []).push(page); + return acc; + }, + {} as Record, + ); + + return html` +
+ ${Object.entries(groups) + .sort(([a], [b]) => new Date(b).getTime() - new Date(a).getTime()) + .map( + ([dateLabel, pages]) => html` + +
+ + chevron_right + expand_more + ${dateLabel} + + + ${pages.map((page) => { + const u = new URL(page.url); + return html` + this._openPage(page)}> +
+ e.stopPropagation()} + > + + ${page.favIconUrl + ? html` + favicon of ${u.hostname} + ` + : html`article`} +
+
+ ${page.title || page.url} + ${u.hostname} +
+
+ `; + })} +
+
+
+ `, + )} +
+ `; + } + + private _formatDate(date: Date): string { + const today = new Date(); + const yesterday = new Date(today); + yesterday.setDate(today.getDate() - 1); + const opts: Intl.DateTimeFormatOptions = { weekday: "long", month: "long", day: "numeric", year: "numeric" }; + const label = date.toLocaleDateString("en-US", opts); + if (date.toDateString() === today.toDateString()) return `Today — ${label}`; + if (date.toDateString() === yesterday.toDateString()) return `Yesterday — ${label}`; + return label; + } + + private _openPage(page: { ts: string; url: string }) { + const tsParam = new Date(Number(page.ts)).toISOString().replace(/[-:TZ.]/g, ""); + const urlEnc = encodeURIComponent(page.url); + const fullUrl = + `${chrome.runtime.getURL("index.html")}?source=local://${this.collId}&url=${urlEnc}` + + `#view=pages&url=${urlEnc}&ts=${tsParam}`; + chrome.tabs.create({ url: fullUrl }); + } +} diff --git a/src/ext/bg.ts b/src/ext/bg.ts index 4dcaa98..ab258c5 100644 --- a/src/ext/bg.ts +++ b/src/ext/bg.ts @@ -4,11 +4,7 @@ import { CollectionLoader } from "@webrecorder/wabac/swlib"; import { listAllMsg } from "../utils"; -import { - getLocalOption, - removeLocalOption, - setLocalOption, -} from "../localstorage"; +import { getLocalOption, removeLocalOption, setLocalOption } from "../localstorage"; // =========================================================================== self.recorders = {}; @@ -45,6 +41,14 @@ function main() { contexts: ["all"], }); } +// Side panel +chrome.sidePanel + .setPanelBehavior({ + openPanelOnActionClick: true, + }) + .catch((err: Error) => { + console.error(err); + }); // @ts-expect-error - TS7006 - Parameter 'port' implicitly has an 'any' type. chrome.runtime.onConnect.addListener((port) => { @@ -52,6 +56,9 @@ chrome.runtime.onConnect.addListener((port) => { case "popup-port": popupHandler(port); break; + case "sidepanel-port": + sidepanelHandler(port); + break; } }); @@ -112,6 +119,80 @@ function popupHandler(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")) { + 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 "getPages": { + const defaultCollId = await getLocalOption("defaultCollId"); + if (!defaultCollId) { + port.postMessage({ type: "pages", pages: [] }); + return; + } + + const coll = await collLoader.loadColl(defaultCollId); + if (coll?.store?.getAllPages) { + const pages = await coll.store.getAllPages(); + port.postMessage({ type: "pages", pages }); + } else { + port.postMessage({ type: "pages", pages: [] }); + } + 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 'tab' implicitly has an 'any' type. | TS7006 - Parameter 'reason' implicitly has an 'any' type. @@ -296,12 +377,7 @@ 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:")); } // =========================================================================== diff --git a/src/ext/manifest.json b/src/ext/manifest.json index b51c154..35a34ff 100644 --- a/src/ext/manifest.json +++ b/src/ext/manifest.json @@ -9,7 +9,8 @@ "activeTab", "storage", "unlimitedStorage", - "webRequest" + "webRequest", + "sidePanel" ], "content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'", "background": { @@ -23,8 +24,10 @@ "default_icon": { "32": "$ICON" }, - "default_title": "Webrecorder ArchiveWeb.page", - "default_popup": "popup.html" + "default_title": "Webrecorder ArchiveWeb.page" + }, + "side_panel": { + "default_path": "sidepanel.html" }, "web_accessible_resources": [ { diff --git a/src/sidepanel.ts b/src/sidepanel.ts new file mode 100644 index 0000000..f2e3ca3 --- /dev/null +++ b/src/sidepanel.ts @@ -0,0 +1,386 @@ +import "@material/web/all.js"; +import { styles as typescaleStyles } from "@material/web/typography/md-typescale-styles.js"; +import { LitElement, html } 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 { + getLocalOption, + // removeLocalOption, + setLocalOption, +} from "./localstorage"; +import { + BEHAVIOR_WAIT_LOAD, + // BEHAVIOR_READY_START, + // BEHAVIOR_RUNNING, + // BEHAVIOR_PAUSED, + // BEHAVIOR_DONE, +} from "./consts"; + +import "@material/web/button/filled-button.js"; +import "@material/web/button/outlined-button.js"; +import "@material/web/divider/divider.js"; + +document.adoptedStyleSheets.push(typescaleStyles.styleSheet!); + +class ArgoViewer extends LitElement { + constructor() { + super(); + + // @ts-expect-error - TS2339 - Property 'collections' does not exist on type 'RecPopup'. + this.collections = []; + // @ts-expect-error - TS2339 - Property 'collTitle' does not exist on type 'RecPopup'. + this.collTitle = ""; + // @ts-expect-error - TS2339 - Property 'collId' does not exist on type 'RecPopup'. + this.collId = ""; + + // @ts-expect-error - TS2339 - Property 'tabId' does not exist on type 'RecPopup'. + this.tabId = 0; + // @ts-expect-error - TS2339 - Property 'recording' does not exist on type 'RecPopup'. + this.recording = false; + // @ts-expect-error - TS2339 - Property 'status' does not exist on type 'RecPopup'. + this.status = null; + + // @ts-expect-error - TS2339 - Property 'port' does not exist on type 'RecPopup'. + this.port = null; + + // @ts-expect-error - TS2339 - Property 'pageUrl' does not exist on type 'RecPopup'. + this.pageUrl = ""; + // @ts-expect-error - TS2339 - Property 'pageTs' does not exist on type 'RecPopup'. + this.pageTs = 0; + // @ts-expect-error - TS2339 - Property 'replayUrl' does not exist on type 'RecPopup'. + this.replayUrl = ""; + + // @ts-expect-error - TS2339 - Property 'canRecord' does not exist on type 'RecPopup'. + this.canRecord = false; + // @ts-expect-error - TS2339 - Property 'failureMsg' does not exist on type 'RecPopup'. + this.failureMsg = null; + + // @ts-expect-error - TS2339 - Property 'collDrop' does not exist on type 'RecPopup'. + this.collDrop = ""; + + // @ts-expect-error - TS2339 - Property 'allowCreate' does not exist on type 'RecPopup'. + this.allowCreate = true; + + // @ts-expect-error - TS2339 - Property 'waitingForStart' does not exist on type 'RecPopup'. + this.waitingForStart = false; + // @ts-expect-error - TS2339 - Property 'waitingForStop' does not exist on type 'RecPopup'. + this.waitingForStop = false; + // @ts-expect-error - TS2339 - Property 'behaviorState' does not exist on type 'RecPopup'. + this.behaviorState = BEHAVIOR_WAIT_LOAD; + // @ts-expect-error - TS2339 - Property 'behaviorMsg' does not exist on type 'RecPopup'. + this.behaviorMsg = ""; + // @ts-expect-error - TS2339 - Property 'autorun' does not exist on type 'RecPopup'. + this.autorun = false; + } + + static get properties() { + return { + collections: { type: Array }, + collId: { type: String }, + collTitle: { type: String }, + collDrop: { type: String }, + + recording: { type: Boolean }, + status: { type: Object }, + waitingForStart: { type: Boolean }, + + replayUrl: { type: String }, + pageUrl: { type: String }, + pageTs: { type: Number }, + + canRecord: { type: Boolean }, + failureMsg: { type: String }, + + behaviorState: { type: String }, + behaviorResults: { type: Object }, + behaviorMsg: { type: String }, + autorun: { type: Boolean }, + }; + } + + firstUpdated() { + this.registerMessages(); + } + + registerMessages() { + // @ts-expect-error - TS2339 - Property 'port' does not exist on type 'RecPopup'. + 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'. + this.tabId = tabs[0].id; + // @ts-expect-error - TS2339 - Property 'pageUrl' does not exist on type 'RecPopup'. + 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. + chrome.action.getTitle({ tabId: this.tabId }, (result) => { + // @ts-expect-error - TS2339 - Property 'recording' does not exist on type 'RecPopup'. + this.recording = result.indexOf("Recording:") >= 0; + }); + + // @ts-expect-error - TS2339 - Property 'tabId' does not exist on type 'RecPopup'. + this.sendMessage({ tabId: this.tabId, type: "startUpdates" }); + } + }); + + // this.sendMessage({ type: "getPages" }); + + // @ts-expect-error - TS2339 - Property 'port' does not exist on type 'RecPopup'. + this.port.onMessage.addListener((message) => { + this.onMessage(message); + }); + } + + // @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'. + 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'. + this.recording = message.recording; + // @ts-expect-error - TS2339 - Property 'waitingForStart' does not exist on type 'RecPopup'. + if (this.waitingForStart && message.firstPageStarted) { + // @ts-expect-error - TS2339 - Property 'waitingForStart' does not exist on type 'RecPopup'. + this.waitingForStart = false; + } + // @ts-expect-error - TS2339 - Property 'waitingForStop' does not exist on type 'RecPopup'. + if (this.waitingForStop && !message.recording && !message.stopping) { + // @ts-expect-error - TS2339 - Property 'waitingForStop' does not exist on type 'RecPopup'. + this.waitingForStop = false; + } + // @ts-expect-error - TS2339 - Property 'status' does not exist on type 'RecPopup'. + this.status = message; + // @ts-expect-error - TS2339 - Property 'behaviorState' does not exist on type 'RecPopup'. + this.behaviorState = message.behaviorState; + // @ts-expect-error - TS2339 - Property 'behaviorMsg' does not exist on type 'RecPopup'. + this.behaviorMsg = message.behaviorData?.msg || "Starting..."; + // @ts-expect-error - TS2339 - Property 'behaviorResults' does not exist on type 'RecPopup'. + this.behaviorResults = message.behaviorData?.state; + // @ts-expect-error - TS2339 - Property 'autorun' does not exist on type 'RecPopup'. + this.autorun = message.autorun; + if (message.pageUrl) { + // @ts-expect-error - TS2339 - Property 'pageUrl' does not exist on type 'RecPopup'. + this.pageUrl = message.pageUrl; + } + if (message.pageTs) { + // @ts-expect-error - TS2339 - Property 'pageTs' does not exist on type 'RecPopup'. + this.pageTs = message.pageTs; + } + // @ts-expect-error - TS2339 - Property 'failureMsg' does not exist on type 'RecPopup'. + this.failureMsg = message.failureMsg; + // @ts-expect-error - TS2339 - Property 'collId' does not exist on type 'RecPopup'. + if (this.collId !== message.collId) { + // @ts-expect-error - TS2339 - Property 'collId' does not exist on type 'RecPopup'. + 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'. + 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'. + await setLocalOption(`${this.tabId}-collId`, this.collId); + } + break; + case "collections": + // @ts-expect-error - TS2339 - Property 'collections' does not exist on type 'RecPopup'. + 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'. + this.collId = await getLocalOption(`${this.tabId}-collId`); + // @ts-expect-error - TS2339 - Property 'collTitle' does not exist on type 'RecPopup'. + this.collTitle = ""; + // @ts-expect-error - TS2339 - Property 'collId' does not exist on type 'RecPopup'. + if (this.collId) { + // @ts-expect-error - TS2339 - Property 'collTitle' does not exist on type 'RecPopup'. | TS2339 - Property 'collId' does not exist on type 'RecPopup'. + 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'. + if (!this.collTitle) { + // @ts-expect-error - TS2339 - Property 'collId' does not exist on type 'RecPopup'. + 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'. + this.collTitle = this.findTitleFor(this.collId); + } + // @ts-expect-error - TS2339 - Property 'collTitle' does not exist on type 'RecPopup'. + if (!this.collTitle) { + // @ts-expect-error - TS2339 - Property 'collTitle' does not exist on type 'RecPopup'. + this.collTitle = "[No Title]"; + } + break; + } + } + + 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'. + 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'. + this.pageUrl && + // @ts-expect-error - TS2339 - Property 'pageTs' does not exist on type 'RecPopup'. + this.pageTs && + (changedProperties.has("pageUrl") || + changedProperties.has("pageTs") || + changedProperties.has("recording") || + changedProperties.has("collId")) + ) { + const params = new URLSearchParams(); + // @ts-expect-error - TS2339 - Property 'pageUrl' does not exist on type 'RecPopup'. + params.set("url", this.pageUrl); + params.set( + "ts", + // @ts-expect-error - TS2339 - Property 'pageTs' does not exist on type 'RecPopup'. + new Date(this.pageTs).toISOString().replace(/[-:TZ.]/g, ""), + ); + params.set("view", "pages"); + + // @ts-expect-error - TS2339 - Property 'replayUrl' does not exist on type 'RecPopup'. + 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'. + this.canRecord = + // @ts-expect-error - TS2339 - Property 'pageUrl' does not exist on type 'RecPopup'. + this.pageUrl && + // @ts-expect-error - TS2339 - Property 'pageUrl' does not exist on type 'RecPopup'. + (this.pageUrl === "about:blank" || + // @ts-expect-error - TS2339 - Property 'pageUrl' does not exist on type 'RecPopup'. + this.pageUrl.startsWith("http:") || + // @ts-expect-error - TS2339 - Property 'pageUrl' does not exist on type 'RecPopup'. + this.pageUrl.startsWith("https:")); + } + } + getHomePage() { + return chrome.runtime.getURL("index.html"); + } + get extRoot() { + return chrome.runtime.getURL(""); + } + + getCollPage() { + const sourceParams = new URLSearchParams(); + // @ts-expect-error - TS2339 - Property 'collId' does not exist on type 'RecPopup'. + sourceParams.set("source", "local://" + this.collId); + + return this.getHomePage() + "?" + sourceParams.toString(); + } + + onStart() { + this.sendMessage({ + type: "startRecording", + // @ts-expect-error - TS2339 - Property 'collId' does not exist on type 'RecPopup'. + collId: this.collId, + // @ts-expect-error - TS2339 - Property 'pageUrl' does not exist on type 'RecPopup'. + url: this.pageUrl, + // @ts-expect-error - TS2339 - Property 'autorun' does not exist on type 'RecPopup'. + autorun: this.autorun, + }); + // @ts-expect-error - TS2339 - Property 'waitingForStart' does not exist on type 'RecPopup'. + this.waitingForStart = true; + // @ts-expect-error - TS2339 - Property 'waitingForStop' does not exist on type 'RecPopup'. + this.waitingForStop = false; + } + + onStop() { + this.sendMessage({ type: "stopRecording" }); + // @ts-expect-error - TS2339 - Property 'waitingForStart' does not exist on type 'RecPopup'. + this.waitingForStart = false; + // @ts-expect-error - TS2339 - Property 'waitingForStop' does not exist on type 'RecPopup'. + this.waitingForStop = true; + } + render() { + return html` + +
+ ${ + // @ts-expect-error - TS2339 - Property 'canRecord' does not exist on type 'RecPopup'. + this.canRecord + ? html` + ${ + // @ts-expect-error - TS2339 - Property 'recording' does not exist on type 'RecPopup'. + !this.recording + ? html` + + public + Resume Archiving + + ` + : html` + + pause + Pause Archiving + + ` + } + ` + : html`` + } + + + settings + +
+ `; + } +} + +class WrIcon extends LitElement { + constructor() { + super(); + // @ts-expect-error - TS2339 - Property 'size' does not exist on type 'WrIcon'. + this.size = "0.9em"; + } + + static get properties() { + return { + src: { type: Object }, + size: { type: String }, + }; + } + + render() { + return html` + + + ${ + // @ts-expect-error - TS2339 - Property 'src' does not exist on type 'WrIcon'. + unsafeSVG(this.src) + } + + + `; + } +} + +customElements.define("wr-icon", WrIcon); +customElements.define("argo-viewer", ArgoViewer); + +export { ArgoViewer }; diff --git a/static/sidepanel.html b/static/sidepanel.html new file mode 100644 index 0000000..ed57b29 --- /dev/null +++ b/static/sidepanel.html @@ -0,0 +1,99 @@ + + + + + My Sidepanel + + + + + + +
+ + search + +
+ + + + + My Archives + My Shared Archives + + +
+
+ +
+
+ +
+
+ + + + \ No newline at end of file diff --git a/webpack.config.js b/webpack.config.js index 9149f53..2951cad 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -227,6 +227,7 @@ const extensionWebConfig = (env, argv) => { const entry = { bg: "./src/ext/bg.ts", popup: "./src/popup.ts", + sidepanel: "./src/sidepanel.ts", }; return sharedBuild(DIST_EXT, { plugins, copy, entry }, argv); diff --git a/yarn.lock b/yarn.lock index 7d7d701..43101ca 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1330,7 +1330,7 @@ resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz#c08679063f279615a3326583ba3a90d1d82cc721" integrity sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA== -"@jridgewell/set-array@^1.0.1": +"@jridgewell/set-array@^1.0.1", "@jsonjoy.com/base64@^1.1.1": version "1.1.2" resolved "https://registry.yarnpkg.com/@jsonjoy.com/base64/-/base64-1.1.2.tgz#cf8ea9dcb849b81c95f14fc0aaa151c6b54d2578" integrity sha512-q6XAnWQDIMA3+FTiOYajoYqySkO+JSat0ytXGSuRdq9uXE7o92gzuQwQM14xaCRlBLGq3v5miDGC4vkVTn54xA== @@ -1382,11 +1382,6 @@ "@jridgewell/resolve-uri" "3.1.0" "@jridgewell/sourcemap-codec" "1.4.14" -"@jsonjoy.com/base64@^1.1.1": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@jsonjoy.com/base64/-/base64-1.1.2.tgz#cf8ea9dcb849b81c95f14fc0aaa151c6b54d2578" - integrity sha512-q6XAnWQDIMA3+FTiOYajoYqySkO+JSat0ytXGSuRdq9uXE7o92gzuQwQM14xaCRlBLGq3v5miDGC4vkVTn54xA== - "@jsonjoy.com/json-pack@^1.0.3": version "1.0.4" resolved "https://registry.yarnpkg.com/@jsonjoy.com/json-pack/-/json-pack-1.0.4.tgz#ab59c642a2e5368e8bcfd815d817143d4f3035d0" @@ -1424,6 +1419,13 @@ dependencies: "@lit-labs/ssr-dom-shim" "^1.2.0" +"@lit/reactive-element@^2.1.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@lit/reactive-element/-/reactive-element-2.1.0.tgz#177148214488068ae209669040b7ce0f4dcc0d36" + integrity sha512-L2qyoZSQClcBmq0qajBVbhYEcG6iK0XfLn66ifLe/RfC0/ihpc+pl0Wdn8bJ8o+hj38cG0fGXRgSS20MuXn7qA== + dependencies: + "@lit-labs/ssr-dom-shim" "^1.2.0" + "@malept/cross-spawn-promise@^1.1.0": version "1.1.1" resolved "https://registry.yarnpkg.com/@malept/cross-spawn-promise/-/cross-spawn-promise-1.1.1.tgz#504af200af6b98e198bce768bc1730c6936ae01d" @@ -1441,6 +1443,14 @@ lodash "^4.17.15" tmp-promise "^3.0.2" +"@material/web@^2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@material/web/-/web-2.3.0.tgz#d0dda48159d148b1a0982b10c2e8b48940da81fe" + integrity sha512-r7ccZHthMk5tM05goPJ965hQ99ptMyZt7i8Xi8+RmEqK3ZXaMtjx+s4p+9OVX+vgOS3zpop+g1yGYXtOOlrwUg== + dependencies: + lit "^2.8.0 || ^3.0.0" + tslib "^2.4.0" + "@multiformats/murmur3@^2.1.0", "@multiformats/murmur3@^2.1.3": version "2.1.8" resolved "https://registry.yarnpkg.com/@multiformats/murmur3/-/murmur3-2.1.8.tgz#81c1c15b6391109f3febfca4b3205196615a04e9" @@ -5544,6 +5554,15 @@ lit-element@^4.0.0, lit-element@^4.0.4: "@lit/reactive-element" "^2.0.4" lit-html "^3.1.2" +lit-element@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/lit-element/-/lit-element-4.2.0.tgz#75dcf9e5fae3e3b5fd3f02a5d297c582d0bb0ba3" + integrity sha512-MGrXJVAI5x+Bfth/pU9Kst1iWID6GHDLEzFEnyULB/sFiRLgkd8NPK/PeeXxktA3T6EIIaq8U3KcbTU5XFcP2Q== + dependencies: + "@lit-labs/ssr-dom-shim" "^1.2.0" + "@lit/reactive-element" "^2.1.0" + lit-html "^3.3.0" + lit-html@^3.1.0, lit-html@^3.1.2: version "3.1.4" resolved "https://registry.yarnpkg.com/lit-html/-/lit-html-3.1.4.tgz#30ad4f11467a61e2f08856de170e343184e9034e" @@ -5551,6 +5570,13 @@ lit-html@^3.1.0, lit-html@^3.1.2: dependencies: "@types/trusted-types" "^2.0.2" +lit-html@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/lit-html/-/lit-html-3.3.0.tgz#f66c734a6c69dbb12abf9a718fa5d3dfb46d0b7c" + integrity sha512-RHoswrFAxY2d8Cf2mm4OZ1DgzCoBKUKSPvA1fhtSELxUERq2aQQ2h05pO9j81gS1o7RIRJ+CePLogfyahwmynw== + dependencies: + "@types/trusted-types" "^2.0.2" + lit@3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/lit/-/lit-3.1.1.tgz#49340c8875019a777cc83904f75a2bf7764617dc" @@ -5560,6 +5586,15 @@ lit@3.1.1: lit-element "^4.0.0" lit-html "^3.1.0" +"lit@^2.8.0 || ^3.0.0": + version "3.3.0" + resolved "https://registry.yarnpkg.com/lit/-/lit-3.3.0.tgz#b3037ea94676fb89c3dde9951914efefd0441f17" + integrity sha512-DGVsqsOIHBww2DqnuZzW7QsuCdahp50ojuDaBPC7jUDRpYoH0z7kHBBYZewRzer75FwtrkmkKk7iOAwSaWdBmw== + dependencies: + "@lit/reactive-element" "^2.1.0" + lit-element "^4.2.0" + lit-html "^3.3.0" + lit@^3.0.0: version "3.1.4" resolved "https://registry.yarnpkg.com/lit/-/lit-3.1.4.tgz#03a72e9f0b1f5da317bf49b1ab579a7132e73d7a" @@ -7752,7 +7787,7 @@ stream-browserify@^3.0.0: inherits "~2.0.4" readable-stream "^3.5.0" -"string-width-cjs@npm:string-width@^4.2.0": +"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -7779,15 +7814,6 @@ string-width@^4.1.0, string-width@^4.2.0: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.0" -string-width@^4.2.3: - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - string-width@^5.0.1, string-width@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" @@ -7811,7 +7837,7 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1": +"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -7832,13 +7858,6 @@ strip-ansi@^6.0.0: dependencies: ansi-regex "^5.0.0" -strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - strip-ansi@^7.0.1: version "7.1.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" @@ -8714,7 +8733,7 @@ worker-loader@^2.0.0: loader-utils "^1.0.0" schema-utils "^0.4.0" -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -8741,15 +8760,6 @@ wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" -wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"