diff --git a/src/renderer/components/FtListVideo/FtListVideo.vue b/src/renderer/components/FtListVideo/FtListVideo.vue
index 832fb03f4d8bb..ce92697b80848 100644
--- a/src/renderer/components/FtListVideo/FtListVideo.vue
+++ b/src/renderer/components/FtListVideo/FtListVideo.vue
@@ -38,14 +38,29 @@
>
- {{ isLive ? t("Video.Live") : (isUpcoming ? t("Video.Upcoming") : displayDuration) }}
+
+ {{ t("Video.Live") }}
+
+
+ {{ t("Video.Upcoming") }}
+
+
+
+ {{ t("Video.Station") }}
+
+
+ {{ displayDuration }}
+
•
{{ t('Global.Counts.View Count', { count: parsedViewCount }, viewCount) }}
• {{ uploadedTime }}
• {{ t('Global.Counts.Watching Count', { count: parsedViewCount }, viewCount) }}
@@ -412,6 +427,7 @@ const isVr360 = ref(false)
const is3D = ref(false)
const hasCaptions = ref(false)
const isUpcoming = ref(false)
+const isStation = ref(false)
const isPremium = ref(false)
const hideViews = ref(false)
const deArrowTogglePinned = ref(false)
@@ -1018,7 +1034,8 @@ function parseVideoData() {
}
description.value = props.data.description
- isLive.value = props.data.liveNow || props.data.lengthSeconds === undefined
+ isStation.value = props.data.isStation === true
+ isLive.value = !isStation.value && (props.data.liveNow || props.data.lengthSeconds === undefined)
isUpcoming.value = props.data.isUpcoming || props.data.premiere
is4k.value = props.data.is4k
is8k.value = props.data.is8k
@@ -1042,7 +1059,7 @@ function parseVideoData() {
} else if (props.data.premiereTimestamp !== undefined) {
uploadedTime.value = new Date(props.data.premiereTimestamp * 1000).toLocaleString([locale.value, 'en'])
published.value = props.data.premiereTimestamp * 1000
- } else if (typeof props.data.published === 'number' && !isLive.value) {
+ } else if (typeof props.data.published === 'number' && !isLive.value && !isStation.value) {
published.value = props.data.published
if (inHistory.value) {
@@ -1077,6 +1094,7 @@ function markAsWatched() {
watchProgress: 0,
timeWatched: Date.now(),
isLive: false,
+ isStation: false,
type: 'video'
}
diff --git a/src/renderer/helpers/api/local.js b/src/renderer/helpers/api/local.js
index 0df5a6821f581..c1651a600d39c 100644
--- a/src/renderer/helpers/api/local.js
+++ b/src/renderer/helpers/api/local.js
@@ -1824,7 +1824,9 @@ function parseLockupView(lockupView, channelId = undefined, channelName = undefi
}
}
case 'SHORT':
+ case 'STATION':
case 'VIDEO': {
+ const isStation = lockupView.content_type === 'STATION'
let publishedText
let lengthSeconds = ''
let liveNow = false
@@ -1839,7 +1841,8 @@ function parseLockupView(lockupView, channelId = undefined, channelName = undefi
}
/** @type {YTNodes.ThumbnailBottomOverlayView | undefined } */
- const thumbnailBottomOverlayView = lockupView.content_image?.overlays?.firstOfType(YTNodes.ThumbnailBottomOverlayView)
+ const thumbnailBottomOverlayView = lockupView.content_image?.overlays?.firstOfType(YTNodes.ThumbnailBottomOverlayView) ??
+ lockupView.content_image?.primary_thumbnail?.overlays?.firstOfType(YTNodes.ThumbnailBottomOverlayView)
if (thumbnailBottomOverlayView) {
if (thumbnailBottomOverlayView.badges.some(badge => badge.badge_style === 'THUMBNAIL_OVERLAY_BADGE_STYLE_LIVE')) {
@@ -1901,6 +1904,11 @@ function parseLockupView(lockupView, channelId = undefined, channelName = undefi
author = maybeAuthorText
}
+ // I think this is only used for stations at the moment
+ if (author == null) {
+ author = lockupView.metadata?.metadata?.metadata_rows[0].metadata_parts?.[0].avatar_stack.text?.text
+ }
+
return {
type: 'video',
videoId: lockupView.content_id,
@@ -1912,6 +1920,7 @@ function parseLockupView(lockupView, channelId = undefined, channelName = undefi
lengthSeconds,
liveNow,
isUpcoming,
+ isStation,
premiereDate
}
}
diff --git a/src/renderer/views/Watch/Watch.js b/src/renderer/views/Watch/Watch.js
index d95dde49c6b9a..6222be1daf5f5 100644
--- a/src/renderer/views/Watch/Watch.js
+++ b/src/renderer/views/Watch/Watch.js
@@ -524,7 +524,7 @@ export default defineComponent({
this.recommendedVideos = result.watch_next_feed
?.filter((item) => {
return item.type === 'CompactVideo' || item.type === 'CompactMovie' ||
- (item.type === 'LockupView' && item.content_type === 'VIDEO')
+ (item.type === 'LockupView' && (item.content_type === 'VIDEO' || item.content_type === 'STATION'))
})
.map(parseLocalWatchNextVideo).filter(_ => _)
// place watched recommended videos last
diff --git a/static/locales/en-US.yaml b/static/locales/en-US.yaml
index 3fff1d0f079a1..4d358dddb31fd 100644
--- a/static/locales/en-US.yaml
+++ b/static/locales/en-US.yaml
@@ -889,6 +889,7 @@ Video:
Premieres: Premieres
Upcoming: Upcoming
Unlisted: Unlisted
+ Station: Station
Live: Live
Live Now: Live Now
Live Chat: Live Chat