Removes the "Direct message privacy" section from the profile modal's Messages tab, as these settings are now managed via the AppShell (gear icon).
- Removed privacy section HTML from `components/profile-modal.html`.
- Updated `js/ui/profileModalController.js` to remove legacy DOM references and event listeners.
- Preserved `handleReadReceiptsToggle` and `handleTypingIndicatorsToggle` methods for AppShell integration.
- Updated `syncDmPrivacySettingsUi` to be a no-op to prevent errors in existing call sites.
- Added 'Safety' tab to `components/profile-modal.html`, positioned before 'Blocked'
- Moved `profileModerationSettings` and `profileLinkPreviewSettings` panels to the new tab
- Updated `ProfileModalController.js` to manage the new tab and initialize settings when selected
- Renamed 'Safety & Moderation' panel header to 'Safety'
Explicitly set `size: "md"` in ContactRow and added `min-width` / `min-height` to avatar CSS classes to prevent flexbox squashing. This ensures consistent avatar rendering in the conversations column.
- Maximized profile modal to be full-screen for better content visibility.
- Cleaned up DM conversation list by removing message previews and timestamps.
- Updated DM badges and outgoing messages to use theme accent color instead of generic blue.
- Refactored DM composer to move privacy and zap toggles into a "More" menu.
- Added `scripts/agent/validate-events.mjs` to validate event builders against schemas.
- Fixed `NOTE_TYPES.REPOST` schema content format (json instead of empty).
- Added `NOTE_TYPES.MUTE_LIST` and `buildMuteListEvent`.
- Added `buildProfileMetadataEvent` to standardise Kind 0 creation.
- Updated `js/ui/profileModalController.js` to use `buildProfileMetadataEvent`.
- Updated `js/userBlocks.js` to use `buildMuteListEvent` for publishing mute list snapshots.
- Updated `docs/nostr-event-schemas.md` with new schemas and builders.
Moved tag preference menu logic into `js/ui/tagPreferenceMenuController.js`.
Kept `js/app.js` interface intact via thin wrappers.
Added unit tests covering new controller.
Followed AGENTS.md refactor checklist.
- Updated `For You` page to rely on feed engine filtering for tag preferences.
- Removed the `recentVideoTags` HTML element from `views/for-you.html`.
- Updated `js/app.js` and `js/ui/videoListViewController.js` to optionally skip finding the `recentVideoTags` element.
- Updated `loadForYouVideos` in `js/app.js` to explicitly skip `recentVideoTags`.
- Confirmed feed logic via `tests/feed-engine/tag-preference-filter.test.mjs`.
- Verified UI changes via Playwright.
- Fixed inline style violations in `js/ui/components/EventDetailsModal.js` and `js/ui/components/SimilarContentCard.js` by converting to Tailwind classes.
- Fixed Tailwind token violations in `components/login-modal.html`.
- Fixed Tailwind color violations in `js/ui/components/EventDetailsModal.js`.
- Formatted `README.md`.
- Updated CSS formatting in `css/tailwind.source.css`.
- Added "Edit Profile" button to active profile card in profile modal
- Created `profilePaneEdit` with form fields for profile metadata (Kind 0)
- Implemented `populateEditPane`, `handleEditProfile`, `handleSaveProfile` in `ProfileModalController`
- Added file upload support for profile/banner images using `r2Service`
- Injected `r2Service` into `ProfileModalController` via `ApplicationBootstrap`
- Verified functionality with manual check of logic and structure
Removes a premature call to `initializeLoginModalController` in `ApplicationBootstrap` which was attempting to initialize the login modal before the DOM was fully hydrated, causing a "modal container not found" warning during startup. The modal is already correctly initialized later in `js/index.js` after markup loading completes.
Moved torrent status update logic to `js/ui/torrentStatusController.js` to improve separation of concerns as per `AGENTS.md`. The controller accepts a `getVideoModal` accessor and an `onRemovePoster` callback to decouple it from direct `videoModal` or `Application` dependencies. Added unit tests in `tests/ui/torrentStatusController.test.mjs`.
I modified `js/channelProfile.js` to implement the logic that toggles the "Send" button to "Done" and closes the dialog when clicked. Additionally, I updated `js/ui/zapController.js` to prevent the form from resetting entirely on success, which preserves receipts; instead, it now manually clears the comment and sets the completed state.
These changes ensure consistent "Done" button behavior across both the Channel Profile and Video Modal zap interfaces. I also included minor `package.json` updates for linting dependencies.
- Updated `EventDetailsModal` to handle cases where fetching the raw event fails or returns null.
- Implemented `getRawEvent` logic to reconstruct the `content` JSON string from available video metadata (title, thumbnail, description, etc.) if the raw content is missing.
- Ensures the user can inspect key metadata (like thumbnail URLs) even when the original signed event payload is not available in memory or via network fetch.
- Explicitly marks the signature as "unavailable (cached)" in fallback scenarios.
- Updated `EventDetailsModal` to handle cases where fetching the raw event fails or returns null.
- Implemented `getRawEvent` logic to reconstruct the `content` JSON string from available video metadata (title, thumbnail, description, etc.) if the raw content is missing.
- Ensures the user can inspect key metadata (like thumbnail URLs) even when the original signed event payload is not available in memory or via network fetch.
- Explicitly marks the signature as "unavailable (cached)" in fallback scenarios.