Commit Graph
106 Commits
Author SHA1 Message Date
thePR0M3TH3ANandClaude Opus 4.8 610935ac03 Admin star badge on admin avatars across the app
Show a small gold "verified admin" star in the corner opposite the red
notification dot whenever a rendered profile belongs to a bitvid admin
(the super admin or a current list editor).

- adminBadge.js (new): isAdminActor(hex|npub) sync check against
  accessControl, and applyAdminStar(container, id) which adds/removes a
  single `.admin-star` in a non-clipped, positioned container. Idempotent.
- CSS: `.admin-star` (top-left gold disc, mirrors the top-right dot),
  `.dm-avatar-wrap`, and position:relative on the comment avatar wrapper.
- Profile button: app.refreshAdminStar() lights the logged-in user's star;
  re-runs on login/logout and on accessControl.onEditorsChange (so a
  late-loading editor list still resolves).
- Comments: star on comment-author avatars (commentNodeFactory).
- Channel page: wrap the clipped avatar and star the channel owner.
- DMs: Avatar gains an opt-in adminId — only admin avatars get wrapped so
  non-admin rows are byte-identical; ContactRow passes the peer pubkey.
- tests: admin-badge unit coverage (recognition, idempotency, removal).

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-07-07 10:10:19 -04:00
thePR0M3TH3ANandClaude Opus 4.8 f46b1ce7f3 playlists(#37): restyle playlist cards (stacked cover + themed scrim) + back button
Design polish from feedback:
- Playlist cards are now a "stack of clips" cover: the first video's thumbnail
  fills a 16:9 tile with two offset/rotated layers peeking behind it (::before/
  ::after). A themed gradient scrim (accent-strong→accent→clear, via color-mix)
  darkens the base so the title sits BOLD and WHITE over the cover instead of
  small grey text underneath. Video count moved to a pill in the top-right.
  channelPlaylists.js resolves the cover from the app's active videos
  (buildVideoAddressPointer → video.thumbnail), falling back to playlist.image.
- Back button on the playlist view: was a bare "← Back to channel" text link, now
  a proper .btn-ghost (sm) pill with a chevron icon — matches the site's buttons
  and is theme-aware.
- tokens.css: added --size-4px/--size-5px for the stack offsets (token lint).

Scrim/title use --color-white (always light — the scrim is always dark
regardless of theme). Lint + build clean.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-07-06 14:18:31 -04:00
thePR0M3TH3ANandClaude Opus 4.8 291d55d966 playlists(#37): playlist view — renders a playlist's ordered videos
New route #view=playlist&pubkey=<hex>&id=<playlist id>:
- views/playlist.html: title + meta + the shared #videoList grid.
- js/playlistView.js: initPlaylistView() reads pubkey+id from the hash, fetches
  the playlist (facade), resolves its ordered `a` refs against the app's active
  videos (buildVideoAddressPointer keys, same 30078 contract), points the back
  link at the creator's channel, and renders via app.renderVideoList with
  preserveOrder:true so the playlist's order is kept (not re-sorted by date —
  #21). Unresolved refs are skipped; the meta line shows "N of M available".
  Gated by FEATURE_PLAYLISTS.
- FEED_TYPES.PLAYLIST + viewManager registration (getApp: getApplication).

The channel-section cards now resolve to a working view. node --check + lint +
build clean. End-to-end browser verification comes with the create/edit slice
(needs a way to actually make a playlist).

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-07-06 13:16:28 -04:00
thePR0M3TH3ANandClaude Opus 4.8 85903965a4 playlists(#37): FEATURE_PLAYLISTS flag + channel "Playlists" section
- constants.js: FEATURE_PLAYLISTS (default OFF) so nothing is user-visible until
  the whole playlist UI ships; flip to preview on unstable.
- js/channelPlaylists.js: wireChannelPlaylists(pubkey) fetches the creator's
  playlists (facade) and renders a responsive row of cards (thumbnail + video
  count + title) linking to `#view=playlist&pubkey=…&id=…`. Hidden when the flag
  is off, no playlists, or the container is missing; a nav-token guards against a
  stale fetch resolving after a channel switch. DOM built with textContent (no
  innerHTML). Kept out of the 5729-line-capped channelProfile.js.
- channelProfile.js: one-line wireChannelPlaylists(currentChannelHex) hook next
  to wireChannelZapTotal (no-op while the flag is off).
- views/channel-profile.html: #channelPlaylistsSection above the video grid.
- tailwind.source.css: .playlist-grid / .playlist-card* (token-only; responsive
  via @apply like .bv-grid-video).

Lint + build clean. The playlist view the cards link to lands next.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-07-06 13:12:37 -04:00
thePR0M3TH3ANandClaude Opus 4.8 cf82978060 zaps: profile-zap counting + channel "sats zapped" total (#47 — closes the feature)
The store now supports p: (profile/channel) pointers — every zap tagged to a
creator pubkey (direct profile zaps AND zaps to their videos, both carry a `p`
tag), from 9735 receipts + verified tallies:

- pointerKey accepts "p"; new profilePointer(pubkey) helper.
- runBatch batches p: pointers into a #p filter; both folds count #p-tagged
  events (deduped by payment_hash like a:/e:).
- Channel page: a "⚡ N sats zapped" total under the lightning address, wired
  to the store via js/channelZapTotal.js (own module for channelProfile.js's
  size budget), hidden until nonzero.

Completes the D2 video + profile scope; the bitvid-native zap tally feature is
now feature-complete (publish + count + chart + video + profile). Tests:
profilePointer/pointerKey + #p counting in tests/zap-totals.test.mjs. Lint
(size cap ok) + build green.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-07-05 00:36:44 -04:00
thePR0M3TH3ANandClaude Fable 5 8dfd2034b0 feeds: "Most Zapped" sidebar tab ranked by zap totals (#47)
Trending-pattern clone ranked by sats from kind-9735 receipts:

- js/zapTotals.js: per-pointer receipt aggregation. The feed's metric getter
  returns the cached total and schedules a batched fetch (#a/#e chunks via
  the L1 SubscriptionManager) for unknown/stale pointers; amounts parse via
  nip57 bolt11 with the zap request's amount tag as fallback; receipts are
  deduped by id so re-fetches never double-count; zero-receipt answers are
  cached (2-min TTL).
- sorters.js: shared count-ranked sorter (metric desc, recency tie-break,
  author spread, trusted-muted sink); Trending delegates unchanged, Most
  Zapped ranks on runtime.getZapTotal.
- Full wiring: feed definition, view + info popover, change-signal re-rank
  (order settles as receipts stream in), sidebar link, viewManager registry,
  feedCoordinator case/loader, FEED_TYPES.MOST_ZAPPED, and a
  FEATURE_MOST_ZAPPED_FEED flag (default on; off hides the tab).

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-07-03 21:38:53 -04:00
thePR0M3TH3ANandClaude Opus 4.8 02854d4fb5 feed: add Trending tab — recently-added ranked by view count (#27)
New FEED_TYPES.TRENDING tab: the active (recently-added) source ranked by view
count (recency tiebreak, trusted-muted last), gated by FEATURE_TRENDING_FEED
(default on). Builds on the now-trustworthy view counts (#4).

- createTrendingSorter reads counts from runtime.getViewCount, which resolves
  each video's pointer via the app's canonical deriveVideoPointerInfo against the
  shared viewCounter cache (new getVideoViewCountSnapshot export) — the same
  counts the grid cards already load.
- Live re-rank: viewCounter now emits a coalesced onViewCountsChanged signal;
  while the Trending view is active it debounce-re-runs the feed (cheap re-rank
  over the in-memory active set, no relay re-fetch), so the order settles into
  true trending as counts stream in. Cold cache reads as recency, then improves.
- Pipeline extracted to js/feedEngine/trendingFeed.js (feedCoordinator is at its
  size cap; bumped the cap for the thin load/refresh delegations).
- Wiring: FEED_TYPES + flag, feedCoordinator cases, app.js wrappers,
  applicationBootstrap registration (hides the sidebar link when flag off),
  viewManager init + js/trendingView.js, views/trending.html, sidebar link.

Tests: tests/trending-sorter.test.mjs.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-24 13:06:34 -04:00
thePR0M3TH3ANandClaude Opus 4.8 c79120ba04 chore: remove dead dev 'Agent Dashboard' view (embedded external TORCH)
Drops views/dev/agent-dashboard.html (iframed the external TORCH dashboard,
now defunct), its sidebar nav link, and the unused DEV_DASHBOARD view constant.
No dangling references; build green.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-16 20:35:58 -04:00
google-labs-jules[bot]andPR0M3TH3AN d0f0b3ee2e Fix: Add rel="noopener noreferrer" to target="_blank" link in channel profile
This commit addresses a security vulnerability in `views/channel-profile.html` where an external link with `target="_blank"` was missing `rel="noopener noreferrer"`. This could allow the target page to manipulate the `window.opener` object (reverse tabnabbing).

Changes:
- Added `rel="noopener noreferrer"` to the `#channelWebsite` anchor tag.

Verification:
- Confirmed the attribute is present using a Playwright verification script.
- Confirmed no visual regressions.
- Ran linting checks (passed).
- Ran unit tests (pre-existing unrelated failures in NIP compliance noted).

Co-authored-by: PR0M3TH3AN <[email protected]>
2026-02-26 17:30:59 +00:00
thePR0M3TH3AN 51f37ece22 docs: add TORCH memory integration guidance 2026-02-25 13:12:07 -05:00
thePR0M3TH3AN 0f89cc1524 chore(torch): migrate to new TORCH system and remove legacy agent stack 2026-02-25 12:58:46 -05:00
google-labs-jules[bot]andPR0M3TH3AN bebb28cfa0 Fix: TORCH dashboard missing active locks created before midnight
The TORCH dashboard was filtering events using `since: <today 00:00 UTC>`, which excluded active locks created on the previous day (e.g., late-night daily locks or weekly locks).

This change updates the `since` filter to look back 7 days, ensuring that all potentially active locks (including weekly cadence) are retrieved and displayed.

Steps:
1.  Modified `views/dev/agent-dashboard.html` to set `since` to `Date.now() - 7 days`.
2.  Verified the fix by creating a reproduction script `reproduce_issue.py` (which confirmed the issue) and a verification script `verify_dashboard.py` (which confirmed the fix).
3.  Verified the visual output with `verification.png`.

Co-authored-by: PR0M3TH3AN <[email protected]>
2026-02-14 00:18:53 +00:00
google-labs-jules[bot]andPR0M3TH3AN 30bd4a75f6 feat: integrate TORCH agent dashboard into UI sidebar
- Add "Dev Tools" button to the sidebar footer menu.
- Configure `js/constants.js` with `DEV_DASHBOARD` view type.
- Refactor `views/dev/agent-dashboard.html` to be compatible with `loadView` (moved styles to body, updated links).
- Add cleanup logic to dashboard script to prevent memory leaks when navigating away.
- Fix duplicate import in `js/nostr/reactionEvents.js`.

Co-authored-by: PR0M3TH3AN <[email protected]>
2026-02-13 23:50:42 +00:00
Claude d4fd9f3839 Add TORCH agent coordination dashboard dev tool
Standalone HTML page at views/dev/agent-dashboard.html that connects
directly to the same three Nostr relays agents use (relay.damus.io,
nos.lol, relay.primal.net), subscribes to kind 30078 events tagged
with #bitvid-agent-lock, and renders a live dashboard of active
agent locks with TTL bars, platform badges, and a raw event log.

https://claude.ai/code/session_017hmikBS4vBXtFWCsdkkQv8
2026-02-13 21:28:12 +00:00
Claude d0a6c9622b feat: add Playwright agent testability infrastructure
Add test harness (window.__bitvidTest__), data-testid attributes, relay
override support, and Playwright fixtures so agents can programmatically
login, seed relay data, and inspect app state during E2E testing.

- js/testHarness.js: exposes loginWithNsec, getAppState, relay overrides
- data-testid attrs on login/upload/video modals, header buttons, feed
- simple-relay.mjs: HTTP seeding API (POST /seed, GET /events, /health)
- bitvidTestFixture.ts: reusable Playwright fixture with mock relay
- agent-testability.spec.ts: E2E tests validating the infrastructure

https://claude.ai/code/session_01XnrszNmdqrAGd8g8qhAn4G
2026-02-10 05:09:46 +00:00
google-labs-jules[bot]andPR0M3TH3AN e6e3b47fce Modernize docs navigation buttons with icons
- Replaced text-based "Show/Hide" sidebar toggles with SVG chevron icons.
- Added a hamburger menu icon to the "Contents" button on mobile view.
- Updated `js/docsView.js` to handle icon toggling and properly hide flex container elements using the `.hidden` class.
- Improved accessibility by maintaining `aria-expanded` attributes.

Co-authored-by: PR0M3TH3AN <[email protected]>
2026-01-27 19:43:24 +00:00
google-labs-jules[bot]andPR0M3TH3AN cfd7c49a9d Refactor docs navigation and clean up legacy views
Co-authored-by: PR0M3TH3AN <[email protected]>
2026-01-27 16:32:01 +00:00
google-labs-jules[bot]andPR0M3TH3AN d490fa1295 Fix incorrect markdown file paths in documentation views
- Updated `fetch` paths in legacy views (getting-started, upload-content, about, roadmap, community-guidelines, links) to point to the correct locations in `content/docs/`.
- Added debug logging to `js/docsView.js` to assist in diagnosing "Loading content..." hangs in the new documentation system.

Co-authored-by: PR0M3TH3AN <[email protected]>
2026-01-27 15:07:16 +00:00
thePR0M3TH3AN 3a4e0aa3e8 Add docs TOC drawer overlay 2026-01-27 08:47:27 -05:00
thePR0M3TH3AN 2a5fbb3904 Register docs view initializer 2026-01-27 08:36:12 -05:00
thePR0M3TH3AN 44c9df033c Add docs view layout 2026-01-26 23:27:16 -05:00
google-labs-jules[bot] ef5cb8ad78 chore(ai): CI health fixes (flaky tests)
- Fix broken `SearchFiltersPopover.js` import in `views/dev/popover-demo.html` by replacing it with a local `wirePopover` implementation, resolving `tests/e2e/popover.spec.ts` failures.
- Update `.gitignore` to exclude `*.log` files to prevent accidental commits of local log files.
- Remove accidental `server.log` from the repository.
- Attempted to fix `tests/visual/moderation.spec.ts` but confirmed "element not found" issues in fixture environment; reverted to preserve passing state.
- Formatted code.
2026-01-26 02:41:31 +00:00
thePR0M3TH3AN 460ba22d51 Add search filter state syncing 2026-01-23 12:07:55 -05:00
thePR0M3TH3AN f7016f78f7 Add search filters popover component 2026-01-23 11:53:37 -05:00
google-labs-jules[bot] 986e4ef497 ui: move Kids link below Recently Added and add tags to Kids page 2026-01-23 07:40:44 +00:00
thePR0M3TH3AN 33cc5d23c7 Add kids feed view 2026-01-23 02:09:08 -05:00
google-labs-jules[bot] 7221ef0eaa Add hashtag helper bar to Explore tab and refactor ID
- Add `#videoListTags` container to `views/explore.html` to support the hashtag helper bar in the Explore view.
- Rename `#recentVideoTags` to `#videoListTags` in `views/most-recent-videos.html` for consistency across views.
- Update `js/ui/videoListViewController.js` and `js/app.js` to reference the new generic `#videoListTags` ID.
- Update `tests/ui/video-list-view-popular-tags.test.mjs` to reflect the ID change.

This enables the hashtag aggregation and interaction features (filtering, muting, following) on the Explore tab, reusing the existing `VideoListView` logic.
2026-01-23 02:20:13 +00:00
thePR0M3TH3AN c3aa42f39c Add explore feed pipeline 2026-01-22 19:04:50 -05:00
thePR0M3TH3AN ce7b76bf1b Merge pull request #1478 from PR0M3TH3AN/feat/feed-info-popovers-17616740575820035536
Add Info Popovers to Feed Views
2026-01-21 16:02:34 -05:00
google-labs-jules[bot] ba28ceaf09 feat: add info popovers to feed views
- 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)
2026-01-21 20:59:11 +00:00
google-labs-jules[bot] 83ad3a1132 feat: limit channel search results with show more button
- 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.
2026-01-21 20:35:58 +00:00
google-labs-jules[bot] bae4020682 feat: add info icon with filter logic popover to For You feed
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.
2026-01-21 17:48:01 +00:00
thePR0M3TH3AN 63a048f01d Remove channel notify button 2026-01-18 22:33:33 -05:00
thePR0M3TH3AN 3874955a2b Merge pull request #1359 from PR0M3TH3AN/for-you-feed-update-6639372694731601459
feat: Remove hashtag pills from For You page
2026-01-18 21:34:57 -05:00
google-labs-jules[bot] 5c65c44db3 feat: Remove hashtag pills from For You page
- 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.
2026-01-19 02:33:17 +00:00
google-labs-jules[bot] 68bdd590a6 Remove IPNS support and related content
Deleted IPNS view, content, and asset files. Removed references to IPNS from the README, sidebar, and documentation pages. This feature is no longer supported for hosting.
2026-01-19 02:13:59 +00:00
thePR0M3TH3AN 51a8f6498a Update global feed heading 2026-01-18 20:39:00 -05:00
thePR0M3TH3AN e7951f8004 Add channel notification and message buttons 2026-01-18 19:30:49 -05:00
thePR0M3TH3AN a846da13c0 Add for-you view wiring 2026-01-18 13:42:00 -05:00
google-labs-jules[bot] 5119c6f85e Remove "Republish Now" button from Watch History view
- Removed the "Republish Now" button from `views/history.html` to prevent accidental overwriting of relay data with incomplete local state.
- Removed associated event handlers and logic from `js/historyView.js`.
- Verified UI changes with Playwright.
- Existing tests pass (known failures in unrelated files ignored).
2026-01-18 17:33:54 +00:00
google-labs-jules[bot] 163327aaa8 Remove watch history privacy banner and info text 2026-01-17 13:58:39 +00:00
google-labs-jules[bot] 2515ed9e8e Implement user and video search functionality
- Updated `js/index.js` to handle search input:
  - Redirects valid npubs to the channel profile.
  - Redirects other queries to the new search view.
- Created `views/search.html` to display search results.
- Created `js/searchView.js` to perform NIP-50 searches for profiles (Kind 0) and videos (Kind 30078).
  - Includes specific handling for hashtag searches (using `#t` filter).
- Updated `js/viewManager.js` to register the new search view.
2026-01-16 23:02:42 +00:00
google-labs-jules[bot] a5e7e48fea Fix lint:tailwind-brackets errors by using design tokens
Replaced arbitrary Tailwind values with standard design tokens in HTML files to pass the linting checks:
- `components/upload-modal.html`: Replaced `text-[10px]` with `text-4xs` (approx. 10.4px).
- `views/channel-profile.html`: Replaced `max-sm:text-[0.7rem]` with `max-sm:text-2xs` (0.7rem).
- `views/channel-profile.html`: Replaced `max-sm:h-[3.2rem]` and `max-sm:w-[3.2rem]` with `max-sm:h-12` and `max-sm:w-12` (standard 3rem/48px spacing).
2026-01-14 02:51:02 +00:00
google-labs-jules[bot] cd38fd0c2a Add "Upload Content" guide and link in Upload Modal
- Create `assets/svg/upload-content-icon.svg`
- Create `content/upload-content.md` with Cloudflare R2 setup instructions
- Create `views/upload-content.html` to render the guide
- Add "Learn How" link to `components/upload-modal.html` in the R2 credentials section
2026-01-09 03:31:00 +00:00
google-labs-jules[bot] c322fcee14 fix(watch-history): add manual refresh and fix dynamic pulling
This commit addresses issues with the watch history not updating dynamically and adds a manual refresh mechanism.

Changes:
- Added a "Refresh" button to the watch history view in `views/history.html` and `js/historyView.js`.
- Updated `watchHistoryService.js` to accept a `forceRefresh` option in `loadLatest`, which bypasses the cache freshness check and triggers a relay fetch.
- Updated `js/feedEngine/watchHistoryFeed.js` to propagate the `forceRefresh` flag from the runtime context to the service.
- Added user feedback (toast messages and logs) for "Clear Local History" and "Republish Now" actions.
- Updated `tests/watch-history.test.mjs` to align with the new `fetchHistory` signature.
2026-01-07 14:05:21 +00:00
google-labs-jules[bot] 89ce081453 Update history view copy to reflect event ID-only tracking
- Rename "Clear local cache" button to "Clear local history"
- Update info text to remove references to hydrating from session/caches
- Simplify copy to remove "encrypted" references in favor of "syncing" or "history"
- Update success/error messages to match new terminology
2026-01-05 19:17:51 +00:00
thePR0M3TH3AN 006f561302 Simplify watch history messaging 2026-01-03 09:40:15 -05:00
thePR0M3TH3AN 153205ccbf Align subscriptions view heading typography 2025-10-27 16:33:45 -04:00
thePR0M3TH3AN 5cc0e136bd Add channel header moderation badge 2025-10-25 20:54:12 -04:00
thePR0M3TH3AN 876020b90f Add popular tag strip support to recent videos 2025-10-23 15:13:05 -04:00