mirror of
https://github.com/advplyr/audiobookshelf-app.git
synced 2025-08-05 02:25:45 +02:00
Enchancements for Android Auto library
- Hide libraries without audiobooks - Sort books in series by sequence value - Added option for selecting ASC or DESC sorting for series - Order authors alphabetically
This commit is contained in:
parent
e4a3cc5290
commit
8134ec84c6
11 changed files with 189 additions and 47 deletions
|
@ -214,7 +214,9 @@ class BookMetadata(
|
|||
var authorName:String?,
|
||||
var authorNameLF:String?,
|
||||
var narratorName:String?,
|
||||
var seriesName:String?
|
||||
var seriesName:String?,
|
||||
@JsonFormat(with=[JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY])
|
||||
var series:List<SeriesType>?
|
||||
) : MediaTypeMetadata(title, explicit) {
|
||||
@JsonIgnore
|
||||
override fun getAuthorDisplayName():String { return authorName ?: "Unknown" }
|
||||
|
@ -342,7 +344,8 @@ data class Library(
|
|||
var name:String,
|
||||
var folders:MutableList<Folder>,
|
||||
var icon:String,
|
||||
var mediaType:String
|
||||
var mediaType:String,
|
||||
var stats: LibraryStats?
|
||||
) {
|
||||
@JsonIgnore
|
||||
fun getMediaMetadata(): MediaMetadataCompat {
|
||||
|
@ -354,6 +357,20 @@ data class Library(
|
|||
}
|
||||
}
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
data class LibraryStats(
|
||||
var totalItems: Int,
|
||||
var totalAuthors: Int,
|
||||
var numAudioTracks: Int
|
||||
)
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
data class SeriesType(
|
||||
var id: String,
|
||||
var name: String,
|
||||
var sequence: String?
|
||||
)
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
data class Folder(
|
||||
var id:String,
|
||||
|
|
|
@ -28,6 +28,10 @@ enum class StreamingUsingCellularSetting {
|
|||
ASK, ALWAYS, NEVER
|
||||
}
|
||||
|
||||
enum class AndroidAutoBrowseSeriesSequenceOrderSetting {
|
||||
ASC, DESC
|
||||
}
|
||||
|
||||
data class ServerConnectionConfig(
|
||||
var id:String,
|
||||
var index:Int,
|
||||
|
@ -136,7 +140,8 @@ data class DeviceSettings(
|
|||
var streamingUsingCellular: StreamingUsingCellularSetting,
|
||||
var androidAutoBrowseForceGrouping: Boolean,
|
||||
var androidAutoBrowseTopLevelLimitForGrouping: Int,
|
||||
var androidAutoBrowseLimitForGrouping: Int
|
||||
var androidAutoBrowseLimitForGrouping: Int,
|
||||
var androidAutoBrowseSeriesSequenceOrder: AndroidAutoBrowseSeriesSequenceOrderSetting
|
||||
) {
|
||||
companion object {
|
||||
// Static method to get default device settings
|
||||
|
@ -165,7 +170,8 @@ data class DeviceSettings(
|
|||
streamingUsingCellular = StreamingUsingCellularSetting.ALWAYS,
|
||||
androidAutoBrowseForceGrouping = false,
|
||||
androidAutoBrowseTopLevelLimitForGrouping = 100,
|
||||
androidAutoBrowseLimitForGrouping = 50
|
||||
androidAutoBrowseLimitForGrouping = 50,
|
||||
androidAutoBrowseSeriesSequenceOrder = AndroidAutoBrowseSeriesSequenceOrderSetting.ASC
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -64,8 +64,27 @@ class LibraryItem(
|
|||
}
|
||||
}
|
||||
|
||||
@get:JsonIgnore
|
||||
val seriesSequence: String
|
||||
get() {
|
||||
if (mediaType != "podcast") {
|
||||
return ((media as Book).metadata as BookMetadata).series?.get(0)?.sequence.orEmpty()
|
||||
} else {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
@get:JsonIgnore
|
||||
val seriesSequenceParts: List<String>
|
||||
get() {
|
||||
if (seriesSequence.isEmpty()) {
|
||||
return listOf("")
|
||||
}
|
||||
return seriesSequence.split(".", limit = 2)
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
fun getMediaDescription(progress:MediaProgressWrapper?, ctx: Context, authorId: String?): MediaDescriptionCompat {
|
||||
fun getMediaDescription(progress:MediaProgressWrapper?, ctx: Context, authorId: String?, showSeriesNumber: Boolean?): MediaDescriptionCompat {
|
||||
val extras = Bundle()
|
||||
|
||||
if (collapsedSeries == null) {
|
||||
|
@ -121,20 +140,29 @@ class LibraryItem(
|
|||
if (collapsedSeries != null) {
|
||||
subtitle = "${collapsedSeries!!.numBooks} books"
|
||||
}
|
||||
var itemTitle = title
|
||||
if (showSeriesNumber == true && seriesSequence != "") {
|
||||
itemTitle = "$seriesSequence. $itemTitle"
|
||||
}
|
||||
return MediaDescriptionCompat.Builder()
|
||||
.setMediaId(mediaId)
|
||||
.setTitle(title)
|
||||
.setTitle(itemTitle)
|
||||
.setIconUri(getCoverUri())
|
||||
.setSubtitle(subtitle)
|
||||
.setExtras(extras)
|
||||
.build()
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
fun getMediaDescription(progress:MediaProgressWrapper?, ctx: Context, authorId: String?): MediaDescriptionCompat {
|
||||
return getMediaDescription(progress, ctx, authorId, null)
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
override fun getMediaDescription(progress:MediaProgressWrapper?, ctx: Context): MediaDescriptionCompat {
|
||||
/*
|
||||
This is needed so Android auto library hierarchy for author series can be implemented
|
||||
*/
|
||||
return getMediaDescription(progress, ctx, null)
|
||||
return getMediaDescription(progress, ctx, null, null)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ data class LocalMediaItem(
|
|||
@JsonIgnore
|
||||
fun getMediaMetadata():MediaTypeMetadata {
|
||||
return if (mediaType == "book") {
|
||||
BookMetadata(name,null, mutableListOf(), mutableListOf(), mutableListOf(),null,null,null,null,null,null,null,false,null,null,null,null)
|
||||
BookMetadata(name,null, mutableListOf(), mutableListOf(), mutableListOf(),null,null,null,null,null,null,null,false,null,null,null, null, null)
|
||||
} else {
|
||||
PodcastMetadata(name,null,null, mutableListOf(), false)
|
||||
}
|
||||
|
|
|
@ -71,6 +71,9 @@ object DeviceManager {
|
|||
if (deviceData.deviceSettings?.androidAutoBrowseLimitForGrouping == null) {
|
||||
deviceData.deviceSettings?.androidAutoBrowseLimitForGrouping = 50
|
||||
}
|
||||
if (deviceData.deviceSettings?.androidAutoBrowseSeriesSequenceOrder == null) {
|
||||
deviceData.deviceSettings?.androidAutoBrowseSeriesSequenceOrder = AndroidAutoBrowseSeriesSequenceOrderSetting.ASC
|
||||
}
|
||||
}
|
||||
|
||||
fun getBase64Id(id:String):String {
|
||||
|
|
|
@ -46,6 +46,10 @@ class MediaManager(private var apiHandler: ApiHandler, var ctx: Context) {
|
|||
return serverLibraries.find { it.id == id } != null
|
||||
}
|
||||
|
||||
fun getLibrary(id:String) : Library? {
|
||||
return serverLibraries.find { it.id == id }
|
||||
}
|
||||
|
||||
fun getSavedPlaybackRate():Float {
|
||||
if (userSettingsPlaybackRate != null) {
|
||||
return userSettingsPlaybackRate ?: 1f
|
||||
|
@ -185,6 +189,14 @@ class MediaManager(private var apiHandler: ApiHandler, var ctx: Context) {
|
|||
cb(seriesWithBooks)
|
||||
}
|
||||
|
||||
fun sortSeriesBooks(seriesBooks: List<LibraryItem>) : List<LibraryItem> {
|
||||
val sortingLogic = compareBy<LibraryItem> { it.seriesSequenceParts[0].length }
|
||||
.thenBy { it.seriesSequenceParts[0].ifEmpty { "" } }
|
||||
.thenBy { it.seriesSequenceParts.getOrElse(1) { "" }.length }
|
||||
.thenBy { it.seriesSequenceParts.getOrElse(1) { "" } }
|
||||
return seriesBooks.sortedWith(sortingLogic)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns books for series from library.
|
||||
* If data is not found from local cache then it will be fetched from server
|
||||
|
@ -202,14 +214,15 @@ class MediaManager(private var apiHandler: ApiHandler, var ctx: Context) {
|
|||
Log.d(tag, "Items for series $seriesId loaded from server | Library $libraryId")
|
||||
val libraryItemsWithAudio = libraryItems.filter { li -> li.checkHasTracks() }
|
||||
|
||||
cachedLibrarySeriesItem[libraryId]!![seriesId] = libraryItemsWithAudio
|
||||
val sortedLibraryItemsWithAudio = sortSeriesBooks(libraryItemsWithAudio)
|
||||
cachedLibrarySeriesItem[libraryId]!![seriesId] = sortedLibraryItemsWithAudio
|
||||
|
||||
libraryItemsWithAudio.forEach { libraryItem ->
|
||||
sortedLibraryItemsWithAudio.forEach { libraryItem ->
|
||||
if (serverLibraryItems.find { li -> li.id == libraryItem.id } == null) {
|
||||
serverLibraryItems.add(libraryItem)
|
||||
}
|
||||
}
|
||||
cb(libraryItemsWithAudio)
|
||||
cb(sortedLibraryItemsWithAudio)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -228,8 +241,8 @@ class MediaManager(private var apiHandler: ApiHandler, var ctx: Context) {
|
|||
apiHandler.getLibraryAuthors(libraryId) { authorItems ->
|
||||
Log.d(tag, "Authors with books loaded from server | Library $libraryId ")
|
||||
// TO-DO: This check won't ensure that there is audiobooks. Current API won't offer ability to do so
|
||||
val authorItemsWithBooks = authorItems.filter { li -> li.bookCount != null && li.bookCount!! > 0 }
|
||||
|
||||
var authorItemsWithBooks = authorItems.filter { li -> li.bookCount != null && li.bookCount!! > 0 }
|
||||
authorItemsWithBooks = authorItemsWithBooks.sortedBy { it.name }
|
||||
// Ensure that there is map for library
|
||||
cachedLibraryAuthors[libraryId] = mutableMapOf()
|
||||
// Cache authors
|
||||
|
@ -314,15 +327,16 @@ class MediaManager(private var apiHandler: ApiHandler, var ctx: Context) {
|
|||
Log.d(tag, "Using author name: $authorName")
|
||||
val libraryItemsFromAuthorWithAudio = libraryItemsWithAudio.filter { li -> li.authorName.indexOf(authorName, ignoreCase = true) >= 0 }
|
||||
|
||||
cachedLibraryAuthorSeriesItems[libraryId]!![authorId] = libraryItemsFromAuthorWithAudio
|
||||
val sortedLibraryItemsWithAudio = sortSeriesBooks(libraryItemsFromAuthorWithAudio)
|
||||
cachedLibraryAuthorSeriesItems[libraryId]!![authorId] = sortedLibraryItemsWithAudio
|
||||
|
||||
libraryItemsFromAuthorWithAudio.forEach { libraryItem ->
|
||||
sortedLibraryItemsWithAudio.forEach { libraryItem ->
|
||||
if (serverLibraryItems.find { li -> li.id == libraryItem.id } == null) {
|
||||
serverLibraryItems.add(libraryItem)
|
||||
}
|
||||
}
|
||||
|
||||
cb(libraryItemsFromAuthorWithAudio)
|
||||
cb(sortedLibraryItemsWithAudio)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -443,9 +457,15 @@ class MediaManager(private var apiHandler: ApiHandler, var ctx: Context) {
|
|||
if (serverLibraries.isNotEmpty()) {
|
||||
cb(serverLibraries)
|
||||
} else {
|
||||
apiHandler.getLibraries {
|
||||
serverLibraries = it
|
||||
cb(it)
|
||||
apiHandler.getLibraries { loadedLibraries ->
|
||||
serverLibraries = loadedLibraries.map { library ->
|
||||
apiHandler.getLibraryStats(library.id) { libraryStats ->
|
||||
Log.d(tag, "Library stats for library ${library.id} | $libraryStats")
|
||||
library.stats = libraryStats
|
||||
}
|
||||
library
|
||||
}
|
||||
cb(serverLibraries)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -56,6 +56,7 @@ class BrowseTree(
|
|||
rootList += librariesMetadata
|
||||
|
||||
libraries.forEach { library ->
|
||||
if (library.stats?.numAudioTracks == 0) return@forEach
|
||||
val libraryMediaMetadata = library.getMediaMetadata()
|
||||
val children = mediaIdToChildren[LIBRARIES_ROOT] ?: mutableListOf()
|
||||
children += libraryMediaMetadata
|
||||
|
|
|
@ -1099,30 +1099,44 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
|
|||
}
|
||||
} else if (mediaManager.getIsLibrary(parentMediaId)) { // Load library items for library
|
||||
Log.d(tag, "Loading items for library $parentMediaId")
|
||||
val children = mutableListOf(
|
||||
MediaBrowserCompat.MediaItem(
|
||||
MediaDescriptionCompat.Builder()
|
||||
.setTitle("Library")
|
||||
.setMediaId("__LIBRARY__${parentMediaId}__AUTHORS")
|
||||
.build(),
|
||||
MediaBrowserCompat.MediaItem.FLAG_BROWSABLE
|
||||
),
|
||||
MediaBrowserCompat.MediaItem(
|
||||
MediaDescriptionCompat.Builder()
|
||||
.setTitle("Series")
|
||||
.setMediaId("__LIBRARY__${parentMediaId}__SERIES_LIST")
|
||||
.build(),
|
||||
MediaBrowserCompat.MediaItem.FLAG_BROWSABLE
|
||||
),
|
||||
MediaBrowserCompat.MediaItem(
|
||||
MediaDescriptionCompat.Builder()
|
||||
.setTitle("Collections")
|
||||
.setMediaId("__LIBRARY__${parentMediaId}__COLLECTIONS")
|
||||
.build(),
|
||||
MediaBrowserCompat.MediaItem.FLAG_BROWSABLE
|
||||
val selectedLibrary = mediaManager.getLibrary(parentMediaId)
|
||||
if (selectedLibrary?.mediaType == "podcast") { // Podcasts are browseable
|
||||
mediaManager.loadLibraryItemsWithAudio(parentMediaId) { libraryItems ->
|
||||
val children = libraryItems.map { libraryItem ->
|
||||
val mediaDescription = libraryItem.getMediaDescription(null, ctx)
|
||||
MediaBrowserCompat.MediaItem(
|
||||
mediaDescription,
|
||||
MediaBrowserCompat.MediaItem.FLAG_BROWSABLE
|
||||
)
|
||||
}
|
||||
result.sendResult(children as MutableList<MediaBrowserCompat.MediaItem>?)
|
||||
}
|
||||
} else {
|
||||
val children = mutableListOf(
|
||||
MediaBrowserCompat.MediaItem(
|
||||
MediaDescriptionCompat.Builder()
|
||||
.setTitle("Library")
|
||||
.setMediaId("__LIBRARY__${parentMediaId}__AUTHORS")
|
||||
.build(),
|
||||
MediaBrowserCompat.MediaItem.FLAG_BROWSABLE
|
||||
),
|
||||
MediaBrowserCompat.MediaItem(
|
||||
MediaDescriptionCompat.Builder()
|
||||
.setTitle("Series")
|
||||
.setMediaId("__LIBRARY__${parentMediaId}__SERIES_LIST")
|
||||
.build(),
|
||||
MediaBrowserCompat.MediaItem.FLAG_BROWSABLE
|
||||
),
|
||||
MediaBrowserCompat.MediaItem(
|
||||
MediaDescriptionCompat.Builder()
|
||||
.setTitle("Collections")
|
||||
.setMediaId("__LIBRARY__${parentMediaId}__COLLECTIONS")
|
||||
.build(),
|
||||
MediaBrowserCompat.MediaItem.FLAG_BROWSABLE
|
||||
)
|
||||
)
|
||||
)
|
||||
result.sendResult(children as MutableList<MediaBrowserCompat.MediaItem>?)
|
||||
result.sendResult(children as MutableList<MediaBrowserCompat.MediaItem>?)
|
||||
}
|
||||
} else if (parentMediaId.startsWith("__LIBRARY__")) {
|
||||
Log.d(tag, "Browsing library $parentMediaId")
|
||||
val mediaIdParts = parentMediaId.split("__")
|
||||
|
@ -1201,12 +1215,16 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
|
|||
mediaIdParts[4]
|
||||
) { libraryItems ->
|
||||
Log.d(tag, "Received ${libraryItems.size} library items")
|
||||
val children = libraryItems.map { libraryItem ->
|
||||
var items = libraryItems
|
||||
if (DeviceManager.deviceData.deviceSettings!!.androidAutoBrowseSeriesSequenceOrder === AndroidAutoBrowseSeriesSequenceOrderSetting.DESC) {
|
||||
items = libraryItems.reversed()
|
||||
}
|
||||
val children = items.map { libraryItem ->
|
||||
val progress =
|
||||
mediaManager.serverUserMediaProgress.find { it.libraryItemId == libraryItem.id }
|
||||
val localLibraryItem = DeviceManager.dbManager.getLocalLibraryItemByLId(libraryItem.id)
|
||||
libraryItem.localLibraryItemId = localLibraryItem?.id
|
||||
val description = libraryItem.getMediaDescription(progress, ctx)
|
||||
val description = libraryItem.getMediaDescription(progress, ctx, null, true)
|
||||
MediaBrowserCompat.MediaItem(description, MediaBrowserCompat.MediaItem.FLAG_PLAYABLE)
|
||||
}
|
||||
result.sendResult(children as MutableList<MediaBrowserCompat.MediaItem>?)
|
||||
|
@ -1279,11 +1297,15 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
|
|||
}
|
||||
} else if (mediaIdParts[3] == "AUTHOR_SERIES") {
|
||||
mediaManager.loadAuthorSeriesBooksWithAudio(mediaIdParts[2], mediaIdParts[4], mediaIdParts[5]) { libraryItems ->
|
||||
val children = libraryItems.map { libraryItem ->
|
||||
var items = libraryItems
|
||||
if (DeviceManager.deviceData.deviceSettings!!.androidAutoBrowseSeriesSequenceOrder === AndroidAutoBrowseSeriesSequenceOrderSetting.DESC) {
|
||||
items = libraryItems.reversed()
|
||||
}
|
||||
val children = items.map { libraryItem ->
|
||||
val progress = mediaManager.serverUserMediaProgress.find { it.libraryItemId == libraryItem.id }
|
||||
val localLibraryItem = DeviceManager.dbManager.getLocalLibraryItemByLId(libraryItem.id)
|
||||
libraryItem.localLibraryItemId = localLibraryItem?.id
|
||||
val description = libraryItem.getMediaDescription(progress, ctx)
|
||||
val description = libraryItem.getMediaDescription(progress, ctx, null, true)
|
||||
if (libraryItem.collapsedSeries != null) {
|
||||
MediaBrowserCompat.MediaItem(description, MediaBrowserCompat.MediaItem.FLAG_BROWSABLE)
|
||||
} else {
|
||||
|
|
|
@ -150,6 +150,18 @@ class ApiHandler(var ctx:Context) {
|
|||
}
|
||||
}
|
||||
|
||||
fun getLibraryStats(libraryItemId:String, cb: (LibraryStats?) -> Unit) {
|
||||
getRequest("/api/libraries/$libraryItemId/stats", null, null) {
|
||||
if (it.has("error")) {
|
||||
Log.e(tag, it.getString("error") ?: "getLibraryStats Failed")
|
||||
cb(null)
|
||||
} else {
|
||||
val libraryStats = jacksonMapper.readValue<LibraryStats>(it.toString())
|
||||
cb(libraryStats)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getLibraryItem(libraryItemId:String, cb: (LibraryItem?) -> Unit) {
|
||||
getRequest("/api/items/$libraryItemId?expanded=1", null, null) {
|
||||
if (it.has("error")) {
|
||||
|
|
|
@ -170,6 +170,12 @@
|
|||
<ui-text-input type="number" v-model="settings.androidAutoBrowseLimitForGrouping" style="width: 145px; max-width: 145px" @input="androidAutoBrowseLimitForGroupingUpdated" />
|
||||
<span class="material-icons-outlined ml-2" @click.stop="showInfo('androidAutoBrowseLimitForGrouping')">info</span>
|
||||
</div>
|
||||
<div class="py-3 flex items-center">
|
||||
<p class="pr-4 w-36">{{ $strings.LabelAndroidAutoBrowseSeriesSequenceOrder }}</p>
|
||||
<div @click.stop="showAndroidAutoBrowseSeriesSequenceOrderOptions">
|
||||
<ui-text-input :value="androidAutoBrowseSeriesSequenceOrderOption" readonly append-icon="expand_more" style="max-width: 200px" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div v-show="loading" class="w-full h-full absolute top-0 left-0 flex items-center justify-center z-10">
|
||||
|
@ -218,7 +224,8 @@ export default {
|
|||
streamingUsingCellular: 'ALWAYS',
|
||||
androidAutoBrowseForceGrouping: false,
|
||||
androidAutoBrowseTopLevelLimitForGrouping: 100,
|
||||
androidAutoBrowseLimitForGrouping: 50
|
||||
androidAutoBrowseLimitForGrouping: 50,
|
||||
androidAutoBrowseSeriesSequenceOrder: 'ASC'
|
||||
},
|
||||
theme: 'dark',
|
||||
lockCurrentOrientation: false,
|
||||
|
@ -323,6 +330,16 @@ export default {
|
|||
text: this.$strings.LabelNever,
|
||||
value: 'NEVER'
|
||||
}
|
||||
],
|
||||
androidAutoBrowseSeriesSequenceOrderItems: [
|
||||
{
|
||||
text: this.$strings.LabelAscending,
|
||||
value: 'ASC'
|
||||
},
|
||||
{
|
||||
text: this.$strings.LabelDescending,
|
||||
value: 'DESC'
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
|
@ -405,6 +422,10 @@ export default {
|
|||
const item = this.streamingUsingCellularItems.find((i) => i.value === this.settings.streamingUsingCellular)
|
||||
return item?.text || 'Error'
|
||||
},
|
||||
androidAutoBrowseSeriesSequenceOrderOption() {
|
||||
const item = this.androidAutoBrowseSeriesSequenceOrderItems.find((i) => i.value === this.settings.androidAutoBrowseSeriesSequenceOrder)
|
||||
return item?.text || 'Error'
|
||||
},
|
||||
moreMenuItems() {
|
||||
if (this.moreMenuSetting === 'shakeSensitivity') return this.shakeSensitivityItems
|
||||
else if (this.moreMenuSetting === 'hapticFeedback') return this.hapticFeedbackItems
|
||||
|
@ -412,6 +433,7 @@ export default {
|
|||
else if (this.moreMenuSetting === 'theme') return this.themeOptionItems
|
||||
else if (this.moreMenuSetting === 'downloadUsingCellular') return this.downloadUsingCellularItems
|
||||
else if (this.moreMenuSetting === 'streamingUsingCellular') return this.streamingUsingCellularItems
|
||||
else if (this.moreMenuSetting === 'androidAutoBrowseSeriesSequenceOrder') return this.androidAutoBrowseSeriesSequenceOrderItems
|
||||
return []
|
||||
}
|
||||
},
|
||||
|
@ -454,6 +476,10 @@ export default {
|
|||
this.moreMenuSetting = 'streamingUsingCellular'
|
||||
this.showMoreMenuDialog = true
|
||||
},
|
||||
showAndroidAutoBrowseSeriesSequenceOrderOptions() {
|
||||
this.moreMenuSetting = 'androidAutoBrowseSeriesSequenceOrder'
|
||||
this.showMoreMenuDialog = true
|
||||
},
|
||||
clickMenuAction(action) {
|
||||
this.showMoreMenuDialog = false
|
||||
if (this.moreMenuSetting === 'shakeSensitivity') {
|
||||
|
@ -474,6 +500,9 @@ export default {
|
|||
} else if (this.moreMenuSetting === 'streamingUsingCellular') {
|
||||
this.settings.streamingUsingCellular = action
|
||||
this.saveSettings()
|
||||
} else if (this.moreMenuSetting === 'androidAutoBrowseSeriesSequenceOrder') {
|
||||
this.settings.androidAutoBrowseSeriesSequenceOrder = action
|
||||
this.saveSettings()
|
||||
}
|
||||
},
|
||||
saveTheme(theme) {
|
||||
|
@ -629,6 +658,7 @@ export default {
|
|||
this.settings.androidAutoBrowseForceGrouping = deviceSettings.androidAutoBrowseForceGrouping
|
||||
this.settings.androidAutoBrowseTopLevelLimitForGrouping = deviceSettings.androidAutoBrowseTopLevelLimitForGrouping
|
||||
this.settings.androidAutoBrowseLimitForGrouping = deviceSettings.androidAutoBrowseLimitForGrouping
|
||||
this.settings.androidAutoBrowseSeriesSequenceOrder = deviceSettings.androidAutoBrowseSeriesSequenceOrder || 'ASC'
|
||||
},
|
||||
async init() {
|
||||
this.loading = true
|
||||
|
|
|
@ -85,6 +85,7 @@
|
|||
"HeaderTableOfContents": "Table of Contents",
|
||||
"HeaderUserInterfaceSettings": "User Interface Settings",
|
||||
"HeaderYourStats": "Your Stats",
|
||||
"LabelAscending": "Ascending",
|
||||
"LabelAddToPlaylist": "Add to Playlist",
|
||||
"LabelAdded": "Added",
|
||||
"LabelAddedAt": "Added At",
|
||||
|
@ -95,6 +96,7 @@
|
|||
"LabelAndroidAutoBrowseForceGroupingHelp": "Forces alphabetical drawdown while browsing library and series in Android Auto",
|
||||
"LabelAndroidAutoBrowseLimitForGrouping": "Alphabetical drawdown stopitems",
|
||||
"LabelAndroidAutoBrowseLimitForGroupingHelp": "Stop alphabetical drawdown when there is less than this amount of items to show",
|
||||
"LabelAndroidAutoBrowseSeriesSequenceOrder": "Series books order",
|
||||
"LabelAndroidAutoBrowseTopLevelLimitForGrouping": "Alphabetical drawdown start items",
|
||||
"LabelAndroidAutoBrowseTopLevelLimitForGroupingHelp": "If top-level has more items than this alphabetical drawdown will be used",
|
||||
"LabelAskConfirmation": "Ask for confirmation",
|
||||
|
@ -120,6 +122,7 @@
|
|||
"LabelContinueReading": "Continue Reading",
|
||||
"LabelContinueSeries": "Continue Series",
|
||||
"LabelCustomTime": "Custom time",
|
||||
"LabelDescending": "Descending",
|
||||
"LabelDescription": "Description",
|
||||
"LabelDisableAudioFadeOut": "Disable audio fade out",
|
||||
"LabelDisableAudioFadeOutHelp": "Audio volume will start decreasing when there is less than 1 minute remaining on the sleep timer. Enable this setting to not fade out.",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue