mirror of
https://github.com/purrgrammer/grimoire.git
synced 2026-06-05 18:21:28 +02:00
fix: address PR review comments
- nostr-kinds.ts: clarify exclusive boundary comments for kind ranges
- useStable.ts: use JSON.stringify instead of join(",") to prevent
false positives with arrays containing commas
- useProfile.ts: check abort signal before initiating database writes
to prevent race conditions
- KindRenderer.tsx: rename "Regular Lists" to "Replaceable Events",
simplify redundant condition (isReplaceableKind includes kinds 0, 3),
remove unused `kinds` import
- BaseEventRenderer.tsx: remove duplicate comment
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
import { getKindInfo } from "@/constants/kinds";
|
||||
import { kinds } from "nostr-tools";
|
||||
import { NIPBadge } from "./NIPBadge";
|
||||
import { Copy, CopyCheck } from "lucide-react";
|
||||
import { Button } from "./ui/button";
|
||||
@@ -190,7 +189,7 @@ function getKindCategory(kind: number): string {
|
||||
if (kind >= 20 && kind <= 39) return "Media & Content";
|
||||
if (kind >= 40 && kind <= 49) return "Channels";
|
||||
if (kind >= 1000 && kind <= 9999) return "Application Specific";
|
||||
if (isReplaceableKind(kind)) return "Regular Lists";
|
||||
if (isReplaceableKind(kind)) return "Replaceable Events";
|
||||
if (isEphemeralKind(kind)) return "Ephemeral Events";
|
||||
if (isParameterizedReplaceableKind(kind)) return "Parameterized Replaceable";
|
||||
if (kind >= 40000) return "Custom/Experimental";
|
||||
@@ -201,7 +200,8 @@ function getKindCategory(kind: number): string {
|
||||
* Determine the replaceability of an event kind
|
||||
*/
|
||||
function getEventType(kind: number): string {
|
||||
if (kind === kinds.Metadata || kind === kinds.Contacts || isReplaceableKind(kind)) {
|
||||
// nostr-tools' isReplaceableKind already includes kinds 0 (Metadata) and 3 (Contacts)
|
||||
if (isReplaceableKind(kind)) {
|
||||
return "Replaceable";
|
||||
}
|
||||
if (isParameterizedReplaceableKind(kind)) {
|
||||
|
||||
@@ -225,7 +225,6 @@ export function ClickableEventTitle({
|
||||
|
||||
// For replaceable/parameterized replaceable events, use AddressPointer
|
||||
if (isAddressableKind(event.kind)) {
|
||||
// For replaceable/parameterized replaceable events, use AddressPointer
|
||||
const dTag = getTagValue(event, "d") || "";
|
||||
pointer = {
|
||||
kind: event.kind,
|
||||
|
||||
@@ -50,21 +50,18 @@ export function useProfile(pubkey?: string): ProfileContent | undefined {
|
||||
return;
|
||||
}
|
||||
|
||||
// Save to IndexedDB (fire and forget if aborted)
|
||||
const savePromise = db.profiles.put({
|
||||
...profileData,
|
||||
pubkey,
|
||||
created_at: fetchedEvent.created_at,
|
||||
});
|
||||
// Only update state and cache if not aborted
|
||||
if (controller.signal.aborted) return;
|
||||
|
||||
// Only update state if not aborted
|
||||
if (!controller.signal.aborted) {
|
||||
setProfile(profileData);
|
||||
}
|
||||
setProfile(profileData);
|
||||
|
||||
// Await save after state update to avoid blocking UI
|
||||
// Save to IndexedDB after state update to avoid blocking UI
|
||||
try {
|
||||
await savePromise;
|
||||
await db.profiles.put({
|
||||
...profileData,
|
||||
pubkey,
|
||||
created_at: fetchedEvent.created_at,
|
||||
});
|
||||
} catch (err) {
|
||||
// Log but don't throw - cache failure shouldn't break the UI
|
||||
console.error("[useProfile] Failed to cache profile:", err);
|
||||
|
||||
@@ -30,21 +30,20 @@ export function useStableValue<T>(
|
||||
/**
|
||||
* Stabilize a string array for use in dependency arrays
|
||||
*
|
||||
* Optimized version of useStableValue for string arrays.
|
||||
* Uses join(",") instead of JSON.stringify for better performance.
|
||||
* Uses JSON.stringify for safe serialization (handles arrays with commas in elements).
|
||||
*
|
||||
* @param arr - The array to stabilize
|
||||
* @returns The memoized array
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* // Instead of: useMemo(() => relays, [relays.join(",")])
|
||||
* // Instead of: useMemo(() => relays, [JSON.stringify(relays)])
|
||||
* const stableRelays = useStableArray(relays);
|
||||
* ```
|
||||
*/
|
||||
export function useStableArray<T extends string>(arr: T[]): T[] {
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
return useMemo(() => arr, [arr.join(",")]);
|
||||
return useMemo(() => arr, [JSON.stringify(arr)]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -26,14 +26,16 @@ import {
|
||||
} from "nostr-tools/kinds";
|
||||
|
||||
// Kind range boundaries (NIP-01) - exported for display purposes only
|
||||
// Note: END values are exclusive (e.g., REGULAR covers 0-9999, not 10000)
|
||||
// Exception: kinds 0 (Metadata) and 3 (Contacts) are replaceable despite being < 10000
|
||||
export const REGULAR_START = 0;
|
||||
export const REGULAR_END = 10000;
|
||||
export const REGULAR_END = 10000; // exclusive: regular kinds are 0-9999 (except 0, 3)
|
||||
export const REPLACEABLE_START = 10000;
|
||||
export const REPLACEABLE_END = 20000;
|
||||
export const REPLACEABLE_END = 20000; // exclusive: replaceable kinds are 10000-19999
|
||||
export const EPHEMERAL_START = 20000;
|
||||
export const EPHEMERAL_END = 30000;
|
||||
export const EPHEMERAL_END = 30000; // exclusive: ephemeral kinds are 20000-29999
|
||||
export const PARAMETERIZED_REPLACEABLE_START = 30000;
|
||||
export const PARAMETERIZED_REPLACEABLE_END = 40000;
|
||||
export const PARAMETERIZED_REPLACEABLE_END = 40000; // exclusive: parameterized replaceable are 30000-39999
|
||||
|
||||
/**
|
||||
* Check if a kind is parameterized replaceable (NIP-01)
|
||||
|
||||
Reference in New Issue
Block a user