1
0
Fork 0
mirror of https://github.com/miniflux/v2.git synced 2025-08-26 18:21:01 +00:00

PWA: First implementation of offline mode

This commit is contained in:
Brieuc Dubois 2024-06-21 19:13:54 +02:00
parent 05f7a34d43
commit 925ea2c082
10 changed files with 1851 additions and 1076 deletions

View file

@ -52,6 +52,7 @@ type SettingsForm struct {
MediaPlaybackRate float64
BlockFilterEntryRules string
KeepFilterEntryRules string
CacheForOffline bool
}
// MarkAsReadBehavior returns the MarkReadBehavior from the given MarkReadOnView and MarkReadOnMediaPlayerCompletion values.
@ -119,6 +120,8 @@ func (s *SettingsForm) Merge(user *model.User) *model.User {
user.MarkReadOnView = MarkReadOnView
user.MarkReadOnMediaPlayerCompletion = MarkReadOnMediaPlayerCompletion
user.CacheForOffline = s.CacheForOffline
if s.Password != "" {
user.Password = s.Password
}
@ -205,5 +208,6 @@ func NewSettingsForm(r *http.Request) *SettingsForm {
MediaPlaybackRate: mediaPlaybackRate,
BlockFilterEntryRules: r.FormValue("block_filter_entry_rules"),
KeepFilterEntryRules: r.FormValue("keep_filter_entry_rules"),
CacheForOffline: r.FormValue("cache_for_offline") == "1",
}
}

View file

@ -46,6 +46,7 @@ func (h *handler) showSettingsPage(w http.ResponseWriter, r *http.Request) {
MediaPlaybackRate: user.MediaPlaybackRate,
BlockFilterEntryRules: user.BlockFilterEntryRules,
KeepFilterEntryRules: user.KeepFilterEntryRules,
CacheForOffline: user.CacheForOffline,
}
timezones, err := h.store.Timezones()

File diff suppressed because it is too large Load diff

View file

@ -1,44 +1,66 @@
// Incrementing OFFLINE_VERSION will kick off the install event and force
// previously cached resources to be updated from the network.
const OFFLINE_VERSION = 1;
const OFFLINE_VERSION = 2;
const CACHE_NAME = "offline";
console.log(USE_CACHE);
self.addEventListener("install", (event) => {
event.waitUntil(
(async () => {
const cache = await caches.open(CACHE_NAME);
event.waitUntil(
(async () => {
const cache = await caches.open(CACHE_NAME);
// Setting {cache: 'reload'} in the new request will ensure that the
// response isn't fulfilled from the HTTP cache; i.e., it will be from
// the network.
await cache.add(new Request(OFFLINE_URL, { cache: "reload" }));
})()
);
if (USE_CACHE) {
await cache.addAll(["/", "/unread", OFFLINE_URL]);
} else {
// Setting {cache: 'reload'} in the new request will ensure that the
// response isn't fulfilled from the HTTP cache; i.e., it will be from
// the network.
await cache.add(new Request(OFFLINE_URL, { cache: "reload" }));
}
})(),
);
// Force the waiting service worker to become the active service worker.
self.skipWaiting();
// Force the waiting service worker to become the active service worker.
self.skipWaiting();
});
self.addEventListener("fetch", (event) => {
// We proxify requests through fetch() only if we are offline because it's slower.
if (navigator.onLine === false && event.request.mode === "navigate") {
event.respondWith(
(async () => {
try {
// Always try the network first.
const networkResponse = await fetch(event.request);
return networkResponse;
} catch (error) {
// catch is only triggered if an exception is thrown, which is likely
// due to a network error.
// If fetch() returns a valid HTTP response with a response code in
// the 4xx or 5xx range, the catch() will NOT be called.
const cache = await caches.open(CACHE_NAME);
const cachedResponse = await cache.match(OFFLINE_URL);
return cachedResponse;
}
})()
);
}
// We proxify requests through fetch() only if we are offline because it's slower.
if (
USE_CACHE ||
(navigator.onLine === false && event.request.mode === "navigate")
) {
event.respondWith(
(async () => {
try {
// Always try the network first.
const networkResponse = await fetch(event.request);
if (USE_CACHE) {
const cache = await caches.open(CACHE_NAME);
cache.put(event.request, networkResponse.clone());
}
return networkResponse;
} catch (error) {
// catch is only triggered if an exception is thrown, which is likely
// due to a network error.
// If fetch() returns a valid HTTP response with a response code in
// the 4xx or 5xx range, the catch() will NOT be called.
const cache = await caches.open(CACHE_NAME);
if (!USE_CACHE) {
return await cache.match(OFFLINE_URL);
}
const cachedResponse = await cache.match(event.request);
if (cachedResponse) {
return cachedResponse;
}
return await cache.match(OFFLINE_URL);
}
})(),
);
}
});

View file

@ -31,7 +31,19 @@ func (h *handler) showJavascript(w http.ResponseWriter, r *http.Request) {
contents := static.JavascriptBundles[filename]
if filename == "service-worker" {
variables := fmt.Sprintf(`const OFFLINE_URL=%q;`, route.Path(h.router, "offline"))
user, err := h.store.UserByID(request.UserID(r))
if err != nil {
html.ServerError(w, r, err)
return
}
cacheForOffline := 0
if user.CacheForOffline {
cacheForOffline = 1
}
variables := fmt.Sprintf(`const OFFLINE_URL=%q;const USE_CACHE=%d;`, route.Path(h.router, "offline"), cacheForOffline)
contents = append([]byte(variables), contents...)
}