Compare commits

..
Author SHA1 Message Date
advplyr 882ed1871a iOS version bump 0.9.78 2025-01-18 17:45:04 -06:00
advplyr 7c5c7d5632 Version bump v0.9.78-beta 2025-01-18 16:56:36 -06:00
advplyrandGitHub 240c0da577 Merge pull request #1438 from weblate/weblate-audiobookshelf-abs-mobile-app
Translations update from Hosted Weblate
2025-01-18 16:42:07 -06:00
Максим ГорпинічandHosted Weblate 7472ef01a8 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (340 of 340 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/uk/
2025-01-18 22:24:44 +00:00
Максим ГорпинічandHosted Weblate 9907095a2d Translated using Weblate (Ukrainian)
Currently translated at 100.0% (337 of 337 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/uk/
2025-01-18 22:24:44 +00:00
Максим ГорпинічandHosted Weblate 658a527d93 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (336 of 336 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/uk/
2025-01-18 22:24:43 +00:00
Максим ГорпинічandHosted Weblate 3d25f3dd62 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (336 of 336 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/uk/
2025-01-18 22:24:42 +00:00
Bezruchenko SimonandHosted Weblate 6290e983e9 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (336 of 336 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/uk/
2025-01-18 22:24:41 +00:00
Максим ГорпинічandHosted Weblate 10ae92ec41 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (333 of 333 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/uk/
2025-01-18 22:24:41 +00:00
Jan-Eric MyhrgrenandHosted Weblate 2c25286155 Translated using Weblate (Swedish)
Currently translated at 92.4% (307 of 332 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/sv/
2025-01-18 22:24:40 +00:00
Jan-Eric MyhrgrenandHosted Weblate 656ede98b6 Translated using Weblate (Swedish)
Currently translated at 92.4% (307 of 332 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/sv/
2025-01-18 22:24:40 +00:00
Kieli PuoliandHosted Weblate 5fb0118f60 Translated using Weblate (Finnish)
Currently translated at 88.5% (294 of 332 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/fi/
2025-01-18 22:24:39 +00:00
Jan-Eric MyhrgrenandHosted Weblate 27e47b2b4b Translated using Weblate (Swedish)
Currently translated at 92.4% (307 of 332 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/sv/
2025-01-18 22:24:39 +00:00
Kieli PuoliandHosted Weblate f02e3358aa Translated using Weblate (Finnish)
Currently translated at 88.2% (293 of 332 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/fi/
2025-01-18 22:24:38 +00:00
Jan-Eric MyhrgrenandHosted Weblate 7caae3171c Translated using Weblate (Swedish)
Currently translated at 92.4% (307 of 332 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/sv/
2025-01-18 22:24:38 +00:00
Kieli PuoliandHosted Weblate 0cded599b1 Translated using Weblate (Finnish)
Currently translated at 87.9% (292 of 332 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/fi/
2025-01-18 22:24:37 +00:00
Kieli PuoliandHosted Weblate 4e48240158 Translated using Weblate (Finnish)
Currently translated at 87.6% (291 of 332 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/fi/
2025-01-18 22:24:36 +00:00
Jan-Eric MyhrgrenandHosted Weblate b488e24798 Translated using Weblate (Swedish)
Currently translated at 92.4% (307 of 332 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/sv/
2025-01-18 22:24:36 +00:00
Jan-Eric MyhrgrenandHosted Weblate 7e7d87c147 Translated using Weblate (Swedish)
Currently translated at 92.4% (307 of 332 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/sv/
2025-01-18 22:24:35 +00:00
Jan-Eric MyhrgrenandHosted Weblate 8b6389cf3a Translated using Weblate (Swedish)
Currently translated at 92.4% (307 of 332 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/sv/
2025-01-18 22:24:34 +00:00
Kieli PuoliandHosted Weblate 8a2725b48b Translated using Weblate (Finnish)
Currently translated at 83.7% (278 of 332 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/fi/
2025-01-18 22:24:34 +00:00
Jan-Eric MyhrgrenandHosted Weblate a7e8fe12f4 Translated using Weblate (Swedish)
Currently translated at 92.4% (307 of 332 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/sv/
2025-01-18 22:24:33 +00:00
Jan-Eric MyhrgrenandHosted Weblate 67a5473e27 Translated using Weblate (Swedish)
Currently translated at 92.4% (307 of 332 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/sv/
2025-01-18 22:24:33 +00:00
Jan-Eric MyhrgrenandHosted Weblate e16fba8eab Translated using Weblate (Swedish)
Currently translated at 92.4% (307 of 332 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/sv/
2025-01-18 22:24:32 +00:00
Jan-Eric MyhrgrenandHosted Weblate cdfbafc789 Translated using Weblate (Swedish)
Currently translated at 92.4% (307 of 332 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/sv/
2025-01-18 22:24:31 +00:00
Jan-Eric MyhrgrenandHosted Weblate c318f5d57b Translated using Weblate (Swedish)
Currently translated at 92.4% (307 of 332 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/sv/
2025-01-18 22:24:30 +00:00
Jan-Eric MyhrgrenandHosted Weblate 556ab85b0d Translated using Weblate (Swedish)
Currently translated at 91.8% (305 of 332 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/sv/
2025-01-18 22:24:30 +00:00
Jan-Eric MyhrgrenandHosted Weblate 20018aed27 Translated using Weblate (Swedish)
Currently translated at 91.8% (305 of 332 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/sv/
2025-01-18 22:24:29 +00:00
Jan-Eric MyhrgrenandHosted Weblate e2facc87f0 Translated using Weblate (Swedish)
Currently translated at 91.8% (305 of 332 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/sv/
2025-01-18 22:24:29 +00:00
Jan-Eric MyhrgrenandHosted Weblate 07e951039c Translated using Weblate (Swedish)
Currently translated at 91.8% (305 of 332 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/sv/
2025-01-18 22:24:28 +00:00
Jan-Eric MyhrgrenandHosted Weblate 386d9ebc52 Translated using Weblate (Swedish)
Currently translated at 91.8% (305 of 332 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/sv/
2025-01-18 22:24:28 +00:00
Jan-Eric MyhrgrenandHosted Weblate d8e058a416 Translated using Weblate (Swedish)
Currently translated at 91.8% (305 of 332 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/sv/
2025-01-18 22:24:27 +00:00
Jan-Eric MyhrgrenandHosted Weblate f5d9c6076c Translated using Weblate (Swedish)
Currently translated at 91.8% (305 of 332 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/sv/
2025-01-18 22:24:26 +00:00
Jan-Eric MyhrgrenandHosted Weblate e870855602 Translated using Weblate (Swedish)
Currently translated at 91.8% (305 of 332 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/sv/
2025-01-18 22:24:26 +00:00
Jan-Eric MyhrgrenandHosted Weblate a3a6b4618b Translated using Weblate (Swedish)
Currently translated at 91.8% (305 of 332 strings)

Translation: Audiobookshelf/Abs Mobile App
Translate-URL: https://hosted.weblate.org/projects/audiobookshelf/abs-mobile-app/sv/
2025-01-18 22:24:25 +00:00
advplyr 3ecae3e16b Fix ereader settings scroll #1374 2025-01-18 16:24:18 -06:00
advplyr 111e8d38dc Remove token from image requests & fix download raw cover image #1328 2025-01-18 15:42:40 -06:00
advplyr d5fa36b11a Update error icon on audio player cover to show progress sync alert dialog when tapped #1396 2025-01-18 14:46:12 -06:00
advplyr a35c94cf03 Update numbers to use Intl.NumberFormat with selected locale #1427 2025-01-18 14:24:44 -06:00
advplyr b2eff46c38 Add # of episodes sort option for podcast libraries 2025-01-18 14:19:14 -06:00
advplyr 07c0187423 Update podcast items incomplete episodes display 2025-01-18 14:15:34 -06:00
advplyr 0074078539 Update server connections list to show warning for connections with an old user id #1411 2025-01-18 13:44:16 -06:00
advplyr d1641ac0e8 Update epub reader settings to be 75vh 2025-01-18 11:48:41 -06:00
advplyrandGitHub 13d3489cde Merge pull request #1439 from advplyr/reader-keep-screen-awake
Add epub reader setting to keep screen awake #1207
2025-01-18 11:37:52 -06:00
27 changed files with 210 additions and 140 deletions
+2 -2
View File
@@ -36,8 +36,8 @@ android {
applicationId "com.audiobookshelf.app"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 108
versionName "0.9.77-beta"
versionCode 109
versionName "0.9.78-beta"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
manifestPlaceholders = [
"appAuthRedirectScheme": "com.audiobookshelf.app"
@@ -41,8 +41,11 @@ data class DownloadItemPart(
val destinationUri = Uri.fromFile(destinationFile)
val finalDestinationUri = Uri.fromFile(finalDestinationFile)
var downloadUrl = "${DeviceManager.serverAddress}${serverPath}?token=${DeviceManager.token}"
if (serverPath.endsWith("/cover")) downloadUrl += "&format=jpeg&raw=1" // For cover images force to jpeg
var downloadUrl = "${DeviceManager.serverAddress}${serverPath}"
downloadUrl += if (serverPath.endsWith("/cover")) "?raw=1" // Download raw cover image
else "?token=${DeviceManager.token}"
val downloadUri = Uri.parse(downloadUrl)
Log.d("DownloadItemPart", "Audio File Destination Uri: $destinationUri | Final Destination Uri: $finalDestinationUri | Download URI $downloadUri")
return DownloadItemPart(
@@ -77,7 +80,7 @@ data class DownloadItemPart(
val isInternalStorage get() = localFolderId.startsWith("internal-")
@get:JsonIgnore
val serverUrl get() = "${DeviceManager.serverAddress}${serverPath}?token=${DeviceManager.token}"
val serverUrl get() = uri.toString()
@JsonIgnore
fun getDownloadRequest(): DownloadManager.Request {
+9 -1
View File
@@ -35,7 +35,7 @@
<covers-book-cover v-if="libraryItem || localLibraryItemCoverSrc" ref="cover" :library-item="libraryItem" :download-cover="localLibraryItemCoverSrc" :width="bookCoverWidth" :book-cover-aspect-ratio="bookCoverAspectRatio" raw @imageLoaded="coverImageLoaded" />
</div>
<div v-if="syncStatus === $constants.SyncStatus.FAILED" class="absolute top-0 left-0 w-full h-full flex items-center justify-center z-30">
<div v-if="syncStatus === $constants.SyncStatus.FAILED" class="absolute top-0 left-0 w-full h-full flex items-center justify-center z-30" @click.stop="showSyncsFailedDialog">
<span class="material-icons text-error text-3xl">error</span>
</div>
</div>
@@ -107,6 +107,7 @@
<script>
import { Capacitor } from '@capacitor/core'
import { AbsAudioPlayer } from '@/plugins/capacitor'
import { Dialog } from '@capacitor/dialog'
import { FastAverageColor } from 'fast-average-color'
import WrappingMarquee from '@/assets/WrappingMarquee.js'
@@ -390,6 +391,13 @@ export default {
}
},
methods: {
showSyncsFailedDialog() {
Dialog.alert({
title: this.$strings.HeaderProgressSyncFailed,
message: this.$strings.MessageProgressSyncFailed,
cancelText: this.$strings.ButtonOk
})
},
clickChaptersBtn() {
if (!this.chapters.length) return
this.showChapterModal = true
-3
View File
@@ -42,9 +42,6 @@ export default {
}
},
computed: {
userToken() {
return this.$store.getters['user/getToken']
},
_author() {
return this.author || {}
},
+2 -2
View File
@@ -94,8 +94,8 @@
</div>
<!-- Podcast Num Episodes Incomplete -->
<div v-else-if="numEpisodesIncomplete && !isSelectionMode" class="absolute rounded-full bg-black bg-opacity-90 box-shadow-md z-10 flex items-center justify-center" :style="{ top: 0.375 * sizeMultiplier + 'rem', right: 0.375 * sizeMultiplier + 'rem', width: 1.25 * sizeMultiplier + 'rem', height: 1.25 * sizeMultiplier + 'rem' }">
<p class="text-white" :style="{ fontSize: sizeMultiplier * 0.8 + 'rem' }">{{ numEpisodesIncomplete }}</p>
<div v-else-if="numEpisodesIncomplete && !isSelectionMode" class="absolute rounded-full bg-yellow-400 box-shadow-md z-10 flex items-center justify-center" :style="{ top: 0.375 * sizeMultiplier + 'rem', right: 0.375 * sizeMultiplier + 'rem', width: 1.25 * sizeMultiplier + 'rem', height: 1.25 * sizeMultiplier + 'rem' }">
<p class="text-black" :style="{ fontSize: sizeMultiplier * 0.8 + 'rem' }">{{ numEpisodesIncomplete }}</p>
</div>
</div>
</template>
+14 -7
View File
@@ -21,7 +21,13 @@
<p class="truncate text-fg-muted" :style="{ fontSize: 0.7 * sizeMultiplier + 'rem' }">{{ displayAuthor }}</p>
<p v-if="displaySortLine" class="truncate text-fg-muted" :style="{ fontSize: 0.7 * sizeMultiplier + 'rem' }">{{ displaySortLine }}</p>
<p v-if="duration" class="truncate text-fg-muted" :style="{ fontSize: 0.7 * sizeMultiplier + 'rem' }">{{ $elapsedPretty(duration) }}</p>
<p v-if="episodes" class="truncate text-fg-muted" :style="{ fontSize: 0.7 * sizeMultiplier + 'rem' }">{{ episodes }}</p>
<p v-if="numEpisodesIncomplete" class="truncate text-fg-muted" :style="{ fontSize: 0.7 * sizeMultiplier + 'rem' }">
{{ $getString('LabelNumEpisodesIncomplete', [numEpisodes, numEpisodesIncomplete]) }}
</p>
<p v-else-if="numEpisodes" class="truncate text-fg-muted" :style="{ fontSize: 0.7 * sizeMultiplier + 'rem' }">
{{ $getString('LabelNumEpisodes', [numEpisodes]) }}
</p>
</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` }">
@@ -106,12 +112,13 @@ export default {
isPodcast() {
return this.mediaType === 'podcast'
},
episodes() {
if (this.isPodcast) {
return this.$getString('LabelNumEpisodes', [this.media.numEpisodes])
} else {
return null
}
numEpisodes() {
if (this.isLocal && this.isPodcast && this.media.episodes) return this.media.episodes.length
return this.media.numEpisodes
},
numEpisodesIncomplete() {
if (this.isLocal) return 0
return this._libraryItem.numEpisodesIncomplete || 0
},
placeholderUrl() {
return '/book_placeholder.jpg'
+22 -5
View File
@@ -3,12 +3,19 @@
<div v-show="!loggedIn" class="mt-8 bg-primary overflow-hidden shadow rounded-lg px-4 py-6 w-full">
<!-- list of server connection configs -->
<template v-if="!showForm">
<div v-for="config in serverConnectionConfigs" :key="config.id" class="flex items-center py-4 my-1 border-b border-fg/10 relative" @click="connectToServer(config)">
<span class="material-icons-outlined text-xl text-fg-muted">dns</span>
<p class="pl-3 pr-6 text-base text-fg">{{ config.name }}</p>
<div v-for="config in serverConnectionConfigs" :key="config.id" class="border-b border-fg/10 py-4">
<div class="flex items-center my-1 relative" @click="connectToServer(config)">
<span class="material-icons-outlined text-xl text-fg-muted">dns</span>
<p class="pl-3 pr-6 text-base text-fg">{{ config.name }}</p>
<div class="absolute top-0 right-0 h-full px-4 flex items-center" @click.stop="editServerConfig(config)">
<span class="material-icons text-lg text-fg-muted">more_vert</span>
<div class="absolute top-0 right-0 h-full px-4 flex items-center" @click.stop="editServerConfig(config)">
<span class="material-icons text-lg text-fg-muted">more_vert</span>
</div>
</div>
<!-- warning message if server connection config is using an old user id -->
<div v-if="!checkIdUuid(config.userId)" class="flex flex-nowrap justify-between items-center space-x-4 pt-4">
<p class="text-xs text-warning">{{ $strings.MessageOldServerConnectionWarning }}</p>
<ui-btn class="text-xs whitespace-nowrap" :padding-x="2" :padding-y="1" @click="showOldUserIdWarningDialog">{{ $strings.LabelMoreInfo }}</ui-btn>
</div>
</div>
<div class="my-1 py-4 w-full">
@@ -141,6 +148,16 @@ export default {
}
},
methods: {
showOldUserIdWarningDialog() {
Dialog.alert({
title: 'Old Server Connection Warning',
message: this.$strings.MessageOldServerConnectionWarningHelp,
cancelText: this.$strings.ButtonOk
})
},
checkIdUuid(userId) {
return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(userId)
},
/**
* Initiates the login process using OpenID via OAuth2.0.
* 1. Verifying the server's address
+2 -5
View File
@@ -39,9 +39,6 @@ export default {
}
},
computed: {
userToken() {
return this.$store.getters['user/getToken']
},
_author() {
return this.author || {}
},
@@ -61,9 +58,9 @@ export default {
if (!this.imagePath || !this.serverAddress) return null
if (process.env.NODE_ENV !== 'production' && this.serverAddress.startsWith('http://192.168')) {
// Testing
return `http://localhost:3333/api/authors/${this.authorId}/image?token=${this.userToken}&ts=${this.updatedAt}`
return `http://localhost:3333/api/authors/${this.authorId}/image?ts=${this.updatedAt}`
}
return `${this.serverAddress}/api/authors/${this.authorId}/image?token=${this.userToken}&ts=${this.updatedAt}`
return `${this.serverAddress}/api/authors/${this.authorId}/image?ts=${this.updatedAt}`
}
},
methods: {
-3
View File
@@ -141,9 +141,6 @@ export default {
},
authorBottom() {
return 0.75 * this.sizeMultiplier
},
userToken() {
return this.$store.getters['user/getToken']
}
},
methods: {
+2 -2
View File
@@ -2,8 +2,8 @@
<div class="w-full h-9 bg-bg relative z-20">
<div id="bookshelf-toolbar" class="absolute top-0 left-0 w-full h-full z-20 flex items-center px-2">
<div class="flex items-center w-full text-sm">
<p v-show="!selectedSeriesName" class="pt-1">{{ totalEntities }} {{ entityTitle }}</p>
<p v-show="selectedSeriesName" class="ml-2 pt-1">{{ selectedSeriesName }} ({{ totalEntities }})</p>
<p v-show="!selectedSeriesName" class="pt-1">{{ $formatNumber(totalEntities) }} {{ entityTitle }}</p>
<p v-show="selectedSeriesName" class="ml-2 pt-1">{{ selectedSeriesName }} ({{ $formatNumber(totalEntities) }})</p>
<div class="flex-grow" />
<span v-if="page == 'library' || seriesBookPage" class="material-icons px-2" @click="changeView">{{ !bookshelfListView ? 'view_list' : 'grid_view' }}</span>
<template v-if="page === 'library'">
+2 -2
View File
@@ -1,5 +1,5 @@
<template>
<div ref="wrapper" class="modal modal-bg w-screen fixed bottom-0 left-0 flex items-center justify-center z-50" :class="halfScreen ? 'h-[50vh] min-h-[400px]' : 'h-screen'" @click.stop @touchstart.stop @touchend.stop>
<div ref="wrapper" class="modal modal-bg w-screen fixed bottom-0 left-0 flex items-center justify-center z-50" :class="threeQuartersScreen ? 'h-[75vh] min-h-[400px]' : 'h-screen'" @click.stop @touchstart.stop @touchend.stop>
<div ref="content" class="relative text-fg h-full w-full bg-bg">
<slot />
</div>
@@ -11,7 +11,7 @@ export default {
props: {
value: Boolean,
processing: Boolean,
halfScreen: Boolean
threeQuartersScreen: Boolean
},
data() {
return {
+4
View File
@@ -86,6 +86,10 @@ export default {
text: this.$strings.LabelSize,
value: 'size'
},
{
text: this.$strings.LabelNumberOfEpisodes,
value: 'media.numTracks'
},
{
text: this.$strings.LabelFileBirthtime,
value: 'birthtimeMs'
+4 -4
View File
@@ -54,15 +54,15 @@
</modals-fullscreen-modal>
<!-- ereader settings modal -->
<modals-fullscreen-modal v-model="showSettingsModal" :theme="ereaderTheme">
<modals-fullscreen-modal v-model="showSettingsModal" :theme="ereaderTheme" threeQuartersScreen>
<div style="box-shadow: 0px -8px 8px #11111155">
<div class="flex items-end justify-between h-20 px-4 pb-2 mb-6">
<div class="flex items-end justify-between h-14 px-4 pb-2 mb-6">
<h1 class="text-lg">{{ $strings.HeaderEreaderSettings }}</h1>
<button class="flex" @click="showSettingsModal = false">
<span class="material-icons">close</span>
</button>
</div>
<div class="w-full overflow-y-auto overflow-x-hidden h-full max-h-[calc(100vh-85px)]">
<div class="w-full overflow-y-auto overflow-x-hidden h-full max-h-[calc(75vh-85px)]">
<div class="w-full h-full px-4">
<div class="flex items-center mb-6">
<div class="w-32">
@@ -106,7 +106,7 @@
</div>
<ui-toggle-btns v-model="ereaderSettings.navigateWithVolumeWhilePlaying" name="navigate-volume-playing" :items="onOffToggleButtonItems" @input="settingsUpdated" />
</div>
<div class="flex items-center">
<div class="flex items-center mb-6">
<div class="w-32">
<p class="text-sm">{{ $strings.LabelKeepScreenAwake }}</p>
</div>
+4 -4
View File
@@ -33,22 +33,22 @@
<div class="flex justify-between pt-12">
<div>
<p class="text-sm text-center">{{ $strings.LabelStatsWeekListening }}</p>
<p class="text-5xl font-semibold text-center" style="line-height: 0.85">{{ totalMinutesListeningThisWeek }}</p>
<p class="text-5xl font-semibold text-center" style="line-height: 0.85">{{ $formatNumber(totalMinutesListeningThisWeek) }}</p>
<p class="text-sm text-center">{{ $strings.LabelStatsMinutes }}</p>
</div>
<div>
<p class="text-sm text-center">{{ $strings.LabelStatsDailyAverage }}</p>
<p class="text-5xl font-semibold text-center" style="line-height: 0.85">{{ averageMinutesPerDay }}</p>
<p class="text-5xl font-semibold text-center" style="line-height: 0.85">{{ $formatNumber(averageMinutesPerDay) }}</p>
<p class="text-sm text-center">{{ $strings.LabelStatsMinutes }}</p>
</div>
<div>
<p class="text-sm text-center">{{ $strings.LabelStatsBestDay }}</p>
<p class="text-5xl font-semibold text-center" style="line-height: 0.85">{{ mostListenedDay }}</p>
<p class="text-5xl font-semibold text-center" style="line-height: 0.85">{{ $formatNumber(mostListenedDay) }}</p>
<p class="text-sm text-center">{{ $strings.LabelStatsMinutes }}</p>
</div>
<div>
<p class="text-sm text-center">{{ $strings.LabelStatsDays }}</p>
<p class="text-5xl font-semibold text-center" style="line-height: 0.85">{{ daysInARow }}</p>
<p class="text-5xl font-semibold text-center" style="line-height: 0.85">{{ $formatNumber(daysInARow) }}</p>
<p class="text-sm text-center">{{ $strings.LabelStatsInARow }}</p>
</div>
</div>
@@ -50,9 +50,6 @@ export default {
libraryItemId() {
return this.libraryItem.id
},
userToken() {
return this.$store.getters['user/getToken']
},
ebookFiles() {
return (this.libraryItem.libraryFiles || []).filter((lf) => lf.fileType === 'ebook')
},
@@ -24,9 +24,6 @@ export default {
return {}
},
computed: {
userToken() {
return this.$store.getters['user/getToken']
},
userCanUpdate() {
return this.$store.getters['user/getUserCanUpdate']
},
+4 -4
View File
@@ -744,12 +744,12 @@
ASSETCATALOG_COMPILER_APPICON_NAME = Icons;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 34;
CURRENT_PROJECT_VERSION = 35;
DEVELOPMENT_TEAM = 7UFJ7D8V6A;
INFOPLIST_FILE = App/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
MARKETING_VERSION = 0.9.77;
MARKETING_VERSION = 0.9.78;
OTHER_SWIFT_FLAGS = "$(inherited) \"-D\" \"COCOAPODS\" \"-DDEBUG\"";
PRODUCT_BUNDLE_IDENTIFIER = com.audiobookshelf.app.dev;
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -768,12 +768,12 @@
ASSETCATALOG_COMPILER_APPICON_NAME = Icons;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 34;
CURRENT_PROJECT_VERSION = 35;
DEVELOPMENT_TEAM = 7UFJ7D8V6A;
INFOPLIST_FILE = App/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
MARKETING_VERSION = 0.9.77;
MARKETING_VERSION = 0.9.78;
PRODUCT_BUNDLE_IDENTIFIER = com.audiobookshelf.app;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "";
+2 -2
View File
@@ -1,12 +1,12 @@
{
"name": "audiobookshelf-app",
"version": "0.9.77-beta",
"version": "0.9.78-beta",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "audiobookshelf-app",
"version": "0.9.77-beta",
"version": "0.9.78-beta",
"dependencies": {
"@byteowls/capacitor-filesharer": "^6.0.0",
"@capacitor-community/keep-awake": "^5.0.1",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "audiobookshelf-app",
"version": "0.9.77-beta",
"version": "0.9.78-beta",
"author": "advplyr",
"scripts": {
"dev": "nuxt --hostname 0.0.0.0 --port 1337",
-3
View File
@@ -366,9 +366,6 @@ export default {
user() {
return this.$store.state.user.user
},
userToken() {
return this.$store.getters['user/getToken']
},
userItemProgress() {
if (this.isPodcast) return null
if (this.isLocal) return this.localItemProgress
+3 -3
View File
@@ -10,21 +10,21 @@
<div class="flex text-center justify-center">
<div class="flex p-2">
<div class="px-3">
<p class="text-4xl md:text-5xl font-bold">{{ userItemsFinished.length }}</p>
<p class="text-4xl md:text-5xl font-bold">{{ $formatNumber(userItemsFinished.length) }}</p>
<p class="text-xs md:text-sm text-fg-muted">{{ $strings.LabelStatsItemsFinished }}</p>
</div>
</div>
<div class="flex p-2">
<div class="px-1">
<p class="text-4xl md:text-5xl font-bold">{{ totalDaysListened }}</p>
<p class="text-4xl md:text-5xl font-bold">{{ $formatNumber(totalDaysListened) }}</p>
<p class="text-xs md:text-sm text-fg-muted">{{ $strings.LabelStatsDaysListened }}</p>
</div>
</div>
<div class="flex p-2">
<div class="px-1">
<p class="text-4xl md:text-5xl font-bold">{{ totalMinutesListening }}</p>
<p class="text-4xl md:text-5xl font-bold">{{ $formatNumber(totalMinutesListening) }}</p>
<p class="text-xs md:text-sm text-fg-muted">{{ $strings.LabelStatsMinutesListening }}</p>
</div>
</div>
+4
View File
@@ -62,6 +62,10 @@ Vue.prototype.$getString = (key, subs) => {
return Vue.prototype.$strings[key]
}
Vue.prototype.$formatNumber = (num) => {
return Intl.NumberFormat(Vue.prototype.$languageCodes.current).format(num)
}
var translations = {
[defaultCode]: enUsStrings
}
+65 -56
View File
@@ -44,62 +44,71 @@ export const state = () => ({
})
export const getters = {
getDownloadItem: state => (libraryItemId, episodeId = null) => {
return state.itemDownloads.find(i => {
// if (episodeId && !i.episodes.some(e => e.id == episodeId)) return false
if (episodeId && i.episodeId !== episodeId) return false
return i.libraryItemId == libraryItemId
})
},
getLibraryItemCoverSrc: (state, getters, rootState, rootGetters) => (libraryItem, placeholder, raw = false) => {
if (!libraryItem) return placeholder
const media = libraryItem.media
if (!media || !media.coverPath || media.coverPath === placeholder) return placeholder
getDownloadItem:
(state) =>
(libraryItemId, episodeId = null) => {
return state.itemDownloads.find((i) => {
// if (episodeId && !i.episodes.some(e => e.id == episodeId)) return false
if (episodeId && i.episodeId !== episodeId) return false
return i.libraryItemId == libraryItemId
})
},
getLibraryItemCoverSrc:
(state, getters, rootState, rootGetters) =>
(libraryItem, placeholder, raw = false) => {
if (!libraryItem) return placeholder
const media = libraryItem.media
if (!media || !media.coverPath || media.coverPath === placeholder) return placeholder
// Absolute URL covers (should no longer be used)
if (media.coverPath.startsWith('http:') || media.coverPath.startsWith('https:')) return media.coverPath
// Absolute URL covers (should no longer be used)
if (media.coverPath.startsWith('http:') || media.coverPath.startsWith('https:')) return media.coverPath
const userToken = rootGetters['user/getToken']
const serverAddress = rootGetters['user/getServerAddress']
if (!userToken || !serverAddress) return placeholder
const serverAddress = rootGetters['user/getServerAddress']
if (!serverAddress) return placeholder
const lastUpdate = libraryItem.updatedAt || Date.now()
const lastUpdate = libraryItem.updatedAt || Date.now()
if (process.env.NODE_ENV !== 'production') { // Testing
// return `http://localhost:3333/api/items/${libraryItem.id}/cover?token=${userToken}&ts=${lastUpdate}`
}
if (process.env.NODE_ENV !== 'production') {
// Testing
// return `http://localhost:3333/api/items/${libraryItem.id}/cover?ts=${lastUpdate}`
}
const url = new URL(`${serverAddress}/api/items/${libraryItem.id}/cover`)
return `${url}?token=${userToken}&ts=${lastUpdate}${raw ? '&raw=1' : ''}`
},
getLibraryItemCoverSrcById: (state, getters, rootState, rootGetters) => (libraryItemId, placeholder = null) => {
if (!placeholder) placeholder = `${rootState.routerBasePath}/book_placeholder.jpg`
if (!libraryItemId) return placeholder
const userToken = rootGetters['user/getToken']
const serverAddress = rootGetters['user/getServerAddress']
if (!userToken || !serverAddress) return placeholder
const url = new URL(`${serverAddress}/api/items/${libraryItem.id}/cover`)
return `${url}?ts=${lastUpdate}${raw ? '&raw=1' : ''}`
},
getLibraryItemCoverSrcById:
(state, getters, rootState, rootGetters) =>
(libraryItemId, placeholder = null) => {
if (!placeholder) placeholder = `${rootState.routerBasePath}/book_placeholder.jpg`
if (!libraryItemId) return placeholder
const serverAddress = rootGetters['user/getServerAddress']
if (!serverAddress) return placeholder
const url = new URL(`${serverAddress}/api/items/${libraryItemId}/cover`)
return `${url}?token=${userToken}`
},
getLocalMediaProgressById: (state) => (localLibraryItemId, episodeId = null) => {
return state.localMediaProgress.find(lmp => {
if (episodeId != null && lmp.localEpisodeId != episodeId) return false
return lmp.localLibraryItemId == localLibraryItemId
})
},
getLocalMediaProgressByServerItemId: (state) => (libraryItemId, episodeId = null) => {
return state.localMediaProgress.find(lmp => {
if (episodeId != null && lmp.episodeId != episodeId) return false
return lmp.libraryItemId == libraryItemId
})
},
getJumpForwardIcon: state => (jumpForwardTime) => {
const item = state.jumpForwardItems.find(i => i.value == jumpForwardTime)
const url = new URL(`${serverAddress}/api/items/${libraryItemId}/cover`)
return url.toString()
},
getLocalMediaProgressById:
(state) =>
(localLibraryItemId, episodeId = null) => {
return state.localMediaProgress.find((lmp) => {
if (episodeId != null && lmp.localEpisodeId != episodeId) return false
return lmp.localLibraryItemId == localLibraryItemId
})
},
getLocalMediaProgressByServerItemId:
(state) =>
(libraryItemId, episodeId = null) => {
return state.localMediaProgress.find((lmp) => {
if (episodeId != null && lmp.episodeId != episodeId) return false
return lmp.libraryItemId == libraryItemId
})
},
getJumpForwardIcon: (state) => (jumpForwardTime) => {
const item = state.jumpForwardItems.find((i) => i.value == jumpForwardTime)
return item ? item.icon : 'forward_10'
},
getJumpBackwardsIcon: state => (jumpBackwardsTime) => {
const item = state.jumpBackwardsItems.find(i => i.value == jumpBackwardsTime)
getJumpBackwardsIcon: (state) => (jumpBackwardsTime) => {
const item = state.jumpBackwardsItems.find((i) => i.value == jumpBackwardsTime)
return item ? item.icon : 'replay_10'
}
}
@@ -116,7 +125,7 @@ export const mutations = {
state.isModalOpen = val
},
addUpdateItemDownload(state, downloadItem) {
var index = state.itemDownloads.findIndex(i => i.id == downloadItem.id)
var index = state.itemDownloads.findIndex((i) => i.id == downloadItem.id)
if (index >= 0) {
state.itemDownloads.splice(index, 1, downloadItem)
} else {
@@ -124,7 +133,7 @@ export const mutations = {
}
},
updateDownloadItemPart(state, downloadItemPart) {
const downloadItem = state.itemDownloads.find(i => i.id == downloadItemPart.downloadItemId)
const downloadItem = state.itemDownloads.find((i) => i.id == downloadItemPart.downloadItemId)
if (!downloadItem) {
console.error('updateDownloadItemPart: Download item not found for itemPart', JSON.stringify(downloadItemPart))
return
@@ -132,7 +141,7 @@ export const mutations = {
let totalBytes = 0
let totalBytesDownloaded = 0
downloadItem.downloadItemParts = downloadItem.downloadItemParts.map(dip => {
downloadItem.downloadItemParts = downloadItem.downloadItemParts.map((dip) => {
let newDip = dip.id == downloadItemPart.id ? downloadItemPart : dip
totalBytes += newDip.completed ? Number(newDip.bytesDownloaded) : Number(newDip.fileSize)
@@ -149,7 +158,7 @@ export const mutations = {
}
},
removeItemDownload(state, id) {
state.itemDownloads = state.itemDownloads.filter(i => i.id != id)
state.itemDownloads = state.itemDownloads.filter((i) => i.id != id)
},
setBookshelfListView(state, val) {
state.bookshelfListView = val
@@ -164,7 +173,7 @@ export const mutations = {
if (!prog || !prog.id) {
return
}
var index = state.localMediaProgress.findIndex(lmp => lmp.id == prog.id)
var index = state.localMediaProgress.findIndex((lmp) => lmp.id == prog.id)
if (index >= 0) {
state.localMediaProgress.splice(index, 1, prog)
} else {
@@ -172,10 +181,10 @@ export const mutations = {
}
},
removeLocalMediaProgress(state, id) {
state.localMediaProgress = state.localMediaProgress.filter(lmp => lmp.id != id)
state.localMediaProgress = state.localMediaProgress.filter((lmp) => lmp.id != id)
},
removeLocalMediaProgressForItem(state, llid) {
state.localMediaProgress = state.localMediaProgress.filter(lmp => lmp.localLibraryItemId !== llid)
state.localMediaProgress = state.localMediaProgress.filter((lmp) => lmp.localLibraryItemId !== llid)
},
setLastSearch(state, val) {
state.lastSearch = val
@@ -203,4 +212,4 @@ export const mutations = {
state.rssFeedEntity = entity
state.showRSSFeedOpenCloseModal = true
}
}
}
+7
View File
@@ -29,6 +29,7 @@
"ButtonManageLocalFiles": "Manage Local Files",
"ButtonNewFolder": "New Folder",
"ButtonNextEpisode": "Next Episode",
"ButtonOk": "Ok",
"ButtonOpenFeed": "Open Feed",
"ButtonOverride": "Override",
"ButtonPause": "Pause",
@@ -75,6 +76,7 @@
"HeaderPlaybackSettings": "Playback Settings",
"HeaderPlaylist": "Playlist",
"HeaderPlaylistItems": "Playlist Items",
"HeaderProgressSyncFailed": "Progress Sync Failed",
"HeaderRSSFeed": "RSS Feed",
"HeaderRSSFeedGeneral": "RSS Details",
"HeaderRSSFeedIsOpen": "RSS Feed is Open",
@@ -195,6 +197,8 @@
"LabelNotFinished": "Not Finished",
"LabelNotStarted": "Not Started",
"LabelNumEpisodes": "{0} episodes",
"LabelNumEpisodesIncomplete": "{0} episodes, {1} incomplete",
"LabelNumberOfEpisodes": "# of Episodes",
"LabelOff": "Off",
"LabelOn": "On",
"LabelPassword": "Password",
@@ -308,7 +312,10 @@
"MessageNoSeries": "No series",
"MessageNoUpdatesWereNecessary": "No updates were necessary",
"MessageNoUserPlaylists": "You have no playlists",
"MessageOldServerConnectionWarning": "Server connection config is using an old user ID. Please delete and re-add this server connection.",
"MessageOldServerConnectionWarningHelp": "You originally set up the connection to this server prior to the database migration in 2.3.0, released June 2023. A future server update will remove the ability to sign in with this old connection. Please delete the existing server connection and connect again (using the same server address and credentials). If you have any downloaded media on this device, the media will need to be downloaded again to sync with the server.",
"MessagePodcastSearchField": "Enter search term or RSS feed URL",
"MessageProgressSyncFailed": "The most recent attempt to report your listening progress to the server has failed. Progress sync requests will continue to be attempted every 15 seconds to 1 minute while media is playing.",
"MessageReportBugsAndContribute": "Report bugs, request features, and contribute on",
"MessageSeriesAlreadyDownloaded": "You have already downloaded all books in this series.",
"MessageSeriesDownloadConfirm": "Download missing {0} book(s) with {1} file(s), totaling {2} to folder {3}?",
+19
View File
@@ -37,6 +37,8 @@
"ButtonPlaying": "Toistetaan",
"ButtonPlaylists": "Soittolistat",
"ButtonRead": "Lue",
"ButtonReadLess": "Lue vähemmän",
"ButtonReadMore": "Lue enemmän",
"ButtonRemove": "Poista",
"ButtonRemoveFromServer": "Poista palvelimelta",
"ButtonSave": "Tallenna",
@@ -52,6 +54,7 @@
"ButtonYes": "Kyllä",
"HeaderAccount": "Tili",
"HeaderAdvanced": "Edistynyt",
"HeaderAndroidAutoSettings": "Android Auto -asetukset",
"HeaderAudioTracks": "Ääniraidat",
"HeaderChapters": "Luvut",
"HeaderCollection": "Kokoelma",
@@ -86,6 +89,7 @@
"HeaderYourStats": "Tilastosi",
"LabelAddToPlaylist": "Lisää soittolistaan",
"LabelAddedAt": "Lisätty listalle",
"LabelAddedDate": "Lisätty {0}",
"LabelAll": "Kaikki",
"LabelAllowSeekingOnMediaControls": "Salli kelaaminen ilmoituksen säätimillä",
"LabelAlways": "Aina",
@@ -128,8 +132,10 @@
"LabelEbook": "E-kirja",
"LabelEbooks": "E-kirjat",
"LabelEnable": "Ota käyttöön",
"LabelEnableMp3IndexSeeking": "Ota mp3-hakemistohaku käyttöön",
"LabelEnd": "Loppu",
"LabelEndOfChapter": "Luvun loppu",
"LabelEndTime": "Päättymisaika",
"LabelEpisode": "Jakso",
"LabelFeedURL": "Syötteen URL",
"LabelFile": "Tiedosto",
@@ -138,6 +144,8 @@
"LabelFilename": "Tiedostonimi",
"LabelFinished": "Valmis",
"LabelFolder": "Kansio",
"LabelFontBoldness": "Kirjasintyyppien lihavointi",
"LabelFontScale": "Kirjasintyyppien skaalautuminen",
"LabelGenre": "Lajityyppi",
"LabelGenres": "Lajityypit",
"LabelHapticFeedback": "Tuntopalaute",
@@ -145,14 +153,18 @@
"LabelHost": "Isäntä",
"LabelInProgress": "Kesken",
"LabelIncomplete": "Keskeneräinen",
"LabelInternalAppStorage": "Sovelluksen sisäinen tallennustila",
"LabelJumpBackwardsTime": "Hyppää taaksepäin ajassa",
"LabelJumpForwardsTime": "Hyppää eteenpäin ajassa",
"LabelLanguage": "Kieli",
"LabelLayout": "Asettelu",
"LabelLayoutSinglePage": "Yksi sivu",
"LabelLight": "Vaalea",
"LabelLineSpacing": "Riviväli",
"LabelListenAgain": "Kuuntele uudelleen",
"LabelLocalBooks": "Paikalliset kirjat",
"LabelLocalPodcasts": "Paikalliset podcastit",
"LabelLockOrientation": "Lukitse suunta",
"LabelLockPlayer": "Lukitse soitin",
"LabelLow": "Matala",
"LabelMediaType": "Mediatyyppi",
@@ -163,11 +175,15 @@
"LabelNarrator": "Lukija",
"LabelNarrators": "Lukijat",
"LabelNavigateWithVolume": "Navigoi äänenvoimakkuus-painikkeilla",
"LabelNavigateWithVolumeMirrored": "Peilattu",
"LabelNavigateWithVolumeWhilePlaying": "Salli siirtyminen äänenvoimakkuuspainikkeilla toiston aikana",
"LabelNever": "Ei koskaan",
"LabelNewestAuthors": "Uusimmat kirjailijat",
"LabelNewestEpisodes": "Uusimmat jaksot",
"LabelNo": "Ei",
"LabelNotFinished": "Ei valmis",
"LabelNotStarted": "Ei aloitettu",
"LabelNumEpisodes": "{0} jaksoa",
"LabelOff": "Pois päältä",
"LabelOn": "Päällä",
"LabelPassword": "Salasana",
@@ -176,7 +192,10 @@
"LabelPlaybackSpeed": "Toistonopeus",
"LabelPodcast": "Podcast",
"LabelPodcasts": "Podcastit",
"LabelProgress": "Edistyminen",
"LabelPubDate": "Julkaisupäivä",
"LabelPublishYear": "Julkaisuvuosi",
"LabelPublishedDate": "Julkaistu {0}",
"LabelRSSFeedPreventIndexing": "Estä indeksointi",
"LabelRandomly": "Satunnaisesti",
"LabelRead": "Lue",
+23 -21
View File
@@ -55,7 +55,7 @@
"HeaderAudioTracks": "Ljudspår",
"HeaderChapters": "Kapitel",
"HeaderCollection": "Samling",
"HeaderCollectionItems": "Samlingselement",
"HeaderCollectionItems": "Böcker i samlingen",
"HeaderConnectionStatus": "Anslutnings Status",
"HeaderDataSettings": "Data Inställningar",
"HeaderDetails": "Detaljer",
@@ -63,7 +63,7 @@
"HeaderEbookFiles": "E-boksfiler",
"HeaderEpisodes": "Avsnitt",
"HeaderEreaderSettings": "E-boksinställningar",
"HeaderLatestEpisodes": "Senaste avsnitt",
"HeaderLatestEpisodes": "Senaste avsnitten",
"HeaderLibraries": "Bibliotek",
"HeaderLocalFolders": "Lokala Kataloger",
"HeaderLocalLibraryItems": "Lokala Bibliotek Filer",
@@ -71,16 +71,16 @@
"HeaderOpenRSSFeed": "Öppna RSS-flöde",
"HeaderPlaybackSettings": "Uppspelningsinställningar",
"HeaderPlaylist": "Spellista",
"HeaderPlaylistItems": "Spellistobjekt",
"HeaderPlaylistItems": "Böcker i spellistan",
"HeaderRSSFeed": "RSS flöde",
"HeaderRSSFeedGeneral": "RSS-information",
"HeaderRSSFeedIsOpen": "RSS-flödet är öppet",
"HeaderSelectDownloadLocation": "Välj Nedladdnings Plats",
"HeaderSettings": "Inställningar",
"HeaderSleepTimer": "Sovtidtagare",
"HeaderSleepTimer": "Timer för att sova",
"HeaderSleepTimerSettings": "Sovtimer Inställningar",
"HeaderStatsMinutesListeningChart": "Minuters lyssning (senaste 7 dagar)",
"HeaderStatsRecentSessions": "Senaste sessioner",
"HeaderStatsMinutesListeningChart": "Minuters lyssning (senaste 7 dagarna)",
"HeaderStatsRecentSessions": "Senaste tillfällena",
"HeaderTableOfContents": "Innehållsförteckning",
"HeaderUserInterfaceSettings": "Användargränssnittsinställningar",
"HeaderYourStats": "Dina statistik",
@@ -104,7 +104,7 @@
"LabelChapterTrack": "Kapitel Spår",
"LabelChapters": "Kapitel",
"LabelClosePlayer": "Stäng spelaren",
"LabelCollapseSeries": "Fäll ihop serie",
"LabelCollapseSeries": "Komprimera serier",
"LabelComplete": "Komplett",
"LabelContinueBooks": "Fortsätt Böcker",
"LabelContinueEpisodes": "Fortsätt Episoder",
@@ -126,7 +126,7 @@
"LabelDownloaded": "Nedladdat",
"LabelDuration": "Varaktighet",
"LabelEbook": "E-bok",
"LabelEbooks": "Eböcker",
"LabelEbooks": "E-böcker",
"LabelEnable": "Aktivera",
"LabelEnableMp3IndexSeeking": "Aktivera mp3 index sökning",
"LabelEnableMp3IndexSeekingHelp": "Den här inställningen bör endast aktiveras om du har mp3-filer som inte söker korrekt. Felaktig sökning beror med största sannolikhet på MP3-filer med variabel birate (VBR). Den här inställningen tvingar fram indexsökning, där en tid-till-byte-mappning byggs upp när filen läses. I vissa fall med stora MP3-filer blir det en fördröjning vid sökning mot slutet av filen.",
@@ -136,8 +136,8 @@
"LabelEpisode": "Avsnitt",
"LabelFeedURL": "Flödes-URL",
"LabelFile": "Fil",
"LabelFileBirthtime": "Födelse-tidpunkt för fil",
"LabelFileModified": "Fil ändrad",
"LabelFileBirthtime": "Tidpunkt, filen skapades",
"LabelFileModified": "Tidpunkt, filen ändrades",
"LabelFilename": "Filnamn",
"LabelFinished": "Avslutad",
"LabelFolder": "Mapp",
@@ -146,8 +146,8 @@
"LabelGenre": "Genre",
"LabelGenres": "Genrer",
"LabelHapticFeedback": "Haptisk feedback",
"LabelHasEbook": "Har E-bok",
"LabelHasSupplementaryEbook": "Har komplimenterande E-bok",
"LabelHasEbook": "Har e-bok",
"LabelHasSupplementaryEbook": "Har kompletterande e-bok",
"LabelHeavy": "Tung",
"LabelHigh": "Hög",
"LabelHost": "Värd",
@@ -182,7 +182,7 @@
"LabelNewestEpisodes": "Senast tillagda avsnitt",
"LabelNo": "Nej",
"LabelNotFinished": "Ej avslutad",
"LabelNotStarted": "Inte påbörjad",
"LabelNotStarted": "Ej påbörjad",
"LabelOff": "Av",
"LabelOn": "På",
"LabelPassword": "Lösenord",
@@ -204,7 +204,7 @@
"LabelRandomly": "Slumpartat",
"LabelRead": "Läst",
"LabelReadAgain": "Läs igen",
"LabelRecentSeries": "Senaste serier",
"LabelRecentSeries": "Senaste serierna",
"LabelRecentlyAdded": "Nyligen tillagd",
"LabelRemoveFromPlaylist": "Ta bort från spellista",
"LabelScaleElapsedTimeBySpeed": "Skaländra uppspelningsposition efter uppspelningshastighet.",
@@ -217,17 +217,17 @@
"LabelShakeSensitivity": "Skakkänslighet",
"LabelShowAll": "Visa alla",
"LabelSize": "Storlek",
"LabelSleepTimer": "Sleeptimer",
"LabelSleepTimer": "Timer för sova",
"LabelStart": "Starta",
"LabelStartTime": "Starttid",
"LabelStatsBestDay": "Bästa dag",
"LabelStatsDailyAverage": "Dagligt genomsnitt",
"LabelStatsDays": "Dagar",
"LabelStatsDaysListened": "Dagar lyssnade",
"LabelStatsDaysListened": "dagars lyssnande",
"LabelStatsInARow": "i rad",
"LabelStatsItemsFinished": "Objekt avslutade",
"LabelStatsItemsFinished": "böcker avslutade",
"LabelStatsMinutes": "minuter",
"LabelStatsMinutesListening": "Minuter av lyssnande",
"LabelStatsMinutesListening": "minuters lyssnande",
"LabelStatsWeekListening": "Veckans lyssnande",
"LabelStreamingUsingCellular": "Strömma över mobildata",
"LabelTag": "Tagg",
@@ -247,6 +247,8 @@
"LabelUsername": "Användarnamn",
"LabelVeryHigh": "Väldigt hög",
"LabelVeryLow": "Väldigt låg",
"LabelYearReviewHide": "Dölj årets sammanställning",
"LabelYearReviewShow": "Visa årets sammanställning",
"LabelYourBookmarks": "Dina bokmärken",
"LabelYourProgress": "Din framsteg",
"MessageAndroid10Downloads": "Android 10 och lägre använder intern applagring för nedladdningar.",
@@ -282,7 +284,7 @@
"MessageNoChapters": "Inga kapitel",
"MessageNoItems": "Inga objekt",
"MessageNoItemsFound": "Inga objekt hittades",
"MessageNoListeningSessions": "Inga lyssningssessioner",
"MessageNoListeningSessions": "Inga lyssningstillfällen",
"MessageNoMediaFolders": "Inga Mediamappar",
"MessageNoNetworkConnection": "Ingen nätverksanslutning",
"MessageNoPodcastsFound": "Inga podcasts hittade",
@@ -298,8 +300,8 @@
"ToastBookmarkRemoveFailed": "Det gick inte att ta bort bokmärket",
"ToastBookmarkUpdateFailed": "Det gick inte att uppdatera bokmärket",
"ToastDownloadNotAllowedOnCellular": "Nedladdning tillåts inte över mobildata",
"ToastItemMarkedAsFinishedFailed": "Misslyckades med att markera som färdig",
"ToastItemMarkedAsNotFinishedFailed": "Misslyckades med att markera som ej färdig",
"ToastItemMarkedAsFinishedFailed": "Misslyckades med att markera den som avslutad",
"ToastItemMarkedAsNotFinishedFailed": "Misslyckades med att markera den som ej avslutad",
"ToastPlaylistCreateFailed": "Det gick inte att skapa spellistan",
"ToastPodcastCreateFailed": "Misslyckades med att skapa podcasten",
"ToastPodcastCreateSuccess": "Podcasten skapad framgångsrikt",
+9 -1
View File
@@ -29,6 +29,7 @@
"ButtonManageLocalFiles": "Керування локальними файлами",
"ButtonNewFolder": "Нова тека",
"ButtonNextEpisode": "Наступний епізод",
"ButtonOk": "Добре",
"ButtonOpenFeed": "Відкрити стрічку",
"ButtonOverride": "Перевизначити",
"ButtonPause": "Призупинити",
@@ -75,6 +76,7 @@
"HeaderPlaybackSettings": "Налаштування відтворення",
"HeaderPlaylist": "Список відтворення",
"HeaderPlaylistItems": "Елементи списку відтворення",
"HeaderProgressSyncFailed": "Помилка синхронізації прогресу",
"HeaderRSSFeed": "RSS-канал",
"HeaderRSSFeedGeneral": "Деталі RSS",
"HeaderRSSFeedIsOpen": "RSS-канал відкрито",
@@ -163,6 +165,7 @@
"LabelInternalAppStorage": "Внутрішня пам'ять додатку",
"LabelJumpBackwardsTime": "Час відмотування назад",
"LabelJumpForwardsTime": "Час перемотування вперед",
"LabelKeepScreenAwake": "Тримайте екран активним",
"LabelLanguage": "Мова",
"LabelLayout": "Вигляд",
"LabelLayoutAuto": "Авто",
@@ -194,6 +197,8 @@
"LabelNotFinished": "Незавершені",
"LabelNotStarted": "Непочаті",
"LabelNumEpisodes": "{0} епізодів",
"LabelNumEpisodesIncomplete": "{0} серій, {1} не завершено",
"LabelNumberOfEpisodes": "Кількість серій",
"LabelOff": "Вимкнути",
"LabelOn": "Увімкнено",
"LabelPassword": "Пароль",
@@ -233,7 +238,7 @@
"LabelSize": "Розмір",
"LabelSleepTimer": "Таймер вимкнення",
"LabelStart": "Початок",
"LabelStartTime": "Час початку",
"LabelStartTime": "Час Початку",
"LabelStatsBestDay": "Найкращий день",
"LabelStatsDailyAverage": "В середньому за добу",
"LabelStatsDays": "Днів",
@@ -307,7 +312,10 @@
"MessageNoSeries": "Серії відсутні",
"MessageNoUpdatesWereNecessary": "Оновлень не потрібно",
"MessageNoUserPlaylists": "У вас немає списків відтворення",
"MessageOldServerConnectionWarning": "Конфігурація підключення до сервера використовує старий ідентифікатор користувача. Видаліть і додайте це підключення до сервера заново.",
"MessageOldServerConnectionWarningHelp": "Ви спочатку налаштували з’єднання з цим сервером перед міграцією бази даних у версії 2.3.0, випущеній у червні 2023 року. Майбутнє оновлення сервера скасує можливість входу за допомогою цього старого з’єднання. Будь ласка, видаліть існуюче підключення до сервера та підключіться знову (використовуючи ту саму адресу сервера та облікові дані). Якщо на цьому пристрої є будь-які завантажені медіафайли, їх потрібно буде завантажити ще раз, щоб синхронізувати із сервером.",
"MessagePodcastSearchField": "Введіть пошуковий запит або URL RSS-стрічки",
"MessageProgressSyncFailed": "Остання спроба повідомити про прогрес прослуховування на сервер не вдалася. Під час відтворення мультимедійних файлів кожні 15 секунд – 1 хвилину надсилатимуться запити на синхронізацію.",
"MessageReportBugsAndContribute": "Повідомляйте про помилки, пропонуйте функції та долучайтеся на",
"MessageSeriesAlreadyDownloaded": "Ви вже завантажили всі книги в цій серії.",
"MessageSeriesDownloadConfirm": "Завантажити відсутні {0} книгу(ок) з {1} файл(ів), загалом {2}, до папки {3}?",