Merge branch 'master' into new_jwt_auth

This commit is contained in:
advplyr 2025-07-05 08:06:40 -05:00
commit b99e0b112b
9 changed files with 135 additions and 58 deletions

View file

@ -14,7 +14,7 @@
<!-- No progress shown for collapsed series or podcasts in library -->
<div v-if="!isPodcast && !collapsedSeries" class="absolute bottom-0 left-0 h-1 shadow-sm max-w-full z-10 rounded-b" :class="itemIsFinished ? 'bg-success' : 'bg-yellow-400'" :style="{ width: coverWidth * userProgressPercent + 'px' }"></div>
</div>
<div class="flex-grow px-2">
<div class="flex-grow pl-2" :class="showPlayButton ? 'pr-12' : 'pr-2'">
<p class="whitespace-normal line-clamp-2" :style="{ fontSize: 0.8 * sizeMultiplier + 'rem' }">
<span v-if="seriesSequence">#{{ seriesSequence }}&nbsp;</span>{{ displayTitle }}
</p>
@ -29,6 +29,11 @@
{{ $getString('LabelNumEpisodes', [numEpisodes]) }}
</p>
</div>
<div v-if="showPlayButton" class="absolute top-0 bottom-0 right-0 h-full flex items-center justify-center z-20 pr-1">
<button type="button" class="p-2 rounded-full bg-fg-muted/50" @click.stop.prevent="play">
<span class="material-symbols text-2xl fill text-white">{{ playerIsPlaying ? 'pause' : 'play_arrow' }}</span>
</button>
</div>
<div v-if="localLibraryItem || isLocal" class="absolute top-0 right-0 z-20" :style="{ top: 0.375 * sizeMultiplier + 'rem', right: 0.375 * sizeMultiplier + 'rem', padding: `${0.1 * sizeMultiplier}rem ${0.25 * sizeMultiplier}rem` }">
<span class="material-symbols text-2xl text-success">download_done</span>
@ -129,6 +134,9 @@ export default {
libraryItemId() {
return this._libraryItem.id
},
localLibraryItemId() {
return this.localLibraryItem?.id
},
series() {
return this.mediaMetadata.series
},
@ -217,13 +225,23 @@ export default {
return this.isMissing || this.isInvalid
},
isStreaming() {
return this.store.getters['getlibraryItemIdStreaming'] === this.libraryItemId
return this.isPlaying && !this.store.getters['getIsCurrentSessionLocal']
},
isPlaying() {
if (this.localLibraryItemId && this.store.getters['getIsMediaStreaming'](this.localLibraryItemId)) return true
return this.store.getters['getIsMediaStreaming'](this.libraryItemId)
},
playerIsPlaying() {
return this.store.state.playerIsPlaying && (this.isStreaming || this.isPlaying)
},
isCasting() {
return this.store.state.isCasting
},
showReadButton() {
return !this.isSelectionMode && !this.showPlayButton && this.hasEbook
},
showPlayButton() {
return !this.isSelectionMode && !this.isMissing && !this.isInvalid && this.numTracks && !this.isStreaming
return !this.isSelectionMode && !this.isMissing && !this.isInvalid && this.numTracks && !this.isPodcast
},
showSmallEBookIcon() {
return !this.isSelectionMode && this.hasEbook
@ -293,9 +311,30 @@ export default {
this.selected = !this.selected
this.$emit('select', this.libraryItem)
},
play() {
var eventBus = this.$eventBus || this.$nuxt.$eventBus
eventBus.$emit('play-item', { libraryItemId: this.libraryItemId })
async play() {
const hapticsImpact = this.$hapticsImpact || this.$nuxt.$hapticsImpact
if (hapticsImpact) {
await hapticsImpact()
}
const eventBus = this.$eventBus || this.$nuxt.$eventBus
if (this.playerIsPlaying) {
eventBus.$emit('pause-item')
} else {
// Audiobook
let libraryItemId = this.libraryItemId
// When casting use server library item
if (this.localLibraryItem && !this.isCasting) {
libraryItemId = this.localLibraryItem.id
} else if (this.hasLocal) {
libraryItemId = this.localLibraryItem.id
}
this.store.commit('setPlayerIsStartingPlayback', libraryItemId)
eventBus.$emit('play-item', { libraryItemId, serverLibraryItemId: this.libraryItemId })
}
},
destroy() {
// destroy the vue listeners, etc

View file

@ -54,8 +54,39 @@ export default {
},
data() {
return {
sublist: null,
bookItems: [
sublist: null
}
},
watch: {
show(newVal) {
if (!newVal) {
if (this.sublist && !this.selectedItemSublist) this.sublist = null
if (!this.sublist && this.selectedItemSublist) this.sublist = this.selectedItemSublist
}
}
},
computed: {
show: {
get() {
return this.value
},
set(val) {
this.$emit('input', val)
}
},
selected: {
get() {
return this.filterBy
},
set(val) {
this.$emit('update:filterBy', val)
}
},
userCanAccessExplicitContent() {
return this.$store.getters['user/getUserCanAccessExplicitContent']
},
bookItems() {
const items = [
{
text: this.$strings.LabelAll,
value: 'all'
@ -110,8 +141,20 @@ export default {
value: 'feed-open',
sublist: false
}
],
podcastItems: [
]
if (this.userCanAccessExplicitContent) {
items.push({
text: this.$strings.LabelExplicit,
value: 'explicit',
sublist: false
})
}
return items
},
podcastItems() {
const items = [
{
text: this.$strings.LabelAll,
value: 'all'
@ -132,32 +175,16 @@ export default {
sublist: false
}
]
}
},
watch: {
show(newVal) {
if (!newVal) {
if (this.sublist && !this.selectedItemSublist) this.sublist = null
if (!this.sublist && this.selectedItemSublist) this.sublist = this.selectedItemSublist
}
}
},
computed: {
show: {
get() {
return this.value
},
set(val) {
this.$emit('input', val)
}
},
selected: {
get() {
return this.filterBy
},
set(val) {
this.$emit('update:filterBy', val)
if (this.userCanAccessExplicitContent) {
items.push({
text: this.$strings.LabelExplicit,
value: 'explicit',
sublist: false
})
}
return items
},
isPodcast() {
return this.$store.getters['libraries/getCurrentLibraryMediaType'] === 'podcast'

View file

@ -57,6 +57,9 @@ export const getters = {
},
getUserCanDownload: (state) => {
return !!state.user?.permissions?.download
},
getUserCanAccessExplicitContent: (state) => {
return !!state.user?.permissions?.accessExplicitContent
}
}

View file

@ -6,6 +6,7 @@
"ButtonCancel": "Annuller",
"ButtonCancelTimer": "Stop timer",
"ButtonClearFilter": "Ryd filter",
"ButtonClearLogs": "Rens Logfiler",
"ButtonCloseFeed": "Luk feed",
"ButtonCollections": "Samlinger",
"ButtonConnect": "Forbind",
@ -26,7 +27,9 @@
"ButtonLatest": "Seneste",
"ButtonLibrary": "Bibliotek",
"ButtonLocalMedia": "Lokalt medie",
"ButtonLogs": "Logfiler",
"ButtonManageLocalFiles": "Administrér Lokale Filer",
"ButtonMaskServerAddress": "Maskér server adresse",
"ButtonNewFolder": "Ny Folder",
"ButtonNextEpisode": "Næste Afsnit",
"ButtonOk": "Ok",
@ -50,6 +53,7 @@
"ButtonStream": "Stream",
"ButtonSubmit": "Send",
"ButtonSwitchServerUser": "Skift Server/Bruger",
"ButtonUnmaskServerAddress": "Afmaskér server adresse",
"ButtonUserStats": "Bruger statitstik",
"ButtonYes": "Ja",
"HeaderAccount": "Konto",
@ -238,6 +242,8 @@
"LabelShowAll": "Vis alle",
"LabelSize": "Størrelse",
"LabelSleepTimer": "Søvntimer",
"LabelSleepTimerAlmostDoneChime": "Afspil lyd når snart færdig",
"LabelSleepTimerAlmostDoneChimeHelp": "Afspil lyd når sove timeren har 30 sekunder tilbage",
"LabelStart": "Start",
"LabelStartTime": "Starttid",
"LabelStatsBestDay": "Bedste dag",
@ -311,6 +317,7 @@
"MessageNoItems": "Ingen elementer",
"MessageNoItemsFound": "Ingen elementer fundet",
"MessageNoListeningSessions": "Ingen lyttesessioner",
"MessageNoLogs": "Ingen logfiler",
"MessageNoMediaFolders": "Ingen Mediemapper",
"MessageNoNetworkConnection": "Ingen Internetforbindelse",
"MessageNoPodcastsFound": "Ingen podcasts fundet",

View file

@ -32,7 +32,7 @@
"ButtonMaskServerAddress": "Server Adresse verstecken",
"ButtonNewFolder": "Neuer Ordner",
"ButtonNextEpisode": "Nächste Episode",
"ButtonOk": "Einverstanden",
"ButtonOk": "Ok",
"ButtonOpenFeed": "Feed öffnen",
"ButtonOverride": "Überschreiben",
"ButtonPause": "Pausieren",
@ -220,7 +220,7 @@
"LabelPublishedDate": "Veröffentlicht {0}",
"LabelRSSFeedCustomOwnerEmail": "Benutzerdefinierte Eigentümer-E-Mail",
"LabelRSSFeedCustomOwnerName": "Benutzerdefinierter Name des Eigentümers",
"LabelRSSFeedOpen": "RSS Feed öffnen",
"LabelRSSFeedOpen": "RSS Feed offen",
"LabelRSSFeedPreventIndexing": "Indizierung verhindern",
"LabelRSSFeedSlug": "RSS-Feed-Schlagwort",
"LabelRandomly": "Zufällig",

View file

@ -146,6 +146,7 @@
"LabelEndOfChapter": "End of Chapter",
"LabelEndTime": "End time",
"LabelEpisode": "Episode",
"LabelExplicit": "Explicit",
"LabelFeedURL": "Feed URL",
"LabelFile": "File",
"LabelFileBirthtime": "File Birthtime",

View file

@ -6,12 +6,12 @@
"ButtonCancel": "Annuleren",
"ButtonCancelTimer": "Timer annuleren",
"ButtonClearFilter": "Filter verwijderen",
"ButtonClearLogs": "Log bestanden verwijderen",
"ButtonClearLogs": "Logbestanden verwijderen",
"ButtonCloseFeed": "Feed sluiten",
"ButtonCollections": "Collecties",
"ButtonConnect": "Verbinden",
"ButtonConnectToServer": "Verbind met server",
"ButtonCreate": "Creëer",
"ButtonCreate": "Aanmaken",
"ButtonCreateBookmark": "Creëer bladwijzer",
"ButtonCreateNewPlaylist": "Maak nieuwe afspeellijst",
"ButtonDelete": "Verwijder",
@ -27,9 +27,9 @@
"ButtonLatest": "Meest recent",
"ButtonLibrary": "Bibliotheek",
"ButtonLocalMedia": "Lokale Media",
"ButtonLogs": "Log bestanden",
"ButtonLogs": "Logbestanden",
"ButtonManageLocalFiles": "Beheer Lokale Bestanden",
"ButtonMaskServerAddress": "Server adres maskeren",
"ButtonMaskServerAddress": "Serveradres maskeren",
"ButtonNewFolder": "Nieuwe map",
"ButtonNextEpisode": "Volgende aflevering",
"ButtonOk": "Akkoord",
@ -39,13 +39,13 @@
"ButtonPlay": "Afspelen",
"ButtonPlayEpisode": "Aflevering afspelen",
"ButtonPlaylists": "Afspeellijsten",
"ButtonRead": "Lees",
"ButtonRead": "Lezen",
"ButtonReadLess": "Minder lezen",
"ButtonReadMore": "Meer lezen",
"ButtonRemove": "Verwijder",
"ButtonRemoveFromServer": "Verwijder van server",
"ButtonSave": "Opslaan",
"ButtonSaveOrder": "Volgorde bewaren",
"ButtonSaveOrder": "Volgorde opslaan",
"ButtonSearch": "Zoeken",
"ButtonSendEbookToDevice": "Verzend Ebook naar Apparaat",
"ButtonSeries": "Series",

View file

@ -36,7 +36,7 @@
"ButtonOpenFeed": "Відкрити стрічку",
"ButtonOverride": "Перевизначити",
"ButtonPause": "Призупинити",
"ButtonPlay": "Слухати",
"ButtonPlay": "Відтворити",
"ButtonPlayEpisode": "Слухати епізод",
"ButtonPlaylists": "Списки відтворення",
"ButtonRead": "Читати",
@ -112,7 +112,7 @@
"LabelAutoSleepTimerAutoRewind": "Автоперемотування автотаймеру вимкнення",
"LabelAutoSleepTimerAutoRewindHelp": "Коли сплине автотаймер вимкнення, відтворення знову автоматично перемотає доріжку.",
"LabelAutoSleepTimerHelp": "Таймер вимкнення автоматично ввімкнеться при відтворенні медіа між вказаним початковим та кінцевим часом.",
"LabelBooks": "Книги",
"LabelBooks": "Книг",
"LabelChapterTrack": "Прогрес глави",
"LabelChapters": "Глави",
"LabelClosePlayer": "Закрити програвач",
@ -133,7 +133,7 @@
"LabelDisableVibrateOnReset": "Вимкнути вібрацію при скиданні",
"LabelDisableVibrateOnResetHelp": "Коли таймер вимкнення буде скинуто, ваш пристрій завібрує. Увімкніть цей параметр, щоб не вібрувати при скиданні таймера.",
"LabelDiscover": "Огляд",
"LabelDownload": "Завантажити",
"LabelDownload": "Скачати",
"LabelDownloadUsingCellular": "Завантажувати через мобільний інтернет",
"LabelDownloaded": "Завантажено",
"LabelDuration": "Тривалість",
@ -148,8 +148,8 @@
"LabelEpisode": "Епізод",
"LabelFeedURL": "Адреса стрічки",
"LabelFile": "Файл",
"LabelFileBirthtime": "Дата створення",
"LabelFileModified": "Дата змінення",
"LabelFileBirthtime": "Дата створення файлу",
"LabelFileModified": "Дата зміни файлу",
"LabelFilename": "Ім'я файлу",
"LabelFinished": "Завершено",
"LabelFolder": "Тека",
@ -295,8 +295,8 @@
"MessageDiscardProgress": "Скинути прогрес",
"MessageDownloadCompleteProcessing": "Завантаження завершено. Обробка...",
"MessageDownloading": "Завантажується...",
"MessageDownloadingEpisode": "Завантаження епізоду",
"MessageEpisodesQueuedForDownload": "Епізодів у черзі завантаження: {0}",
"MessageDownloadingEpisode": "Скачування епізоду",
"MessageEpisodesQueuedForDownload": "{0} епізод(ів) у черзі на завантаження",
"MessageFeedURLWillBe": "URL-адреса каналу буде {0}",
"MessageFetching": "Отримання...",
"MessageFollowTheProjectOnGithub": "Слідкуйте за проєктом на GitHub",
@ -305,7 +305,7 @@
"MessageLoading": "Завантаження...",
"MessageLoadingServerData": "Завантаження даних сервера...",
"MessageLocalFolderDescription": "«Внутрішня пам’ять програми» доступна лише цій програмі. Ця програма підтримує лише мультимедійні файли, завантажені безпосередньо через програму. Спільні папки для зберігання можна використовувати, щоб надати іншим програмам доступ до медіафайлів, завантажених цією програмою.",
"MessageMarkAsFinished": "Позначити завершеним",
"MessageMarkAsFinished": "Позначити як завершене",
"MessageMediaLinkedToADifferentServer": "Медіа пов'язане з Audiobookself-сервером за іншою адресою ({0}). Прогрес буде синхронізовано після підключення до вказаного сервера.",
"MessageMediaLinkedToADifferentUser": "Медіа пов'язане з цим сервером, але було завантажене іншим користувачем. Прогрес буде синхронізовано лише для користувача, що завантажив медіа.",
"MessageMediaLinkedToServer": "Пов'язано з сервером {0}",
@ -317,12 +317,12 @@
"MessageNoItems": "Елементи відсутні",
"MessageNoItemsFound": "Елементів не знайдено",
"MessageNoListeningSessions": "Сеанси прослуховування відсутні",
"MessageNoLogs": "Без журнал",
"MessageNoLogs": "Без журналу",
"MessageNoMediaFolders": "Теки медіа відсутні",
"MessageNoNetworkConnection": "Немає підключення до мережі",
"MessageNoPodcastsFound": "Подкастів не знайдено",
"MessageNoSeries": "Серії відсутні",
"MessageNoUpdatesWereNecessary": "Оновлень не потрібно",
"MessageNoUpdatesWereNecessary": "Оновлення не потрібні",
"MessageNoUserPlaylists": "У вас немає списків відтворення",
"MessageOldServerConnectionWarning": "Конфігурація підключення до сервера використовує старий ідентифікатор користувача. Видаліть і додайте це підключення до сервера заново.",
"MessageOldServerConnectionWarningHelp": "Ви спочатку налаштували з’єднання з цим сервером перед міграцією бази даних у версії 2.3.0, випущеній у червні 2023 року. Майбутнє оновлення сервера скасує можливість входу за допомогою цього старого з’єднання. Будь ласка, видаліть існуюче підключення до сервера та підключіться знову (використовуючи ту саму адресу сервера та облікові дані). Якщо на цьому пристрої є будь-які завантажені медіафайли, їх потрібно буде завантажити ще раз, щоб синхронізувати із сервером.",
@ -337,8 +337,8 @@
"MessageSocketConnectedOverUnmeteredCellular": "Сокет під'єднано до безлімітної мобільної мережі",
"MessageSocketConnectedOverUnmeteredWifi": "Сокет під'єднано до безлімітної мережі Wi-Fi",
"MessageSocketNotConnected": "Сокет не під'єднано",
"NoteRSSFeedPodcastAppsHttps": "Попередження: Більшість додатків подкастів вимагатимуть використання протоколу HTTPS від RSS-каналу",
"NoteRSSFeedPodcastAppsPubDate": "Попередження: 1 або більше ваших епізодів не мають дати публікації. Деякі додатки подкастів вимагають це.",
"NoteRSSFeedPodcastAppsHttps": "Попередження: більшість додатків подкастів вимагають використання HTTPS для RSS-каналу",
"NoteRSSFeedPodcastAppsPubDate": "Попередження: один або більше ваших епізодів не мають дати публікації. Деякі додатки подкастів цього вимагають.",
"ToastBookmarkCreateFailed": "Не вдалося створити закладку",
"ToastBookmarkRemoveFailed": "Не вдалося видалити закладку",
"ToastBookmarkUpdateFailed": "Не вдалося оновити закладку",

View file

@ -246,11 +246,11 @@
"LabelSleepTimerAlmostDoneChimeHelp": "当睡眠定时器还剩30秒时播放铃声",
"LabelStart": "开始",
"LabelStartTime": "开始时间",
"LabelStatsBestDay": "最好的一天",
"LabelStatsBestDay": "单日最高",
"LabelStatsDailyAverage": "每日平均值",
"LabelStatsDays": "",
"LabelStatsDays": "连续收听",
"LabelStatsDaysListened": "收听天数",
"LabelStatsInARow": "在一行",
"LabelStatsInARow": "",
"LabelStatsItemsFinished": "已完成的项目",
"LabelStatsMinutes": "分钟",
"LabelStatsMinutesListening": "收听分钟数",