From 8183715f9698a8d3209c3c36eb5d6c6cca2485a9 Mon Sep 17 00:00:00 2001 From: Juan Date: Thu, 1 May 2025 14:14:15 -0500 Subject: [PATCH 1/8] emtpy sidepanel --- src/ext/bg.ts | 6 ++++++ src/ext/manifest.json | 9 ++++++--- static/sidepanel.html | 10 ++++++++++ 3 files changed, 22 insertions(+), 3 deletions(-) create mode 100644 static/sidepanel.html diff --git a/src/ext/bg.ts b/src/ext/bg.ts index 4dcaa98..52782e2 100644 --- a/src/ext/bg.ts +++ b/src/ext/bg.ts @@ -45,6 +45,12 @@ 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) => { 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/static/sidepanel.html b/static/sidepanel.html new file mode 100644 index 0000000..531ca79 --- /dev/null +++ b/static/sidepanel.html @@ -0,0 +1,10 @@ + + + + My Sidepanel + + +

All sites sidepanel extension

+

This side panel is enabled on all sites

+ + \ No newline at end of file From f8e1b3ef815ac1e108f34fb108e833d20d27f737 Mon Sep 17 00:00:00 2001 From: Juan Date: Thu, 1 May 2025 14:58:58 -0500 Subject: [PATCH 2/8] material web with sidepanel example --- package.json | 1 + src/sidepanel.ts | 5 +++ static/sidepanel.html | 18 ++++++++-- webpack.config.js | 1 + yarn.lock | 78 ++++++++++++++++++++++++------------------- 5 files changed, 67 insertions(+), 36 deletions(-) create mode 100644 src/sidepanel.ts diff --git a/package.json b/package.json index a76db38..190f100 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "dependencies": { "@fortawesome/fontawesome-free": "^5.13.0", "@ipld/car": "^5.3.1", + "@material/web": "^2.3.0", "@webrecorder/awp-sw": "^0.5.3", "@webrecorder/wabac": "^2.20.8", "auto-js-ipfs": "^2.3.0", diff --git a/src/sidepanel.ts b/src/sidepanel.ts new file mode 100644 index 0000000..ad8b220 --- /dev/null +++ b/src/sidepanel.ts @@ -0,0 +1,5 @@ + +import '@material/web/all.js'; +import {styles as typescaleStyles} from '@material/web/typography/md-typescale-styles.js'; + +document.adoptedStyleSheets.push(typescaleStyles.styleSheet!); \ No newline at end of file diff --git a/static/sidepanel.html b/static/sidepanel.html index 531ca79..a0728be 100644 --- a/static/sidepanel.html +++ b/static/sidepanel.html @@ -2,9 +2,23 @@ My Sidepanel + + -

All sites sidepanel extension

-

This side panel is enabled on all sites

+

Searchbar here

+ + 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 0246e64..40c9b03 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1340,7 +1340,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== @@ -1392,11 +1392,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" @@ -1434,6 +1429,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" @@ -1451,6 +1453,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" @@ -5558,6 +5568,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" @@ -5565,6 +5584,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" @@ -5574,6 +5600,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" @@ -7750,7 +7785,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== @@ -7777,15 +7812,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" @@ -7809,7 +7835,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== @@ -7830,13 +7856,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" @@ -8692,7 +8711,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== @@ -8719,15 +8738,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" From 0954cca65915f0dd7a33aeb95d4e67ccf192188b Mon Sep 17 00:00:00 2001 From: Juan Date: Thu, 1 May 2025 15:14:59 -0500 Subject: [PATCH 3/8] added link to home page --- src/sidepanel.ts | 78 +++++++++++++++++++++++++++++++++++++++++-- static/sidepanel.html | 1 + 2 files changed, 77 insertions(+), 2 deletions(-) diff --git a/src/sidepanel.ts b/src/sidepanel.ts index ad8b220..211e3f1 100644 --- a/src/sidepanel.ts +++ b/src/sidepanel.ts @@ -1,5 +1,79 @@ import '@material/web/all.js'; -import {styles as typescaleStyles} from '@material/web/typography/md-typescale-styles.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"; -document.adoptedStyleSheets.push(typescaleStyles.styleSheet!); \ No newline at end of file +import fasHome from "@fortawesome/fontawesome-free/svgs/solid/home.svg"; + +document.adoptedStyleSheets.push(typescaleStyles.styleSheet!); + + +class ArgoViewer extends LitElement { + constructor() { + super(); + } + + getHomePage() { + return chrome.runtime.getURL("index.html"); + } + + render() { + return html`
+ + + + + +
`; + } +} + +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 index a0728be..f4c2625 100644 --- a/static/sidepanel.html +++ b/static/sidepanel.html @@ -16,6 +16,7 @@

Searchbar here

+ My Archives My Shared Archives From 14ee7652fcf005cb742e604d371d1c2d99306bf7 Mon Sep 17 00:00:00 2001 From: Juan Date: Fri, 2 May 2025 13:47:02 -0500 Subject: [PATCH 4/8] added old buttons --- src/ext/bg.ts | 61 ++++++++++ src/sidepanel.ts | 288 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 349 insertions(+) diff --git a/src/ext/bg.ts b/src/ext/bg.ts index 52782e2..4aa9065 100644 --- a/src/ext/bg.ts +++ b/src/ext/bg.ts @@ -58,6 +58,9 @@ chrome.runtime.onConnect.addListener((port) => { case "popup-port": popupHandler(port); break; + case "sidepanel-port": + sidepanelHandler(port); + break; } }); @@ -118,6 +121,64 @@ 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 "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 }); + console.log("newColl", name); + 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. diff --git a/src/sidepanel.ts b/src/sidepanel.ts index 211e3f1..3771fb8 100644 --- a/src/sidepanel.ts +++ b/src/sidepanel.ts @@ -5,6 +5,16 @@ import { LitElement, html } from "lit"; import { unsafeSVG } from "lit/directives/unsafe-svg.js"; import fasHome from "@fortawesome/fontawesome-free/svgs/solid/home.svg"; +import fasBox from "@fortawesome/fontawesome-free/svgs/solid/square.svg"; +import wrRec from "./assets/icons/recLogo.svg"; + +import { + BEHAVIOR_WAIT_LOAD, + // BEHAVIOR_READY_START, + // BEHAVIOR_RUNNING, + // BEHAVIOR_PAUSED, + // BEHAVIOR_DONE, +} from "./consts"; document.adoptedStyleSheets.push(typescaleStyles.styleSheet!); @@ -12,12 +22,257 @@ 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 = "default-collection"; + + // @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" }); + } + }); + + // @ts-expect-error - TS2339 - Property 'port' does not exist on type 'RecPopup'. + this.port.onMessage.addListener((message) => { + this.onMessage(message); + }); + + this.sendMessage({ + // @ts-expect-error - TS2339 - Property 'tabId' does not exist on type 'RecPopup'. + tabId: this.tabId, + type: "newColl", + title: "default-collection", + }); } + // @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; + } + } + 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`
+ Home - All Archives + ${ + // @ts-expect-error - TS2339 - Property 'canRecord' does not exist on type 'RecPopup'. + this.canRecord + ? html` + + ` + : "" + }
`; } } From 252739853f5e5d085324ed6e728db259eca7c022 Mon Sep 17 00:00:00 2001 From: Juan Date: Mon, 5 May 2025 13:08:16 -0500 Subject: [PATCH 5/8] merge --- src/ext/bg.ts | 1 - src/sidepanel.ts | 39 ++++++++++++++++++++++++++++++++------- 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/src/ext/bg.ts b/src/ext/bg.ts index 4aa9065..012e6d7 100644 --- a/src/ext/bg.ts +++ b/src/ext/bg.ts @@ -162,7 +162,6 @@ function sidepanelHandler(port) { case "newColl": { const { name } = await collLoader.initNewColl({ title: message.title }); - console.log("newColl", name); defaultCollId = name; port.postMessage(await listAllMsg(collLoader, { defaultCollId })); await setLocalOption("defaultCollId", defaultCollId); diff --git a/src/sidepanel.ts b/src/sidepanel.ts index 3771fb8..0e3421b 100644 --- a/src/sidepanel.ts +++ b/src/sidepanel.ts @@ -8,6 +8,11 @@ import fasHome from "@fortawesome/fontawesome-free/svgs/solid/home.svg"; import fasBox from "@fortawesome/fontawesome-free/svgs/solid/square.svg"; import wrRec from "./assets/icons/recLogo.svg"; +import { + getLocalOption, + // removeLocalOption, + setLocalOption, +} from "./localstorage"; import { BEHAVIOR_WAIT_LOAD, // BEHAVIOR_READY_START, @@ -28,7 +33,7 @@ class ArgoViewer extends LitElement { // @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 = "default-collection"; + this.collId = ""; // @ts-expect-error - TS2339 - Property 'tabId' does not exist on type 'RecPopup'. this.tabId = 0; @@ -126,12 +131,6 @@ class ArgoViewer extends LitElement { this.onMessage(message); }); - this.sendMessage({ - // @ts-expect-error - TS2339 - Property 'tabId' does not exist on type 'RecPopup'. - tabId: this.tabId, - type: "newColl", - title: "default-collection", - }); } // @ts-expect-error - TS7006 - Parameter 'message' implicitly has an 'any' type. @@ -185,6 +184,32 @@ class ArgoViewer extends LitElement { 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() { From 8cd1b0d96654c969f0d5745b5d3d5d034569ac83 Mon Sep 17 00:00:00 2001 From: nikitalokhmachev-ai Date: Mon, 5 May 2025 17:41:02 -0400 Subject: [PATCH 6/8] feat: implement basic archive links --- .gitignore | 1 + .prettierrc | 7 ++++ src/argo-archive-list.ts | 79 ++++++++++++++++++++++++++++++++++++++++ src/ext/bg.ts | 42 +++++++++++++-------- src/sidepanel.ts | 73 +++++++++++++++++++++++++++++-------- static/sidepanel.html | 8 ++++ 6 files changed, 178 insertions(+), 32 deletions(-) create mode 100644 .prettierrc create mode 100644 src/argo-archive-list.ts 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/src/argo-archive-list.ts b/src/argo-archive-list.ts new file mode 100644 index 0000000..18d8cdf --- /dev/null +++ b/src/argo-archive-list.ts @@ -0,0 +1,79 @@ +import { LitElement, html, css } from "lit"; +import { customElement, property, state } from "lit/decorators.js"; +import { getLocalOption } from "./localstorage"; + +@customElement("argo-archive-list") +export class ArgoArchiveList extends LitElement { + @state() + private pages: any[] = []; + + @property({ type: String }) + collId = ""; + + static styles = css` + ul { + list-style: none; + padding-left: 0; + } + li { + cursor: pointer; + margin: 0.3em 0; + color: #0066cc; + text-decoration: underline; + } + `; + + async connectedCallback() { + super.connectedCallback(); + + this.collId = (await getLocalOption("defaultCollId")) || ""; + + const port = chrome.runtime.connect({ name: "sidepanel-port" }); + + // @ts-expect-error - TS7006 - Parameter 'message' implicitly has an 'any' type. + port.onMessage.addListener((message) => { + if (message.type === "pages") { + this.pages = message.pages || []; + } + }); + + port.postMessage({ type: "getPages" }); + } + + render() { + if (!this.pages.length) { + return html`

No archives found yet.

`; + } + + return html` +
    + ${this.pages.map((page) => { + const tsString = page.ts + ? new Date(Number(page.ts)).toISOString().replace(/[-:TZ.]/g, "") + : ""; + + const query = new URLSearchParams({ + source: `local://${page.coll || ""}`, + url: page.url, + }).toString(); + + const hash = new URLSearchParams({ + view: "pages", + url: page.url, + ts: tsString, + }).toString(); + + const fullUrl = `${chrome.runtime.getURL( + "index.html", + )}?source=local://${this.collId}&url=${encodeURIComponent( + page.url, + )}#view=pages&url=${encodeURIComponent(page.url)}&ts=${tsString}`; + + return html`
  • chrome.tabs.create({ url: fullUrl })}> + ${page.title || page.url} +
  • `; + })} +
+ `; + } +} diff --git a/src/ext/bg.ts b/src/ext/bg.ts index 012e6d7..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 = {}; @@ -46,11 +42,13 @@ function main() { }); } // Side panel -chrome.sidePanel.setPanelBehavior({ - openPanelOnActionClick: true -}).catch((err: Error) => { - console.error(err); -}); +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) => { @@ -143,6 +141,23 @@ function sidepanelHandler(port) { 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. @@ -362,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/sidepanel.ts b/src/sidepanel.ts index 0e3421b..8bb072f 100644 --- a/src/sidepanel.ts +++ b/src/sidepanel.ts @@ -1,12 +1,12 @@ - -import '@material/web/all.js'; -import { styles as typescaleStyles } from '@material/web/typography/md-typescale-styles.js'; +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 fasHome from "@fortawesome/fontawesome-free/svgs/solid/home.svg"; import fasBox from "@fortawesome/fontawesome-free/svgs/solid/square.svg"; import wrRec from "./assets/icons/recLogo.svg"; +import "./argo-archive-list"; import { getLocalOption, @@ -23,7 +23,6 @@ import { document.adoptedStyleSheets.push(typescaleStyles.styleSheet!); - class ArgoViewer extends LitElement { constructor() { super(); @@ -101,10 +100,46 @@ class ArgoViewer extends LitElement { } firstUpdated() { - this.registerMessages(); } + // // @ts-expect-error - TS7006 - Parameter 'pages' implicitly has an 'any' type. + // renderArchivedPages(pages) { + // const listEl = (this.renderRoot as ShadowRoot).getElementById("archived-list"); + // if (!listEl) return; + + // listEl.innerHTML = ""; + // // @ts-expect-error - a and b are any + // pages.sort((a, b) => Number(b.ts || 0) - Number(a.ts || 0)); // newest first + + // for (const page of pages) { + // const li = document.createElement("li"); + // li.textContent = page.title || page.url; + // li.style.cursor = "pointer"; + // li.onclick = () => { + // const tsString = page.ts ? new Date(Number(page.ts)).toISOString().replace(/[-:TZ.]/g, "") : ""; + + // const query = new URLSearchParams({ + // // @ts-expect-error - TS2339 - Property 'collId' does not exist on type 'RecPopup'. + // source: `local://${this.collId}`, + // url: page.url, + // }).toString(); + + // const hash = new URLSearchParams({ + // view: "pages", + // url: page.url, + // ts: tsString, + // }).toString(); + + // const fullUrl = `${chrome.runtime.getURL("index.html")}?${query}#${hash}`; + + // chrome.tabs.create({ url: fullUrl }); + // }; + // listEl.appendChild(li); + // } + // } + // + registerMessages() { // @ts-expect-error - TS2339 - Property 'port' does not exist on type 'RecPopup'. this.port = chrome.runtime.connect({ name: "sidepanel-port" }); @@ -126,11 +161,12 @@ class ArgoViewer extends LitElement { } }); + // 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. @@ -210,10 +246,13 @@ class ArgoViewer extends LitElement { this.collTitle = "[No Title]"; } break; + // case "pages": + // this.renderArchivedPages(message.pages); + // break; } } - get actionButtonDisabled() { + 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; } @@ -346,6 +385,8 @@ class ArgoViewer extends LitElement { ` : "" } +

Archived Pages

+
    `; } } @@ -368,18 +409,18 @@ class WrIcon extends LitElement { return html` ${ - // @ts-expect-error - TS2339 - Property 'src' does not exist on type 'WrIcon'. - unsafeSVG(this.src) - } + // @ts-expect-error - TS2339 - Property 'src' does not exist on type 'WrIcon'. + unsafeSVG(this.src) + } `; diff --git a/static/sidepanel.html b/static/sidepanel.html index f4c2625..e760c30 100644 --- a/static/sidepanel.html +++ b/static/sidepanel.html @@ -21,5 +21,13 @@

    Searchbar here

    My Archives My Shared Archives
    +
    +
    + +
    +
    +

    Shared content goes here

    +
    +
    \ No newline at end of file From 25e6479e1227aa9803391dc5731da38f2086e0e8 Mon Sep 17 00:00:00 2001 From: nikitalokhmachev-ai Date: Tue, 6 May 2025 18:32:52 -0400 Subject: [PATCH 7/8] feat: argo sidepanel styling --- src/argo-archive-list.ts | 256 ++++++++++++++++++++++++++++++--------- src/sidepanel.ts | 147 ++++++++-------------- static/sidepanel.html | 94 +++++++++++--- 3 files changed, 330 insertions(+), 167 deletions(-) diff --git a/src/argo-archive-list.ts b/src/argo-archive-list.ts index 18d8cdf..c36101e 100644 --- a/src/argo-archive-list.ts +++ b/src/argo-archive-list.ts @@ -1,79 +1,223 @@ -import { LitElement, html, css } from "lit"; -import { customElement, property, state } from "lit/decorators.js"; +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 { - @state() - private pages: any[] = []; + static styles: CSSResultGroup = [ + typescaleStyles as unknown as CSSResultGroup, + css` + md-elevated-card { + display: block; + margin: 1rem 0; + padding: 0; + overflow: visible; + } - @property({ type: String }) - collId = ""; + md-elevated-card > details { + border-radius: inherit; + overflow: hidden; + margin: 0; + background: transparent; + } - static styles = css` - ul { - list-style: none; - padding-left: 0; - } - li { - cursor: pointer; - margin: 0.3em 0; - color: #0066cc; - text-decoration: underline; - } - `; + md-elevated-card > details summary { + background: transparent !important; + padding: 0.75rem 1rem; + } - async connectedCallback() { - super.connectedCallback(); + md-elevated-card > details md-list { + background: transparent; + padding: 0 0rem 0rem; + } - this.collId = (await getLocalOption("defaultCollId")) || ""; + md-list-item { + --md-list-item-top-space: 0px; + --md-list-item-bottom-space: 0px; - const port = chrome.runtime.connect({ name: "sidepanel-port" }); + --md-list-item-leading-space: 0px; + --md-list-item-trailing-space: 12px; - // @ts-expect-error - TS7006 - Parameter 'message' implicitly has an 'any' type. - port.onMessage.addListener((message) => { - if (message.type === "pages") { - this.pages = message.pages || []; + --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 found yet.

    `; + 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` -
      - ${this.pages.map((page) => { - const tsString = page.ts - ? new Date(Number(page.ts)).toISOString().replace(/[-:TZ.]/g, "") - : ""; - - const query = new URLSearchParams({ - source: `local://${page.coll || ""}`, - url: page.url, - }).toString(); - - const hash = new URLSearchParams({ - view: "pages", - url: page.url, - ts: tsString, - }).toString(); - - const fullUrl = `${chrome.runtime.getURL( - "index.html", - )}?source=local://${this.collId}&url=${encodeURIComponent( - page.url, - )}#view=pages&url=${encodeURIComponent(page.url)}&ts=${tsString}`; - - return html`
    • chrome.tabs.create({ url: fullUrl })}> - ${page.title || page.url} -
    • `; - })} -
    +
    + ${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/sidepanel.ts b/src/sidepanel.ts index 8bb072f..f2e3ca3 100644 --- a/src/sidepanel.ts +++ b/src/sidepanel.ts @@ -2,11 +2,9 @@ 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 fasHome from "@fortawesome/fontawesome-free/svgs/solid/home.svg"; -import fasBox from "@fortawesome/fontawesome-free/svgs/solid/square.svg"; -import wrRec from "./assets/icons/recLogo.svg"; import "./argo-archive-list"; +import "@material/web/textfield/outlined-text-field.js"; +import "@material/web/icon/icon.js"; import { getLocalOption, @@ -21,6 +19,10 @@ import { // 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 { @@ -103,43 +105,6 @@ class ArgoViewer extends LitElement { this.registerMessages(); } - // // @ts-expect-error - TS7006 - Parameter 'pages' implicitly has an 'any' type. - // renderArchivedPages(pages) { - // const listEl = (this.renderRoot as ShadowRoot).getElementById("archived-list"); - // if (!listEl) return; - - // listEl.innerHTML = ""; - // // @ts-expect-error - a and b are any - // pages.sort((a, b) => Number(b.ts || 0) - Number(a.ts || 0)); // newest first - - // for (const page of pages) { - // const li = document.createElement("li"); - // li.textContent = page.title || page.url; - // li.style.cursor = "pointer"; - // li.onclick = () => { - // const tsString = page.ts ? new Date(Number(page.ts)).toISOString().replace(/[-:TZ.]/g, "") : ""; - - // const query = new URLSearchParams({ - // // @ts-expect-error - TS2339 - Property 'collId' does not exist on type 'RecPopup'. - // source: `local://${this.collId}`, - // url: page.url, - // }).toString(); - - // const hash = new URLSearchParams({ - // view: "pages", - // url: page.url, - // ts: tsString, - // }).toString(); - - // const fullUrl = `${chrome.runtime.getURL("index.html")}?${query}#${hash}`; - - // chrome.tabs.create({ url: fullUrl }); - // }; - // listEl.appendChild(li); - // } - // } - // - registerMessages() { // @ts-expect-error - TS2339 - Property 'port' does not exist on type 'RecPopup'. this.port = chrome.runtime.connect({ name: "sidepanel-port" }); @@ -246,9 +211,6 @@ class ArgoViewer extends LitElement { this.collTitle = "[No Title]"; } break; - // case "pages": - // this.renderArchivedPages(message.pages); - // break; } } @@ -283,10 +245,7 @@ class ArgoViewer extends LitElement { this.replayUrl = this.getCollPage() + "#" + params.toString(); } - if ( - changedProperties.has("pageUrl") || - changedProperties.has("failureMsg") - ) { + 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'. @@ -338,56 +297,50 @@ class ArgoViewer extends LitElement { this.waitingForStop = true; } render() { - return html`
    - - - - Home - All Archives - - - ${ - // @ts-expect-error - TS2339 - Property 'canRecord' does not exist on type 'RecPopup'. - this.canRecord - ? html` - - ` - : "" - } -

    Archived Pages

    -
      -
      `; + !this.recording + ? html` + + public + Resume Archiving + + ` + : html` + + pause + Pause Archiving + + ` + } + ` + : html`` + } + + + settings + + + `; } } diff --git a/static/sidepanel.html b/static/sidepanel.html index e760c30..f27a8e4 100644 --- a/static/sidepanel.html +++ b/static/sidepanel.html @@ -1,33 +1,99 @@ + My Sidepanel + + - -

      Searchbar here

      - - - My Archives - My Shared Archives + +
      + + search + +
      + + + + + My Archives + My Shared Archives -
      + +
      -

      Shared content goes here

      +
      + + \ No newline at end of file From 0070d494175004353840374dbac9bd100d36d6e4 Mon Sep 17 00:00:00 2001 From: nikitalokhmachev-ai Date: Wed, 7 May 2025 11:12:53 -0400 Subject: [PATCH 8/8] fix: move md-tabs --- static/sidepanel.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/static/sidepanel.html b/static/sidepanel.html index f27a8e4..ed57b29 100644 --- a/static/sidepanel.html +++ b/static/sidepanel.html @@ -19,10 +19,10 @@ --md-sys-color-background: white; --md-sys-color-surface-container: white; --md-elevated-card-container-color: white; + } - md-tabs { + md-tabs { background-color: white; - } } .search-container {