mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-10-27 07:52:24 +00:00
Align sidebar loading indicators and history heading
This commit is contained in:
1 parent
259bd3b281
commit
284bab6cff
8 files changed
+97
-36
No files matched your search
+23
-6
@@ -1144,12 +1144,6 @@ button:not(.icon-button):focus {
|
|||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
.watch-history-status {
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.status-spinner--inline {
|
.status-spinner--inline {
|
||||||
animation: spin 1s linear infinite;
|
animation: spin 1s linear infinite;
|
||||||
border: 0.125rem solid rgba(96, 165, 250, 0.35);
|
border: 0.125rem solid rgba(96, 165, 250, 0.35);
|
||||||
@@ -1160,6 +1154,29 @@ button:not(.icon-button):focus {
|
|||||||
width: 1rem;
|
width: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sidebar-loading-wrapper {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
padding: 3rem 0;
|
||||||
|
width: 100%;
|
||||||
|
grid-column: 1 / -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-loading-indicator {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.75rem;
|
||||||
|
color: #6b7280;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
font-weight: 500;
|
||||||
|
letter-spacing: 0.01em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-loading-text {
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
.status-banner {
|
.status-banner {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background-color: rgba(31, 41, 55, 0.9);
|
background-color: rgba(31, 41, 55, 0.9);
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ import {
|
|||||||
} from "./storage/r2-s3.js";
|
} from "./storage/r2-s3.js";
|
||||||
import { initQuickR2Upload } from "./r2-quick.js";
|
import { initQuickR2Upload } from "./r2-quick.js";
|
||||||
import { createWatchHistoryRenderer } from "./historyView.js";
|
import { createWatchHistoryRenderer } from "./historyView.js";
|
||||||
|
import { getSidebarLoadingMarkup } from "./sidebarLoading.js";
|
||||||
import {
|
import {
|
||||||
initViewCounter,
|
initViewCounter,
|
||||||
subscribeToVideoViewCount,
|
subscribeToVideoViewCount,
|
||||||
@@ -7534,10 +7535,9 @@ class bitvidApp {
|
|||||||
if (!this.videoSubscription) {
|
if (!this.videoSubscription) {
|
||||||
if (this.videoList) {
|
if (this.videoList) {
|
||||||
this.lastRenderedVideoSignature = null;
|
this.lastRenderedVideoSignature = null;
|
||||||
this.videoList.innerHTML = `
|
this.videoList.innerHTML = getSidebarLoadingMarkup(
|
||||||
<p class="text-center text-gray-500">
|
"Fetching recent videos…"
|
||||||
Loading videos as they arrive...
|
);
|
||||||
</p>`;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new subscription
|
// Create a new subscription
|
||||||
|
|||||||
+5
-8
@@ -4,6 +4,7 @@ import { nostrClient } from "./nostr.js";
|
|||||||
import { WATCH_HISTORY_BATCH_RESOLVE } from "./config.js";
|
import { WATCH_HISTORY_BATCH_RESOLVE } from "./config.js";
|
||||||
import { subscriptions } from "./subscriptions.js";
|
import { subscriptions } from "./subscriptions.js";
|
||||||
import { accessControl } from "./accessControl.js";
|
import { accessControl } from "./accessControl.js";
|
||||||
|
import { getSidebarLoadingMarkup } from "./sidebarLoading.js";
|
||||||
|
|
||||||
const DEFAULT_BATCH_SIZE = 20;
|
const DEFAULT_BATCH_SIZE = 20;
|
||||||
const BATCH_SIZE = WATCH_HISTORY_BATCH_RESOLVE ? DEFAULT_BATCH_SIZE : 1;
|
const BATCH_SIZE = WATCH_HISTORY_BATCH_RESOLVE ? DEFAULT_BATCH_SIZE : 1;
|
||||||
@@ -672,14 +673,10 @@ export function createWatchHistoryRenderer(config = {}) {
|
|||||||
|
|
||||||
const nextMessage = typeof message === "string" ? message.trim() : "";
|
const nextMessage = typeof message === "string" ? message.trim() : "";
|
||||||
if (nextMessage) {
|
if (nextMessage) {
|
||||||
if (nextMessage === WATCH_HISTORY_LOADING_STATUS) {
|
const showSpinner = nextMessage === WATCH_HISTORY_LOADING_STATUS;
|
||||||
statusEl.innerHTML =
|
statusEl.innerHTML = getSidebarLoadingMarkup(nextMessage, {
|
||||||
'<span class="watch-history-status watch-history-status--loading"><span class="status-spinner status-spinner--inline" aria-hidden="true"></span><span>' +
|
showSpinner,
|
||||||
WATCH_HISTORY_LOADING_STATUS +
|
});
|
||||||
"</span></span>";
|
|
||||||
} else {
|
|
||||||
statusEl.textContent = nextMessage;
|
|
||||||
}
|
|
||||||
statusEl.classList.remove("hidden");
|
statusEl.classList.remove("hidden");
|
||||||
} else {
|
} else {
|
||||||
statusEl.textContent = "";
|
statusEl.textContent = "";
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
// js/sidebarLoading.js
|
||||||
|
|
||||||
|
function escapeHtml(value) {
|
||||||
|
if (typeof value !== "string") {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
return value
|
||||||
|
.replace(/&/g, "&")
|
||||||
|
.replace(/</g, "<")
|
||||||
|
.replace(/>/g, ">")
|
||||||
|
.replace(/"/g, """)
|
||||||
|
.replace(/'/g, "'");
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getSidebarLoadingMarkup(message = "", options = {}) {
|
||||||
|
const trimmed = typeof message === "string" ? message.trim() : "";
|
||||||
|
const copy = trimmed || "Fetching data…";
|
||||||
|
const safeCopy = escapeHtml(copy);
|
||||||
|
const showSpinner = options?.showSpinner !== false;
|
||||||
|
const spinnerMarkup = showSpinner
|
||||||
|
? '<span class="status-spinner status-spinner--inline" aria-hidden="true"></span>'
|
||||||
|
: "";
|
||||||
|
|
||||||
|
return `
|
||||||
|
<div class="sidebar-loading-wrapper" role="status" aria-live="polite">
|
||||||
|
<div class="sidebar-loading-indicator">
|
||||||
|
${spinnerMarkup}
|
||||||
|
<span class="sidebar-loading-text">${safeCopy}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
@@ -9,6 +9,7 @@ import {
|
|||||||
buildSubscriptionListEvent,
|
buildSubscriptionListEvent,
|
||||||
SUBSCRIPTION_LIST_IDENTIFIER,
|
SUBSCRIPTION_LIST_IDENTIFIER,
|
||||||
} from "./nostrEventSchemas.js";
|
} from "./nostrEventSchemas.js";
|
||||||
|
import { getSidebarLoadingMarkup } from "./sidebarLoading.js";
|
||||||
|
|
||||||
function getAbsoluteShareUrl(nevent) {
|
function getAbsoluteShareUrl(nevent) {
|
||||||
if (!nevent) {
|
if (!nevent) {
|
||||||
@@ -226,6 +227,8 @@ class SubscriptionsManager {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
container.innerHTML = getSidebarLoadingMarkup("Fetching subscriptions…");
|
||||||
|
|
||||||
// Gather all videos
|
// Gather all videos
|
||||||
const videos = await this.fetchSubscribedVideos(channelHexes);
|
const videos = await this.fetchSubscribedVideos(channelHexes);
|
||||||
this.renderSameGridStyle(videos, containerId);
|
this.renderSameGridStyle(videos, containerId);
|
||||||
|
|||||||
+15
-16
@@ -1,21 +1,20 @@
|
|||||||
<!-- views/history.html -->
|
<!-- views/history.html -->
|
||||||
<section id="watchHistoryView" class="space-y-6">
|
<section id="watchHistoryView" class="space-y-6">
|
||||||
<div class="flex items-center justify-between">
|
<h2 class="text-xl mb-4 text-gray-700">Watch History</h2>
|
||||||
<h2 class="text-2xl font-semibold text-white">Watch History</h2>
|
<div id="watchHistoryLoading">
|
||||||
</div>
|
<div id="watchHistoryStatus">
|
||||||
<div
|
<div class="sidebar-loading-wrapper" role="status" aria-live="polite">
|
||||||
id="watchHistoryLoading"
|
<div class="sidebar-loading-indicator">
|
||||||
class="flex flex-col items-center justify-center py-12 space-y-4"
|
<span
|
||||||
>
|
class="status-spinner status-spinner--inline"
|
||||||
<div
|
aria-hidden="true"
|
||||||
class="h-10 w-10 border-4 border-blue-500 border-t-transparent rounded-full animate-spin"
|
></span>
|
||||||
aria-hidden="true"
|
<span class="sidebar-loading-text"
|
||||||
></div>
|
>Fetching watch history from relays…</span
|
||||||
<p
|
>
|
||||||
id="watchHistoryStatus"
|
</div>
|
||||||
class="text-gray-300 text-center hidden"
|
</div>
|
||||||
aria-live="polite"
|
</div>
|
||||||
></p>
|
|
||||||
</div>
|
</div>
|
||||||
<div id="watchHistoryGrid" class="watch-history-grid hidden"></div>
|
<div id="watchHistoryGrid" class="watch-history-grid hidden"></div>
|
||||||
<p id="watchHistoryEmpty" class="hidden text-gray-400 text-center py-12">
|
<p id="watchHistoryEmpty" class="hidden text-gray-400 text-center py-12">
|
||||||
|
|||||||
@@ -8,6 +8,11 @@
|
|||||||
id="videoList"
|
id="videoList"
|
||||||
class="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-8"
|
class="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-8"
|
||||||
>
|
>
|
||||||
<!-- Videos will be dynamically inserted here -->
|
<div class="sidebar-loading-wrapper" role="status" aria-live="polite">
|
||||||
|
<div class="sidebar-loading-indicator">
|
||||||
|
<span class="status-spinner status-spinner--inline" aria-hidden="true"></span>
|
||||||
|
<span class="sidebar-loading-text">Fetching recent videos…</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
@@ -9,5 +9,12 @@
|
|||||||
gap: 2rem;
|
gap: 2rem;
|
||||||
padding: 1.5rem 0;
|
padding: 1.5rem 0;
|
||||||
"
|
"
|
||||||
></div>
|
>
|
||||||
|
<div class="sidebar-loading-wrapper" role="status" aria-live="polite">
|
||||||
|
<div class="sidebar-loading-indicator">
|
||||||
|
<span class="status-spinner status-spinner--inline" aria-hidden="true"></span>
|
||||||
|
<span class="sidebar-loading-text">Fetching subscriptions…</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
Reference in new issue
Block a user