From bf4f6584e165b4628824ff2b7a80b0f65377f293 Mon Sep 17 00:00:00 2001 From: Nicholas Wallace Date: Mon, 14 Oct 2024 19:49:25 -0700 Subject: [PATCH] Update: lazy episode table and row --- .../components/tables/podcast/LazyEpisodeRow.vue | 16 ++++++++-------- .../tables/podcast/LazyEpisodesTable.vue | 8 ++++---- client/strings/en-us.json | 8 ++++++++ 3 files changed, 20 insertions(+), 12 deletions(-) diff --git a/client/components/tables/podcast/LazyEpisodeRow.vue b/client/components/tables/podcast/LazyEpisodeRow.vue index 2284da7f6..20e6b9f98 100644 --- a/client/components/tables/podcast/LazyEpisodeRow.vue +++ b/client/components/tables/podcast/LazyEpisodeRow.vue @@ -12,10 +12,10 @@
-

Season #{{ episode.season }}

-

Episode #{{ episode.episode }}

-

{{ episode.chapters.length }} Chapters

-

Published {{ $formatDate(publishedAt, dateFormat) }}

+

{{ $getString('LabelSeasonNumber', [episode.season]) }}

+

{{ $getString('LabelEpisodeNumber', [episode.episode]) }}

+

{{ $getString('LabelChapterCount', [episode.chapters.length]) }}

+

{{ $getString('LabelPublishedDate', [$formatDate(publishedAt, dateFormat)]) }}

@@ -132,13 +132,13 @@ export default { return this.store.state.streamIsPlaying && this.isStreaming }, timeRemaining() { - if (this.streamIsPlaying) return 'Playing' + if (this.streamIsPlaying) return this.$strings.ButtonPlaying if (!this.itemProgress) return this.$elapsedPretty(this.episode?.duration || 0) - if (this.userIsFinished) return 'Finished' + if (this.userIsFinished) return this.$strings.LabelFinished const duration = this.itemProgress.duration || this.episode?.duration || 0 const remaining = Math.floor(duration - this.itemProgress.currentTime) - return `${this.$elapsedPretty(remaining)} left` + return this.$getString('LabelTimeLeft', [this.$elapsedPretty(remaining)]) } }, methods: { @@ -182,7 +182,7 @@ export default { toggleFinished(confirmed = false) { if (!this.userIsFinished && this.itemProgressPercent > 0 && !confirmed) { const payload = { - message: `Are you sure you want to mark "${this.episodeTitle}" as finished?`, + message: this.$getString('MessageConfirmMarkItemFinished', [this.episodeTitle]), callback: (confirmed) => { if (confirmed) { this.toggleFinished(true) diff --git a/client/components/tables/podcast/LazyEpisodesTable.vue b/client/components/tables/podcast/LazyEpisodesTable.vue index 3b0d3cee1..46b17c4c7 100644 --- a/client/components/tables/podcast/LazyEpisodesTable.vue +++ b/client/components/tables/podcast/LazyEpisodesTable.vue @@ -96,7 +96,7 @@ export default { const menuItems = [] if (this.userIsAdminOrUp) { menuItems.push({ - text: 'Quick match all episodes', + text: this.$strings.MessageQuickMatchAllEpisodes, action: 'quick-match-episodes' }) } @@ -262,21 +262,21 @@ export default { this.processing = true const payload = { - message: 'Quick matching episodes will overwrite details if a match is found. Only unmatched episodes will be updated. Are you sure?', + message: this.$strings.LabelSettingsQuickMatchEpisodes, callback: (confirmed) => { if (confirmed) { this.$axios .$post(`/api/podcasts/${this.libraryItem.id}/match-episodes?override=1`) .then((data) => { if (data.numEpisodesUpdated) { - this.$toast.success(`${data.numEpisodesUpdated} episodes updated`) + this.$toast.success(this.$getString('ToastEpisodeUpdateSuccess', [data.numEpisodesUpdated])) } else { this.$toast.info(this.$strings.ToastNoUpdatesNecessary) } }) .catch((error) => { console.error('Failed to request match episodes', error) - this.$toast.error('Failed to match episodes') + this.$toast.error(this.$strings.ToastFailedToMatch) }) } this.processing = false diff --git a/client/strings/en-us.json b/client/strings/en-us.json index d40feb870..f1f8b4789 100644 --- a/client/strings/en-us.json +++ b/client/strings/en-us.json @@ -256,6 +256,7 @@ "LabelByAuthor": "by {0}", "LabelChangePassword": "Change Password", "LabelChannels": "Channels", + "LabelChapterCount": "{0} Chapters", "LabelChapterTitle": "Chapter Title", "LabelChapters": "Chapters", "LabelChaptersFound": "chapters found", @@ -322,6 +323,7 @@ "LabelEndOfChapter": "End of Chapter", "LabelEpisode": "Episode", "LabelEpisodeNotLinkedToRssFeed": "Episode not linked to RSS feed", + "LabelEpisodeNumber": "Episode #{0}", "LabelEpisodeTitle": "Episode Title", "LabelEpisodeType": "Episode Type", "LabelEpisodeUrlFromRssFeed": "Episode URL from RSS feed", @@ -511,6 +513,7 @@ "LabelSearchTitle": "Search Title", "LabelSearchTitleOrASIN": "Search Title or ASIN", "LabelSeason": "Season", + "LabelSeasonNumber": "Season #{0}", "LabelSelectAll": "Select all", "LabelSelectAllEpisodes": "Select all episodes", "LabelSelectEpisodesShowing": "Select {0} episodes showing", @@ -552,6 +555,7 @@ "LabelSettingsParseSubtitlesHelp": "Extract subtitles from audiobook folder names.
Subtitle must be seperated by \" - \"
i.e. \"Book Title - A Subtitle Here\" has the subtitle \"A Subtitle Here\"", "LabelSettingsPreferMatchedMetadata": "Prefer matched metadata", "LabelSettingsPreferMatchedMetadataHelp": "Matched data will override item details when using Quick Match. By default Quick Match will only fill in missing details.", + "LabelSettingsQuickMatchEpisodes": "Quick matching episodes will overwrite details if a match is found. Only unmatched episodes will be updated. Are you sure?", "LabelSettingsSkipMatchingBooksWithASIN": "Skip matching books that already have an ASIN", "LabelSettingsSkipMatchingBooksWithISBN": "Skip matching books that already have an ISBN", "LabelSettingsSortingIgnorePrefixes": "Ignore prefixes when sorting", @@ -610,6 +614,7 @@ "LabelTimeDurationXMinutes": "{0} minutes", "LabelTimeDurationXSeconds": "{0} seconds", "LabelTimeInMinutes": "Time in minutes", + "LabelTimeLeft": "{0} left", "LabelTimeListened": "Time Listened", "LabelTimeListenedToday": "Time Listened Today", "LabelTimeRemaining": "{0} remaining", @@ -792,6 +797,7 @@ "MessagePodcastSearchField": "Enter search term or RSS feed URL", "MessageQuickEmbedInProgress": "Quick embed in progress", "MessageQuickEmbedQueue": "Queued for quick embed ({0} in queue)", + "MessageQuickMatchAllEpisodes": "Quick Match All Episodes", "MessageQuickMatchDescription": "Populate empty item details & cover with first match result from '{0}'. Does not overwrite details unless 'Prefer matched metadata' server setting is enabled.", "MessageRemoveChapter": "Remove chapter", "MessageRemoveEpisodes": "Remove {0} episode(s)", @@ -937,8 +943,10 @@ "ToastEncodeCancelSucces": "Encode canceled", "ToastEpisodeDownloadQueueClearFailed": "Failed to clear queue", "ToastEpisodeDownloadQueueClearSuccess": "Episode download queue cleared", + "ToastEpisodeUpdateSuccess": "{0} episodes updated", "ToastErrorCannotShare": "Cannot share natively on this device", "ToastFailedToLoadData": "Failed to load data", + "ToastFailedToMatch": "Failed to match", "ToastFailedToShare": "Failed to share", "ToastFailedToUpdate": "Failed to update", "ToastInvalidImageUrl": "Invalid image URL",