diff --git a/CHANGES.md b/CHANGES.md
index 2ea6bb4..810a00a 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,5 +1,17 @@
## CHANGES
+v1.3.0
+- UI: Condense navbar and location bar: add logo to location bar, condense button spacing, add about link to context menu
+- UI: Add collection info dropdown to be a separate tab instead
+- UI: Convert Terms into general About dialog
+- Loading: IPFS support! Load from `ipfs://` URLs, eg. `ipfs://hash/filename.wacz. Possible to specify extension for root with: `ipfs://hash#filename=.wacz`
+- App: Electron App uses IPFS in node, proxies through file proxy.
+- Loading: Native File System (Chrome-only) support: Loading local files on Chrome uses FileHandle, which allows persistent reuse of files with permission
+- Loading: Optimize local file loading on all browsers: No more separate webworker, serviceworker caches entire blob into memory. Should fix Firefox loading issues streaming from blob.
+- Loading/UI: Revamp permissions UI to replace iframe instead of popup
+- UI: Favicon smoother update, better check for valid icon
+- UI: Purge Cache / Full Reload reloads current frame, not parent
+
v1.2.1
- Loading/UI: Fix Google Drive Loading/Reauthorization: Only trigger when reauth is needed. For rate-limit errors, attempt reloading more slowly (exponential backoff)
- Loading: ReplayWeb.page App supports opening WACZ, WARC and HAR files via double-clicking from OS and via command-line.
diff --git a/package.json b/package.json
index 10b1081..79d3121 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "replaywebpage",
"productName": "ReplayWeb.page",
- "version": "1.2.3",
+ "version": "1.3.0",
"description": "Serverless Web Archive Replay",
"repository": "https://github.com/webrecorder/replayweb.page",
"homepage": "https://replayweb.page/",
@@ -9,10 +9,11 @@
"license": "AGPL-3.0-or-later",
"dependencies": {
"@fortawesome/fontawesome-free": "^5.13.0",
- "@webrecorder/wabac": "^2.1.5",
+ "@webrecorder/wabac": "^2.2.0",
"bulma": "^0.9.0",
"fetch-ndjson": "^1.1.0",
"flexsearch": "^0.6.32",
+ "ipfs-core": "^0.2.0",
"keyword-mark-element": "^0.1.2",
"lit-element": "^2.3.1",
"marked": "^1.0.0",
@@ -23,6 +24,7 @@
"split.js": "^1.6.2"
},
"devDependencies": {
+ "copy-webpack-plugin": "^6.3.0",
"css-loader": "^3.5.3",
"electron": "^10.1.3",
"electron-builder": "^22.7.0",
@@ -35,7 +37,7 @@
"style-loader": "^1.2.1",
"svg-inline-loader": "^0.8.2",
"to-string-loader": "^1.1.6",
- "webpack": "^4.43.0",
+ "webpack": "^4.44.2",
"webpack-cli": "^3.3.11",
"webpack-dev-server": "^3.10.3"
},
@@ -56,6 +58,7 @@
"start-electron": "NODE_ENV=development electron ./dist/electron.js $1",
"start-jekyll": "yarn run build-docs && bundle exec jekyll serve",
"dist": "yarn run build && yarn run pack",
+ "dist-dev": "yarn run build-dev && yarn run pack",
"release": "yarn run build && electron-builder"
},
"build": {
@@ -70,6 +73,8 @@
"files": [
"!**/node_modules/**/*",
"dist/*.js",
+ "dist/prebuilds/${platform}-${arch}/*",
+ "dist/build/*",
"*.js",
"*.html",
"webmanifest.json",
diff --git a/src/appmain.js b/src/appmain.js
index 9657bea..86f80e9 100644
--- a/src/appmain.js
+++ b/src/appmain.js
@@ -1,14 +1,11 @@
import { LitElement, html, css } from 'lit-element';
import { wrapCss, rwpLogo, IS_APP, clickOnSpacebarPress } from './misc';
-import { registerSW, initDBWorker } from './pageutils';
-
-import prettyBytes from 'pretty-bytes';
+import { registerSW } from './pageutils';
import fasHelp from '@fortawesome/fontawesome-free/svgs/solid/question-circle.svg';
import fasArrowLeft from '@fortawesome/fontawesome-free/svgs/solid/arrow-left.svg';
import fasArrowRight from '@fortawesome/fontawesome-free/svgs/solid/arrow-right.svg';
-import fasInfoIcon from '@fortawesome/fontawesome-free/svgs/solid/info-circle.svg';
// ===========================================================================
@@ -19,14 +16,13 @@ class App extends LitElement
super();
this.sourceUrl = null;
this.collInfo = null;
- this.showTerms = false;
+ this.showAbout = false;
this.pageParams = {};
this.inited = false;
this.navMenuShown = false;
registerSW(__SW_NAME__);
- initDBWorker();
this.safariKeyframes();
}
@@ -37,7 +33,7 @@ class App extends LitElement
pageParams: { type: Object },
sourceUrl: { type: String },
navMenuShown: { type: Boolean },
- showTerms: { type: Boolean },
+ showAbout: { type: Boolean },
collInfo: { type: Object },
loadInfo: { type: Object },
embed: { type: String },
@@ -112,12 +108,19 @@ class App extends LitElement
`);
}
+ renderNavBar() {
+
+ }
+
render() {
if (!this.inited) {
return html``;
}
+
+ const showNavBar = !this.collInfo && (!this.embed || this.embed === "full");
+
return html`
- ${!this.embed || this.embed === "full" ? html`
+ ${showNavBar ? html`
Skip main navigation
@@ -158,37 +161,6 @@ class App extends LitElement
` : ``}
- ${this.sourceUrl && this.collInfo ? html`
-
-
-
-
About this Archive
-
-
- Source: ${this.sourceUrl}
-
-
- Filename: ${this.collInfo.filename}
-
-
- Total Size: ${prettyBytes(Number(this.collInfo.size || 0))}
-
-
- Loading Mode: ${this.collInfo.onDemand ? "Download On-Demand" : "Fully Local"}
-
-
- Collection Id: ${this.collInfo.coll}
-
-
-
- ReplayWeb.page Version: ${__VERSION__}
-
-
-
- ` : ``}
${!this.embed ? html`
` : html``}
Skipped
@@ -211,7 +183,8 @@ class App extends LitElement
sourceUrl="${this.sourceUrl}"
embed="${this.embed}"
@replay-favicons=${this.onFavIcons}
- @coll-loaded=${this.onCollLoaded}>
+ @coll-loaded=${this.onCollLoaded}
+ @about-show=${(e) => this.showAbout = true}>
` : html`
@@ -222,42 +195,8 @@ class App extends LitElement
`}
- ${this.showTerms ? html`
-
-
this.showTerms = false}">
-
-
- Terms and Privacy
- this.showTerms = false}">
-
-
-
-
-
This site is a static browser-based application that loads web archive files provided by the user
- and renders them for replay in the browser.
-
The site is operated by the Webrecorder Project
-
See the Docs for more info on how it works.
-
-
Privacy
-
No data is uploaded anywhere and no information is collected.
-
All content rendered stays directly in your browser. When loading an archive from Google Drive,
- the site may ask for account authorization to download the specified file only.
-
-
Disclaimer of Warranties
-
The application may not always be available. No guarantees!
-
Some legalese:
-
DISCLAIMER OF SOFTWARE WARRANTY. WEBRECORDER SOFTWARE PROVIDES THIS SOFTWARE TO YOU "AS AVAILABLE"
- AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE,
- INCLUDING WITHOUT LIMITATION ANY WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
-
-
this.showTerms = false}">Close
-
-
-
-
-
-
- ` : ``} `
+ ${this.showAbout ? this.renderAbout() : ``}
+ `;
}
firstUpdated() {
@@ -344,7 +283,7 @@ class App extends LitElement
this.embed = this.pageParams.get("embed") || "";
if (this.pageParams.has("terms")) {
- this.showTerms = true;
+ this.showAbout = true;
}
if (this.pageParams.get("config")) {
@@ -438,6 +377,69 @@ class App extends LitElement
document.head.appendChild(style);
style.appendChild(document.createTextNode(css));
}
+
+ renderAbout() {
+ return html`
+
+
+
+
+
+
+
+
+
+
+
${IS_APP ? 'App' : ''} v${__VERSION__}
+
+
+ ${IS_APP ? html`
+
ReplayWeb.page App is a standalone app for Mac, Windows and Linux that loads web archive files provided by the user
+ and renders them for replay.
+
+ ` : html`
+
ReplayWeb.page is a browser-based viewer that loads web archive files provided by the user
+ and renders them for replay in the browser.
`}
+
+
+
Full source code is available at:
+ https://github.com/webrecorder/replayweb.page
+
+
+
See the User Docs or the GitHub README for more info on how it works.
+
+
ReplayWeb.page is part of the Webrecorder Project .
+
+
Privacy
+
No data is uploaded anywhere and no information is collected.
+
All content rendered stays directly in your browser. When loading an archive from Google Drive,
+ the site may ask for account authorization to download the specified file only.
+
+
Disclaimer of Warranties
+
The application is provided "as is" without any guarantees.
+
+ Legalese:
+ DISCLAIMER OF SOFTWARE WARRANTY. WEBRECORDER SOFTWARE PROVIDES THIS SOFTWARE TO YOU "AS AVAILABLE"
+ AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE,
+ INCLUDING WITHOUT LIMITATION ANY WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+
+
+
+
+
+
+ `;
+ }
+
+ onAboutClose() {
+ this.showAbout = false;
+ }
}
customElements.define("replay-app-main", App);
diff --git a/src/chooser.js b/src/chooser.js
index 3959d38..1d3a0e0 100644
--- a/src/chooser.js
+++ b/src/chooser.js
@@ -1,5 +1,5 @@
import { LitElement, html, css } from 'lit-element';
-import { wrapCss } from './misc';
+import { IS_APP, wrapCss } from './misc';
import fasUpload from '@fortawesome/fontawesome-free/svgs/solid/upload.svg';
@@ -12,6 +12,14 @@ class Chooser extends LitElement
this.fileDisplayName = "";
this.file = null;
+
+ this.hasNativeFS = !!window.showOpenFilePicker && !IS_APP;
+ }
+
+ static get properties() {
+ return {
+ fileDisplayName: { type: String }
+ }
}
onChooseFile(event) {
@@ -22,7 +30,32 @@ class Chooser extends LitElement
this.file = event.currentTarget.files[0];
// file.path only available in electron app
this.fileDisplayName = "file://" + (this.file.path || this.file.name);
- this.requestUpdate();
+ }
+
+ async onChooseNativeFile() {
+ const options = {
+ types: [
+ {
+ description: 'WARC, WACZ, HAR and WBN Files',
+ accept: {
+ 'application/warc': ['.warc', '.gz'],
+ 'application/har': ['.har'],
+ 'application/wacz': ['.wacz'],
+ 'application/wbn': ['.wbn']
+ }
+ }
+ ]
+ }
+
+ const [fileHandle] = await window.showOpenFilePicker(options);
+ this.fileHandle = fileHandle;
+
+ this.file = await fileHandle.getFile();
+ this.fileDisplayName = "file://" + fileHandle.name;
+ }
+
+ randomId() {
+ return Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
}
onStartLoad(event) {
@@ -37,12 +70,17 @@ class Chooser extends LitElement
const url = new URL(__APP_FILE_SERVE_PREFIX__);
url.searchParams.set("filename", this.file.path);
loadInfo.loadUrl = url.href;
+ loadInfo.noCache = true;
+ } else if (this.fileHandle) {
+ loadInfo.loadUrl = this.fileDisplayName + "-" + this.randomId();
+ loadInfo.extra = {fileHandle: this.fileHandle};
+ loadInfo.noCache = false;
} else {
loadInfo.loadUrl = URL.createObjectURL(this.file);
loadInfo.blob = this.file;
+ loadInfo.noCache = false;
}
loadInfo.size = this.file.size;
- loadInfo.noCache = this.file.path !== undefined;
loadInfo.name = this.fileDisplayName;
}
@@ -116,10 +154,11 @@ class Chooser extends LitElement