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.
@@ -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>
@@ -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.6.5",
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.5",
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": "^19.0.4",
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
- if (swName) {
32
- registerSW(swName);
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.get("config")) {
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
- if (!this.loadInfo) {
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
- render() {
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}&nbsp;</a>` : html`
413
+ ${coll.sourceUrl}&nbsp;`}
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
- const detailed = this.detailed;
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
- ${detailed && coll.desc ? html`
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 is-4">
428
- <span class="source-text"><p class="minihead">Source</p>
429
- ${coll.sourceUrl && (coll.sourceUrl.startsWith("http://") || coll.sourceUrl.startsWith("https://")) ? html`
430
- <a href="${coll.sourceUrl}">${coll.sourceUrl}&nbsp;</a>` : html`
431
- ${coll.sourceUrl}&nbsp;`}
432
- </span>
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
- <a @click="${(e) => this.onCopy(e, coll.sourceUrl)}" class="copy"><fa-icon .svg="${fasCopy}"/></a>
435
- ${coll.sourceUrl && coll.sourceUrl.startsWith("googledrive://") ? html`
436
- <p><i>(${coll.filename})</i></p>` : ""}
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 is-2"><p class="minihead">Date Loaded</p>${coll.ctime ? new Date(coll.ctime).toLocaleString() : ""}</div>
442
- <div class="column is-2"><p class="minihead">Total Size</p>${prettyBytes(Number(coll.size || 0))}</div>
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
- // purge + delete buttons
459
- //
460
- // <div class="column">
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 { IPFSClient } from "@webrecorder/wabac/src/ipfs";
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
- await this.ipfsClient.initIPFS();
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.getFileSize(ipfsCID);
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.cat(ipfsCID, {offset, length}));
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});