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 +2 -2
- package/src/appmain.js +65 -1
- package/src/chooser.js +44 -19
- package/src/coll.js +1 -0
- package/src/pages.js +11 -0
- package/sw.js +10 -10
- package/ui.js +54 -26
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "replaywebpage",
|
|
3
3
|
"productName": "ReplayWeb.page",
|
|
4
|
-
"version": "1.7.
|
|
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.
|
|
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
|
-
|
|
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
|
|
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
|
|
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
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 {
|