Diagnostics revealed the delete does NOT go through watchHistoryController
(app.watchHistoryController is undefined — it lives on modalCoordinator, not the
app root), so the renderer's `remove` handler always falls through to the
uninstrumented defaultRemoveHandler. That's why no [watch-history:remove] logs
appeared even though a refresh fired. Instrument defaultRemoveHandler to log the
published (reduced) item count + snapshot/list-update results, so we can confirm
whether the publish reduces correctly and isolate the read/cache layer.
Flag-gated; no behavior change.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Watch-history delete still misbehaves for the user; add targeted diagnostics to
pinpoint whether it's the publish, relay propagation, or the local cache/read.
- logWatchHistoryDebug now routes to console (not the prod-suppressed devLogger),
so enabling the existing `bitvid:debug:watch-history` flag surfaces logs on the
hosted site too.
- Instrument the removal path (watchHistoryController): the computed remaining
list (count + values + source), snapshot result, list-update result/finalCount,
and publish failures.
- Instrument the read path (historyView.loadHistory): what a (force) refresh
actually returns (count + values) — directly tests the "is the cache returning
the stale full list?" hypothesis.
Flag-gated and off by default; no behavior change (watch-history tests green).
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Root cause of "watch history delete does not work at all": the removal paths
call watchHistoryService.snapshot(remaining, …), but snapshot published via
updateWatchHistoryList WITHOUT replace:true. The default merges incoming items
with the existing cached list, so the just-removed item was merged straight back
and the deletion silently had no effect. Removing the LAST item was worse: an
empty list fell through to republishing the pending queue instead of clearing.
- snapshot now honors options.replace: forwards it to updateWatchHistoryList,
treats an explicit empty replace as a clear (publishes empty instead of
short-circuiting or falling back to the queue), and skips the cached-items
merge when replacing. Adds (the default) keep merge semantics.
- Both removal call sites (watchHistoryController.handleWatchHistoryRemoval and
historyView.defaultRemoveHandler) now pass replace:true.
Tests (snapshot at the updateWatchHistoryList boundary): removing an item
publishes the remaining list with replace:true; removing the last item publishes
an empty replace (not a queue republish / no-op); a normal watch-tracking
snapshot still merges (replace not forced). Mutation-verified — dropping the
replace forwarding fails 2 cases and reverting the empty-clear handling fails the
clear case.
Build + full lint green.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Added public API JSDoc blocks to `js/historyView.js`.
Created standalone architectural and execution overview `docs/historyView-overview.md`.
Completed required docs-code-investigator daily scheduling execution.
Co-authored-by: PR0M3TH3AN <[email protected]>
- Add docs/capacitor-native-app-plan.md to hex-lint ignore list (code examples
naturally reference hex colors in Capacitor config)
- Replace direct console.error/console.log calls with logger utility in
historyView.js, profileCache.js, EventDetailsModal.js, ZapInterface.js,
and notificationController.js
- Update CI workflow from Node 20 to Node 22 to match package.json engines
https://claude.ai/code/session_01LzErpH9FNw4hAPsjoYb1v9
Four issues caused login to be extremely slow and lists to fail syncing:
1. Subscription list decryption excluded NIP-04 when NIP-44 was available,
preventing decryption of NIP-04-encrypted lists entirely. Removed the
allowNip04 gate so NIP-04 is always a fallback (matching userBlocks.js
and hashtagPreferencesService.js which already worked correctly).
2. When the NIP-07 extension permission pre-grant failed (common on page
refresh when the extension injects slowly), all list services were called
with allowPermissionPrompt:false and could never recover. Now list
services are allowed to prompt for permissions themselves when the
pre-grant fails, avoiding 6-10 second retry delays.
3. The profile modal storage tab was never refreshed on login or logout,
so it stayed locked even after authentication succeeded. Added
populateStoragePane() calls to handleAuthLogin and handleAuthLogout.
4. The watch-history feed engine.run() call was missing await, so rejected
promises from unregistered feeds escaped the try/catch and propagated
as unhandled errors instead of falling through to the service fallback.
https://claude.ai/code/session_013puYzbf1cC7a59HLcGQUdJ
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
- 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.
- 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)
- 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).
- Shorten npubs in history view cards.
- Add Refresh, Privacy Banner, and Info to Profile Modal Watch History.
- Wire up Profile Modal Watch History controls.
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.
- Enforce descending month order in `js/nostr/watchHistory.js` by explicitly sorting keys before flattening buckets.
- Update `js/feedEngine/watchHistoryFeed.js` and `js/historyView.js` to use `video.created_at` as a fallback sort key when `watchedAt` is missing or equal.
- Verified logic with `tests/verify_sort.mjs`.
- 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