Files
bitvid/views/channel-profile.html
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

199 lines
6.7 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<section class="channel-profile-container" data-ds="new">
<!-- Modified banner wrapper for taller, rounded style -->
<div class="profile-banner relative mb-6 rounded-lg shadow-lg">
<!-- Increase the default height classes -->
<img
id="channelBanner"
class="h-48 w-full rounded-lg object-cover md:h-64"
src="assets/jpg/bitvid.jpg"
alt="Banner"
loading="lazy"
referrerpolicy="no-referrer"
data-fallback-src="assets/jpg/bitvid.jpg"
/>
<div class="pointer-events-none absolute inset-0 rounded-lg bg-overlay-channel"></div>
<div
class="absolute bottom-4 left-4 right-4 flex flex-col gap-3 sm:flex-row sm:items-end sm:justify-between"
>
<div class="flex flex-col gap-3">
<div
id="channelModerationBadge"
class="channel-moderation-badge-anchor"
aria-live="polite"
></div>
<div class="flex items-center">
<div id="channelAvatarWrap" class="relative">
<div
class="h-16 w-16 overflow-hidden rounded-full border-2 border-border-translucent-bright max-sm:h-12 max-sm:w-12"
>
<img
id="channelAvatar"
src="assets/svg/default-profile.svg"
alt="Avatar"
class="h-full w-full object-cover"
/>
</div>
</div>
<div class="ml-4 text-text">
<h2 id="channelName" class="text-xl font-bold max-sm:text-base">User Name</h2>
<p id="channelNpub" class="text-sm opacity-80 max-sm:text-2xs">npub...</p>
</div>
</div>
</div>
<div class="flex flex-col items-end gap-3 self-start sm:self-end">
<div class="flex items-center gap-2">
<button
id="zapButton"
type="button"
class="icon-button accent-action-button"
aria-label="Open zap dialog"
aria-haspopup="dialog"
aria-expanded="false"
aria-controls="zapControls"
>
<svg
class="icon-image"
viewBox="0 0 24 24"
aria-hidden="true"
focusable="false"
>
<polygon
points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
/>
</svg>
</button>
<button
id="channelMessageBtn"
type="button"
class="icon-button accent-action-button"
aria-label="Send message"
title="Send message"
>
<svg
class="icon-image"
viewBox="0 0 24 24"
aria-hidden="true"
focusable="false"
>
<path
fill="currentColor"
d="M4 4h16a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2H9l-5 4v-4H4a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2Zm0 2v9h1.5L7 14h13V6H4Zm2.5 2h11v2h-11V8Zm0 4h7v2h-7v-2Z"
/>
</svg>
</button>
<button
id="channelShareBtn"
type="button"
class="icon-button accent-action-button"
aria-label="Share channel"
>
<svg
class="icon-image"
viewBox="0 0 24 24"
aria-hidden="true"
focusable="false"
>
<path
fill="currentColor"
d="M5 7a5 5 0 1 1 0 10 5 5 0 0 1 0-10Zm11.122 12.065A4 4 0 1 1 24 20a4 4 0 0 1-7.878-.935l-5.488-2.927a6.009 6.009 0 0 1-.943 1.764l5.488 2.927ZM24 4a4 4 0 1 1-7.878.935l-5.488 2.927a6.01 6.01 0 0 1-.943-1.764l5.488-2.927A4 4 0 0 1 24 4Z"
/>
</svg>
</button>
<button
id="channelMoreBtn"
type="button"
class="icon-button accent-action-button"
aria-haspopup="true"
aria-expanded="false"
aria-label="Channel options"
aria-controls="channelProfileMoreMenu"
>
<svg
class="icon-image"
viewBox="0 0 24 24"
aria-hidden="true"
focusable="false"
>
<circle cx="5" cy="12" r="2" fill="currentColor" />
<circle cx="12" cy="12" r="2" fill="currentColor" />
<circle cx="19" cy="12" r="2" fill="currentColor" />
</svg>
</button>
</div>
</div>
</div>
</div>
<!-- Basic profile details: about text, website, LN address -->
<div class="profile-details mt-4 px-4">
<p id="channelAbout" class="mb-2 text-text-strong"></p>
<a
id="channelWebsite"
href="#"
target="_blank"
rel="noopener noreferrer"
class="mb-2 block text-info-strong hover:underline"
>Website</a
>
<p id="channelLightning" class="text-sm text-muted-strong"></p>
<!-- #47: total sats zapped to this creator (bitvid tallies + 9735s).
Hidden until there's a nonzero total. -->
<p
id="channelZapTotal"
class="text-sm text-zap font-medium hidden"
title="Total sats zapped to this creator via bitvid"
></p>
</div>
<!-- Area for Subscribe/Unsubscribe button -->
<div class="my-4 px-4">
<div id="subscribeBtnArea" class="hidden"></div>
</div>
<hr class="my-6" />
<!-- #37: creator playlists. Hidden unless FEATURE_PLAYLISTS is on and the
creator has at least one playlist (populated by js/channelPlaylists.js). -->
<section id="channelPlaylistsSection" class="hidden mb-8">
<h3 class="text-lg font-bold text-text-strong mb-4">Playlists</h3>
<div id="channelPlaylistsGrid" class="playlist-grid">
<!-- Playlist cards go here -->
</div>
</section>
<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>
</section>