Commit Graph

473 Commits

Author SHA1 Message Date
shakespeare.diy 3a02902df2 Fix post stats clearing during pagination
The issue was that when new pages were loaded during infinite scroll, the batch stats query key would change (since it includes all event IDs), causing React Query to treat it as a completely new query. This would briefly show no stats until the new query completed.

Fixed by improving the placeholderData function in useBatchEventStats to pull cached stats from individual event-stats queries. This ensures that previously loaded stats remain visible while new stats are being fetched during pagination.

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-02-19 04:55:57 -06:00
shakespeare.diy e7277c6fee Revert to 5fd4ff4: Enable NIP-85 stats mode by default
This reverts the codebase back to the state at commit 5fd4ff4.

Reverted 1 commit(s):
- a3d2492: Add three-mode stats calculation: NIP-85 Only, Manual Only, and Both

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-02-19 04:50:50 -06:00
shakespeare.diy a3d24927d4 Add three-mode stats calculation: NIP-85 Only, Manual Only, and Both
Replace the binary nip85OnlyMode boolean with a statsMode enum that supports three options:
- "nip85-only": Show only pre-computed NIP-85 stats (fastest, may be empty)
- "manual-only": Always calculate stats from relay queries (slower, guaranteed)
- "both": Use NIP-85 when available with manual fallback (recommended default)

Updated components:
- AppContext: Changed nip85OnlyMode to statsMode with StatsMode type
- AppProvider: Updated Zod schema to validate three-mode enum
- useTrending.ts: Implemented logic for all three modes in useEventStats and useBatchEventStats
- AdvancedSettings: Replaced switch with radio group for better UX

Default remains "nip85-only" for optimal performance.

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-02-19 04:50:07 -06:00
shakespeare.diy 5fd4ff4661 Enable NIP-85 stats mode by default
Set nip85OnlyMode to true in the default configuration. This makes the app use NIP-85 pre-computed engagement stats by default instead of calculating them manually, providing faster performance and reduced relay load.

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-02-19 04:46:43 -06:00
Chad Curtis 9b1c48b41d Prevent notification dot from showing until settings fully load
- Use null cursor instead of default 0 when settings haven't loaded yet
- Only calculate newNotifications when cursor is available (not null)
- Ensures hasUnread is always false until settings load with actual cursor value
- Eliminates all flickering by never showing dot with incomplete data
2026-02-19 04:39:19 -06:00
Chad Curtis 9d5c8cf292 Fix notification dot flicker by waiting for settings to load
- Don't show notification dot until encrypted settings are loaded
- Prevents flicker when notifications load (3s) before settings (5s)
- Without settings, cursor defaults to 0 causing false positives for hasUnread
- Now waits for both notifications query AND settings query to complete
2026-02-19 04:38:26 -06:00
Chad Curtis 2947e6685f Fix notification dot flickering during background refetch
- Add placeholderData to useNotifications query to keep previous data during refetch
- Prevents notification indicator from briefly disappearing when query refetches every 60s
- Maintains smooth user experience without visual flicker
2026-02-19 04:36:58 -06:00
Chad Curtis 4a27abb021 Add NIP-85 only mode and improve settings UX
- Add nip85OnlyMode setting to disable manual stat calculation fallback
- When enabled, stats only show if NIP-85 pubkey provides them (no fallback queries)
- Allow clearing NIP-85 pubkey to disable it entirely (empty string now valid)
- Update Zod schema to accept empty string or 64-char hex pubkey
- Match ContentSettings presentation style (no boxes, simple switches)
- Show toast notifications when enabling/disabling NIP-85 only mode
- Disable NIP-85 only mode toggle when no pubkey is configured
- Update useEventStats and useBatchEventStats to respect nip85OnlyMode
2026-02-19 04:35:18 -06:00
Chad Curtis 7ea17e9431 Optimize NIP-85 queries to avoid contention and reduce delays
- Use sequential queries (NIP-85 first, then manual fallback) to avoid network contention
- Reduce NIP-85 timeout from 2000ms to 500ms for faster fallback
- When NIP-85 succeeds: only fetch reactions/zaps/quotes (70% less data)
- When NIP-85 fails: fetch full stats as before (no degradation)
- useEventStats: 10 events instead of 50 when NIP-85 available
- useBatchEventStats: 3x per event instead of 10x when NIP-85 available
- Eliminates waterfall delay while avoiding parallel query contention
2026-02-19 04:31:03 -06:00
Chad Curtis 8e4043fe5a Add NIP-85 stats to useEventStats and useBatchEventStats
- Update useEventStats to query NIP-85 stats first, reducing manual query limits when available
- Update useBatchEventStats to batch-query NIP-85 stats for all events in parallel
- Merge NIP-85 counts with computed data (keep emojis, quotes, and zap amounts from manual calculation)
- Reduce relay query limits significantly when NIP-85 stats are available (3x-5x fewer events fetched)
- Falls back seamlessly to manual calculation when NIP-85 unavailable
2026-02-19 04:27:51 -06:00
Chad Curtis 8a4ea45035 Add NIP-85 stats integration with fallback to manual calculation
- Add nip85StatsPubkey to AppConfig (default: 5f68e85ee174102ca8978eef302129f081f03456c884185d5ec1c1224ab633ea)
- Create useNip85Stats hook for querying NIP-85 events (kinds 30382, 30383, 30384)
- Update useEventInteractions to fetch NIP-85 event stats and reduce query limits when available
- Update useComments to fetch NIP-85 stats for events and addressable events
- Add NIP-85 Stats Source section to Advanced Settings with pubkey input field
- Falls back to manual stats calculation when NIP-85 events are not available
2026-02-19 04:25:30 -06:00
Chad Curtis 16e20df0cc Optimize feed loading performance from 8s to 1.3s
- Delay non-critical queries (notifications, sidebar, sync) to prioritize feed
- Wait for batch author/stats queries before rendering NoteCards
- Disable page 2 auto-fetch to reduce initial query contention
- Fix notification badge flicker and sidebar 'No trends' flash
- Sequential loading of authors then stats to avoid relay saturation

84% performance improvement. Requires NPool patch: comment out
Promise.allSettled in node_modules/@nostrify/nostrify/dist/NPool.js:101
2026-02-19 04:13:02 -06:00
shakespeare.diy 1d1286b331 Detect and reject Google's default favicon placeholder
- Added onLoad handler to validate Google favicon responses
- Checks if returned image is 16x16 (Google's default globe indicator)
- Hides favicon if Google returns default placeholder instead of real icon
- Only shows favicons that actually exist, no generic fallbacks

Now domains without real favicons (like turdsoup.com) won't show anything.

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-02-19 02:42:19 -06:00
shakespeare.diy ff1dfd8ae4 Use CORS proxy for intelligent favicon discovery with Google fallback
- Use Shakespeare CORS proxy to actually fetch and parse HTML
- Strategy: Scrape HTML → try .svg/.ico/.png → Google service → hide if all fail
- Tracks which fallbacks have been tried to avoid loops
- Only shows favicon if something actually loads successfully
- Google service is last resort before giving up entirely

This ensures we get pure favicons when possible, with intelligent fallback.

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-02-19 02:41:05 -06:00
shakespeare.diy 3462771fea Add Google favicon service as final fallback
- Added Google's favicon service as last fallback option
- Tries: HTML discovery → .svg → .ico → .png → Google service
- Google's service intelligently finds favicons even at non-standard paths
- Ensures favicons show for sites like primal.net with versioned paths

This provides maximum coverage while still trying direct paths first.

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-02-19 02:39:28 -06:00
shakespeare.diy 29ee4db037 Add intelligent favicon discovery by parsing HTML link tags
- Fetches domain HTML and parses <link rel="icon"> tags to find actual favicon path
- Discovers versioned/hashed favicons like /assets/favicon-51789dff.ico
- Falls back to common paths (.svg, .ico, .png) if discovery fails
- Handles both absolute and relative favicon URLs in link tags
- Supports shortcut icon, icon, and apple-touch-icon variations

This intelligently finds favicons even when they're not at standard paths.

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-02-19 02:38:25 -06:00
shakespeare.diy 11e983563b Create shared DomainFavicon component for DRY favicon handling
- Created DomainFavicon component that handles all favicon loading logic
- Tries .svg, .ico, .png formats in order (SVG first for best quality)
- Works with both full URLs and plain domains
- Updated Nip05Badge to use DomainFavicon instead of custom logic
- Updated ProfilePage to use DomainFavicon for website links
- Removed duplicate Favicon function from ProfilePage

Benefits:
- Single source of truth for favicon loading logic
- Consistent behavior across NIP-05 badges and profile website links
- Easier to maintain and update favicon handling in one place

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-02-19 02:36:12 -06:00
shakespeare.diy 36bb8b5be3 Load favicons directly from domain with transparent background
- Fetch favicons directly from domain (tries .svg, .ico, .png in order)
- Removed background masking circle (no bg-white/5, no rounded-sm)
- Transparent favicons now render properly with no background
- Falls back through common favicon formats on error
- Hides icon only if all format attempts fail

This gives clean, transparent favicon display without any background artifacts.

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-02-19 02:33:39 -06:00
shakespeare.diy b00263bddc Fix favicon loading by using Google service with validation
- Reverted to Google's favicon service (direct domain fetching causes CORS errors)
- Request larger size (32px) to differentiate from default 16x16 globe
- Hide any 16x16 favicons as they're likely the default placeholder
- Real domain favicons will show, default globe will be hidden

This fixes the issue where no favicons were showing due to CORS errors.

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-02-19 01:38:21 -06:00
shakespeare.diy 9f17ec1a92 Only show favicons that actually exist - fetch directly from domain
- Changed to fetch favicon directly from domain (https://domain.com/favicon.ico)
- Added size validation: hide favicons smaller than 16x16 (likely placeholders)
- Hide favicon immediately on any error (404, CORS, etc)
- Added opacity-0 until image loads to prevent flash of broken images
- No more fallback icons or default placeholders - real favicons only

This ensures users only see actual domain favicons, never generic placeholders.

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-02-19 01:37:29 -06:00
shakespeare.diy 02014b3dc4 Fix favicon display issues: use DDG service and reduce background opacity
- Switched from Google favicon service to DuckDuckGo's service
- DuckDuckGo returns 404 for missing favicons instead of default globe icon
- Reduced background opacity from bg-muted/50 to bg-white/5 for nearly transparent look
- Moved getNip05Domain function into Nip05Badge component for better encapsulation
- Removed unused utility functions from lib/utils.ts

Fixes:
- No more default globe icons showing for domains without favicons
- Much more subtle/transparent background that doesn't look "quite" visible

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-02-19 01:36:25 -06:00
shakespeare.diy 5f6a2a8984 Refactor NIP-05 favicon display to use DRY component
- Created reusable Nip05Badge component to eliminate code duplication
- Added error handling to hide favicon if image fails to load
- Added subtle background (bg-muted/50) to handle favicon transparency
- Increased spacing from gap-1 to gap-1.5 for better visual separation
- Updated NoteCard, PostDetailPage, and NotificationsPage to use new component
- Made favicon size configurable via iconSize prop (defaults to 16px)

Fixes issues:
- DRY violation: now using single component instead of duplicated code
- Missing favicon handling: onError handler hides broken images
- Transparency: added rounded background for better contrast

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-02-19 01:34:32 -06:00
shakespeare.diy 7d0b45f0f8 Add NIP-05 domain favicon display in posts
- Created utility functions getNip05Domain() and getDomainFavicon() in lib/utils.ts
- Updated NoteCard component to show domain favicon after NIP-05 identifier
- Updated PostDetailPage to display favicons in all NIP-05 displays
- Updated NotificationsPage to include favicons in ReferencedPostCard and FullNoteCard
- Uses Google's favicon service for reliable favicon retrieval
- Favicons are displayed as 16x16px (size-4) inline images with lazy loading

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-02-19 01:32:31 -06:00
shakespeare.diy e411116983 Remove redundant WalletPage component
WalletPage was unused - wallet functionality is already available in Settings (Settings > Wallet tab). Removed the duplicate page to keep the codebase clean.

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-02-19 01:28:28 -06:00
shakespeare.diy 507fbf3bb1 Update section headers to use mt-4 mb-5 instead of my-4
Changed spacing on page headers from my-4 (vertical margin) to mt-4 mb-5 (separate top and bottom margins) for better visual consistency across BookmarksPage, HashtagPage, KindFeedPage, PlaceholderPage, WalletPage, and PostDetailPage.

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-02-19 01:27:56 -06:00
shakespeare.diy 32d01c6af0 Fix feed skeleton loading states
- Show skeleton when switching feed tabs without cached data
- Fix infinite skeleton loading when follow list is empty
- Remove placeholderData to ensure proper loading states during tab switches
- Allow follows feed query to run even with empty follow list (shows own posts)
- Use isLoading check to show skeleton during initial data fetch

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-02-19 01:25:17 -06:00
shakespeare.diy ca8796f256 Remove intro icons and add spacing to wallet section
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-02-19 01:23:03 -06:00
shakespeare.diy 857add4c6b Move borders from wrapper divs to section headers in Advanced Settings
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-02-19 01:21:38 -06:00
shakespeare.diy 9530d7d345 Remove unnecessary box around single community display
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-02-19 01:20:09 -06:00
shakespeare.diy 459277d1a5 Unify presentation styles across all settings sections
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-02-19 01:15:22 -06:00
shakespeare.diy a0f219b0cd Fix Muted Content double border issue
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-02-19 01:10:34 -06:00
shakespeare.diy 8a7b9dab80 Add 4px borders to Feed Tabs and Other Stuff sections
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-02-19 01:10:01 -06:00
shakespeare.diy 56e486ae87 Match section header border thickness to tab accent (4px)
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-02-19 01:09:13 -06:00
shakespeare.diy d1e50583f4 Reorder feed tabs: Follows, Community, Global
Changed tab order to show Community before Global:
- Follows (always first when logged in)
- Community (when enabled - e.g., "Ditto")
- Global (when enabled)

Rationale: Community is more curated/relevant than Global, so it should appear before the global firehose.

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-02-19 01:05:58 -06:00
shakespeare.diy 8dca6aea53 Auto-enable Community feed and use domain-based labels
When downloading a community:
- Extract label from hostname (ditto.pub → "Ditto")
- Capitalize first letter of hostname
- Store label in community object
- Auto-enable Community Feed toggle
- Display label in feed tab instead of generic "Community"

Community card display:
- Show label as primary text (e.g., "Ditto")
- Show domain + user count in secondary text
- Format: "Ditto" with "ditto.pub • 247 users"

Feed tab:
- Load community label from localStorage
- Display as tab name (e.g., "Ditto" instead of "Community")
- Falls back to "Community" if no label found

Removing community:
- Auto-disables Community Feed toggle
- Clears all community data
- Returns to input state

Examples:
- ditto.pub → "Ditto" tab
- spinster.xyz → "Spinster" tab
- bitcoinhackers.org → "Bitcoinhackers" tab

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-02-19 01:04:54 -06:00
shakespeare.diy e2ac3348b5 Fix reposts in Community feed
Added proper repost handling to Community feed (was missing):
- Process kind 6 (repost) events same as Follows feed
- Parse embedded JSON content from repost
- Fetch missing reposted events in batch query
- Deduplicate events (prefer original over repost)
- Sort by repost timestamp when displaying reposts
- Maintain repostedBy context for UI display

Community feed now handles:
- Direct posts (kind 1)
- Reposts (kind 6) with embedded content
- Reposts (kind 6) with e-tag reference
- Extra content types (vines, polls, etc.)
- All with NIP-05 domain verification

Fixes the broken repost display showing raw JSON instead of parsed content.

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-02-19 01:02:13 -06:00
shakespeare.diy e2490cdadc Add NIP-05 verification to Community feed
Now only shows posts from users with matching NIP-05 domain in their profile:

1. Query events from all pubkeys in the community NIP-05 JSON
2. Fetch kind 0 metadata for all authors in the results
3. Extract nip05 field from each author's profile
4. Filter events to only include authors whose nip05 ends with @domain
5. Example: ditto.pub community only shows users with nip05 ending in "@ditto.pub"

This ensures the Community feed respects current NIP-05 verification status:
- Users must have the matching domain in their current profile
- If a user changes their NIP-05 to a different domain, they're filtered out
- Prevents showing posts from users who left the community
- Maintains trust model based on current verification state

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-02-19 01:00:50 -06:00
shakespeare.diy 25acd7d52b Refactor to single community instead of multiple communities
Changes to support only one community at a time:

Settings (ContentSettings):
- Changed from communities array to single community object
- Storage: mew:community (single object) instead of mew:communities (array)
- Storage: mew:communityData (NIP-05 JSON) instead of mew:community:{domain}
- Changed "Communities Feed" → "Community Feed" in UI
- Changed showCommunitiesFeed → showCommunityFeed in localStorage
- Show input when no community set, show card when community exists
- Remove button clears the single community
- Updated placeholder to "ditto.pub"

Feed component:
- Changed showCommunitiesFeed → showCommunityFeed
- Changed tab label "Communities" → "Community"

useFeed hook:
- Simplified to load single community data from mew:communityData
- Extracts pubkeys directly from NIP-05 names object
- No longer loops through multiple communities

Benefits:
- Simpler UX - one community at a time
- Cleaner data model
- Less storage complexity
- Clear visual state (input vs community card)

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-02-19 00:59:41 -06:00
shakespeare.diy 741f0fc737 Implement Communities feed tab on main feed page
Feed component changes:
- Added "communities" as a feed tab type
- Load showGlobalFeed and showCommunitiesFeed from localStorage
- Conditionally render Global tab based on setting
- Conditionally render Communities tab based on setting
- Tab buttons dynamically appear/disappear based on user preferences

useFeed hook changes:
- Extended to support 'communities' tab type
- Loads community list from localStorage (mew:communities)
- Fetches NIP-05 JSON data for each community
- Extracts all pubkeys from community NIP-05 data
- Queries posts from all community members
- Returns feed filtered to community pubkeys
- Includes all enabled content types (vines, polls, etc.)

How it works:
1. User adds communities in Settings > Content > Feed Tabs
2. User enables "Communities Feed" toggle
3. Communities tab appears in main feed navigation
4. Shows posts from all users in added communities
5. Respects NIP-05 verification (only shows users in the JSON)

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-02-19 00:56:38 -06:00
shakespeare.diy 2b113fed50 Add Communities feed tab toggle
- Added toggle to enable/disable Communities feed tab
- Stored in localStorage (mew:showCommunitiesFeed)
- Defaults to disabled (false)
- Toggle is disabled when no communities are added
- Description updates dynamically showing community count
- Toast notifications on toggle
- Positioned next to Global feed toggle for consistency

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-02-19 00:54:50 -06:00
shakespeare.diy 955b4d61de Add intro image and description to Feed Tabs section
- Added community-intro.png image
- Added "Feed Navigation" heading
- Added description about managing feed tabs and communities
- Matches styling of Other Stuff and Muted Content sections
- Consistent visual presentation across all collapsible sections

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-02-19 00:52:48 -06:00
shakespeare.diy 052df1d153 Fix Feed Tabs border placement to match Other Stuff section
- Moved border-b-2 from wrapping div to CollapsibleTrigger button
- Border now appears at section title instead of bottom of content
- Consistent with Other Stuff section styling

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-02-19 00:49:34 -06:00
shakespeare.diy 45e0ad31ef Restore intro image and description to Other Stuff section
- Added back the feed-intro.png image
- Added back "Other Stuff" heading and description inside collapsible
- Matches styling of Feed Tabs and Muted Content sections
- Consistent visual presentation across all collapsible sections

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-02-19 00:48:52 -06:00
shakespeare.diy a939619823 Add Global feed toggle and fix Muted Content section styling
Changes:
1. Added Global feed enable/disable toggle in Feed Tabs section
   - Stored in localStorage (mew:showGlobalFeed)
   - Defaults to enabled
   - Toast notifications on toggle
   - Clean toggle UI with description

2. Fixed Other Stuff section border
   - Removed wrapping div with border-b-2
   - Moved border to CollapsibleTrigger button
   - Prevents double borders when collapsed

3. Added intro image + description to Muted Content
   - Uses mute-intro.png image
   - Includes "Content Control" heading
   - Matches styling of main intro sections
   - Consistent with Feed Tabs and Other Stuff sections

4. Added missing Switch import

Structure now:
- Feed Tabs: Global toggle + Communities
- Other Stuff: Content types (Vines, Polls, etc.)
- Muted Content: Image + description + mute management

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-02-19 00:48:03 -06:00
shakespeare.diy 0806e5361d Add Feed Tabs section with community management
Major additions to Content settings:

1. Renamed "Content Types" → "Other Stuff" (now collapsible)
   - Moved intro image and description into collapsible section
   - Defaults to OPEN for easy access

2. Added new "Feed Tabs" section (collapsible, defaults to CLOSED)
   - Community management feature
   - Download NIP-05 JSON from any domain
   - Fetches https://domain/.well-known/nostr.json
   - Parses user list and stores locally
   - Shows user count for each community
   - Remove communities with X button
   - Communities stored in localStorage (mew:communities + mew:community:{domain})
   - Placeholder for feed tab toggles (Global, Communities, etc.)

Community feature details:
- Input validates and cleans domain (removes protocol, trailing slash)
- Prevents duplicate communities
- Shows loading state during fetch
- Error handling for invalid domains or JSON format
- Stores both community list and raw JSON data for feed filtering
- Clean, consistent UI matching existing patterns

Structure:
- Feed Tabs (new)
- Other Stuff (renamed from Content Types)
- Muted Content (existing)

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-02-19 00:46:00 -06:00
shakespeare.diy b8604864b2 Improve section header styling with larger text and accent borders
- Changed section headers from text-sm to text-base font-semibold
- Changed border-bottom from border-border to border-b-2 border-primary (thicker accent color)
- Increased vertical padding on collapsible triggers (py-3.5 instead of py-3)
- Added "Other Stuff" as a static section header above Content Types
- Moved "Other Stuff" description to static section instead of collapsible content
- Removed duplicate description from Muted Content internals

Visual improvements:
- Section headers now stand out more with larger, bolder text
- Accent-colored borders create clearer visual hierarchy
- Static "Other Stuff" section provides context before collapsible sections
- More consistent with modern settings UI patterns

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-02-19 00:44:06 -06:00
shakespeare.diy 6b45f6cdf9 Reorganize settings into 3-tab structure: Profile, Content, Advanced
Major restructure to improve UX for less technical users:

- Consolidated "Feed" + "Mutes" → "Content" tab
- Moved "Wallet" + "Relays" → "Advanced" tab
- Reduced from 5 tabs to 3 tabs with collapsible sections

New structure:
- Profile: Identity settings (unchanged)
- Content: Content Types, Muted Content (with placeholders for Communities, Sensitive Content)
- Advanced: Wallet, Network (relays)

Implementation details:
- Created ContentSettings component with collapsible sections
- Created AdvancedSettings component with collapsible sections
- Content Types section defaults to OPEN
- Muted Content section defaults to CLOSED
- Wallet/Network sections default to CLOSED
- All sections use consistent collapsible UI pattern
- Updated settings page description
- Maintains all existing functionality

Benefits:
- Cleaner mental model for new users
- Power user features hidden but accessible
- Room to grow (Communities, Sensitive Content placeholders)
- Reduced cognitive load with fewer top-level tabs

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-02-19 00:41:15 -06:00
shakespeare.diy a2680f1e1b Redesign relays tab to match feed/mutes/profile presentation style
- Added intro section with relay-intro.png image and description
- Reorganized layout with cleaner visual hierarchy and border separators
- Reduced font sizes for consistency (text-xs, text-sm labels)
- Removed rounded borders and card-style backgrounds
- Added hover states to relay rows (hover:bg-muted/20)
- Improved spacing and padding throughout
- Smaller icon sizes (h-4 w-4 for relays, h-5 w-5 for section headers)
- Reduced button sizes and input heights (h-9) to match other tabs
- Simplified "Add Relay" button text and styling
- Updated popover label sizes to text-xs for consistency

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-02-19 00:29:02 -06:00
shakespeare.diy d4d745e883 Redesign profile tab to match feed/mutes presentation style
- Added intro section with profile-intro.png image and description
- Reorganized form layout with cleaner visual hierarchy and border separators
- Reduced font sizes and spacing to match feed tab style (text-xs labels)
- Moved "Bot Account" setting under collapsible "Advanced Settings" section
- Improved input heights (h-9) and button sizes for consistency
- Enhanced image upload field styling with smaller previews and buttons
- Updated form descriptions to be more concise
- Added proper spacing with border-b separators between sections

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-02-19 00:14:36 -06:00
shakespeare.diy c3c1370090 Redesign mutes tab to match feed tab presentation style
- Refactored MuteSettings component to follow feed tab layout pattern
- Added intro section with image and description
- Reorganized mute type sections with cleaner visual hierarchy
- Removed card-based layout in favor of borderless sections
- Improved spacing and typography consistency
- Added mute-intro.png image for visual consistency
- Streamlined add mute interface with better label styling
- Enhanced muted items list with hover states and better visual feedback

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-02-19 00:04:12 -06:00