- Update `UploadModal.js` to pre-calculate R2 keys and public URLs before upload.
- Update `torrentHash.js` to embed the calculated video URL as a webseed (`url-list`) in the `.torrent` file.
- Update `r2Service.js` to accept forced keys/URLs and append `&xs=` (pointing to the .torrent file) to the magnet link.
- Ensures magnet links work for peerless downloads via WebSeed (BEP19) and HTTP Seeding (BEP17).
- Added toggle buttons and stat counters to `video-modal.html`.
- Updated `VideoModal.js` to manage toggle visibility (show if either source exists, disable unavailable option) and dispatch `playback:switch-source` events.
- Updated `app.js` to handle source switching by restarting playback with a `forcedSource`.
- Updated `playbackService.js` to respect `forcedSource` by bypassing probe logic when a specific source is requested.
- Added source toggle UI in `components/video-modal.html`.
- Updated `VideoModal.js` to manage toggle visibility (only when both URL and Magnet exist), update peer/server counts, and dispatch `playback:switch-source` events.
- Updated `PlaybackService.js` to support a `forcedSource` option, allowing bypassing of the URL probe when "torrent" is forced.
- Updated `app.js` to listen for the toggle event and re-initialize playback with the forced source preference.
- Updated `tests/ui/helpers/jsdom-test-helpers.mjs` to expose necessary globals for JSDOM testing.
- Verified functionality with targeted updates and existing unit tests.
- Added `EventDetailsModal` to display raw JSON and metadata.
- Implemented `open-channel` action to navigate to creator profile.
- Fixed profile image loading by checking `creatorPicture` and `creator.picture`.
- Added `hideModal()` to `Application` class to fix crash in `openCreatorChannel`.
- Wired up "Event Details" menu option in video card menu.
- Ensured edit history is sorted Newest First for navigation.
- Fix circular dependency in `js/adminListStore.js` by importing from `js/nostrClientRegistry.js`.
- Update `js/services/hashtagPreferencesService.js` to include legacy kind 30005 in filters.
- Fix JSDOM mocking in `tests/modal-accessibility.test.mjs` (navigator getter) and `UploadModal` selectors.
- Add `getRoot()` to `js/ui/components/UploadModal.js` for API consistency.
- Update `tests/magnet-utils.test.mjs` expectations to reflect removed default tracker.
- Mock `ensureActiveSignerForPubkey` in `tests/moderation/submit-report.test.mjs`.
- Fix mock loader path in `tests/moderation/trust-seeds.test.mjs` to target `trustBootstrap.js`.
- Fix duplicate pointer tags in `js/nostrEventSchemas.js`'s `buildCommentEvent`.
- Update `tests/nostr/comment-events.test.mjs` and `tests/comment-event-builder.test.mjs` to match current code behavior (legacy kinds, unique tags).
Moves the moderation warning badge ("Content blocked...") to overlay the blurred thumbnail image instead of sitting below it or increasing card height. This logic is applied to both the main `VideoCard` and the `SimilarContentCard` to ensure layout consistency.
Changes:
- VideoCard.js: Refactor `updateModerationBadge` to append the badge container as a child of the `anchorEl` (thumbnail wrapper) with absolute positioning.
- SimilarContentCard.js: Implement `refreshModerationUi` logic to generate and overlay a simplified moderation badge on the thumbnail when `trustedMuted` context is present.
- Fix tests/moderation/video-card.test.mjs: Patch test environment to mock `globalThis.navigator`.
- Remove view count and separator from the metadata row in `SimilarContentCard.js`.
- Add new `buildEngagementSection` method to render view count and discussion count in a dedicated footer.
- Use Eye and Message SVG icons for engagement metrics.
- Ensure visual consistency with the main Video Card component.
- Fix import and definition of `SVG_NAMESPACE` to support icon creation.
- Moved view count and comments to a new bottom engagement section in `VideoCard.js`.
- Replaced text labels with Eye and Message SVG icons in `VideoCard.js`.
- Updated `video-modal.html` to include an Eye icon for the view count.
- Refactored `VideoModal.js` to update only the text node for view counts, preserving the icon.
- Removed "views" text suffix in favor of a cleaner numeric display.
- Moved view count from author metadata section to a new bottom "Engagement Section".
- Replaced "views" and "notes" text with SVG icons (Eye and Message Circle).
- Grouped views and comments side-by-side in the new section.
- Preserved existing data attributes for view/discussion counters.
- Cleaned up author metadata to only show Time and Edited status.
- Added `deleteObject` to `js/storage/r2-s3.js` for cleanup.
- Added `verifyPublicAccess` to `js/services/r2Service.js` to test bucket configuration.
- Refactored `components/upload-modal.html` to support wizard steps.
- Updated `js/ui/components/UploadModal.js` to manage wizard state and trigger verification.
- Removed requirement for Cloudflare API Token, Zone ID, and Worker Token from Upload Modal and R2Service.
- Simplified R2 configuration to require only Account ID, S3 Access Keys, and a user-provided Public Bucket URL.
- Added a read-only field in Upload Modal displaying the derived target bucket name (npub-based) for user reference.
- Implemented client-side torrent info hash calculation using `WebTorrent` (via `js/utils/torrentHash.js`) to generate magnet links before upload.
- Added a visual upload progress bar to the Upload Modal.
- Updated `js/r2.js` to ensure the Public Bucket URL always includes the `https://` protocol.
- Update `VideoCard.js` to display "• Edited" instead of "(edited)" for better visual consistency.
- Update `app.js` to format the modal's "Last Edited" timestamp as "Last edited: [Absolute] ([Relative])".
- Ensure `EditModal.js` correctly backfills and preserves `published_at` to prevent date resets.
- Verify edit logic with existing tests.
Prioritize `published_at` metadata over event `created_at` timestamp.
Backfill `published_at` during edit if missing to preserve original date.
Add "(edited)" label to video cards for modified content.
Display "Last Edited: [Date]" on video player modal.
- Replaced the button with a simple text link (`<a id="link-r2-help">`) inside the R2 credentials section.
- Added a click event listener in `UploadModal.js` to call `this.close()` when the link is clicked, allowing users to navigate to the setup guide without obstruction.
- Modified `js/ui/components/UploadModal.js` to hide the thumbnail browse button when in 'External Link' mode.
- Ensured the browse button is visible when switching back to 'Upload File' mode.
- Added logic to clear the thumbnail file input when resetting the form.
- Added file input and browse button for thumbnails in `upload-modal.html`.
- Updated `UploadModal.js` to handle thumbnail file selection and UI toggling.
- Updated `r2Service.js` to upload thumbnail file (if present) to R2 and update metadata.
- Ensured thumbnail keys are derived from video keys for consistent naming.
- Refactored `SimilarContentCard.js` to use Flexbox layout.
- Updated `css/tailwind.source.css` to remove grid layout and use standard flex utilities.
- Improved thumbnail sizing (16:9, fixed width) and responsiveness.
- Added hover effects (background color, thumbnail zoom).
- Cleaned up typography and metadata hierarchy.
- Replaces split "Custom" vs "Cloudflare" forms with a single unified form
- Implements source switching between "Upload File" and "External Link"
- Consolidates NIP-71 advanced fields into a single collapsible section
- Moves R2 storage configuration to a dedicated, collapsible settings block
- Improves responsiveness and modernizes the UI layout
- Updates internal JS logic to handle unified form submission and validation
- Rename "Legacy description" to "Video description"
- Group technical NIP-71 fields (Event Type, IMETA, Tracks, Segments) into a hidden "Advanced Options" section
- Automate "Summary" field to mirror "Video description" by default (with unlock toggle)
- Automate "Web seed" field to mirror "Hosted video URL"
- Automate "Content Warning" based on NSFW toggle status
- Maintain visibility of Hashtags in the main form flow
- Apply changes consistently to both Custom and Cloudflare R2 upload modes
- Fix cleanup handler registration for advanced toggle listener
- Rename "Legacy description" to "Video description"
- Group technical NIP-71 fields (Event Type, IMETA, Tracks, Segments) into a hidden "Advanced Options" section
- Automate "Summary" field to mirror "Video description" by default (with unlock toggle)
- Automate "Web seed" field to mirror "Hosted video URL"
- Automate "Content Warning" based on NSFW toggle status
- Maintain visibility of Hashtags in the main form flow
- Apply changes consistently to both Custom and Cloudflare R2 upload modes
- Add a confirmation dialog in `UploadModal.js` when a user uploads a video with only a magnet link to warn about potential data loss.
- Replace the hardcoded limit of 300 in `NostrClient.fetchVideos` with a configurable limit that respects `DEFAULT_VIDEO_REQUEST_LIMIT` and `MAX_VIDEO_REQUEST_LIMIT`, improving client-side scalability.
This addresses an issue where comments would not display on the first load of the video modal if the DOM elements were not fully bound. The `open()` method now checks if the `commentsList` is missing or disconnected and re-initializes the `CommentsController` if necessary.
Also updated `tests/video-modal-accessibility.test.mjs` to fix a JSDOM environment issue with `navigator` mocking.