浏览代码

Refactor

Delay showing page content until JS has finished setting up page elements
That then allows the following:
Leave relative time to be rendered on the client
Leave collapsible lists to be rendered on the client
Which massively simplfies the backend templates which were error prone
Svilen Markov 1 年之前
父节点
当前提交
36f8eac3e4

+ 35 - 33
internal/assets/static/main.css

@@ -57,6 +57,14 @@
     font-size: var(--font-size-h4);
 }
 
+.page-content, .page.content-ready .page-loading-container {
+    display: none;
+}
+
+.page.content-ready > .page-content {
+    display: block;
+}
+
 .page-column-full .size-title-dynamic {
     font-size: var(--font-size-h3);
 }
@@ -117,6 +125,14 @@
     padding-top: var(--list-half-gap);
 }
 
+.list-collapsible:not(.list-collapsible-expanded) > .list-collapsible-item {
+    display: none;
+}
+
+.list-collapsible-item {
+    animation: listItemReveal 0.3s backwards;
+}
+
 @keyframes listItemReveal {
     from {
         opacity: 0;
@@ -124,56 +140,42 @@
     }
 }
 
-.list-collapsible-item {
-    display: none;
-    animation: listItemReveal 0.3s backwards;
-    animation-delay: var(--animation-delay);
-}
-
 .list-collapsible-label {
-    display: flex;
-    align-items: center;
-    gap: 1rem;
+    font: inherit;
+    border: 0;
+    cursor: pointer;
+    display: block;
+    width: 100%;
+    text-align: left;
+    color: var(--color-text-base);
+    text-transform: uppercase;
+    font-size: var(--font-size-h4);
     padding: var(--widget-content-vertical-padding) 0;
     background: var(--color-widget-background);
 }
 
-.list-collapsible-label:has(.list-collapsible-input:checked) {
+.list-collapsible-label-expanded {
     position: sticky;
     bottom: 0;
 }
 
-.list-collapsible:has(+ .list-collapsible-label > .list-collapsible-input:checked) .list-collapsible-item {
-    display: block;
-}
-
-.list-collapsible-input {
-    display: none;
-}
-
-.list-collapsible-label::before, .list-collapsible-label::after {
-    cursor: pointer;
-    display: block;
-}
-
-.list-collapsible-label::before {
-    content: 'SHOW MORE';
-    font-size: var(--font-size-h4);
-}
-
-.list-collapsible-label:has(.list-collapsible-input:checked)::before {
-    content: 'SHOW LESS';
+.list-collapsible-label-icon {
+    display: inline-block;
+    margin-left: 1rem;
+    position: relative;
+    top: -.2rem;
 }
 
-.list-collapsible-label::after {
+.list-collapsible-label-icon::before {
     content: '';
     font-size: 0.8rem;
     transform: rotate(90deg);
     line-height: 1;
+    display: inline-block;
     transition: transform 0.3s;
 }
 
-.list-collapsible-label:has(.list-collapsible-input:checked)::after {
+.list-collapsible-label-expanded .list-collapsible-label-icon::before {
     transform: rotate(-90deg);
 }
 
@@ -1107,7 +1109,7 @@ body {
         box-shadow: 0 calc(var(--spacing) * -1) 0 0 currentColor, 0 var(--spacing) 0 0 currentColor;
     }
 
-    .list-collapsible-label:has(.list-collapsible-input:checked) {
+    .list-collapsible-label-expanded {
         bottom: var(--mobile-navigation-height);
     }
 }

+ 91 - 19
internal/assets/static/main.js

@@ -21,7 +21,7 @@ function throttledDebounce(callback, maxDebounceTimes, debounceDelay) {
 };
 
 
-async function fetchPageContents (pageSlug) {
+async function fetchPageContent(pageSlug) {
     // TODO: handle non 200 status codes/time outs
     // TODO: add retries
     const response = await fetch(`/api/pages/${pageSlug}/content/`);
@@ -33,6 +33,10 @@ async function fetchPageContents (pageSlug) {
 function setupCarousels() {
     const carouselElements = document.getElementsByClassName("carousel-container");
 
+    if (carouselElements.length == 0) {
+        return;
+    }
+
     for (let i = 0; i < carouselElements.length; i++) {
         const carousel = carouselElements[i];
         carousel.classList.add("show-right-cutoff");
@@ -57,7 +61,7 @@ function setupCarousels() {
         itemsContainer.addEventListener("scroll", determineSideCutoffsRateLimited);
         document.addEventListener("resize", determineSideCutoffsRateLimited);
 
-        determineSideCutoffs();
+        setTimeout(determineSideCutoffs, 1);
     }
 }
 
@@ -108,6 +112,8 @@ function setupDynamicRelativeTime() {
     const updateInterval = 60 * 1000;
     let lastUpdateTime = Date.now();
 
+    updateRelativeTimeForElements(elements);
+
     const updateElementsAndTimestamp = () => {
         updateRelativeTimeForElements(elements);
         lastUpdateTime = Date.now();
@@ -154,35 +160,101 @@ function setupLazyImages() {
         image.classList.add("finished-transition");
     }
 
-    for (let i = 0; i < images.length; i++) {
-        const image = images[i];
-
-        if (image.complete) {
-            image.classList.add("cached");
-            setTimeout(() => imageFinishedTransition(image), 5);
-        } else {
-            // TODO: also handle error event
-            image.addEventListener("load", () => {
-                image.classList.add("loaded");
-                setTimeout(() => imageFinishedTransition(image), 500);
-            });
+    setTimeout(() => {
+        for (let i = 0; i < images.length; i++) {
+            const image = images[i];
+
+            if (image.complete) {
+                image.classList.add("cached");
+                setTimeout(() => imageFinishedTransition(image), 5);
+            } else {
+                // TODO: also handle error event
+                image.addEventListener("load", () => {
+                    image.classList.add("loaded");
+                    setTimeout(() => imageFinishedTransition(image), 500);
+                });
+            }
+        }
+    }, 5);
+}
+
+function setupCollapsibleLists() {
+    const collapsibleListElements = document.getElementsByClassName("list-collapsible");
+
+    if (collapsibleListElements.length == 0) {
+        return;
+    }
+
+    const showMoreText = "Show more";
+    const showLessText = "Show less";
+
+    const attachExpandToggleButton = (listElement) => {
+        let expanded = false;
+        const button = document.createElement("button");
+        const arrowElement = document.createElement("span");
+        arrowElement.classList.add("list-collapsible-label-icon");
+        const textNode = document.createTextNode(showMoreText);
+        button.classList.add("list-collapsible-label");
+        button.append(textNode, arrowElement);
+        button.addEventListener("click", () => {
+            if (expanded) {
+                listElement.classList.remove("list-collapsible-expanded");
+                button.classList.remove("list-collapsible-label-expanded");
+                textNode.nodeValue = showMoreText;
+            } else {
+                listElement.classList.add("list-collapsible-expanded");
+                button.classList.add("list-collapsible-label-expanded");
+                textNode.nodeValue = showLessText;
+            }
+
+            expanded = !expanded;
+        });
+
+        listElement.after(button);
+    };
+
+    for (let i = 0; i < collapsibleListElements.length; i++) {
+        const listElement = collapsibleListElements[i];
+
+        if (listElement.dataset.collapseAfter === undefined) {
+            continue;
+        }
+
+        const collapseAfter = parseInt(listElement.dataset.collapseAfter);
+
+        if (listElement.children.length <= collapseAfter) {
+            continue;
+        }
+
+        attachExpandToggleButton(listElement);
+
+        for (let c = collapseAfter; c < listElement.children.length; c++) {
+            const child = listElement.children[c];
+            child.classList.add("list-collapsible-item");
+            child.style.animationDelay = ((c - collapseAfter) * 20).toString() + "ms";
         }
     }
 }
 
 async function setupPage() {
     const pageElement = document.getElementById("page");
-    const pageContents = await fetchPageContents(pageData.slug);
+    const pageContentElement = document.getElementById("page-content");
+    const pageContent = await fetchPageContent(pageData.slug);
 
-    pageElement.innerHTML = pageContents;
+    pageContentElement.innerHTML = pageContent;
 
     setTimeout(() => {
         document.body.classList.add("animate-element-transition");
     }, 200);
 
-    setTimeout(setupLazyImages, 5);
-    setupCarousels();
-    setupDynamicRelativeTime();
+    try {
+        setupLazyImages();
+        setupCarousels();
+        setupCollapsibleLists();
+        setupDynamicRelativeTime();
+    } finally {
+        pageElement.classList.add("content-ready");
+    }
 }
 
 if (document.readyState === "loading") {

+ 12 - 15
internal/assets/templates/forum-posts.html

@@ -1,14 +1,14 @@
 {{ template "widget-base.html" . }}
 
 {{ define "widget-content" }}
-<ul class="list list-gap-14 list-collapsible">
-    {{ range $i, $post := .Posts }}
-    <li {{ if shouldCollapse $i $.CollapseAfter }}class="list-collapsible-item" style="--animation-delay: {{ itemAnimationDelay $i $.CollapseAfter }};"{{ end }}>
+<ul class="list list-gap-14 list-collapsible" data-collapse-after="{{ .CollapseAfter }}">
+    {{ range .Posts }}
+    <li>
         <div class="forum-post-list-item thumbnail-container">
             {{ if $.ShowThumbnails }}
-                {{ if ne $post.ThumbnailUrl "" }}
-                <img class="forum-post-list-thumbnail thumbnail" src="{{ $post.ThumbnailUrl }}" alt="" loading="lazy">
-                {{ else if $post.HasTargetUrl }}
+                {{ if ne .ThumbnailUrl "" }}
+                <img class="forum-post-list-thumbnail thumbnail" src="{{ .ThumbnailUrl }}" alt="" loading="lazy">
+                {{ else if .HasTargetUrl }}
                 <svg class="forum-post-list-thumbnail hide-on-mobile" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="-9 -8 40 40" stroke-width="1.5" stroke="var(--color-text-subdue)">
                     <path stroke-linecap="round" stroke-linejoin="round" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622 1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244" />
                 </svg>
@@ -19,13 +19,13 @@
                 {{ end }}
             {{ end }}
             <div class="grow">
-                <a href="{{ $post.DiscussionUrl }}" class="size-h3 color-primary-if-not-visited" target="_blank" rel="noreferrer">{{ .Title }}</a>
+                <a href="{{ .DiscussionUrl }}" class="size-h3 color-primary-if-not-visited" target="_blank" rel="noreferrer">{{ .Title }}</a>
                 <ul class="list-horizontal-text">
-                    <li title="{{ $post.TimePosted | formatTime }}" {{ dynamicRelativeTimeAttrs $post.TimePosted }}>{{ $post.TimePosted | relativeTime }}</li>
-                    <li>{{ $post.Score | formatNumber }} points</li>
-                    <li>{{ $post.CommentCount | formatNumber }} comments</li>
-                    {{ if $post.HasTargetUrl }}
-                    <li class="shrink min-width-0"><a class="visited-indicator text-truncate block" href="{{ .TargetUrl }}" target="_blank" rel="noreferrer">{{ $post.TargetUrlDomain }}</a></li>
+                    <li {{ dynamicRelativeTimeAttrs .TimePosted }}></li>
+                    <li>{{ .Score | formatNumber }} points</li>
+                    <li>{{ .CommentCount | formatNumber }} comments</li>
+                    {{ if .HasTargetUrl }}
+                    <li class="shrink min-width-0"><a class="visited-indicator text-truncate block" href="{{ .TargetUrl }}" target="_blank" rel="noreferrer">{{ .TargetUrlDomain }}</a></li>
                     {{ end }}
                 </ul>
             </div>
@@ -33,7 +33,4 @@
     </li>
     {{ end }}
 </ul>
-{{ if gt (len .Posts) $.CollapseAfter }}
-<label class="list-collapsible-label"><input type="checkbox" autocomplete="off" class="list-collapsible-input"></label>
-{{ end }}
 {{ end }}

+ 1 - 0
internal/assets/templates/page.html

@@ -50,6 +50,7 @@
 
 <div class="content-bounds">
     <div class="page" id="page">
+        <div class="page-content" id="page-content"></div>
         <div class="page-loading-container">
             <!-- TODO: add a bigger/better loading indicator -->
             <div class="loading-icon"></div>

+ 1 - 1
internal/assets/templates/reddit-horizontal-cards.html

@@ -20,7 +20,7 @@
                 {{ end }}
                 <a href="{{ .DiscussionUrl }}" title="{{ .Title }}" class="text-truncate-3-lines color-primary-if-not-visited margin-top-7 margin-bottom-auto" target="_blank" rel="noreferrer">{{ .Title }}</a>
                 <ul class="list-horizontal-text margin-top-7">
-                    <li title="{{ .TimePosted | formatTime }}" {{ dynamicRelativeTimeAttrs .TimePosted }}>{{ .TimePosted | relativeTime }}</li>
+                    <li {{ dynamicRelativeTimeAttrs .TimePosted }}></li>
                     <li>{{ .Score | formatNumber }} points</li>
                 </ul>
             </div>

+ 1 - 1
internal/assets/templates/reddit-vertical-cards.html

@@ -19,7 +19,7 @@
             {{ end }}
             <a href="{{ .DiscussionUrl }}" title="{{ .Title }}" class="text-truncate-3-lines color-primary-if-not-visited margin-top-7" target="_blank" rel="noreferrer">{{ .Title }}</a>
             <ul class="list-horizontal-text margin-top-7">
-                <li title="{{ .TimePosted | formatTime }}" {{ dynamicRelativeTimeAttrs .TimePosted }}>{{ .TimePosted | relativeTime }}</li>
+                <li {{ dynamicRelativeTimeAttrs .TimePosted }}></li>
                 <li>{{ .Score | formatNumber }} points</li>
             </ul>
         </div>

+ 1 - 1
internal/assets/templates/releases.html

@@ -6,7 +6,7 @@
     <li {{ if shouldCollapse $i $.CollapseAfter }}class="list-collapsible-item" style="--animation-delay: {{ itemAnimationDelay $i $.CollapseAfter }};"{{ end }}>
         <a class="size-h4 block text-truncate color-primary-if-not-visited" href="{{ $release.NotesUrl }}" target="_blank" rel="noreferrer">{{ .Name }}</a>
         <ul class="list-horizontal-text">
-            <li title="{{ $release.TimeReleased | formatTime }}" {{ dynamicRelativeTimeAttrs $release.TimeReleased }}>{{ $release.TimeReleased | relativeTime }}</li>
+            <li {{ dynamicRelativeTimeAttrs $release.TimeReleased }}></li>
             <li>{{ $release.Version }}</li>
             {{ if gt $release.Downvotes 3 }}
             <li>{{ $release.Downvotes | formatNumber }} ⚠</li>

+ 2 - 2
internal/assets/templates/repository.html

@@ -13,7 +13,7 @@
 <div class="flex gap-7 size-h5 margin-top-3">
     <ul class="list list-gap-2">
         {{ range .RepositoryDetails.PullRequests }}
-        <li title="{{ .CreatedAt | formatTime }}" {{ dynamicRelativeTimeAttrs .CreatedAt }}>{{ .CreatedAt | relativeTime }}</li>
+        <li {{ dynamicRelativeTimeAttrs .CreatedAt }}></li>
         {{ end }}
     </ul>
     <ul class="list list-gap-2 min-width-0">
@@ -30,7 +30,7 @@
 <div class="flex gap-7 size-h5 margin-top-3">
     <ul class="list list-gap-2">
         {{ range .RepositoryDetails.Issues }}
-        <li title="{{ .CreatedAt | formatTime }}" {{ dynamicRelativeTimeAttrs .CreatedAt }}>{{ .CreatedAt | relativeTime }}</li>
+        <li {{ dynamicRelativeTimeAttrs .CreatedAt }}></li>
         {{ end }}
     </ul>
     <ul class="list list-gap-2 min-width-0">

+ 1 - 1
internal/assets/templates/rss-horizontal-cards-2.html

@@ -17,7 +17,7 @@
             <div class="rss-card-2-content padding-inline-widget">
                 <a href="{{ .Link }}" title="{{ .Title }}" class="block text-truncate color-primary-if-not-visited" target="_blank" rel="noreferrer">{{ .Title }}</a>
                 <ul class="list-horizontal-text flex-nowrap margin-top-5">
-                    <li class="shrink-0" title="{{ .PublishedAt | formatTime }}" {{ dynamicRelativeTimeAttrs .PublishedAt }}>{{ .PublishedAt | relativeTime }}</li>
+                    <li class="shrink-0" {{ dynamicRelativeTimeAttrs .PublishedAt }}></li>
                     <li class="shrink min-width-0 text-truncate">{{ .ChannelName }}</li>
                 </ul>
             </div>

+ 1 - 1
internal/assets/templates/rss-horizontal-cards.html

@@ -17,7 +17,7 @@
             <div class="margin-bottom-widget padding-inline-widget flex flex-column grow">
                 <a href="{{ .Link }}" title="{{ .Title }}" class="text-truncate-3-lines color-primary-if-not-visited margin-top-10 margin-bottom-auto" target="_blank" rel="noreferrer">{{ .Title }}</a>
                 <ul class="list-horizontal-text flex-nowrap margin-top-7">
-                    <li class="shrink-0" title="{{ .PublishedAt | formatTime }}" {{ dynamicRelativeTimeAttrs .PublishedAt }}>{{ .PublishedAt | relativeTime }}</li>
+                    <li class="shrink-0" {{ dynamicRelativeTimeAttrs .PublishedAt }}></li>
                     <li class="shrink min-width-0 text-truncate">{{ .ChannelName }}</li>
                 </ul>
             </div>

+ 4 - 7
internal/assets/templates/rss-list.html

@@ -1,12 +1,12 @@
 {{ template "widget-base.html" . }}
 
 {{ define "widget-content" }}
-<ul class="list list-gap-14 list-collapsible">
-    {{ range $i, $item := .Items }}
-    <li {{ if shouldCollapse $i $.CollapseAfter }}class="list-collapsible-item" style="--animation-delay: {{ itemAnimationDelay $i $.CollapseAfter }};"{{ end }}>
+<ul class="list list-gap-14 list-collapsible" data-collapse-after="{{ .CollapseAfter }}">
+    {{ range .Items }}
+    <li>
         <a class="size-title-dynamic color-primary-if-not-visited" href="{{ .Link }}" target="_blank" rel="noreferrer">{{ .Title }}</a>
         <ul class="list-horizontal-text">
-            <li title="{{ $item.PublishedAt | formatTime }}" {{ dynamicRelativeTimeAttrs $item.PublishedAt }}>{{ .PublishedAt | relativeTime }}</li>
+            <li {{ dynamicRelativeTimeAttrs .PublishedAt }}></li>
             {{ if gt (len $.FeedRequests) 1 }}
                 <li><a href="{{ .ChannelURL }}" target="_blank" rel="noreferrer">{{ .ChannelName }}</a></li>
             {{ end }}
@@ -14,7 +14,4 @@
     </li>
     {{ end }}
 </ul>
-    {{ if gt (len .Items) $.CollapseAfter }}
-        <label class="list-collapsible-label"><input type="checkbox" autocomplete="off" class="list-collapsible-input"></label>
-    {{ end }}
 {{ end }}

+ 12 - 15
internal/assets/templates/twitch-channels.html

@@ -1,13 +1,13 @@
 {{ template "widget-base.html" . }}
 
 {{ define "widget-content" }}
-<ul class="list list-gap-14 list-collapsible">
-    {{ range $i, $channel := .Channels }}
-    <li {{ if shouldCollapse $i $.CollapseAfter }}class="list-collapsible-item" style="--animation-delay: {{ itemAnimationDelay $i $.CollapseAfter }};"{{ end }}>
-        <div class="{{ if $channel.IsLive }}twitch-channel-live {{ end }}flex gap-10 items-start thumbnail-container">
+<ul class="list list-gap-14 list-collapsible" data-collapse-after="{{ .CollapseAfter }}">
+    {{ range .Channels }}
+    <li>
+        <div class="{{ if .IsLive }}twitch-channel-live {{ end }}flex gap-10 items-start thumbnail-container">
             <div class="twitch-channel-avatar-container">
-                {{ if $channel.Exists }}
-                <img class="twitch-channel-avatar thumbnail" src="{{ $channel.AvatarUrl }}" alt="" loading="lazy">
+                {{ if .Exists }}
+                <img class="twitch-channel-avatar thumbnail" src="{{ .AvatarUrl }}" alt="" loading="lazy">
                 {{ else }}
                 <svg class="twitch-channel-avatar thumbnail" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
                     <path stroke-linecap="round" stroke-linejoin="round" d="M15.75 6a3.75 3.75 0 1 1-7.5 0 3.75 3.75 0 0 1 7.5 0ZM4.501 20.118a7.5 7.5 0 0 1 14.998 0A17.933 17.933 0 0 1 12 21.75c-2.676 0-5.216-.584-7.499-1.632Z" />
@@ -15,13 +15,13 @@
                 {{ end }}
             </div>
             <div class="shrink min-width-0">
-                <a href="https://twitch.tv/{{ $channel.Login }}" class="size-h3{{ if $channel.IsLive }} color-highlight{{ end }} block text-truncate" target="_blank" rel="noreferrer">{{ $channel.Name }}</a>
-                {{ if $channel.Exists }}
-                    {{ if $channel.IsLive }}
-                    <a class="text-truncate block" href="https://www.twitch.tv/directory/category/{{ $channel.CategorySlug }}" target="_blank" rel="noreferrer">{{ $channel.Category }}</a>
+                <a href="https://twitch.tv/{{ .Login }}" class="size-h3{{ if .IsLive }} color-highlight{{ end }} block text-truncate" target="_blank" rel="noreferrer">{{ .Name }}</a>
+                {{ if .Exists }}
+                    {{ if .IsLive }}
+                    <a class="text-truncate block" href="https://www.twitch.tv/directory/category/{{ .CategorySlug }}" target="_blank" rel="noreferrer">{{ .Category }}</a>
                     <ul class="list-horizontal-text">
-                        <li title="{{ $channel.LiveSince | formatTime }}" {{ dynamicRelativeTimeAttrs $channel.LiveSince }}>{{ $channel.LiveSince | relativeTime }}</li>
-                        <li>{{ $channel.ViewersCount | formatViewerCount }} viewers</li>
+                        <li {{ dynamicRelativeTimeAttrs .LiveSince }}></li>
+                        <li>{{ .ViewersCount | formatViewerCount }} viewers</li>
                     </ul>
                     {{ else }}
                     <div>Offline</div>
@@ -34,7 +34,4 @@
     </li>
     {{ end }}
 </ul>
-{{ if gt (len .Channels) $.CollapseAfter }}
-<label class="list-collapsible-label"><input type="checkbox" autocomplete="off" class="list-collapsible-input"></label>
-{{ end }}
 {{ end }}

+ 8 - 12
internal/assets/templates/twitch-games-list.html

@@ -1,22 +1,21 @@
 {{ template "widget-base.html" . }}
 
 {{ define "widget-content" }}
-<ul class="list list-gap-14 list-collapsible">
-    {{ range $i, $category := .Categories }}
-    {{ $shouldCollapseItem := shouldCollapse $i $.CollapseAfter }}
-    <li class="twitch-category thumbnail-container{{ if $shouldCollapseItem }} list-collapsible-item{{ end }}" {{ if $shouldCollapseItem }}style="--animation-delay: {{ itemAnimationDelay $i $.CollapseAfter }};"{{ end }}>
+<ul class="list list-gap-14 list-collapsible" data-collapse-after="{{ .CollapseAfter }}">
+    {{ range .Categories }}
+    <li class="twitch-category thumbnail-container">
         <div class="flex gap-10 items-center">
-            <img class="twitch-category-thumbnail thumbnail" loading="lazy" src="{{ $category.AvatarUrl }}" alt="">
+            <img class="twitch-category-thumbnail thumbnail" loading="lazy" src="{{ .AvatarUrl }}" alt="">
             <div class="shrink min-width-0">
-                <a class="size-h3 color-highlight text-truncate block" href="https://www.twitch.tv/directory/category/{{ $category.Slug }}" target="_blank" rel="noreferrer">{{ $category.Name }}</a>
+                <a class="size-h3 color-highlight text-truncate block" href="https://www.twitch.tv/directory/category/{{ .Slug }}" target="_blank" rel="noreferrer">{{ .Name }}</a>
                 <ul class="list-horizontal-text">
-                    <li>{{ $category.ViewersCount | formatViewerCount }} viewers</li>
-                    {{ if $category.IsNew }}
+                    <li>{{ .ViewersCount | formatViewerCount }} viewers</li>
+                    {{ if .IsNew }}
                     <li class="color-primary">NEW</li>
                     {{ end }}
                 </ul>
                 <ul class="list-horizontal-text flex-nowrap">
-                    {{ range $i, $tag := $category.Tags }}
+                    {{ range $i, $tag := .Tags }}
                         {{ if eq $i 0 }}
                         <li class="shrink-0">{{ $tag.Name }}</li>
                         {{ else }}
@@ -29,7 +28,4 @@
     </li>
     {{ end }}
 </ul>
-{{ if gt (len .Categories) $.CollapseAfter }}
-<label class="list-collapsible-label"><input type="checkbox" autocomplete="off" class="list-collapsible-input"></label>
-{{ end }}
 {{ end }}

+ 1 - 1
internal/assets/templates/video-card-contents.html

@@ -3,7 +3,7 @@
 <div class="margin-top-10 margin-bottom-widget flex flex-column grow padding-inline-widget">
     <a class="video-title color-primary-if-not-visited" href="{{ .Url }}" target="_blank" rel="noreferrer" title="{{ .Title }}">{{ .Title }}</a>
     <ul class="list-horizontal-text flex-nowrap margin-top-7">
-        <li class="shrink-0" title="{{ .TimePosted | formatTime }}" {{ dynamicRelativeTimeAttrs .TimePosted }}>{{ .TimePosted | relativeTime }}</li>
+        <li class="shrink-0" {{ dynamicRelativeTimeAttrs .TimePosted }}></li>
         <li class="shrink min-width-0">
             <a class="block text-truncate" href="{{ .AuthorUrl }}" target="_blank" rel="noreferrer">{{ .Author }}</a>
         </li>