replaywebpage 1.7.13 → 1.7.15

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "replaywebpage",
3
3
  "productName": "ReplayWeb.page",
4
- "version": "1.7.13",
4
+ "version": "1.7.15",
5
5
  "description": "Serverless Web Archive Replay",
6
6
  "repository": "https://github.com/webrecorder/replayweb.page",
7
7
  "homepage": "https://replayweb.page/",
@@ -9,7 +9,7 @@
9
9
  "license": "AGPL-3.0-or-later",
10
10
  "dependencies": {
11
11
  "@fortawesome/fontawesome-free": "^5.15.4",
12
- "@webrecorder/wabac": "^2.15.3",
12
+ "@webrecorder/wabac": "^2.16.0",
13
13
  "bulma": "^0.9.3",
14
14
  "electron-log": "^4.4.1",
15
15
  "electron-updater": "^5.3.0",
package/src/appmain.js CHANGED
@@ -16,6 +16,7 @@ class ReplayWebApp extends LitElement
16
16
  this.sourceUrl = null;
17
17
  this.collTitle = null;
18
18
  this.showAbout = false;
19
+ this.showFileDropOverlay = false;
19
20
  this.pageParams = new URLSearchParams();
20
21
 
21
22
  this.inited = false;
@@ -31,6 +32,37 @@ class ReplayWebApp extends LitElement
31
32
  this.swmanager.register().catch(() => this.swErrorMsg = this.swmanager.renderErrorReport(this.mainLogo));
32
33
 
33
34
  this.safariKeyframes();
35
+
36
+ this.addEventListener("dragenter", (dragEvent) => {
37
+ this.maybeStartFileDrop(dragEvent);
38
+ });
39
+
40
+ this.addEventListener("dragover", (dragEvent) => {
41
+ this.maybeStartFileDrop(dragEvent);
42
+ });
43
+
44
+ this.addEventListener("dragleave", () => {
45
+ this.showFileDropOverlay = false;
46
+ });
47
+
48
+ this.addEventListener("dragend", () => {
49
+ this.showFileDropOverlay = false;
50
+ });
51
+
52
+ this.addEventListener("drop", (dragEvent) => {
53
+ this.droppedFile = dragEvent.dataTransfer.files[0];
54
+ this.showFileDropOverlay = false;
55
+ dragEvent.preventDefault();
56
+ });
57
+
58
+ this.maybeStartFileDrop = (dragEvent) => {
59
+ if (this.sourceUrl) {
60
+ // A source is already loaded. Don't allow dropping a file.
61
+ return;
62
+ }
63
+ this.showFileDropOverlay = true;
64
+ dragEvent.preventDefault();
65
+ };
34
66
  }
35
67
 
36
68
  get appName() {
@@ -48,6 +80,7 @@ class ReplayWebApp extends LitElement
48
80
  sourceUrl: { type: String },
49
81
  navMenuShown: { type: Boolean },
50
82
  showAbout: { type: Boolean },
83
+ showFileDropOverlay: { type: Boolean },
51
84
  collTitle: { type: String },
52
85
  loadInfo: { type: Object },
53
86
  embed: { type: String },
@@ -112,6 +145,29 @@ class ReplayWebApp extends LitElement
112
145
  margin-top: 1.0rem;
113
146
  }
114
147
 
148
+ .drop-file-overlay {
149
+ position: relative;
150
+ display: flex;
151
+ align-items: center;
152
+ justify-content: center;
153
+ position: fixed;
154
+ inset: 0;
155
+ z-index: 50;
156
+ font-weight: bold;
157
+ font-size: 1.5rem;
158
+ background: rgba(255,255,255,.5);
159
+ backdrop-filter: blur(2px);
160
+ }
161
+
162
+ .drop-file-overlay:after {
163
+ pointer-events: none;
164
+ content: " ";
165
+ position: absolute;
166
+ inset: 0;
167
+ border: 5px dashed #aaa;
168
+ margin: 15px;
169
+ }
170
+
115
171
  @media screen and (min-width: 840px) {
116
172
  .menu-only {
117
173
  display: none;
@@ -239,7 +295,7 @@ class ReplayWebApp extends LitElement
239
295
  ${!IS_APP ? html`
240
296
  <p slot="header" class="tagline is-size-5 has-text-centered">Explore and Replay Interactive Archived Webpages Directly in your Browser. <i><a target="_blank" href="./docs/examples">(See Examples)</a></i></p>
241
297
  ` : ""}
242
- <wr-chooser slot="header" @load-start=${this.onStartLoad}></wr-chooser>
298
+ <wr-chooser slot="header" .droppedFile=${this.droppedFile} @did-drop-file="${() => this.droppedFile = null}" @load-start=${this.onStartLoad}></wr-chooser>
243
299
  </wr-coll-index>`;
244
300
  }
245
301
 
@@ -258,6 +314,8 @@ class ReplayWebApp extends LitElement
258
314
  ${this.sourceUrl ? this.renderColl() : this.renderHomeIndex()}
259
315
 
260
316
  ${this.showAbout ? this.renderAbout() : ""}
317
+
318
+ ${this.showFileDropOverlay ? this.renderDropFileOverlay() : ""}
261
319
  `;
262
320
  }
263
321
 
@@ -536,6 +594,12 @@ class ReplayWebApp extends LitElement
536
594
  onAboutClose() {
537
595
  this.showAbout = false;
538
596
  }
597
+
598
+ renderDropFileOverlay() {
599
+ return html`
600
+ <div class="drop-file-overlay">Drop to load web archive</div>
601
+ `;
602
+ }
539
603
  }
540
604
 
541
605
  customElements.define("replay-app-main", ReplayWebApp);
package/src/chooser.js CHANGED
@@ -12,28 +12,66 @@ class Chooser extends LitElement
12
12
 
13
13
  this.fileDisplayName = "";
14
14
  this.file = null;
15
+ this.droppedFile = null;
15
16
 
16
17
  this.hasNativeFS = !!window.showOpenFilePicker && !IS_APP;
17
18
 
18
19
  this.newFullImport = false;
19
20
 
20
21
  this.noHead = false;
22
+
23
+ this.showOpenFilePickerOptions = {
24
+ types: [
25
+ {
26
+ description: "WARC, WACZ, HAR and WBN Files",
27
+ accept: {
28
+ "application/warc": [".warc", ".gz"],
29
+ "application/har": [".har"],
30
+ "application/wacz": [".wacz"],
31
+ "application/wbn": [".wbn"],
32
+ "application/json": [".json"],
33
+ }
34
+ }
35
+ ]
36
+ };
21
37
  }
22
38
 
23
39
  static get properties() {
24
40
  return {
25
41
  fileDisplayName: { type: String },
42
+ droppedFile: { type: File },
26
43
  newFullImport: { type: Boolean },
27
44
  noHead: { type: Boolean }
28
45
  };
29
46
  }
30
47
 
48
+ updated(changedProperties) {
49
+ if (changedProperties.has("droppedFile") && this.droppedFile) {
50
+ this.onDropFile();
51
+ }
52
+ }
53
+
54
+ onDropFile() {
55
+ const allowedFileExtensions = this.showOpenFilePickerOptions.types.map(type => type.accept).map(Object.values).flat(2);
56
+
57
+ const fileHasAllowedExtension = allowedFileExtensions.some(extension => this.droppedFile.name.endsWith(extension));
58
+
59
+ if (fileHasAllowedExtension) {
60
+ this.setFile(this.droppedFile);
61
+ this.dispatchEvent(new CustomEvent("did-drop-file", { bubbles: true, composed: true }));
62
+ this.onStartLoad(); // Automatically load the file
63
+ }
64
+ }
65
+
31
66
  onChooseFile(event) {
32
67
  if (event.currentTarget.files.length === 0) {
33
68
  return;
34
69
  }
70
+ this.setFile(event.currentTarget.files[0]);
71
+ }
35
72
 
36
- this.file = event.currentTarget.files[0];
73
+ setFile(file) {
74
+ this.file = file;
37
75
  // file.path only available in electron app
38
76
  this.fileDisplayName = "file://" + (this.file.path || this.file.name);
39
77
  }
@@ -43,22 +81,7 @@ class Chooser extends LitElement
43
81
  return;
44
82
  }
45
83
 
46
- const options = {
47
- types: [
48
- {
49
- description: "WARC, WACZ, HAR and WBN Files",
50
- accept: {
51
- "application/warc": [".warc", ".gz"],
52
- "application/har": [".har"],
53
- "application/wacz": [".wacz"],
54
- "application/wbn": [".wbn"],
55
- "application/json": [".json"],
56
- }
57
- }
58
- ]
59
- };
60
-
61
- const [fileHandle] = await window.showOpenFilePicker(options);
84
+ const [fileHandle] = await window.showOpenFilePicker(this.showOpenFilePickerOptions);
62
85
  this.fileHandle = fileHandle;
63
86
 
64
87
  this.file = await fileHandle.getFile();
@@ -70,7 +93,9 @@ class Chooser extends LitElement
70
93
  }
71
94
 
72
95
  onStartLoad(event) {
73
- event.preventDefault();
96
+ if (event) {
97
+ event.preventDefault();
98
+ }
74
99
 
75
100
  const loadInfo = {sourceUrl: this.fileDisplayName};
76
101
 
@@ -192,7 +217,7 @@ class Chooser extends LitElement
192
217
  <p class="control is-expanded">
193
218
  <input class="file-name input" type="text"
194
219
  name="filename" id="filename"
195
- pattern="((file|http|https|ipfs|s3):\/\/.*\.(warc|warc.gz|zip|wacz|har|wbn|json))|(googledrive:\/\/.+)|(ssb:\/\/.+)"
220
+ pattern="((file|http|https|ipfs|s3):\/\/.*\.(warc|warc.gz|zip|wacz|har|wbn|json)([?#].*)?)|(googledrive:\/\/.+)|(ssb:\/\/.+)"
196
221
  .value="${this.fileDisplayName}"
197
222
  @input="${this.onInput}"
198
223
  autocomplete="off"
package/src/coll.js CHANGED
@@ -476,6 +476,7 @@ class Coll extends LitElement
476
476
  flex-direction: column;
477
477
  min-height: 0px;
478
478
  flex: auto;
479
+ background-color: white;
479
480
  }
480
481
 
481
482
  #tabContents {
package/src/pages.js CHANGED
@@ -853,6 +853,17 @@ class Pages extends LitElement
853
853
  }
854
854
 
855
855
  formatResults() {
856
+ // Default behavior: Count all available pages
857
+ if (!this.query) {
858
+ const length = this.collInfo.pages.length;
859
+ if (length === this.sortedPages.length) {
860
+ return `${length} Page${length ? "s" : ""} Found`;
861
+ } else {
862
+ return `${this.sortedPages.length} of ${length} Pages Found`;
863
+ }
864
+ }
865
+
866
+ // ... unless they were filtered
856
867
  if (this.sortedPages.length === 1) {
857
868
  return "1 Page Found";
858
869
  } else {