replaywebpage 1.6.5 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/chevron-double-down.svg +4 -0
- package/assets/chevron-double-up.svg +4 -0
- package/assets/globe.svg +3 -0
- package/assets/main.scss +1 -1
- package/package.json +6 -5
- package/src/appmain.js +24 -22
- package/src/coll-index.js +67 -33
- package/src/coll.js +29 -3
- package/src/electron-ipfs-handler.js +44 -0
- package/src/electron-replay-app.js +19 -36
- package/src/embed-receipt.js +279 -0
- package/src/embed.js +73 -19
- package/src/loader.js +5 -15
- package/src/pageutils.js +1 -58
- package/src/replay.js +3 -2
- package/src/swmanager.js +132 -0
- package/sw.js +114 -6
- package/ui.js +472 -217
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-chevron-double-down" viewBox="0 0 16 16">
|
|
2
|
+
<path fill-rule="evenodd" d="M1.646 6.646a.5.5 0 0 1 .708 0L8 12.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z"/>
|
|
3
|
+
<path fill-rule="evenodd" d="M1.646 2.646a.5.5 0 0 1 .708 0L8 8.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z"/>
|
|
4
|
+
</svg>
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-chevron-double-up" viewBox="0 0 16 16">
|
|
2
|
+
<path fill-rule="evenodd" d="M7.646 2.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1-.708.708L8 3.707 2.354 9.354a.5.5 0 1 1-.708-.708l6-6z"/>
|
|
3
|
+
<path fill-rule="evenodd" d="M7.646 6.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1-.708.708L8 7.707l-5.646 5.647a.5.5 0 0 1-.708-.708l6-6z"/>
|
|
4
|
+
</svg>
|
package/assets/globe.svg
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-globe" viewBox="0 0 16 16">
|
|
2
|
+
<path d="M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8zm7.5-6.923c-.67.204-1.335.82-1.887 1.855A7.97 7.97 0 0 0 5.145 4H7.5V1.077zM4.09 4a9.267 9.267 0 0 1 .64-1.539 6.7 6.7 0 0 1 .597-.933A7.025 7.025 0 0 0 2.255 4H4.09zm-.582 3.5c.03-.877.138-1.718.312-2.5H1.674a6.958 6.958 0 0 0-.656 2.5h2.49zM4.847 5a12.5 12.5 0 0 0-.338 2.5H7.5V5H4.847zM8.5 5v2.5h2.99a12.495 12.495 0 0 0-.337-2.5H8.5zM4.51 8.5a12.5 12.5 0 0 0 .337 2.5H7.5V8.5H4.51zm3.99 0V11h2.653c.187-.765.306-1.608.338-2.5H8.5zM5.145 12c.138.386.295.744.468 1.068.552 1.035 1.218 1.65 1.887 1.855V12H5.145zm.182 2.472a6.696 6.696 0 0 1-.597-.933A9.268 9.268 0 0 1 4.09 12H2.255a7.024 7.024 0 0 0 3.072 2.472zM3.82 11a13.652 13.652 0 0 1-.312-2.5h-2.49c.062.89.291 1.733.656 2.5H3.82zm6.853 3.472A7.024 7.024 0 0 0 13.745 12H11.91a9.27 9.27 0 0 1-.64 1.539 6.688 6.688 0 0 1-.597.933zM8.5 12v2.923c.67-.204 1.335-.82 1.887-1.855.173-.324.33-.682.468-1.068H8.5zm3.68-1h2.146c.365-.767.594-1.61.656-2.5h-2.49a13.65 13.65 0 0 1-.312 2.5zm2.802-3.5a6.959 6.959 0 0 0-.656-2.5H12.18c.174.782.282 1.623.312 2.5h2.49zM11.27 2.461c.247.464.462.98.64 1.539h1.835a7.024 7.024 0 0 0-3.072-2.472c.218.284.418.598.597.933zM10.855 4a7.966 7.966 0 0 0-.468-1.068C9.835 1.897 9.17 1.282 8.5 1.077V4h2.355z"/>
|
|
3
|
+
</svg>
|
package/assets/main.scss
CHANGED
|
@@ -113,7 +113,7 @@ a:focus {
|
|
|
113
113
|
|
|
114
114
|
// Add html and body styles to :host for webcomponents
|
|
115
115
|
:host {
|
|
116
|
-
background-color: $body-background-color;
|
|
116
|
+
//background-color: $body-background-color;
|
|
117
117
|
font-size: $body-size;
|
|
118
118
|
-moz-osx-font-smoothing: grayscale;
|
|
119
119
|
-webkit-font-smoothing: antialiased;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "replaywebpage",
|
|
3
3
|
"productName": "ReplayWeb.page",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.7.0",
|
|
5
5
|
"description": "Serverless Web Archive Replay",
|
|
6
6
|
"repository": "https://github.com/webrecorder/replayweb.page",
|
|
7
7
|
"homepage": "https://replayweb.page/",
|
|
@@ -9,13 +9,13 @@
|
|
|
9
9
|
"license": "AGPL-3.0-or-later",
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"@fortawesome/fontawesome-free": "^5.15.4",
|
|
12
|
-
"@webrecorder/wabac": "^2.
|
|
12
|
+
"@webrecorder/wabac": "^2.13.2",
|
|
13
|
+
"auto-js-ipfs": "^1.3.9",
|
|
13
14
|
"bulma": "^0.9.3",
|
|
14
15
|
"electron-log": "^4.4.1",
|
|
15
16
|
"electron-updater": "^4.3.9",
|
|
16
17
|
"fetch-ndjson": "^1.1.6",
|
|
17
18
|
"flexsearch": "^0.7.21",
|
|
18
|
-
"ipfs-core": "^0.10.8",
|
|
19
19
|
"keyword-mark-element": "^0.2.0",
|
|
20
20
|
"lit": "^2.1.1",
|
|
21
21
|
"marked": "^4.0.10",
|
|
@@ -31,9 +31,10 @@
|
|
|
31
31
|
"devDependencies": {
|
|
32
32
|
"copy-webpack-plugin": "^9.0.1",
|
|
33
33
|
"css-loader": "^6.2.0",
|
|
34
|
-
"electron": "^
|
|
34
|
+
"electron": "^20.3.0",
|
|
35
35
|
"electron-builder": "^23.0.3",
|
|
36
36
|
"electron-notarize": "^1.1.1",
|
|
37
|
+
"eslint": "^8.23.1",
|
|
37
38
|
"http-server": "^13.0.2",
|
|
38
39
|
"mini-css-extract-plugin": "^2.3.0",
|
|
39
40
|
"node-sass": "^7.0.1",
|
|
@@ -117,7 +118,7 @@
|
|
|
117
118
|
"extraResources": [
|
|
118
119
|
"plugins-mac"
|
|
119
120
|
],
|
|
120
|
-
"singleArchFiles": "dist/prebuilds
|
|
121
|
+
"singleArchFiles": "{dist/prebuilds,dist/prebuilds/**}"
|
|
121
122
|
},
|
|
122
123
|
"linux": {
|
|
123
124
|
"category": "Archiving;Utility;",
|
package/src/appmain.js
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { LitElement, html, css } from "lit";
|
|
2
2
|
import { wrapCss, rwpLogo, IS_APP, VERSION, clickOnSpacebarPress } from "./misc";
|
|
3
3
|
|
|
4
|
-
import { registerSW } from "./pageutils";
|
|
5
|
-
|
|
6
4
|
import fasHelp from "@fortawesome/fontawesome-free/svgs/solid/question-circle.svg";
|
|
7
5
|
import fasArrowLeft from "@fortawesome/fontawesome-free/svgs/solid/arrow-left.svg";
|
|
8
6
|
import fasArrowRight from "@fortawesome/fontawesome-free/svgs/solid/arrow-right.svg";
|
|
7
|
+
import { SWManager } from "./swmanager";
|
|
9
8
|
|
|
10
9
|
|
|
11
10
|
// ===========================================================================
|
|
@@ -28,9 +27,8 @@ class ReplayWebApp extends LitElement
|
|
|
28
27
|
|
|
29
28
|
this.loadInfo = null;
|
|
30
29
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
}
|
|
30
|
+
this.swmanager = new SWManager({name: swName, appName: this.appName});
|
|
31
|
+
this.swmanager.register().catch(() => this.swErrorMsg = this.swmanager.renderErrorReport(this.mainLogo));
|
|
34
32
|
|
|
35
33
|
this.safariKeyframes();
|
|
36
34
|
}
|
|
@@ -56,7 +54,9 @@ class ReplayWebApp extends LitElement
|
|
|
56
54
|
collPageUrl: { type: String },
|
|
57
55
|
pageTitle: { type: String },
|
|
58
56
|
pageReplay: { type: Boolean },
|
|
59
|
-
source: { type: String }
|
|
57
|
+
source: { type: String },
|
|
58
|
+
|
|
59
|
+
swErrorMsg: { type: Object },
|
|
60
60
|
};
|
|
61
61
|
}
|
|
62
62
|
|
|
@@ -248,6 +248,10 @@ class ReplayWebApp extends LitElement
|
|
|
248
248
|
return html``;
|
|
249
249
|
}
|
|
250
250
|
|
|
251
|
+
if (this.embed && this.swErrorMsg) {
|
|
252
|
+
return this.swErrorMsg;
|
|
253
|
+
}
|
|
254
|
+
|
|
251
255
|
return html`
|
|
252
256
|
${!this.embed || this.embed === "full" ? this.renderNavBar() : ""}
|
|
253
257
|
|
|
@@ -351,10 +355,13 @@ class ReplayWebApp extends LitElement
|
|
|
351
355
|
this.showAbout = true;
|
|
352
356
|
}
|
|
353
357
|
|
|
354
|
-
if (this.pageParams.
|
|
358
|
+
if (this.pageParams.has("embed")) {
|
|
355
359
|
if (!this.loadInfo) {
|
|
356
360
|
this.loadInfo = {};
|
|
357
361
|
}
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
if (this.pageParams.get("config")) {
|
|
358
365
|
try {
|
|
359
366
|
this.loadInfo.extraConfig = JSON.parse(this.pageParams.get("config"));
|
|
360
367
|
} catch (e) {
|
|
@@ -362,38 +369,33 @@ class ReplayWebApp extends LitElement
|
|
|
362
369
|
}
|
|
363
370
|
}
|
|
364
371
|
|
|
372
|
+
if (this.pageParams.get("baseUrlSourcePrefix")) {
|
|
373
|
+
this.loadInfo.extraConfig = this.loadInfo.extraConfig || {};
|
|
374
|
+
this.loadInfo.extraConfig.baseUrlSourcePrefix = this.pageParams.get("baseUrlSourcePrefix");
|
|
375
|
+
}
|
|
376
|
+
|
|
365
377
|
if (this.pageParams.get("basePageUrl")) {
|
|
366
|
-
|
|
367
|
-
this.loadInfo = {extraConfig: {}};
|
|
368
|
-
}
|
|
369
|
-
if (!this.loadInfo.extraConfig) {
|
|
370
|
-
this.loadInfo.extraConfig = {};
|
|
371
|
-
}
|
|
378
|
+
this.loadInfo.extraConfig = this.loadInfo.extraConfig || {};
|
|
372
379
|
this.loadInfo.extraConfig.baseUrl = this.pageParams.get("basePageUrl");
|
|
373
380
|
}
|
|
374
381
|
|
|
375
382
|
if (this.pageParams.get("customColl")) {
|
|
376
|
-
if (!this.loadInfo) {
|
|
377
|
-
this.loadInfo = {};
|
|
378
|
-
}
|
|
379
383
|
this.loadInfo.customColl = this.pageParams.get("customColl");
|
|
380
384
|
}
|
|
381
385
|
|
|
382
386
|
if (this.pageParams.get("noWebWorker") === "1") {
|
|
383
|
-
if (!this.loadInfo) {
|
|
384
|
-
this.loadInfo = {};
|
|
385
|
-
}
|
|
386
387
|
this.loadInfo.noWebWorker = true;
|
|
387
388
|
}
|
|
388
389
|
|
|
389
390
|
|
|
390
391
|
if (this.pageParams.get("noCache") === "1") {
|
|
391
|
-
if (!this.loadInfo) {
|
|
392
|
-
this.loadInfo = {};
|
|
393
|
-
}
|
|
394
392
|
this.loadInfo.noCache = true;
|
|
395
393
|
}
|
|
396
394
|
|
|
395
|
+
if (this.pageParams.get("hideOffscreen") === "1") {
|
|
396
|
+
this.loadInfo.hideOffscreen = true;
|
|
397
|
+
}
|
|
398
|
+
|
|
397
399
|
if (IS_APP && this.sourceUrl.startsWith("file://")) {
|
|
398
400
|
// eslint-disable-next-line no-undef
|
|
399
401
|
const url = new URL(__APP_FILE_SERVE_PREFIX__);
|
package/src/coll-index.js
CHANGED
|
@@ -404,44 +404,88 @@ class CollInfo extends LitElement
|
|
|
404
404
|
`;
|
|
405
405
|
}
|
|
406
406
|
|
|
407
|
-
|
|
407
|
+
renderSource(coll) {
|
|
408
|
+
return html`
|
|
409
|
+
<div class="column is-4">
|
|
410
|
+
<span class="source-text"><p class="minihead">Source</p>
|
|
411
|
+
${coll.sourceUrl && (coll.sourceUrl.startsWith("http://") || coll.sourceUrl.startsWith("https://")) ? html`
|
|
412
|
+
<a href="${coll.sourceUrl}">${coll.sourceUrl} </a>` : html`
|
|
413
|
+
${coll.sourceUrl} `}
|
|
414
|
+
</span>
|
|
415
|
+
|
|
416
|
+
<a @click="${(e) => this.onCopy(e, coll.sourceUrl)}" class="copy"><fa-icon .svg="${fasCopy}"/></a>
|
|
417
|
+
${coll.sourceUrl && coll.sourceUrl.startsWith("googledrive://") ? html`
|
|
418
|
+
<p><i>(${coll.filename})</i></p>` : ""}
|
|
419
|
+
</div>
|
|
420
|
+
<div class="column is-2"><p class="minihead">Date Loaded</p>${coll.ctime ? new Date(coll.ctime).toLocaleString() : ""}</div>
|
|
421
|
+
<div class="column is-2"><p class="minihead">Total Size</p>${prettyBytes(Number(coll.size || 0))}</div>
|
|
422
|
+
`;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
renderSummaryView() {
|
|
426
|
+
const coll = this.coll;
|
|
427
|
+
|
|
428
|
+
return html`
|
|
429
|
+
<div class="columns">
|
|
430
|
+
<div class="column col-title is-4">
|
|
431
|
+
<span class="subtitle has-text-weight-bold">
|
|
432
|
+
<a href="?source=${encodeURIComponent(coll.sourceUrl)}">${coll.title || coll.filename}</a>
|
|
433
|
+
</span>
|
|
434
|
+
</div>
|
|
435
|
+
${this.renderSource(coll)}
|
|
436
|
+
</div>`;
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
renderDetailed() {
|
|
408
440
|
const coll = this.coll;
|
|
409
|
-
|
|
441
|
+
|
|
442
|
+
let {numValid, numInvalid, domain, certFingerprint, datapackageHash, software} = this.coll.verify || {};
|
|
443
|
+
numValid = numValid || 0;
|
|
444
|
+
numInvalid = numInvalid || 0;
|
|
445
|
+
|
|
446
|
+
const certFingerprintUrl = certFingerprint ? `https://search.censys.io/certificates/${certFingerprint}` : "";
|
|
410
447
|
|
|
411
448
|
return html`
|
|
412
449
|
<div class="columns">
|
|
413
450
|
<div class="column col-title is-4">
|
|
414
451
|
<span class="subtitle has-text-weight-bold">
|
|
415
|
-
${detailed ? html`
|
|
416
452
|
${coll.title || coll.filename}
|
|
417
|
-
` : html`
|
|
418
|
-
<a href="?source=${encodeURIComponent(coll.sourceUrl)}">${coll.title || coll.filename}</a>`}
|
|
419
453
|
</span>
|
|
420
454
|
</div>
|
|
421
|
-
${
|
|
455
|
+
${coll.desc ? html`
|
|
422
456
|
<div class="column">
|
|
423
457
|
<p class="minihead">Description</p>
|
|
424
458
|
${coll.desc}
|
|
425
459
|
</div>` : html`
|
|
426
460
|
`}
|
|
427
|
-
<div class="column
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
</
|
|
461
|
+
<div class="column"><p class="minihead">Filename</p>${coll.filename}</div>
|
|
462
|
+
${this.renderSource(coll)}
|
|
463
|
+
|
|
464
|
+
${domain ? html`
|
|
465
|
+
<div class="column">
|
|
466
|
+
<p class="minihead">Observed By</p>
|
|
467
|
+
<p>${domain}</p>
|
|
468
|
+
${certFingerprintUrl ? html`<span><a target="_blank" href="${certFingerprintUrl}">View Certificate</a></span>` : ""}
|
|
469
|
+
</div>
|
|
470
|
+
` : software ? html`
|
|
471
|
+
<div class="column">
|
|
472
|
+
<p class="minihead">Created With</p>
|
|
473
|
+
${software || "Unknown"}
|
|
474
|
+
</div>
|
|
475
|
+
` : ""}
|
|
433
476
|
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
477
|
+
<div class="column">
|
|
478
|
+
<p class="minihead">Validation</p>
|
|
479
|
+
${numValid > 0 || numInvalid > 0 ? html`
|
|
480
|
+
<p>${numValid} hashes verified${numInvalid ? html`, ${numInvalid} invalid` : ""}</p>` : html`
|
|
481
|
+
Not Available`}
|
|
437
482
|
</div>
|
|
438
|
-
${detailed ? html`
|
|
439
|
-
<div class="column"><p class="minihead">Filename</p>${coll.filename}</div>` : html``}
|
|
440
483
|
|
|
441
|
-
<div class="column
|
|
442
|
-
|
|
484
|
+
<div class="column">
|
|
485
|
+
<p class="minihead">Package Hash</p>
|
|
486
|
+
${datapackageHash || "Not Available"}
|
|
487
|
+
</div>
|
|
443
488
|
|
|
444
|
-
${detailed ? html`
|
|
445
489
|
<div class="column">
|
|
446
490
|
<p class="minihead">Loading Mode</p>
|
|
447
491
|
${coll.onDemand ? "Download On-Demand" : "Fully Local"}
|
|
@@ -450,22 +494,12 @@ class CollInfo extends LitElement
|
|
|
450
494
|
<p class="minihead">Collection id</p>
|
|
451
495
|
${coll.coll}
|
|
452
496
|
</div>
|
|
453
|
-
` : html``}
|
|
454
|
-
|
|
455
497
|
</div>`;
|
|
456
498
|
}
|
|
457
499
|
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
// <button @click="${(e) => this.onPurge(true)}" class="button">Purge Cache + Full Reload</button>
|
|
462
|
-
// </div>
|
|
463
|
-
|
|
464
|
-
// ${this.canDelete ? html`
|
|
465
|
-
// <div class="column">
|
|
466
|
-
// <button @click="${(e) => this.onPurge(false)}" class="button is-outlined is-danger">Delete Archive</button>
|
|
467
|
-
// </div>` : html``}
|
|
468
|
-
//
|
|
500
|
+
render() {
|
|
501
|
+
return this.detailed ? this.renderDetailed() : this.renderSummaryView();
|
|
502
|
+
}
|
|
469
503
|
|
|
470
504
|
onCopy(event, sourceUrl) {
|
|
471
505
|
event.preventDefault();
|
package/src/coll.js
CHANGED
|
@@ -24,6 +24,7 @@ import fasMenuV from "@fortawesome/fontawesome-free/svgs/solid/ellipsis-v.svg";
|
|
|
24
24
|
import fasAngleLeft from "@fortawesome/fontawesome-free/svgs/solid/angle-left.svg";
|
|
25
25
|
import fasAngleRight from "@fortawesome/fontawesome-free/svgs/solid/angle-right.svg";
|
|
26
26
|
|
|
27
|
+
import { RWPEmbedReceipt } from "./embed-receipt.js";
|
|
27
28
|
import Split from "split.js";
|
|
28
29
|
|
|
29
30
|
|
|
@@ -61,6 +62,7 @@ class Coll extends LitElement
|
|
|
61
62
|
};
|
|
62
63
|
|
|
63
64
|
this.menuActive = false;
|
|
65
|
+
this.embedDropdownActive = false;
|
|
64
66
|
|
|
65
67
|
this.hasStory = false;
|
|
66
68
|
|
|
@@ -107,6 +109,8 @@ class Coll extends LitElement
|
|
|
107
109
|
menuActive: { type: Boolean },
|
|
108
110
|
|
|
109
111
|
embed: { type: String },
|
|
112
|
+
embedDropdownActive: { type: Boolean },
|
|
113
|
+
|
|
110
114
|
editable: { type: Boolean },
|
|
111
115
|
browsable: { type: Boolean },
|
|
112
116
|
clearable: { type: Boolean },
|
|
@@ -131,7 +135,7 @@ class Coll extends LitElement
|
|
|
131
135
|
this.isFullscreen = !!document.fullscreenElement;
|
|
132
136
|
});
|
|
133
137
|
|
|
134
|
-
if (this.embed) {
|
|
138
|
+
if (this.embed && this.loadInfo && this.loadInfo.hideOffscreen) {
|
|
135
139
|
this.observer = new IntersectionObserver((entries/*, observer*/) => {
|
|
136
140
|
this.isVisible = entries[0].isIntersecting;
|
|
137
141
|
});
|
|
@@ -289,7 +293,7 @@ class Coll extends LitElement
|
|
|
289
293
|
this.collInfo.title = this.collInfo.filename;
|
|
290
294
|
}
|
|
291
295
|
|
|
292
|
-
if (this.embed === "replayonly") {
|
|
296
|
+
if (this.embed === "replayonly" || this.embed === "replay-with-info") {
|
|
293
297
|
this.showSidebar = false;
|
|
294
298
|
}
|
|
295
299
|
|
|
@@ -475,6 +479,13 @@ class Coll extends LitElement
|
|
|
475
479
|
flex: auto;
|
|
476
480
|
}
|
|
477
481
|
|
|
482
|
+
rwp-embed-receipt {
|
|
483
|
+
flex-direction: column;
|
|
484
|
+
display: flex;
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
${RWPEmbedReceipt.embedStyles}
|
|
488
|
+
|
|
478
489
|
${Coll.replayBarStyles}`;
|
|
479
490
|
}
|
|
480
491
|
|
|
@@ -657,6 +668,7 @@ class Coll extends LitElement
|
|
|
657
668
|
} else if (this.collInfo) {
|
|
658
669
|
return html`
|
|
659
670
|
${this.renderLocationBar()}
|
|
671
|
+
${this.renderVerifyInfo()}
|
|
660
672
|
<div id="tabContents">
|
|
661
673
|
<div id="contents" class="is-light ${isSidebar ? "sidebar" : (isReplay ? "is-hidden" : "full-pages")}"
|
|
662
674
|
role="${isSidebar ? "complementary" : ""}" aria-label="${isSidebar ? "Browse Contents" : ""}">
|
|
@@ -744,7 +756,7 @@ class Coll extends LitElement
|
|
|
744
756
|
}
|
|
745
757
|
|
|
746
758
|
renderLocationBar() {
|
|
747
|
-
if (this.embed === "replayonly") {
|
|
759
|
+
if (this.embed === "replayonly" || this.embed == "replay-with-info") {
|
|
748
760
|
return "";
|
|
749
761
|
}
|
|
750
762
|
|
|
@@ -880,6 +892,20 @@ class Coll extends LitElement
|
|
|
880
892
|
</nav><p id="skip-replay-target" tabindex="-1" class="is-sr-only">Skipped</p>`;
|
|
881
893
|
}
|
|
882
894
|
|
|
895
|
+
renderVerifyInfo() {
|
|
896
|
+
if (this.embed !== "replay-with-info") {
|
|
897
|
+
return "";
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
return html`<rwp-embed-receipt
|
|
901
|
+
.collInfo=${this.collInfo}
|
|
902
|
+
url=${this.url}
|
|
903
|
+
ts=${this.ts}
|
|
904
|
+
.appLogo=${this.appLogo}
|
|
905
|
+
>
|
|
906
|
+
</rwp-embed-receipt>`;
|
|
907
|
+
}
|
|
908
|
+
|
|
883
909
|
dragStart() {
|
|
884
910
|
const replay = this.renderRoot.querySelector("wr-coll-replay");
|
|
885
911
|
if (replay) {
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { protocol, session } from "electron";
|
|
2
|
+
|
|
3
|
+
import fetchToHandler from "fetch-to-electron-protocol-handler";
|
|
4
|
+
import makeIPFSFetch from "js-ipfs-fetch";
|
|
5
|
+
import * as IPFS from "ipfs-core";
|
|
6
|
+
|
|
7
|
+
export const PROTOCOL_PERMISSIONS = {
|
|
8
|
+
standard: true,
|
|
9
|
+
secure: true,
|
|
10
|
+
allowServiceWorkers: true,
|
|
11
|
+
supportFetchAPI: true,
|
|
12
|
+
bypassCSP: false,
|
|
13
|
+
corsEnabled: true,
|
|
14
|
+
stream: true
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export function registerPrivileges(privileges = PROTOCOL_PERMISSIONS) {
|
|
18
|
+
protocol.registerSchemesAsPrivileged([
|
|
19
|
+
{scheme: "ipfs", privileges},
|
|
20
|
+
{scheme: "ipns", privileges},
|
|
21
|
+
{scheme: "ipld", privileges}
|
|
22
|
+
]);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function registerHandler(ipfsRepoPath) {
|
|
26
|
+
const handler = createHandler(ipfsRepoPath);
|
|
27
|
+
protocol.registerStreamProtocol("ipfs", handler);
|
|
28
|
+
protocol.registerStreamProtocol("ipns", handler);
|
|
29
|
+
protocol.registerStreamProtocol("ipld", handler);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function createHandler (ipfsRepoPath) {
|
|
33
|
+
const {handler} = fetchToHandler(async () => {
|
|
34
|
+
const ipfs = await IPFS.create({
|
|
35
|
+
repo: ipfsRepoPath
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
const fetch = await makeIPFSFetch({ ipfs });
|
|
39
|
+
|
|
40
|
+
return fetch;
|
|
41
|
+
}, session.defaultSession);
|
|
42
|
+
|
|
43
|
+
return handler;
|
|
44
|
+
}
|
|
@@ -9,7 +9,7 @@ import path from "path";
|
|
|
9
9
|
import fs from "fs";
|
|
10
10
|
|
|
11
11
|
import { ArchiveResponse, Rewriter } from "@webrecorder/wabac/src/rewrite";
|
|
12
|
-
import {
|
|
12
|
+
import {create as createIPFS} from "auto-js-ipfs";
|
|
13
13
|
|
|
14
14
|
import { PassThrough, Readable } from "stream";
|
|
15
15
|
|
|
@@ -27,33 +27,6 @@ const REPLAY_PREFIX = STATIC_PREFIX + "w/";
|
|
|
27
27
|
|
|
28
28
|
const URL_RX = /([^/]+)\/([\d]+)(?:\w\w_)?\/(.*)$/;
|
|
29
29
|
|
|
30
|
-
|
|
31
|
-
let IPFS = null;
|
|
32
|
-
|
|
33
|
-
// ============================================================================
|
|
34
|
-
class NativeIPFSClient extends IPFSClient
|
|
35
|
-
{
|
|
36
|
-
constructor(repoPath) {
|
|
37
|
-
super();
|
|
38
|
-
this.repoPath = repoPath;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
async _doInitIPFS() {
|
|
42
|
-
if (!IPFS) {
|
|
43
|
-
IPFS = require("ipfs-core");
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
this.ipfs = await IPFS.create({
|
|
47
|
-
repo: this.repoPath,
|
|
48
|
-
init: {emptyRepo: true},
|
|
49
|
-
//preload: {enabled: false},
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
this.resetGC();
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
|
|
57
30
|
// ============================================================================
|
|
58
31
|
class ElectronReplayApp
|
|
59
32
|
{
|
|
@@ -145,11 +118,6 @@ class ElectronReplayApp
|
|
|
145
118
|
app.setPath("userData", path.join(app.getPath("appData"), this.profileName));
|
|
146
119
|
}
|
|
147
120
|
|
|
148
|
-
const ipfsRepoPath = path.join(app.getPath("userData"), "js-ipfs");
|
|
149
|
-
console.log("ipfs path", ipfsRepoPath);
|
|
150
|
-
|
|
151
|
-
this.ipfsClient = new NativeIPFSClient(ipfsRepoPath);
|
|
152
|
-
|
|
153
121
|
app.on("will-finish-launching", () => {
|
|
154
122
|
app.on("open-file", (event, filePath) => {
|
|
155
123
|
this.openNextFile = filePath;
|
|
@@ -185,6 +153,9 @@ class ElectronReplayApp
|
|
|
185
153
|
}
|
|
186
154
|
|
|
187
155
|
onAppReady() {
|
|
156
|
+
const ipfsRepoPath = path.join(app.getPath("userData"), "js-ipfs");
|
|
157
|
+
console.log("ipfs path", ipfsRepoPath);
|
|
158
|
+
|
|
188
159
|
this.checkUpdates();
|
|
189
160
|
|
|
190
161
|
this.screenSize = screen.getPrimaryDisplay().workAreaSize;
|
|
@@ -197,6 +168,12 @@ class ElectronReplayApp
|
|
|
197
168
|
return { action: "deny"};
|
|
198
169
|
}
|
|
199
170
|
|
|
171
|
+
// load external URLs in native browser
|
|
172
|
+
if (!url.startsWith(STATIC_PREFIX)) {
|
|
173
|
+
shell.openExternal(url);
|
|
174
|
+
return { action: "deny"};
|
|
175
|
+
}
|
|
176
|
+
|
|
200
177
|
return { action: "allow"};
|
|
201
178
|
});
|
|
202
179
|
});
|
|
@@ -293,13 +270,16 @@ class ElectronReplayApp
|
|
|
293
270
|
return;
|
|
294
271
|
|
|
295
272
|
} else if (ipfsCID) {
|
|
273
|
+
const ipfsURL = `ipfs://${ipfsCID}}`;
|
|
274
|
+
|
|
296
275
|
console.log("ipfs serve:", ipfsCID);
|
|
297
276
|
|
|
298
|
-
|
|
277
|
+
// TODO: Pass in config?
|
|
278
|
+
this.ipfsClient = await createIPFS();
|
|
299
279
|
|
|
300
280
|
console.log("inited");
|
|
301
281
|
|
|
302
|
-
let size = await this.ipfsClient.
|
|
282
|
+
let size = await this.ipfsClient.getSize(ipfsURL);
|
|
303
283
|
|
|
304
284
|
console.log("got size", size);
|
|
305
285
|
|
|
@@ -314,7 +294,10 @@ class ElectronReplayApp
|
|
|
314
294
|
if (request.method === "GET") {
|
|
315
295
|
const offset = start || 0;
|
|
316
296
|
const length = end ? end - start + 1 : size;
|
|
317
|
-
data = Readable.from(await this.ipfsClient.
|
|
297
|
+
data = Readable.from(await this.ipfsClient.get(ipfsURL, {
|
|
298
|
+
start: offset,
|
|
299
|
+
end: offset +length
|
|
300
|
+
}));
|
|
318
301
|
}
|
|
319
302
|
|
|
320
303
|
callback({statusCode, headers, data});
|