Manual fixes for AI slop

This commit is contained in:
binwiederhier
2026-01-06 18:02:08 -05:00
parent 2856793eff
commit 2dd152df3f
11 changed files with 255 additions and 196 deletions

View File

@@ -2,7 +2,7 @@ import api from "./Api";
import notifier from "./Notifier";
import prefs from "./Prefs";
import db from "./db";
import { topicUrl } from "./utils";
import { messageWithSID, topicUrl } from "./utils";
class SubscriptionManager {
constructor(dbImpl) {
@@ -15,7 +15,7 @@ class SubscriptionManager {
return Promise.all(
subscriptions.map(async (s) => ({
...s,
new: await this.db.notifications.where({ subscriptionId: s.id, new: 1 }).count(),
new: await this.db.notifications.where({ subscriptionId: s.id, new: 1 }).count()
}))
);
}
@@ -48,16 +48,17 @@ class SubscriptionManager {
}
async notify(subscriptionId, notification) {
if (notification.deleted) {
return;
}
const subscription = await this.get(subscriptionId);
if (subscription.mutedUntil > 0) {
return;
}
const priority = notification.priority ?? 3;
if (priority < (await prefs.minPriority())) {
return;
}
await notifier.notify(subscription, notification);
}
@@ -82,7 +83,7 @@ class SubscriptionManager {
baseUrl,
topic,
mutedUntil: 0,
last: null,
last: null
};
await this.db.subscriptions.put(subscription);
@@ -100,7 +101,7 @@ class SubscriptionManager {
const local = await this.add(remote.base_url, remote.topic, {
displayName: remote.display_name, // May be undefined
reservation, // May be null!
reservation // May be null!
});
return local.id;
@@ -196,19 +197,20 @@ class SubscriptionManager {
return false;
}
try {
const populatedNotification = notification;
if (!("sid" in populatedNotification)) {
populatedNotification.sid = notification.id;
}
// sw.js duplicates this logic, so if you change it here, change it there too
// Note: Service worker (sw.js) and addNotifications() duplicates this logic,
// so if you change it here, change it there too.
// Add notification to database
await this.db.notifications.add({
...populatedNotification,
...messageWithSID(notification),
subscriptionId,
// New marker (used for bubble indicator); cannot be boolean; Dexie index limitation
new: 1,
}); // FIXME consider put() for double tab
new: 1 // New marker (used for bubble indicator); cannot be boolean; Dexie index limitation
});
// FIXME consider put() for double tab
// Update subscription last message id (for ?since=... queries)
await this.db.subscriptions.update(subscriptionId, {
last: notification.id,
last: notification.id
});
} catch (e) {
console.error(`[SubscriptionManager] Error adding notification`, e);
@@ -219,16 +221,12 @@ class SubscriptionManager {
/** Adds/replaces notifications, will not throw if they exist */
async addNotifications(subscriptionId, notifications) {
const notificationsWithSubscriptionId = notifications.map((notification) => {
const populatedNotification = notification;
if (!("sid" in populatedNotification)) {
populatedNotification.sid = notification.id;
}
return { ...populatedNotification, subscriptionId };
return { ...messageWithSID(notification), subscriptionId };
});
const lastNotificationId = notifications.at(-1).id;
await this.db.notifications.bulkPut(notificationsWithSubscriptionId);
await this.db.subscriptions.update(subscriptionId, {
last: lastNotificationId,
last: lastNotificationId
});
}
@@ -249,6 +247,10 @@ class SubscriptionManager {
await this.db.notifications.delete(notificationId);
}
async deleteNotificationBySid(subscriptionId, sid) {
await this.db.notifications.where({ subscriptionId, sid }).delete();
}
async deleteNotifications(subscriptionId) {
await this.db.notifications.where({ subscriptionId }).delete();
}
@@ -257,25 +259,29 @@ class SubscriptionManager {
await this.db.notifications.where({ id: notificationId }).modify({ new: 0 });
}
async markNotificationReadBySid(subscriptionId, sid) {
await this.db.notifications.where({ subscriptionId, sid }).modify({ new: 0 });
}
async markNotificationsRead(subscriptionId) {
await this.db.notifications.where({ subscriptionId, new: 1 }).modify({ new: 0 });
}
async setMutedUntil(subscriptionId, mutedUntil) {
await this.db.subscriptions.update(subscriptionId, {
mutedUntil,
mutedUntil
});
}
async setDisplayName(subscriptionId, displayName) {
await this.db.subscriptions.update(subscriptionId, {
displayName,
displayName
});
}
async setReservation(subscriptionId, reservation) {
await this.db.subscriptions.update(subscriptionId, {
reservation,
reservation
});
}

View File

@@ -11,16 +11,10 @@ const createDatabase = (username) => {
const dbName = username ? `ntfy-${username}` : "ntfy"; // IndexedDB database is based on the logged-in user
const db = new Dexie(dbName);
db.version(4).stores({
db.version(6).stores({
// FIXME Should be 3
subscriptions: "&id,baseUrl,[baseUrl+mutedUntil]",
notifications: "&id,sid,subscriptionId,time,new,[subscriptionId+new]", // compound key for query performance
users: "&baseUrl,username",
prefs: "&key",
});
db.version(5).stores({
subscriptions: "&id,baseUrl,[baseUrl+mutedUntil]",
notifications: "&id,sid,subscriptionId,time,new,deleted,[subscriptionId+new]", // added deleted index
notifications: "&id,sid,subscriptionId,time,new,deleted,[subscriptionId+new],[subscriptionId+sid]",
users: "&baseUrl,username",
prefs: "&key",
});

View File

@@ -53,14 +53,6 @@ export const badge = "/static/images/mask-icon.svg";
export const toNotificationParams = ({ subscriptionId, message, defaultTitle, topicRoute }) => {
const image = isImage(message.attachment) ? message.attachment.url : undefined;
let tag;
if (message.sid) {
tag = message.sid;
} else {
tag = subscriptionId;
}
// https://developer.mozilla.org/en-US/docs/Web/API/Notifications_API
return [
formatTitleWithDefault(message, defaultTitle),
@@ -70,7 +62,7 @@ export const toNotificationParams = ({ subscriptionId, message, defaultTitle, to
icon,
image,
timestamp: message.time * 1000,
tag,
tag: message.sid || message.id, // Update notification if there is a sequence ID
renotify: true,
silent: false,
// This is used by the notification onclick event

View File

@@ -103,6 +103,13 @@ export const maybeActionErrors = (notification) => {
return actionErrors;
};
export const messageWithSID = (message) => {
if (!message.sid) {
message.sid = message.id;
}
return message;
};
export const shuffle = (arr) => {
const returnArr = [...arr];

View File

@@ -240,22 +240,22 @@ const NotificationItem = (props) => {
const otherTags = unmatchedTags(notification.tags);
const tags = otherTags.length > 0 ? otherTags.join(", ") : null;
const handleDelete = async () => {
console.log(`[Notifications] Deleting notification ${notification.id}`);
await subscriptionManager.deleteNotification(notification.id);
notification.history?.forEach(async (revision) => {
console.log(`[Notifications] Deleting revision ${revision.id}`);
await subscriptionManager.deleteNotification(revision.id);
});
if (notification.sid) {
console.log(`[Notifications] Deleting all notifications with sid ${notification.sid}`);
await subscriptionManager.deleteNotificationBySid(notification.subscriptionId, notification.sid);
} else {
console.log(`[Notifications] Deleting notification ${notification.id}`);
await subscriptionManager.deleteNotification(notification.id);
}
};
const handleMarkRead = async () => {
console.log(`[Notifications] Marking notification ${notification.id} as read`);
await subscriptionManager.markNotificationRead(notification.id);
notification.history
?.filter((revision) => revision.new === 1)
.forEach(async (revision) => {
console.log(`[Notifications] Marking revision ${revision.id} as read`);
await subscriptionManager.markNotificationRead(revision.id);
});
if (notification.sid) {
console.log(`[Notifications] Marking notification with sid ${notification.sid} as read`);
await subscriptionManager.markNotificationReadBySid(notification.subscriptionId, notification.sid);
} else {
console.log(`[Notifications] Marking notification ${notification.id} as read`);
await subscriptionManager.markNotificationRead(notification.id);
}
};
const handleCopy = (s) => {
copyToClipboard(s);

View File

@@ -50,12 +50,23 @@ export const useConnectionListeners = (account, subscriptions, users, webPushTop
};
const handleNotification = async (subscriptionId, notification) => {
if (notification.deleted && notification.sid) {
return handleDeletedNotification(subscriptionId, notification);
}
return handleNewOrUpdatedNotification(subscriptionId, notification);
};
const handleNewOrUpdatedNotification = async (subscriptionId, notification) => {
const added = await subscriptionManager.addNotification(subscriptionId, notification);
if (added) {
await subscriptionManager.notify(subscriptionId, notification);
}
};
const handleDeletedNotification = async (subscriptionId, notification) => {
await subscriptionManager.deleteNotificationBySid(subscriptionId, notification.sid);
};
const handleMessage = async (subscriptionId, message) => {
const subscription = await subscriptionManager.get(subscriptionId);
@@ -231,7 +242,9 @@ export const useIsLaunchedPWA = () => {
useEffect(() => {
if (isIOSStandalone) {
return () => {}; // No need to listen for events on iOS
return () => {
// No need to listen for events on iOS
};
}
const handler = (evt) => {
console.log(`[useIsLaunchedPWA] App is now running ${evt.matches ? "standalone" : "in the browser"}`);