- Deleted `js/magnet.js` as it was a redundant wrapper for `js/magnetUtils.js`.
- Refactored `js/services/videoNotePayload.js`, `js/ui/components/EditModal.js`, and `js/nostr/nip71.js` to use `magnetUtils.js` and `magnetShared.js`.
- Updated `tests/magnet-utils.test.mjs` to remove tests for the deleted file.
- Removed unused exports `DEFAULT_FEED_CONFIG` and `DEFAULT_CONFIG_SCHEMA` from `js/feedEngine/engine.js` and `index.js`.
- Verified changes with unit tests.
- Removed `required` attribute from nsec secret input in `components/login-modal.html` to prevent browser native validation from suppressing custom error UI.
- Updated `js/ui/loginModalController.js` to ensure `required` property is disabled in JavaScript logic.
- Added comprehensive unit tests in `tests/login-modal-controller.test.mjs` to verify:
- Custom error message is shown on empty submission.
- Required attributes remain disabled when toggling between unlock/import modes.
- NIP-46 handshake panel is correctly displayed (regression check).
- Verified fix with existing E2E test `tests/e2e/ui-modals.spec.ts` (NSEC error assertion passes).
- Remove `wss://open.video.lukewarlow.uk:443/announce` from `DEFAULT_WSS_TRACKERS` in `js/constants.js`.
- This tracker was returning `net::ERR_SSL_PROTOCOL_ERROR`, causing console noise and connection failures.
- Added `scripts/agent/debug_frontend.py` to help diagnose frontend initialization errors.
Verified with `scripts/agent/debug_frontend.py` that the error is resolved.
Ran `npm run format`, `npm run lint`, and `npm run test:unit`.
Fuzzer discovered a crash when `pointerTags` is passed as null.
Added array check to prevent TypeError.
Also added fuzz harnesses for schemas, dm decryptor and magnet utils.
- Replaced direct copy-to-clipboard action with a Share menu.
- Added "Copy URL", "Share on Nostr", "Copy Magnet", and "Copy CDN Link" options.
- Moved "Copy Magnet" from the main modal interface to the menu.
- Updated `js/app.js` to handle `video:share-nostr` (placeholder), `video:copy-magnet`, and `video:copy-cdn` events.
- Removed deprecated `setCopyMagnetState` logic.
- Cleaned up `components/video-modal.html`.
- Added JSDoc comments to `js/nostr/client.js` for key methods (`sendDirectMessage`, `subscribeDirectMessages`, `ensurePool`, `saveLocalData`, `persistLocalData`).
- Created `docs/nostr-client-overview.md` to provide a high-level architectural overview of the `NostrClient` class.
- Format `css/tailwind.source.css` with Prettier.
- Add allowlist entry for `VideoCard.js` media query pixel value in `scripts/check-design-tokens.mjs`.
- Remove accidental artifact `js/ui/dm/jules_session_4520373547615093905.zip`.
- Fix bug in `js/app.js` and `js/services/moderationActionController.js` where blocked users' videos were not correctly hidden in the UI immediately after blocking.
- Fix bug in `tests/app/moderation-overrides.test.mjs` where `userBlocks` mocks were insufficient to reflect state changes.
- Added `data-testid` attributes to key modals (Disclaimer, Login, Upload, Video, Profile, Lockdown) to facilitate reliable selection in Playwright tests.
- Updated `js/disclaimer.js` and `js/index.js` to respect a new `playwright-bypass-disclaimer` localStorage flag, allowing automated tests to skip the disclaimer modal entirely.
This change ensures the 'Explore' link is visible in the sidebar when the user is logged in, and hidden when logged out, consistent with other authenticated routes like 'For You' and 'Subscriptions'.
- Updated `js/app.js` to handle `exploreLink` visibility in `applyAuthenticatedUiState` and `applyLoggedOutUiState`.
- Initialized `exploreLink` property in `js/ui/applicationBootstrap.js`.
- Updated `tests/app/hydrate-sidebar-navigation.test.mjs` to verify the behavior.
- Replaced the standalone "Copy Magnet" button and "Share" button with a new Share menu.
- Implemented `createVideoShareMenuPanel` to render the new menu with "Copy URL", "Share on Nostr", "Copy Magnet", and "Copy CDN Link" options.
- Updated `VideoModal.js` to manage the share menu state and handle actions.
- Added `video:share-nostr` and `video:copy-cdn` event handlers in `app.js`.
- Removed the `#copyMagnetBtn` element from `video-modal.html`.
- Preserved existing functionality for "Copy URL" and "Copy Magnet".
- "Share on Nostr" is currently a placeholder logging a message, disabled for logged-out users.
- "Copy CDN Link" is disabled if no URL is available.
Moved `handleRepostAction`, `handleMirrorAction`, and `handleEnsurePresenceAction` from `js/app.js` to `js/ui/engagementController.js`.
This follows the AGENTS.md refactor direction for `bitvidApp` to controllers.
- Extracted logic into `EngagementController`.
- Added unit tests for `EngagementController`.
- Wired `EngagementController` into `js/app.js`.
- Preserved `currentVideoPointer` fallback logic in `derivePointerFromDataset`.
- Relax `VideoCard` active state detection to a 30% viewport sweet spot (rootMargin -35%)
- Strict desktop detection using `window.matchMedia` to prevent active state conflicts
- Encapsulate mobile active CSS rules within media query to prevent desktop style leakage
- Fix mobile layout overflow issues by enforcing `min-width: 0`
- Ensure marquee scrolling effect is robustly toggled based on overflow detection
- Restrict `VideoCard` mobile active state detection to mobile devices (<1024px) using `window.matchMedia`
- Tighten `IntersectionObserver` sweet spot to 10% (rootMargin: -45%) to prevent multiple cards being active
- Encapsulate mobile active CSS rules within media query to prevent desktop style regression
- Ensure proper marquee scrolling behavior on mobile by separating static and animated states
- Prevent layout blowouts by enforcing `min-width: 0` on flex containers
- Add marquee scrolling logic to VideoCard.js using ResizeObserver and CSS animations
- Implement mobile active state detection using IntersectionObserver with a centered rootMargin (-25%)
- Update CSS to apply active state styles (backdrop blur, shadow) via data-mobile-active attribute
- Fix mobile layout overflow issues by enforcing min-width: 0 on flex containers
- Ensure title text color changes to accent on active/hover state
- Add ellipsis truncation for titles and usernames
- Implement scroll-on-hover (desktop) and scroll-on-center (mobile)
- Fix mobile layout blowout using min-width: 0 on flex containers
- Add IntersectionObserver and ResizeObserver mocks for tests
- Reduced view threshold from 12s to 5s in watchHistoryTelemetry.js
- Enabled immediate watch history republishing (0ms delay) for the first attempt in watchHistory.js
- Updated watchHistoryService.js to recursively schedule queue flushes if items accumulate during an inflight sync
- Replaced CSS truncation with a custom marquee structure in `VideoCard.js` for titles and author names.
- Added `css/tailwind.source.css` utilities for `.marquee-host`, `.marquee-static`, and `.marquee-track` animations.
- Implemented `ResizeObserver` (shared singleton) to detect overflow and enable marquee only when needed.
- Implemented `IntersectionObserver` (shared singleton) to trigger marquee on mobile when the card is in the center of the viewport.
- Configured dynamic animation duration based on text content width to ensure constant scrolling speed.
- Verified visual behavior via Playwright screenshots.
- Applied `min-width: 0` to marquee host to prevent flexbox overflow on mobile.
- Updated raw CSS values to use design tokens to pass linting.
Moves the Zap button and Zap statistics from the message thread header to the message composer area, adjacent to the Send button. Refactors the Zap interface creation logic into a standalone component `ZapInterface.js` to decouple it from `MessageThread.js`. Updates `Composer.js` to support an optional `onZap` handler and `zapStats` prop, rendering the button with an icon-only style and the stats pill reusing the existing CSS class. Updates `AppShell.js` to orchestrate the Zap interface display and pass the necessary statistics.
- Increased `PROBE_TIMEOUT_MS` in `js/gridHealth.js` to 20s to reduce false negatives in peer detection.
- Relaxed the peer check in `js/app.js` to allow forcing a switch to WebTorrent even if the liveliness checker reports 0 peers (showing a warning instead of an error).
- Added `tests/verify_app_switch.mjs` to validate the UI logic change.
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.
- Added info buttons to Most Recent, Subscriptions, History, Channel Profile, Search, and Explore views
- Attached popovers with descriptions of feed filtration methods
- Used `attachFeedInfoPopover` helper for consistent implementation
- Verified with Playwright script (verified popover visibility and text content)
- Increased tracker timeout to 6000ms and concurrency to 6 in `js/trackerConfig.js`
- Increased trackers per magnet check to 10 to ensure better peer discovery
- Added new reliable public WebSocket trackers to `DEFAULT_WSS_TRACKERS` in `js/constants.js`
- Verified configuration changes with `tests/verify_tracker_config.mjs`
- Added a "Show More" button to `views/search.html`.
- Implemented responsive truncation logic in `css/tailwind.source.css` using `nth-child` selectors to show 5 items on mobile, 6 on desktop (LG), and 8 on large screens (XL).
- Updated `js/searchView.js` to handle the logic for displaying the button and toggling the limit class.
- Compiled CSS.
Moves the Zap button from the message thread header to the message composer area, adjacent to the Send button. Refactors the Zap interface creation logic into a standalone component `ZapInterface.js` to decouple it from `MessageThread.js`. Updates `Composer.js` to support an optional `onZap` handler and renders the button with an icon-only style matching the video player's accent interaction. Updates `AppShell.js` to orchestrate the Zap interface display.
- Replaced CSS truncation with a custom marquee structure in `VideoCard.js` for titles and author names.
- Added `css/tailwind.source.css` utilities for `.marquee-host`, `.marquee-static`, and `.marquee-track` animations.
- Implemented `ResizeObserver` (shared singleton) to detect overflow and enable marquee only when needed.
- Implemented `IntersectionObserver` (shared singleton) to trigger marquee on mobile when the card is in the center of the viewport.
- Configured dynamic animation duration based on text content width to ensure constant scrolling speed.
- Verified visual behavior via Playwright screenshots.
Adds a clickable info icon next to the "For You" title that displays a popover explaining the feed's filtering logic ("Most Recent Video - Disinterests Tags - Watch History + Interests Tags"). Implemented as a reusable helper `attachFeedInfoPopover` in `js/ui/components/FeedInfoPopover.js` to support future use on other feed pages. Updated `views/for-you.html` and `js/forYouView.js` to integrate the new component. Verified with Playwright.