Add NIP-05 badges, hashtag pages, keyword muting, suggestion dismissal, notification poller

- Article cover: aspect-video replaces max-h-72 for consistent 16:9
- NIP-05 verification badge on note cards with 1-hour TTL cache
- Dedicated hashtag feed pages (clicking #tag opens live feed, not search)
- Keyword muting: word-boundary matching, applied across all feed views
- Follow suggestion dismissal: persistent "don't suggest again" per person
- Background notification poller (60s): mentions, zaps, new followers
- All notification types independently toggleable in settings
- Centralized notification firing (removed inline store notifications)
This commit is contained in:
Jure
2026-03-20 12:09:11 +01:00
parent 989ed01dfc
commit 57630227e1
20 changed files with 499 additions and 35 deletions

View File

@@ -1,7 +1,6 @@
import { create } from "zustand";
import { NDKEvent } from "@nostr-dev-kit/ndk";
import { fetchMentions } from "../lib/nostr";
import { notifyMention, notifyDM } from "../lib/notifications";
const NOTIF_SEEN_KEY = "wrystr_notif_last_seen";
const DM_SEEN_KEY = "wrystr_dm_last_seen";
@@ -55,14 +54,6 @@ export const useNotificationsStore = create<NotificationsState>((set, get) => ({
const events = await fetchMentions(pubkey, lastSeenAt);
const newEvents = events.filter((e) => (e.created_at ?? 0) > lastSeenAt);
const unreadCount = newEvents.length;
// Fire OS notification for new mentions (only truly new ones since last fetch)
const prevCount = get().unreadCount;
if (unreadCount > prevCount && newEvents.length > 0) {
const latest = newEvents[0];
const authorName = latest.pubkey.slice(0, 8) + "…";
const preview = latest.content?.slice(0, 120) || "mentioned you";
notifyMention(authorName, preview).catch(() => {});
}
set({ notifications: events, unreadCount, lastSeenAt });
} catch {
// Non-critical
@@ -86,17 +77,11 @@ export const useNotificationsStore = create<NotificationsState>((set, get) => ({
},
computeDMUnread: (conversations: Array<{ partnerPubkey: string; lastAt: number }>) => {
const { dmLastSeen, dmUnreadCount: prevCount } = get();
const { dmLastSeen } = get();
const unreadConvos = conversations.filter(
(c) => c.lastAt > (dmLastSeen[c.partnerPubkey] ?? 0)
);
const dmUnreadCount = unreadConvos.length;
// Fire OS notification if new unread DMs appeared
if (dmUnreadCount > prevCount && unreadConvos.length > 0) {
const latest = unreadConvos[0];
const name = latest.partnerPubkey.slice(0, 8) + "…";
notifyDM(name, "New message").catch(() => {});
}
set({ dmUnreadCount });
},
}));