Commit Graph

23 Commits

Author SHA1 Message Date
Chad Curtis a27ee3af86 Fix self-review findings: remove dead code, fix task progress display, fix hydration race
- Remove dead code: useSyncTaskCompletions, incrementInteractionTaskTags,
  getInteractionCount, getEvolveInteractionCount, unused lookup maps
- Fix task progress showing 0/N on load: compute event-based task counts
  directly from Nostr query results (authoritative) instead of relying
  solely on the evolution mission store which may not be hydrated yet.
  Use max(queryCount, missionCount) so progress displays immediately.
- Fix hydration race: useDailyMissions raw memo now waits for hydration
  before creating fresh missions, preventing overwrite of persisted
  evolution[] with empty array. Also preserve evolution missions across
  daily resets during hydration.
- Fix session store miss: use ensureSessionStore in incubation/evolution
  start so evolution missions are always populated even if the store
  hasn't been hydrated yet.
- Extract duplicate findMission to shared findEvolutionMission in
  evolution-missions.ts
- Document evolution[] field on kind 11125 in NIP.md
2026-04-16 16:17:57 -05:00
Alex Gleason c4354774ad Add Color Moments and Geocaching to community NIP specs, sort table by kind number 2026-04-01 18:05:52 -05:00
Alex Gleason 8a44f77fb1 Add community NIP specs to NIP.md (Letters, Weather, Blobbi)
Add a Community Kinds section to the overview table and a Community
NIP Specifications section with summaries and links to the full specs
maintained by Chad Curtis, Sam Thomson, and Danifra.
2026-04-01 17:56:50 -05:00
Chad Curtis 865fabce98 Add Letters inbox page with full letter composing from lief
- Port letter protocol (kind 8211, NIP-44 encrypted) from lief
- LettersPage at /letters with inbox and sent tabs
- ComposeLetterSheet with full stationery, font, frame, sticker, drawing support
- LetterCard with expand-to-read animation and deletion
- LetterPreferencesSection stored in encrypted settings (NIP-78)
- /settings/letters route for letter preferences
- Letters added to sidebar nav
- All letter lib utilities: letterTypes, letterUtils, colorUtils extensions, sanitizeSvg, svgDrawing
- StationeryBackground, StationeryPicker, FramePicker, StickerPicker, DrawingCanvas all ported
2026-03-26 16:11:29 -05:00
Alex Gleason 2326dac0b4 Add title font role to f tag spec in NIP.md
Extend the font tag format with a required role marker ("body" or
"title") to support a dedicated profile display-name font. Body tags
must be ordered before title tags for backward compatibility. Legacy
3-element f tags without a role are treated as body.
2026-03-25 13:18:07 -05:00
Alex Gleason 6569478fc4 Remove implementation notes from avatar shape NIP section 2026-03-13 20:48:03 -05:00
Alex Gleason 91b96984cb Make NIP.md implementation notes platform-generic (web, iOS, Android) 2026-03-13 20:47:38 -05:00
Alex Gleason 196f3dd64e Update NIP.md: shape field is emoji-only, remove predefined shape references 2026-03-13 20:47:07 -05:00
Alex Gleason 55e8075542 Support emoji as avatar shape: use any emoji as a mask over the avatar
Extend the kind-0 'shape' field to accept any emoji string in addition to
the predefined geometric shapes (circle, triangle, hexagon, star, etc.).
When an emoji is chosen, its native OS glyph is rendered onto a canvas,
the alpha channel extracted as a PNG mask, and applied via CSS mask-image.

Implementation:
- Widen AvatarShape type to accept emoji strings alongside predefined names
- isEmoji() detects any short non-ASCII string (avoids fragile Unicode regex)
- getEmojiMaskUrl() renders emoji at 512px, crops to tight bounding box
  (with alpha threshold to ignore shadows/glows), squares the crop, scales
  to 256px output, converts to white+alpha mask PNG. Cached per emoji.
- Avatar component applies mask-image for emoji, clip-path for geometric
- ProfileCard uses ring-4 instead of border-4 for emoji shapes to avoid
  mask/content misalignment (border is inside the element; ring is outside)
- AvatarShapePicker adds emoji-mart picker in a popover
- Form schemas use z.string() to accommodate both predefined and emoji values
- NIP.md documents emoji shape support
2026-03-13 20:27:14 -05:00
Alex Gleason 9e03579d0f Fix heart shape: use polygon approximation instead of path() which requires pixel coordinates
clip-path: path() uses pixel coordinates, making a 0-1 normalized path
invisible. Replaced with a parametric heart curve sampled into a 50-point
polygon using percentage coordinates, consistent with all other shapes.
2026-03-13 17:29:03 -05:00
Alex Gleason 61ea5ff1fe Add heart shape and document kind 0 shape extension in NIP.md
- Add 'heart' as the 8th avatar shape using SVG path() clip-path with cubic beziers
- Document the kind 0 'shape' metadata extension in NIP.md with all 8 defined values,
  client behavior rules, and forward-compatibility guidance
2026-03-13 17:25:50 -05:00
Alex Gleason 9ea8788b92 Replace kind 16769 SavedFeedFilters with standard NIP-01 filters and variable tags
The proprietary SavedFeedFilters JSON schema in kind 16769 tab events was
non-interoperable. Replace it with standard NIP-01 filter objects that any
Nostr client can execute, plus a variable system (var tags) for dynamic
values like follow lists.

- Tab filters are now standard NIP-01 filters with optional NIP-50 search
- Variables ($name) in filters are resolved via var tags that extract tag
  values from referenced events (e.g. follow list pubkeys from kind 3)
- $me is the only runtime variable (profile owner's pubkey)
- Variables in arrays are expanded in-place (spliced)
- Add useResolveTabFilter hook for variable resolution with caching
- Update all consumers: ProfilePage, Feed, SearchPage, ContentSettings
- Remove SavedFeedFilters type entirely in favor of TabFilter
2026-03-06 01:28:09 -06:00
Chad Curtis 134236636a Profile tabs: kind 16769 Nostr event, manager modal, + dropdown, wider save button
Kind 16769 (profile tabs):
- src/lib/profileTabsEvent.ts: encode/decode kind 16769 — tab tags are
  ['tab', label, filtersJSON], no UUIDs, label is the stable key
- useProfileTabs: queries kind 16769 with authors filter (secure)
- usePublishProfileTabs: publishes kind 16769, invalidates cache
- useProfileSupplementary: now fetches kind 16769 alongside kind 3 and
  10001 in a single relay round-trip, seeds profile-tabs query cache
- NIP.md: documents kind 16769 schema

ProfileTabEditModal:
- Save button is now full-width with a Check icon (Cancel below)
- hideFrom + hideSort props on SavedFeedFiltersEditor used here — author
  is the profile owner implicitly, sort is irrelevant for profile tabs

ProfileTabsManagerModal:
- dnd-kit drag-to-reorder sortable list of custom tabs
- Per-row edit (pencil) and remove (trash) buttons
- Add custom tab button at the bottom
- Single Save button publishes the full updated list

ProfilePage tab bar (own profile):
- Custom tabs read from kind 16769 via useProfileTabs
- + button opens a DropdownMenu: core tabs listed as already-added
  (dimmed with checkmarks), Add custom tab at the bottom
- SlidersHorizontal pencil at end of row opens the manager modal
  (only shown when custom tabs exist)
- Per-tab onEdit pencil removed — manager handles all editing
- ProfileTab type aliased to CoreProfileTab to avoid collision with
  CustomProfileTab from profileTabsEvent
2026-03-05 22:53:44 -06:00
Alex Gleason c0c65047fa Update NIP.md kind numbers: 33891 -> 36767, 11667 -> 16767 2026-02-26 17:31:05 -06:00
Alex Gleason b5a59ac9a6 Remove 'contain' background mode from NIP.md and codebase, keep only cover and tile 2026-02-26 15:22:35 -06:00
Alex Gleason bc4cc80581 Simplify theme fonts to a single font (remove heading/body roles)
Reduce font complexity from two-role (title/body) to a single font
that applies globally to all text. Updates NIP.md f tag format from
["f", family, role, url] to ["f", family, url], removes ThemeFonts
wrapper in favor of a single ThemeFont on ThemeConfig.font, and
simplifies FontPicker to a single dropdown.
2026-02-26 14:57:41 -06:00
Alex Gleason 51304a3a7c Add font (f) and background (bg) tags to theme event spec
Replace the u tag with a richer bg tag using imeta-style key-value
pairs (url, mode, m required; dim, blurhash optional). Add f tag for
font declarations (family, role, and font file URL required). Both
tags are documented in a shared definitions section for kind 33891
and kind 11667.
2026-02-26 14:26:08 -06:00
Alex Gleason 14dcb8ce81 Add optional u tag for background image to both theme kinds 2026-02-26 12:45:05 -06:00
Alex Gleason ed8a1d59b5 Remove description and t tags from kind 33891 2026-02-26 12:40:15 -06:00
Alex Gleason 9d0efe76a3 Update kind 33891 to use c tags for hex colors instead of content JSON
Align theme definition event with kind 11667 by replacing the HSL
color token JSON in the content field with c tags using 6-digit hex
color codes and required markers (primary, text, background).
2026-02-26 12:39:19 -06:00
Alex Gleason 2c3260760a Update kind 11667 to use c tags for hex colors instead of content JSON
Replace the HSL color tokens in the content field with c tags using
6-digit hex color codes and required markers (primary, text, background).
Remove the a tag for theme attribution. Add optional title tag.
2026-02-26 12:35:56 -06:00
Mary Kate Fain 096096f685 Replace kind 30203 with new multi-theme NIP: kind 33891 (definitions) + kind 11667 (active profile theme)
- Theme definitions are addressable (multiple per user, each with title/description)
- Active profile theme is replaceable (one per user, copies tokens from source)
- Updated all hooks, components, and feed integration for new kinds
- Theme builder preview now shows accent color on streak flame, banner gradient, and repost action
2026-02-25 15:23:18 -06:00
Mary Kate Fain bac31a5b6d Add profile theme sharing: publish kind 30203, scoped themes on profiles, feed cards, and content settings 2026-02-25 13:49:55 -06:00