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

+ `
+ : html`
article`}
+
+
+
+ `;
+ })}
+
+
+
+ `,
+ )}
+
+ `;
+ }
+
+ 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`
+
+ `;
+ }
+}
+
+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"