mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-10-27 07:52:24 +00:00
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)
This commit is contained in:
1 parent
34d57c2072
commit
ba28ceaf09
12 files changed
+198
-60
No files matched your search
@@ -64,6 +64,7 @@ import {
|
||||
openStaticModal
|
||||
} from "./ui/components/staticModalAccessibility.js";
|
||||
import { setModalState as setGlobalModalState } from "./state/appState.js";
|
||||
import { attachFeedInfoPopover } from "./ui/components/FeedInfoPopover.js";
|
||||
|
||||
const getApp = () => getApplication();
|
||||
|
||||
@@ -3703,6 +3704,14 @@ export async function initChannelProfileView() {
|
||||
return;
|
||||
}
|
||||
|
||||
const infoTrigger = document.getElementById("channelInfoTrigger");
|
||||
if (infoTrigger) {
|
||||
attachFeedInfoPopover(
|
||||
infoTrigger,
|
||||
"Videos published by this creator."
|
||||
);
|
||||
}
|
||||
|
||||
currentChannelHex = null;
|
||||
currentChannelNpub = null;
|
||||
currentChannelLightningAddress = "";
|
||||
|
||||
@@ -19,6 +19,7 @@ import {
|
||||
} from "./ui/moderationUiHelpers.js";
|
||||
import { buildModerationBadgeText } from "./ui/moderationCopy.js";
|
||||
import { formatShortNpub } from "./utils/formatters.js";
|
||||
import { attachFeedInfoPopover } from "./ui/components/FeedInfoPopover.js";
|
||||
|
||||
export const WATCH_HISTORY_EMPTY_COPY =
|
||||
"Your watch history is empty. Watch some videos to populate this list.";
|
||||
@@ -2475,6 +2476,13 @@ export function createWatchHistoryRenderer(config = {}) {
|
||||
export const watchHistoryRenderer = createWatchHistoryRenderer();
|
||||
|
||||
export async function initHistoryView() {
|
||||
const infoTrigger = document.getElementById("historyInfoTrigger");
|
||||
if (infoTrigger) {
|
||||
attachFeedInfoPopover(
|
||||
infoTrigger,
|
||||
"Chronological list of videos you have watched."
|
||||
);
|
||||
}
|
||||
await watchHistoryRenderer.init();
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import { escapeHTML } from "./utils/domUtils.js";
|
||||
import { formatShortNpub } from "./utils/formatters.js";
|
||||
import { sanitizeProfileMediaUrl } from "./utils/profileMedia.js";
|
||||
import { devLogger } from "./utils/logger.js";
|
||||
import { attachFeedInfoPopover } from "./ui/components/FeedInfoPopover.js";
|
||||
|
||||
function getApp() {
|
||||
return getApplication();
|
||||
@@ -86,6 +87,14 @@ export async function initSearchView() {
|
||||
titleEl.textContent = query ? `Search Results for "${query}"` : "Search Results";
|
||||
}
|
||||
|
||||
const infoTrigger = document.getElementById("searchInfoTrigger");
|
||||
if (infoTrigger) {
|
||||
attachFeedInfoPopover(
|
||||
infoTrigger,
|
||||
"Results matching your search query."
|
||||
);
|
||||
}
|
||||
|
||||
const channelList = document.getElementById("searchChannelList");
|
||||
const videoList = document.getElementById("searchVideoList");
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import { getApplication } from "./applicationContext.js";
|
||||
import { ASSET_VERSION } from "../config/asset-version.js";
|
||||
import { applyDesignSystemAttributes } from "./designSystem.js";
|
||||
import { devLogger, userLogger } from "./utils/logger.js";
|
||||
import { attachFeedInfoPopover } from "./ui/components/FeedInfoPopover.js";
|
||||
|
||||
const TRACKING_SCRIPT_PATTERN = /(?:^|\/)tracking\.js(?:$|\?)/;
|
||||
|
||||
@@ -92,6 +93,14 @@ export const viewInitRegistry = {
|
||||
if (refreshApp && typeof refreshApp.forceRefreshAllProfiles === "function") {
|
||||
refreshApp.forceRefreshAllProfiles();
|
||||
}
|
||||
|
||||
const infoTrigger = document.getElementById("recentInfoTrigger");
|
||||
if (infoTrigger) {
|
||||
attachFeedInfoPopover(
|
||||
infoTrigger,
|
||||
"Global chronological feed from all relays."
|
||||
);
|
||||
}
|
||||
},
|
||||
"for-you": () => {
|
||||
initForYouView();
|
||||
@@ -110,6 +119,13 @@ export const viewInitRegistry = {
|
||||
},
|
||||
explore: () => {
|
||||
devLogger.log("Explore view loaded.");
|
||||
const infoTrigger = document.getElementById("exploreInfoTrigger");
|
||||
if (infoTrigger) {
|
||||
attachFeedInfoPopover(
|
||||
infoTrigger,
|
||||
"Coming soon."
|
||||
);
|
||||
}
|
||||
},
|
||||
history: async () => {
|
||||
try {
|
||||
@@ -130,6 +146,14 @@ export const viewInitRegistry = {
|
||||
subscriptions: async () => {
|
||||
devLogger.log("Subscriptions view loaded.");
|
||||
|
||||
const infoTrigger = document.getElementById("subscriptionsInfoTrigger");
|
||||
if (infoTrigger) {
|
||||
attachFeedInfoPopover(
|
||||
infoTrigger,
|
||||
"Latest videos from channels you follow."
|
||||
);
|
||||
}
|
||||
|
||||
const app = getApplication();
|
||||
if (!app?.pubkey) {
|
||||
const container = document.getElementById("subscriptionsVideoList");
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 43 KiB |
@@ -1,54 +0,0 @@
|
||||
import sys
|
||||
import os
|
||||
import time
|
||||
from playwright.sync_api import sync_playwright
|
||||
|
||||
def verify_feed_info(page):
|
||||
print("Pre-seeding localStorage...")
|
||||
page.goto("http://localhost:8000") # Go to root first to set storage origin
|
||||
page.evaluate("window.localStorage.setItem('hasSeenDisclaimer', 'true')")
|
||||
|
||||
print("Navigating to For You view...")
|
||||
page.goto("http://localhost:8000/#view=for-you")
|
||||
|
||||
print("Waiting for feed info trigger...")
|
||||
trigger = page.locator("#feedInfoTrigger")
|
||||
try:
|
||||
trigger.wait_for(state="visible", timeout=10000)
|
||||
except Exception:
|
||||
page.screenshot(path="verification/debug_not_found.png")
|
||||
raise
|
||||
|
||||
# Ensure no modals are blocking
|
||||
# We can try to force click or wait for potential overlays to disappear
|
||||
# But pre-seeding should handle the main one.
|
||||
|
||||
print("Clicking trigger...")
|
||||
trigger.click()
|
||||
|
||||
print("Waiting for popover...")
|
||||
popover = page.locator(".popover-panel")
|
||||
popover.wait_for(state="visible", timeout=5000)
|
||||
|
||||
text = popover.inner_text()
|
||||
print(f"Popover text: {text}")
|
||||
|
||||
expected = "Most Recent Video - Disinterests Tags - Watch History + Interests Tags"
|
||||
if expected not in text:
|
||||
raise Exception(f"Unexpected text: {text}")
|
||||
|
||||
page.screenshot(path="verification/feed_info.png")
|
||||
print("Screenshot saved to verification/feed_info.png")
|
||||
|
||||
if __name__ == "__main__":
|
||||
with sync_playwright() as p:
|
||||
browser = p.chromium.launch(headless=True)
|
||||
context = browser.new_context()
|
||||
page = context.new_page()
|
||||
try:
|
||||
verify_feed_info(page)
|
||||
except Exception as e:
|
||||
print(f"Error: {e}")
|
||||
sys.exit(1)
|
||||
finally:
|
||||
browser.close()
|
||||
@@ -148,7 +148,31 @@
|
||||
|
||||
<hr class="my-6" />
|
||||
|
||||
<h3 class="mb-4 text-lg font-bold text-text-strong">Videos by This User</h3>
|
||||
<div class="flex items-center gap-2 mb-4">
|
||||
<h3 class="text-lg font-bold text-text-strong">Videos by This User</h3>
|
||||
<button
|
||||
type="button"
|
||||
id="channelInfoTrigger"
|
||||
class="text-muted hover:text-text focus:outline-none transition-colors"
|
||||
aria-label="How is this feed sorted?"
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
class="w-5 h-5"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<circle cx="12" cy="12" r="10"></circle>
|
||||
<line x1="12" y1="16" x2="12" y2="12"></line>
|
||||
<line x1="12" y1="8" x2="12.01" y2="8"></line>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<div id="channelVideoList" class="bv-grid-video">
|
||||
<!-- User’s videos will go here -->
|
||||
</div>
|
||||
|
||||
+25
-1
@@ -1,5 +1,29 @@
|
||||
<!-- views/explore.html -->
|
||||
<section data-ds="new">
|
||||
<h2 class="mb-4 text-xl font-semibold text-text">Explore</h2>
|
||||
<div class="flex items-center gap-2 mb-4">
|
||||
<h2 class="text-xl font-semibold text-text">Explore</h2>
|
||||
<button
|
||||
type="button"
|
||||
id="exploreInfoTrigger"
|
||||
class="text-muted hover:text-text focus:outline-none transition-colors"
|
||||
aria-label="How is this feed sorted?"
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
class="w-5 h-5"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<circle cx="12" cy="12" r="10"></circle>
|
||||
<line x1="12" y1="16" x2="12" y2="12"></line>
|
||||
<line x1="12" y1="8" x2="12.01" y2="8"></line>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<p class="text-muted-strong">Coming Soon...</p>
|
||||
</section>
|
||||
+25
-1
@@ -5,7 +5,31 @@
|
||||
class="flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between"
|
||||
>
|
||||
<div>
|
||||
<h2 class="text-xl font-semibold text-text">Watch History</h2>
|
||||
<div class="flex items-center gap-2">
|
||||
<h2 class="text-xl font-semibold text-text">Watch History</h2>
|
||||
<button
|
||||
type="button"
|
||||
id="historyInfoTrigger"
|
||||
class="text-muted hover:text-text focus:outline-none transition-colors"
|
||||
aria-label="How is this feed sorted?"
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
class="w-5 h-5"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<circle cx="12" cy="12" r="10"></circle>
|
||||
<line x1="12" y1="16" x2="12" y2="12"></line>
|
||||
<line x1="12" y1="8" x2="12.01" y2="8"></line>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<p class="text-sm text-muted">
|
||||
Review the videos you recently played, grouped by day.
|
||||
</p>
|
||||
|
||||
@@ -1,7 +1,31 @@
|
||||
<!-- views/most-recent-videos.html -->
|
||||
<section data-ds="new">
|
||||
<!-- You can have a heading if you want -->
|
||||
<h2 class="mb-4 text-xl font-semibold text-text">Recently Added Videos</h2>
|
||||
<div class="flex items-center gap-2 mb-4">
|
||||
<h2 class="text-xl font-semibold text-text">Recently Added Videos</h2>
|
||||
<button
|
||||
type="button"
|
||||
id="recentInfoTrigger"
|
||||
class="text-muted hover:text-text focus:outline-none transition-colors"
|
||||
aria-label="How is this feed sorted?"
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
class="w-5 h-5"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<circle cx="12" cy="12" r="10"></circle>
|
||||
<line x1="12" y1="16" x2="12" y2="12"></line>
|
||||
<line x1="12" y1="8" x2="12.01" y2="8"></line>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Video List -->
|
||||
<div id="recentVideoTags" class="mb-4" hidden></div>
|
||||
|
||||
+23
-1
@@ -1,11 +1,33 @@
|
||||
<div class="fade-in bv-stack">
|
||||
<header class="mb-4">
|
||||
<header class="flex items-center gap-2 mb-4">
|
||||
<h1
|
||||
id="searchTitle"
|
||||
class="text-2xl font-bold tracking-tight text-text-strong"
|
||||
>
|
||||
Search Results
|
||||
</h1>
|
||||
<button
|
||||
type="button"
|
||||
id="searchInfoTrigger"
|
||||
class="text-muted hover:text-text focus:outline-none transition-colors"
|
||||
aria-label="How is this feed sorted?"
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
class="w-5 h-5"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<circle cx="12" cy="12" r="10"></circle>
|
||||
<line x1="12" y1="16" x2="12" y2="12"></line>
|
||||
<line x1="12" y1="8" x2="12.01" y2="8"></line>
|
||||
</svg>
|
||||
</button>
|
||||
</header>
|
||||
|
||||
<section class="bv-stack">
|
||||
|
||||
@@ -1,6 +1,30 @@
|
||||
<!-- views/subscriptions.html -->
|
||||
<section data-ds="new">
|
||||
<h2 class="mb-4 text-xl font-semibold text-text">Subscriptions</h2>
|
||||
<div class="flex items-center gap-2 mb-4">
|
||||
<h2 class="text-xl font-semibold text-text">Subscriptions</h2>
|
||||
<button
|
||||
type="button"
|
||||
id="subscriptionsInfoTrigger"
|
||||
class="text-muted hover:text-text focus:outline-none transition-colors"
|
||||
aria-label="How is this feed sorted?"
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
class="w-5 h-5"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<circle cx="12" cy="12" r="10"></circle>
|
||||
<line x1="12" y1="16" x2="12" y2="12"></line>
|
||||
<line x1="12" y1="8" x2="12.01" y2="8"></line>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<div id="subscriptionsVideoList" class="bv-grid-video">
|
||||
<div class="sidebar-loading-wrapper" role="status" aria-live="polite">
|
||||
<div class="sidebar-loading-indicator">
|
||||
|
||||
Reference in new issue
Block a user