Skip to content

Commit 25785f3

Browse files
authored
Merge pull request #1274 from pwnall/add-persistence
Add option to make storage persistent to Offline page.
2 parents c3359eb + 853b493 commit 25785f3

3 files changed

Lines changed: 80 additions & 8 deletions

File tree

‎assets/javascripts/templates/pages/offline_tmpl.js‎

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
app.templates.offlinePage = (docs) => `\
1+
app.templates.offlinePage = (docs, hasPersistence, isPersistent) => `\
22
<h1 class="_lined-heading">Offline Documentation</h1>
33
44
<div class="_docs-tools">
@@ -23,7 +23,9 @@ app.templates.offlinePage = (docs) => `\
2323
${docs}
2424
</table>
2525
</div>
26-
<p class="_note"><strong>Note:</strong> your browser may delete DevDocs's offline data if your computer is running low on disk space and you haven't used the app in a while. Load this page before going offline to make sure the data is still there.
26+
<div id="_offline-persistence-note">
27+
${offlinePersistenceNote(hasPersistence, isPersistent)}
28+
</div>
2729
<h2 class="_block-heading">Questions & Answers</h2>
2830
<dl>
2931
<dt>How does this work?
@@ -42,6 +44,33 @@ app.templates.offlinePage = (docs) => `\
4244
</dl>\
4345
`;
4446

47+
app.templates.persistenceError = function (exception) {
48+
const reason = exception
49+
? `<code class="_label">${exception.name}: ${exception.message}</code>`
50+
: "Bookmark this site and try again.";
51+
52+
return `<p class="_note _note-red"><strong>Persistent storage was denied by your browser.</strong> ${reason}`;
53+
};
54+
55+
var offlinePersistenceNote = function (hasPersistence, isPersistent) {
56+
if (isPersistent) {
57+
return "";
58+
}
59+
60+
let html =
61+
"<p class=\"_note\"><strong>Note:</strong> your browser may delete DevDocs's offline data if your computer is running low on disk space and you haven't used the app in a while.";
62+
63+
if (hasPersistence) {
64+
html +=
65+
' <button type="button" class="_btn-link _bold" data-enable-persistence>Enable persistent storage</button>.';
66+
} else {
67+
html +=
68+
" Load this page before going offline to make sure the data is still there.";
69+
}
70+
71+
return html;
72+
};
73+
4574
var canICloseTheTab = function () {
4675
if (app.ServiceWorker.isEnabled()) {
4776
return ' Yes! Even offline, you can open a new tab, go to <a href="//devdocs.io">devdocs.io</a>, and everything will work as if you were online (provided you installed all the documentations you want to use beforehand). ';

‎assets/javascripts/views/content/offline_page.js‎

Lines changed: 48 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,19 @@ app.views.OfflinePage = class OfflinePage extends app.View {
2525
if (statuses === false) {
2626
this.html(this.tmpl("offlineError", app.db.reason, app.db.error));
2727
} else {
28-
let html = "";
29-
for (var doc of app.docs.all()) {
30-
html += this.renderDoc(doc, statuses[doc.slug]);
31-
}
32-
this.html(this.tmpl("offlinePage", html));
33-
this.refreshLinks();
28+
this.checkPersistence((hasPersistence, isPersistent) => {
29+
if (!this.activated) {
30+
return;
31+
}
32+
let html = "";
33+
for (var doc of app.docs.all()) {
34+
html += this.renderDoc(doc, statuses[doc.slug]);
35+
}
36+
this.html(
37+
this.tmpl("offlinePage", html, hasPersistence, isPersistent)
38+
);
39+
this.refreshLinks();
40+
});
3441
}
3542
});
3643
}
@@ -93,6 +100,8 @@ app.views.OfflinePage = class OfflinePage extends app.View {
93100
for (el of Array.from(this.findAll(`[data-action='${action}']`))) {
94101
$.click(el);
95102
}
103+
} else if (el.hasAttribute("data-enable-persistence")) {
104+
this.requestPersistence();
96105
}
97106
}
98107

@@ -142,4 +151,37 @@ app.views.OfflinePage = class OfflinePage extends app.View {
142151
app.settings.set("manualUpdate", !event.target.checked);
143152
}
144153
}
154+
155+
checkPersistence(callback) {
156+
if (navigator.storage && navigator.storage.persisted) {
157+
navigator.storage
158+
.persisted()
159+
.then((persisted) => callback(true, persisted))
160+
.catch(() => callback(false, false));
161+
} else {
162+
callback(false, false);
163+
}
164+
}
165+
166+
requestPersistence() {
167+
navigator.storage
168+
.persist()
169+
.then((success) => this.onPersistenceRequestCompleted(success))
170+
.catch((exception) =>
171+
this.onPersistenceRequestCompleted(false, exception)
172+
);
173+
}
174+
175+
onPersistenceRequestCompleted(success, exception) {
176+
if (!this.activated) {
177+
return;
178+
}
179+
const note = this.find("#_offline-persistence-note");
180+
if (!note) {
181+
return;
182+
}
183+
// Granting persistence retires the note, which is what a fresh render of
184+
// the page would produce; the disappearing button is the confirmation.
185+
note.innerHTML = success ? "" : this.tmpl("persistenceError", exception);
186+
}
145187
};

‎assets/stylesheets/components/_content.scss‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,7 @@
385385
._bold { font-weight: var(--boldFontWeight); }
386386
._note { @extend %note; }
387387
._note-green { @extend %note-green; }
388+
._note-red { @extend %note-red; }
388389
._label { @extend %label; }
389390
._code { @extend %code; }
390391
._highlight, ._highlight > td { background: var(--highlightBackground) !important; }

0 commit comments

Comments
 (0)