Commit Graph
161 Commits
Author SHA1 Message Date
Claude 8bf8da03b9 Speed up Nostr login and fix list sync, signer persistence, and feed registration
The NIP-07 login flow was extremely slow because list decryption (blocks,
subscriptions, hashtag preferences) started before the signer was ready.
On page refresh, all three services failed with "permission-required" and
scheduled 3-second retry delays, adding 6-10 seconds to every login.

Key fixes:
- List loading now waits for the permission pre-grant to complete before
  attempting decryption, ensuring the signer is available on first try
- Extension wait timeout increased from 3s to 5s for slower extensions
- Decrypt timeouts reduced from 20s to 10s (signer is guaranteed ready)
- Auto-login now forwards authType/providerId from saved profiles
- Storage tab unlock falls back to ensureActiveSignerForPubkey when the
  global signer is not yet registered
- Watch history feed registration adds defensive re-registration and
  try/catch fallback to prevent "Feed not registered" errors
- Decryption scheme cache TTL extended from 10 minutes to 2 hours
- ensureExtensionPermissions waits for extension injection when there
  are outstanding permissions to request (was returning immediately)

https://claude.ai/code/session_01T4wwPu7m5qp1Nxx3H2v57j
2026-02-08 02:02:51 +00:00
Claude 416a809ae4 fix: apply block/mute list filtering to DM messages and conversations
The user's block/mute list (NIP-51) was not being checked when
processing direct messages, allowing blocked users' messages to appear
in conversations, trigger notifications, and increment unseen counts.

This adds block filtering at four layers:
- nostrService.applyDirectMessage: drops incoming DMs from blocked users
  before they enter the in-memory message cache
- nostrService.persistDirectMessageRecord: prevents blocked DM senders
  from being persisted to IndexedDB or triggering notifications
- profileModalController.buildDmConversationData: filters blocked users
  from the conversation list UI (catches pre-block persisted messages)
- applicationBootstrap: excludes blocked-user conversations from the
  unread DM badge count

The block checker is injected via setDmBlockChecker() to keep
nostrService decoupled from userBlocks, wired up in app.js init().

https://claude.ai/code/session_01EAVLtAM14GN99Eik8otLg2
2026-02-06 19:41:50 +00:00
google-labs-jules[bot]andPR0M3TH3AN d45b115f07 Fix annoying DM relay warning and clarify settings UI
- Throttle the "Privacy warning: direct messages are using your default relays..." message so it only appears once per session/identity change.
- Rename "DM Relay Hints" to "NIP-17 Relay List" in the DM Settings modal to match the warning message and reduce user confusion.
- Add regression test for the warning throttling logic.

Co-authored-by: PR0M3TH3AN <[email protected]>
2026-02-04 16:16:15 +00:00
google-labs-jules[bot]andPR0M3TH3AN b3f37058a2 Defer profile modal data loading to improve responsiveness
Co-authored-by: PR0M3TH3AN <[email protected]>
2026-02-03 14:44:32 +00:00
google-labs-jules[bot]andPR0M3TH3AN 9485003ffd Refactor DM settings into a dedicated modal
- Created `DMSettingsModalController` to manage the new settings modal UI.
- Added `components/dm-settings-modal.html` with sections for Privacy and DM Relay Hints.
- Updated `AppShell.js` to delegate the settings action to `onOpenSettings` callback, bypassing the legacy popover.
- Updated `ProfileModalController.js` to wire up the new modal controller, handling state persistence for relays and privacy settings.
- This improves the UX for managing NIP-17 DM relay hints and privacy options.

Co-authored-by: PR0M3TH3AN <[email protected]>
2026-02-02 19:43:06 +00:00
google-labs-jules[bot]andPR0M3TH3AN 5df489e504 Combine relay list with relay health check
- Remove separate relay health panel from profile modal.
- Merge health indicators (latency, errors) directly into the relay list items.
- Consolidate refresh logic to update both list configuration and health status.
- Move telemetry toggle to the bottom of the relay section.

Co-authored-by: PR0M3TH3AN <[email protected]>
2026-02-02 14:03:09 +00:00
google-labs-jules[bot]andPR0M3TH3AN a50e5c861a Add subscription history and backup/restore functionality
- Added `SUBSCRIPTION_BACKUP` note type schema
- Implemented `createBackup`, `fetchHistory`, `restoreBackup`, `rebroadcastBackup` in `SubscriptionsManager`
- Added Subscription History UI modal with list/details view
- Integrated History/Backup buttons into Profile Modal Subscriptions pane
- Fixed XSS vulnerability in history details view
- Added profile fetching for history details

Co-authored-by: PR0M3TH3AN <[email protected]>
2026-02-02 03:05:13 +00:00
google-labs-jules[bot]andPR0M3TH3AN 8383a4f18b Migrate user blocks to standard NIP-51 Mute List
- Updates `js/userBlocks.js` to treat Kind 10000 (standard Mute List) as the primary write target.
- Public mutes are stored in `p` tags, and private blocks are stored in encrypted content within the same event.
- Legacy `d=user-blocks` lists are still read for backward compatibility (preferring the newest event), but no longer written.
- Updates `js/nostrEventSchemas.js` to mark `USER_BLOCK_LIST` as legacy and standardise `MUTE_LIST`.
- Updates UI controllers (`MoreMenuController`, `ProfileModalController`) to use "Mute/Block List" terminology and delegate all mute/block actions to `userBlocks`.
- Updates `ModerationService` to delegate viewer mute operations to `userBlocks` and disable direct Kind 10000 publishing to prevent overwrites.
- Documentation updated in `docs/nostr-event-schemas.md`.
- Fixes regressions in `more-menu-controller.test.mjs`, `moderation-service.test.mjs`, `trusted-mute-lists.test.mjs`, and `user-blocks.test.mjs`.

Co-authored-by: PR0M3TH3AN <[email protected]>
2026-02-01 21:47:29 +00:00
thePR0M3TH3AN ee3923f169 Update DM focus on default selection 2026-02-01 12:57:04 -05:00
thePR0M3TH3AN b1418d02e5 Render DM threads before profile hydration 2026-02-01 12:36:16 -05:00
google-labs-jules[bot]andPR0M3TH3AN 51087fad7e refactor(ai): extract handleAddProfile from js/app.js (agent)
Moves `handleAddProfile` logic from the main application class into `ProfileModalController` to improve separation of concerns as per `AGENTS.md`.

- Extracts `handleAddProfile` to `js/ui/profileModalController.js`.
- Updates `ProfileModalController` to handle add account flow internally.
- Removes legacy callback wiring from `js/app.js` and `js/ui/applicationBootstrap.js`.
- Adds unit tests for the extracted logic in `tests/ui/profileModalController-addProfile.test.mjs`.

Co-authored-by: PR0M3TH3AN <[email protected]>
2026-01-31 03:32:52 +00:00
thePR0M3TH3AN acf73bc5a3 Add permission CTA for subscriptions and hashtags 2026-01-30 15:39:52 -05:00
thePR0M3TH3AN 09c0ac8127 Add relay health summary banner 2026-01-30 11:08:02 -05:00
thePR0M3TH3AN 25ac2a2c6b Handle NIP-44 decryptor DM errors 2026-01-30 10:32:40 -05:00
thePR0M3TH3AN abdfa4b68b Defer NIP-07 encryption permissions 2026-01-30 10:29:00 -05:00
thePR0M3TH3AN 2726ee9ed4 Batch direct message UI updates 2026-01-29 19:07:29 -05:00
thePR0M3TH3AN 379287c87c Defer subscription and hashtag decrypt prompts 2026-01-29 13:08:35 -05:00
thePR0M3TH3AN c4a00653f4 Move DM relay settings into DM settings popover 2026-01-29 11:52:41 -05:00
thePR0M3TH3AN f116fff337 Wire profile modal refresh buttons 2026-01-29 11:35:15 -05:00
google-labs-jules[bot]andPR0M3TH3AN cfbbf78941 chore(ai): add automated PR review report
Co-authored-by: PR0M3TH3AN <[email protected]>
2026-01-28 23:49:33 +00:00
thePR0M3TH3AN c14b29031c Handle empty block list when signed out 2026-01-28 16:49:31 -05:00
thePR0M3TH3AN dd9b9f1968 Defer login hydration loads 2026-01-28 15:15:52 -05:00
thePR0M3TH3AN 7c47208255 Adjust NIP-07 permissions for decrypt flows 2026-01-28 14:47:06 -05:00
google-labs-jules[bot]andPR0M3TH3AN 63d4b3ffd1 feat(dm): implement incremental delivery for direct messages
- Added `onMessage` callback to `NostrClient.listDirectMessages` to stream decrypted messages.
- Updated `NostrService.loadDirectMessages` to use the callback and trigger `applyDirectMessage` incrementally.
- Updated `ProfileModalController` to allow rendering updates during the initial load if the reason is `load-incremental`.
- Verified changes with existing tests and code review.

Co-authored-by: PR0M3TH3AN <[email protected]>
2026-01-28 00:11:32 +00:00
google-labs-jules[bot]andPR0M3TH3AN bc51f21c0d Fix profile modal opening latency by deferring expensive UI updates
The profile modal was slow to open (~100ms+ delay) when a user has many trusted contacts, blocked users, or moderation reports, because `refreshModerationSettingsUi` and `populateBlockedList` were called synchronously before making the modal visible.

This change refactors `ProfileModalController.show()` to:
1. Render the header synchronously (fast).
2. Call `open()` immediately to make the modal visible.
3. Defer expensive data population (`refreshModerationSettingsUi`, `populateBlockedList`, `refreshWalletPaneState`) to the next animation frame using `requestAnimationFrame`.

This significantly improves the perceived responsiveness of the profile button.

Co-authored-by: PR0M3TH3AN <[email protected]>
2026-01-27 19:03:03 +00:00
google-labs-jules[bot]andPR0M3TH3AN fd4318c2f9 fix(core): optimize moderation subscriptions and reduce log noise (agent)
- Refactor `ModerationService` to use batched subscriptions for trusted mute lists, reducing relay load.
- Fix `WebTorrent` memory leak by setting `setMaxListeners(0)` on client instances.
- Suppress "Failed to connect to relay" warnings in `countDiagnostics.js`.
- Degrade benign DM sync errors (e.g. "no-decryptors") to info/debug logs in `profileModalController.js`.

Co-authored-by: PR0M3TH3AN <[email protected]>
2026-01-26 23:40:59 +00:00
thePR0M3TH3AN 5123944a7d update 2026-01-26 13:23:11 -05:00
thePR0M3TH3AN 27b71ba9bb Revert "perf(profile): implement stale-while-revalidate for lists and messages" 2026-01-26 13:18:51 -05:00
thePR0M3TH3AN b570350412 Merge pull request #1747 from PR0M3TH3AN/improve-profile-modal-fetching-11060559516076687952
perf(profile): implement stale-while-revalidate for lists and messages
2026-01-26 13:17:25 -05:00
google-labs-jules[bot] d61074e200 perf(profile): implement stale-while-revalidate for lists and messages 2026-01-26 18:16:45 +00:00
thePR0M3TH3AN c02db755ac Refactor R2 key prefix for deterministic identifiers 2026-01-26 12:47:05 -05:00
google-labs-jules[bot] 6e3562b64b feat(ui): enhance custom S3 storage configuration with helper text and force path style option
- Add helper text to the S3 storage configuration form to guide users on Endpoint URL format.
- Add 'Force Path Style' checkbox to S3 storage configuration to support MinIO and other S3-compatible providers that require it.
- Update `ProfileModalController` to toggle visibility of these new fields based on the selected provider.
- Update `ProfileModalController` to save and load the `forcePathStyle` setting.
- Update `tests/ui/storageService.test.mjs` to verify persistence of `forcePathStyle`.
2026-01-26 16:50:48 +00:00
thePR0M3TH3AN dd363f0086 Allow any public URL for storage 2026-01-26 07:01:35 -05:00
google-labs-jules[bot] 727892c61a fix: add timeout to sticky privacy warnings in profile modal
Updates the privacy warning notifications in `ProfileModalController` to auto-dismiss after 5 seconds. This resolves an issue where warnings about direct message relays and NIP-17 delivery would persist indefinitely, requiring manual dismissal or page reload.

The fix applies `{ autoHideMs: 5000 }` to `this.showStatus` calls for:
- "Privacy warning: direct messages are using your default relays because no NIP-17 relay list is available."
- "Privacy warning: this recipient has not shared NIP-17 relays, so we'll use your default relays."
- "Privacy warning: this message used default relays because no NIP-17 relay list was found."
2026-01-26 11:33:47 +00:00
thePR0M3TH3AN e096a8b136 Add R2 public URL to storage tests 2026-01-25 20:44:21 -05:00
google-labs-jules[bot] ad1d7de092 Clarify Public URL field in storage settings and add validation
- Renamed "Public URL / Prefix" to "Public Access URL" in Profile Modal to differentiate from S3 API Endpoint.
- Added helper text clarifying that Account ID is used for connection and Public URL is for CDN.
- Implemented validation in `ProfileModalController` to detect and warn if an S3/R2 API endpoint is entered into the Public URL field.
- Added blocking validation on save to prevent misconfiguration.
- Verified changes with unit tests and Playwright frontend verification.
2026-01-26 01:24:04 +00:00
google-labs-jules[bot] de03cd4c58 fix(storage): ensure R2 public URL is saved to connection metadata
When saving an R2 storage connection, the "Prefix" input (which holds the Public Bucket URL) was not being mapped to `meta.baseDomain` or `meta.publicBaseUrl`. This caused `R2Service.ensureBucketConfigForNpub` to throw "Public Bucket URL is missing" during upload preparation, as it relies on these properties.

This commit updates `ProfileModalController.handleSaveStorage` to correctly assign the prefix value to `baseDomain` and `publicBaseUrl` for the `cloudflare_r2` provider, aligning it with the behavior for generic S3 providers and resolving the upload error.
2026-01-25 21:14:05 +00:00
google-labs-jules[bot] 94cafc26ab Fix storage credentials persistence on profile switch
This change ensures that cloud storage credentials are not leaked between Nostr profiles when switching accounts in the UI.

Changes:
- Imported `storageService` in `js/app.js` to enable the `bitvid:auth-changed` event listener to correctly lock the previous profile's storage session.
- Updated `ProfileModalController.populateStoragePane` to explicitly clear the storage form before loading new data.
- Enhanced `ProfileModalController.handleClearStorage` to fully reset the form state, including the provider selection and visibility toggles.

Verified with a reproduction script (`reproduce_storage_isolation.mjs`) that `StorageService` correctly isolates data by pubkey at the backend level. The UI fixes address the frontend persistence issue.
2026-01-25 18:32:46 +00:00
google-labs-jules[bot] d50110f685 fix(storage): validate signer identity before unlocking storage
Prevents storage unlock failures and security risks when switching profiles by verifying that the active signer's public key matches the target profile. This ensures users are prompted to switch accounts in their NIP-07 extension if a mismatch occurs.

Fixes an issue where switching profiles caused the storage tab to break due to using the wrong decryption key.
2026-01-25 18:09:28 +00:00
google-labs-jules[bot] b2d5619f78 fix(ai): resolve PROVIDERS undefined in profileModalController (agent)
Import `PROVIDERS` from `../services/storageService.js` in `js/ui/profileModalController.js`.
This fixes a `ReferenceError` when testing or saving generic S3 storage configurations.
The error was caused by using `PROVIDERS.GENERIC` without importing the constant.
2026-01-25 01:14:37 +00:00
thePR0M3TH3AN 15dea2bbf6 Add generic S3 connection support helpers 2026-01-24 12:39:56 -05:00
google-labs-jules[bot]andPR0M3TH3AN c27fc4bae7 Design System Audit: Fix inline styles
Co-authored-by: PR0M3TH3AN <[email protected]>
2026-01-23 15:42:05 +00:00
google-labs-jules[bot] ac9c09c852 feat(dm): add refresh button, fix transparency, and update settings icon
- Added a forced refresh button to the conversation list in the DM tab (via `onRefreshConversations` in `ProfileModalController`).
- Updated the DM settings gear icon to use `icon-button accent-action-button` classes, matching the `VideoCard` style.
- Ensured the `dm-app-shell` container has a transparent background when rendered inside the profile modal to prevent visual clashes with the modal backdrop.
2026-01-23 15:13:45 +00:00
google-labs-jules[bot] 145796c5e0 Add forced refresh button to DM list and update UI styles
- Add a refresh button to `ConversationList` header.
- Make DM sidebar background transparent.
- Update DM settings gear icon to match `VideoCard` style.
- Wire up refresh action in `ProfileModalController` to force-fetch messages.
2026-01-23 14:04:55 +00:00
google-labs-jules[bot] 5eab37905d redesign DM profile pane UI with split view and avatars
- Update AppShell.js to split view into Conversations and Message History.
- Rename sidebar title to "Conversations".
- Update MessageThread.js to pass avatar URLs to bubbles.
- Update MessageBubble.js to render avatars and use flex layout for alignment.
- Update CSS to style message rows, avatars, and bubbles.
- Ensure peak animations match hashtag strip timing (600ms/800ms).
2026-01-23 05:34:06 +00:00
google-labs-jules[bot] 6700c5b76d Redesign watch history cards and fix timestamp display bug
- Redesigned watch history cards to use a list view layout (flex-row) for better space utilization on both desktop and mobile.
- Updated `buildHistoryCard` in `js/historyView.js` to support a `variant` prop ('compact' or 'modal') for context-specific sizing.
- Updated `js/ui/profileModalController.js` to pass `variant: "modal"` to the watch history renderer.
- Fixed a bug where the "Watched [time] ago" timestamp was unavailable because `normalizeHistoryItems` failed to check `pointer.watchedAt`.
- Verified changes with a reproduction script for the timestamp bug and existing unit tests for the controller.
2026-01-23 02:06:38 +00:00
google-labs-jules[bot] 508071a95f Remove "Republish now" button from profile watch history
Removed the "Republish now" button from the watch history tab in the profile modal (profile-modal.html) and its configuration reference in the controller (profileModalController.js). This button was deemed unnecessary for the watch history functionality within the modal. Verified by unit tests and manual inspection.
2026-01-21 21:06:51 +00:00
google-labs-jules[bot] febbc27706 feat: improve DM mobile navigation with list/thread toggle
- Implement mobile view state management (`list` vs `thread`) in `ProfileModalController`.
- Update `AppShell` to apply `data-dm-view` attribute for CSS toggling.
- Update `MessageThread` to render a "Back" button on mobile.
- Add CSS rules to hide/show sidebar and thread panels based on mobile view state.
- Ensure desktop layout remains split-pane.
2026-01-20 18:27:18 +00:00
google-labs-jules[bot] 486c8af4a1 feat: Move logout button to menu list on mobile
- Added a new mobile-specific "Logout" button to the profile navigation list, visible only on screens smaller than `lg`.
- Hid the existing footer logout button on mobile screens.
- Updated `ProfileModalController` to bind the logout logic to the new mobile button.
- Applied `data-variant="critical"` and spacing to the new button to match styling requirements.
2026-01-20 14:26:54 +00:00
thePR0M3TH3AN 1a57cd352c Merge pull request #1423 from PR0M3TH3AN/fix-profile-modal-stacking-2675219131915820694
Fix profile modal stacking issue on desktop
2026-01-19 21:57:12 -05:00