Revert "feat: replace Web Push with ntfy for medication reminders"
This reverts commit 1cada42370.
This commit is contained in:
+14
-14
@@ -2,7 +2,7 @@ import { api } from "./lib/api.js";
|
||||
import { getToken, setToken, clearToken, isLoggedIn } from "./lib/auth.js";
|
||||
import { setStreakBadge } from "./lib/badge.js";
|
||||
import { enqueue, flushQueue } from "./lib/offlineQueue.js";
|
||||
import { registerPwa, wirePwaInstall } from "./lib/pwa.js";
|
||||
import { registerPwa, wirePwaInstall, subscribePush } from "./lib/pwa.js";
|
||||
import { renderSlots, renderHeatmap, updateStats, showToast, showConfetti, showEasterEgg } from "./lib/ui.js";
|
||||
|
||||
const STATUS = { upcoming: "Noch nicht", pending: "Jetzt!", overdue: "Überfällig", snoozed: "Snoozed", taken: "Genommen", missed: "Verpasst" };
|
||||
@@ -153,20 +153,20 @@ async function initApp() {
|
||||
location.reload();
|
||||
});
|
||||
|
||||
try {
|
||||
const notify = await api.notifyConfig();
|
||||
const topicEl = document.getElementById("notifyTopic");
|
||||
const linkEl = document.getElementById("notifySubscribeLink");
|
||||
if (notify.configured && notify.subscribe_url) {
|
||||
topicEl.textContent = `Topic: ${notify.topic}`;
|
||||
linkEl.href = notify.subscribe_url;
|
||||
} else {
|
||||
topicEl.textContent = "ntfy nicht konfiguriert (NTFY_URL + NTFY_TOPIC in .env).";
|
||||
linkEl.hidden = true;
|
||||
document.getElementById("enablePush").addEventListener("click", async () => {
|
||||
const statusEl = document.getElementById("pushStatus");
|
||||
try {
|
||||
const perm = await Notification.requestPermission();
|
||||
if (perm !== "granted") { statusEl.textContent = "Permission verweigert."; return; }
|
||||
const { key } = await api.vapidKey();
|
||||
if (!key) { statusEl.textContent = "VAPID keys nicht konfiguriert."; return; }
|
||||
const sub = await subscribePush(key);
|
||||
await api.pushSubscribe(sub);
|
||||
statusEl.textContent = "Push aktiv! Du wirst dezent erinnert.";
|
||||
} catch (e) {
|
||||
statusEl.textContent = e.message || "Push-Setup fehlgeschlagen.";
|
||||
}
|
||||
} catch {
|
||||
document.getElementById("notifyTopic").textContent = "Notify-Config konnte nicht geladen werden.";
|
||||
}
|
||||
});
|
||||
|
||||
await flushQueue((data) => api.log(data));
|
||||
await refreshDashboard();
|
||||
|
||||
+3
-4
@@ -74,10 +74,9 @@
|
||||
<div id="tab-settings" class="tabPanel" hidden>
|
||||
<div class="settingsGroup">
|
||||
<h2>Benachrichtigungen</h2>
|
||||
<p class="settingsHint">Erinnerungen um 8:00 und 12:00 per ntfy — dezent, kein Alarm.</p>
|
||||
<p id="notifyTopic" class="settingsStatus"></p>
|
||||
<a id="notifySubscribeLink" class="btn btn-accent" href="#" target="_blank" rel="noopener">In ntfy abonnieren</a>
|
||||
<p class="settingsHint">ntfy-App installiert? Link tippen → Topic abonnieren. Danach kommen Reminder zuverlässig.</p>
|
||||
<p class="settingsHint">Push-Erinnerungen um 8:00 und 12:00 — dezent, kein Alarm.</p>
|
||||
<button type="button" class="btn btn-accent" id="enablePush">Push aktivieren</button>
|
||||
<p id="pushStatus" class="settingsStatus"></p>
|
||||
</div>
|
||||
<div class="settingsGroup" id="pwaInstallSection" hidden>
|
||||
<h2>App installieren</h2>
|
||||
|
||||
+3
-1
@@ -27,5 +27,7 @@ export const api = {
|
||||
stats: () => request("/api/stats"),
|
||||
roast: () => request("/api/roast"),
|
||||
snooze: (slot_id, minutes) => request("/api/snooze", { method: "POST", body: JSON.stringify({ slot_id, minutes }) }),
|
||||
notifyConfig: () => request("/api/notify-config"),
|
||||
vapidKey: () => request("/api/vapid-public-key"),
|
||||
pushSubscribe: (subscription) =>
|
||||
request("/api/push/subscribe", { method: "POST", body: JSON.stringify({ subscription }) }),
|
||||
};
|
||||
|
||||
@@ -46,3 +46,23 @@ export async function registerPwa() {
|
||||
console.error("SW registration failed:", e);
|
||||
}
|
||||
}
|
||||
|
||||
export async function subscribePush(vapidPublicKey) {
|
||||
if (!("PushManager" in window)) throw new Error("Push nicht unterstützt");
|
||||
const reg = await navigator.serviceWorker.ready;
|
||||
let sub = await reg.pushManager.getSubscription();
|
||||
if (!sub) {
|
||||
sub = await reg.pushManager.subscribe({
|
||||
userVisibleOnly: true,
|
||||
applicationServerKey: urlBase64ToUint8Array(vapidPublicKey),
|
||||
});
|
||||
}
|
||||
return sub.toJSON();
|
||||
}
|
||||
|
||||
function urlBase64ToUint8Array(base64String) {
|
||||
const padding = "=".repeat((4 - (base64String.length % 4)) % 4);
|
||||
const base64 = (base64String + padding).replace(/-/g, "+").replace(/_/g, "/");
|
||||
const raw = atob(base64);
|
||||
return Uint8Array.from([...raw].map((c) => c.charCodeAt(0)));
|
||||
}
|
||||
|
||||
+57
-1
@@ -1,4 +1,4 @@
|
||||
const CACHE = "tym-v1.1.0";
|
||||
const CACHE = "tym-v1.0.1";
|
||||
const ASSETS = [
|
||||
"/",
|
||||
"/index.html",
|
||||
@@ -64,6 +64,62 @@ self.addEventListener("fetch", (event) => {
|
||||
);
|
||||
});
|
||||
|
||||
self.addEventListener("push", (event) => {
|
||||
if (!event.data) return;
|
||||
let data = {};
|
||||
try { data = event.data.json(); } catch { data = { body: event.data.text() }; }
|
||||
|
||||
const options = {
|
||||
body: data.body || "Med-Time!",
|
||||
icon: "/icon-192x192.png",
|
||||
badge: "/icon-72x72.png",
|
||||
silent: data.silent !== false,
|
||||
tag: data.tag || "med-reminder",
|
||||
renotify: true,
|
||||
data: { slot_id: data.slot_id },
|
||||
actions: [
|
||||
{ action: "take", title: "Genommen ✓" },
|
||||
{ action: "snooze15", title: "+15 Min" },
|
||||
{ action: "snooze30", title: "+30 Min" },
|
||||
],
|
||||
};
|
||||
|
||||
event.waitUntil(
|
||||
self.registration.showNotification(data.title || "TakeYourMeds", options)
|
||||
);
|
||||
});
|
||||
|
||||
async function apiPost(path, body) {
|
||||
const clients = await self.clients.matchAll({ type: "window" });
|
||||
for (const client of clients) {
|
||||
client.postMessage({ type: "API_ACTION", path, body });
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
self.addEventListener("notificationclick", (event) => {
|
||||
event.notification.close();
|
||||
const slotId = event.notification.data?.slot_id;
|
||||
const action = event.action;
|
||||
|
||||
if (action === "take" && slotId) {
|
||||
event.waitUntil(
|
||||
self.clients.openWindow(`/?action=take&slot=${slotId}`)
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((action === "snooze15" || action === "snooze30") && slotId) {
|
||||
const minutes = action === "snooze15" ? 15 : 30;
|
||||
event.waitUntil(
|
||||
self.clients.openWindow(`/?action=snooze&slot=${slotId}&minutes=${minutes}`)
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
event.waitUntil(self.clients.openWindow("/"));
|
||||
});
|
||||
|
||||
self.addEventListener("sync", (event) => {
|
||||
if (event.tag === "sync-logs") {
|
||||
event.waitUntil(
|
||||
|
||||
Reference in New Issue
Block a user