diff --git a/src/lib/admins.ts b/src/lib/admins.ts new file mode 100644 index 0000000..ca68f7f --- /dev/null +++ b/src/lib/admins.ts @@ -0,0 +1,22 @@ +// ─── SkateSpots admin identities ──────────────────────────────────────────── +// +// Single source of truth for who counts as an "admin" across the app +// (newsletter publishing, relay admin dashboard, etc.). +// +// Pubkeys are stored in HEX because that's what `user.pubkey` and Nostr +// filters use. The bech32 npub is kept in a comment for human readability. + +/** Hex pubkeys of SkateSpots admins. */ +export const ADMIN_PUBKEYS: string[] = [ + // SkateSpots founder + // npub1yrnuj56rnen08zp2h9h7p74ghgjx6ma39spmpj6w9hzxywutevsst7k5cx + '20e7c953439e66f3882ab96fe0faa8ba246d6fb12c03b0cb4e2dc4623b8bcb21', + // npub1e2ayjlmmaksx2rtt0z4jzyskunfwh2lwe89xav4qtnhgu4wxsudsp98a4l + 'caba497f7beda0650d6b78ab211216e4d2ebabeec9ca6eb2a05cee8e55c6871b', +]; + +/** Returns true if the given hex pubkey belongs to a SkateSpots admin. */ +export function isAdminPubkey(pubkey: string | undefined | null): boolean { + if (!pubkey) return false; + return ADMIN_PUBKEYS.includes(pubkey); +} diff --git a/src/pages/NewsletterPage.tsx b/src/pages/NewsletterPage.tsx index 205a2ab..76119d1 100644 --- a/src/pages/NewsletterPage.tsx +++ b/src/pages/NewsletterPage.tsx @@ -28,10 +28,7 @@ import { Avatar, AvatarImage, AvatarFallback } from '@/components/ui/avatar'; // ─── Admin pubkeys allowed to publish newsletter as kind 1 ─────────────────── -const NEWSLETTER_ADMIN_PUBKEYS = [ - '20e7c953439e66f3882ab96fe0faa8ba246d6fb12c03b0cb4e2dc4623b8bcb21', - 'caba497f7beda0650d6b78ab211216e4d2ebabeec9ca6eb2a05cee8e55c6871b', -]; +import { isAdminPubkey } from '@/lib/admins'; // ─── Newsletter issue structure ─────────────────────────────────────────────── // diff --git a/src/pages/SpotDetailPage.tsx b/src/pages/SpotDetailPage.tsx index f867a30..8835483 100644 --- a/src/pages/SpotDetailPage.tsx +++ b/src/pages/SpotDetailPage.tsx @@ -54,7 +54,9 @@ import { Star, Flag, MoreHorizontal, + MessageCircle, } from 'lucide-react'; +import { nip19 } from 'nostr-tools'; import { ReportDialog } from '@/components/ReportDialog'; import { WhosSkating } from '@/components/WhosSkating'; import { SetStatusDialog } from '@/components/SetStatusDialog'; @@ -146,6 +148,8 @@ export default function SpotDetailPage() { const metadata = author.data?.metadata; const displayName = metadata?.name ?? genUserName(spot?.pubkey || ''); + // npub for linking to the mapper's profile / messaging them + const mapperNpub = spot?.pubkey ? nip19.npubEncode(spot.pubkey) : ''; const coordinates = useMemo(() => { if (!spot?.geohash) return null; @@ -910,7 +914,10 @@ export default function SpotDetailPage() { -
+ @@ -918,22 +925,40 @@ export default function SpotDetailPage() {
-

{displayName}

+

+ {displayName} +

{new Date(spot.createdAt * 1000).toLocaleDateString()}

-
+

Found this spot useful? Send a zap to thank the mapper!

- +
+ + {/* Message the mapper — e.g. to ask them to add photos. + Hidden when you're the owner (can't message yourself). */} + {!isOwner && ( + + )} +