mirror of
https://github.com/advplyr/audiobookshelf-app.git
synced 2026-07-25 14:08:35 +02:00
Compare commits
9
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
abb41979f4 | ||
|
|
6b59ad5bd3 | ||
|
|
a30fe74da2 | ||
|
|
6157b5923a | ||
|
|
cdcf152049 | ||
|
|
16da0c909f | ||
|
|
1a555eab63 | ||
|
|
4cdcbf79d7 | ||
|
|
c07b527a1d |
@@ -13,8 +13,8 @@ android {
|
||||
applicationId "com.audiobookshelf.app"
|
||||
minSdkVersion rootProject.ext.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
versionCode 57
|
||||
versionName "0.9.37-beta"
|
||||
versionCode 60
|
||||
versionName "0.9.40-beta"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
aaptOptions {
|
||||
// Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps.
|
||||
|
||||
@@ -114,9 +114,36 @@ class AudiobookProgressSyncer constructor(playerNotificationService:PlayerNotifi
|
||||
} else if (listeningStreamId == "download") {
|
||||
// TODO: Save downloaded audiobook progress & send to server if connected
|
||||
Log.d(tag, "ListeningTimer: Is listening download")
|
||||
|
||||
// Send sync data only for local books
|
||||
var syncData: JSObject = JSObject()
|
||||
var duration = playerNotificationService.getAudiobookDuration() / 1000
|
||||
var currentTime = playerNotificationService.getCurrentTime() / 1000
|
||||
syncData.put("totalDuration", duration)
|
||||
syncData.put("currentTime", currentTime)
|
||||
syncData.put("progress", if (duration > 0) (currentTime / duration) else 0)
|
||||
syncData.put("isRead", false)
|
||||
syncData.put("lastUpdate", System.currentTimeMillis())
|
||||
syncData.put("audiobookId", listeningBookId)
|
||||
sendLocalSyncData(syncData) {
|
||||
Log.d(tag, "Local sync done")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun sendLocalSyncData(payload:JSObject, cb: (() -> Unit)) {
|
||||
var serverUrl = playerNotificationService.getServerUrl()
|
||||
var token = playerNotificationService.getUserToken()
|
||||
|
||||
if (serverUrl == "" || token == "") {
|
||||
return
|
||||
}
|
||||
|
||||
Log.d(tag, "Sync Local $serverUrl | $token")
|
||||
var url = "$serverUrl/api/syncLocal"
|
||||
sendServerRequest(url, token, payload, cb)
|
||||
}
|
||||
|
||||
fun sendStreamSyncData(payload:JSObject, cb: (() -> Unit)) {
|
||||
var serverUrl = playerNotificationService.getServerUrl()
|
||||
var token = playerNotificationService.getUserToken()
|
||||
@@ -127,7 +154,10 @@ class AudiobookProgressSyncer constructor(playerNotificationService:PlayerNotifi
|
||||
|
||||
Log.d(tag, "Sync Stream $serverUrl | $token")
|
||||
var url = "$serverUrl/api/syncStream"
|
||||
sendServerRequest(url, token, payload, cb)
|
||||
}
|
||||
|
||||
fun sendServerRequest(url:String, token:String, payload:JSObject, cb: () -> Unit) {
|
||||
val mediaType = "application/json; charset=utf-8".toMediaType()
|
||||
val requestBody = payload.toString().toRequestBody(mediaType)
|
||||
val request = Request.Builder().post(requestBody)
|
||||
|
||||
@@ -45,8 +45,8 @@ class MyNativeAudio : Plugin() {
|
||||
emit("onSleepTimerEnded", currentPosition)
|
||||
}
|
||||
|
||||
override fun onSleepTimerSet(sleepTimerEndTime: Long) {
|
||||
emit("onSleepTimerSet", sleepTimerEndTime)
|
||||
override fun onSleepTimerSet(sleepTimeRemaining: Int) {
|
||||
emit("onSleepTimerSet", sleepTimeRemaining)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
|
||||
fun onMetadata(metadata: JSObject)
|
||||
fun onPrepare(audiobookId: String, playWhenReady: Boolean)
|
||||
fun onSleepTimerEnded(currentPosition: Long)
|
||||
fun onSleepTimerSet(sleepTimerEndTime: Long)
|
||||
fun onSleepTimerSet(sleepTimeRemaining: Int)
|
||||
}
|
||||
|
||||
private val tag = "PlayerService"
|
||||
@@ -648,8 +648,7 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
|
||||
Log.d(tag, "Playing ${getCurrentBookTitle()} | ${currentPlayer.mediaMetadata.title} | ${currentPlayer.mediaMetadata.displayTitle}")
|
||||
if (player.isPlaying) {
|
||||
audiobookProgressSyncer.start()
|
||||
}
|
||||
if (!player.isPlaying && audiobookProgressSyncer.listeningTimerRunning) {
|
||||
} else {
|
||||
audiobookProgressSyncer.stop()
|
||||
}
|
||||
|
||||
@@ -673,19 +672,18 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
|
||||
}
|
||||
|
||||
// Issue with onenote plus crashing when using local cover art. https://github.com/advplyr/audiobookshelf-app/issues/35
|
||||
// Same issue with sony xperia https://github.com/advplyr/audiobookshelf-app/issues/94
|
||||
if (currentAudiobookStreamData?.coverUri != null && currentAudiobookStreamData?.isLocal == true) {
|
||||
try {
|
||||
Log.d(tag, "CHECKING COVER ${currentAudiobookStreamData?.coverUri}")
|
||||
var file = DocumentFile.fromTreeUri(ctx, currentAudiobookStreamData!!.coverUri)
|
||||
Log.d(tag, "GOT FILE ${file?.name} | ${file?.type} | Can Read: ${file?.canRead()} |isExternalStorageDocument: ${file?.isExternalStorageDocument}")
|
||||
if (file?.canRead() !== true) {
|
||||
Log.d(tag, "Invalid cover: no read access")
|
||||
currentAudiobookStreamData?.clearCover()
|
||||
}
|
||||
} catch(e:Exception) {
|
||||
Log.d(tag, "Invalid cover: Failed to read local cover file $e")
|
||||
var deviceName = Build.DEVICE
|
||||
var deviceMan = Build.MANUFACTURER
|
||||
var deviceModel = Build.MODEL
|
||||
Log.d(tag, "Checking device $deviceName | Model $deviceModel | Manufacturer $deviceMan")
|
||||
if (deviceMan.toLowerCase().contains("oneplus") || deviceName.toLowerCase().contains("oneplus")) {
|
||||
Log.d(tag, "Detected OnePlus device - removing local cover")
|
||||
currentAudiobookStreamData?.clearCover()
|
||||
} else if (deviceName.toLowerCase().contains("xperia") || deviceModel.toLowerCase().contains("xperia")) {
|
||||
Log.d(tag, "Detected Sony Xperia device - removing local cover")
|
||||
currentAudiobookStreamData?.clearCover()
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -774,6 +772,12 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
|
||||
return currentAudiobookStreamData?.id
|
||||
}
|
||||
|
||||
// The duration stored on the audiobook
|
||||
fun getAudiobookDuration() : Long {
|
||||
if (currentAudiobookStreamData == null) return 0L
|
||||
return currentAudiobookStreamData!!.duration
|
||||
}
|
||||
|
||||
fun getServerUrl(): String {
|
||||
return audiobookManager.serverUrl
|
||||
}
|
||||
@@ -786,8 +790,8 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
|
||||
if (lastPauseTime <= 0) return 0
|
||||
var time: Long = System.currentTimeMillis() - lastPauseTime
|
||||
var seekback: Long = 0
|
||||
if (time < 3000) seekback = 0
|
||||
else if (time < 60000) seekback = time / 6
|
||||
if (time < 60000) seekback = 0
|
||||
else if (time < 120000) seekback = 10000
|
||||
else if (time < 300000) seekback = 15000
|
||||
else if (time < 1800000) seekback = 20000
|
||||
else if (time < 3600000) seekback = 25000
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.audiobookshelf.app
|
||||
|
||||
import android.hardware.SensorManager
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.util.Log
|
||||
@@ -17,6 +16,8 @@ class SleepTimerManager constructor(playerNotificationService:PlayerNotification
|
||||
private var sleepTimerTask:TimerTask? = null
|
||||
private var sleepTimerRunning:Boolean = false
|
||||
private var sleepTimerEndTime:Long = 0L
|
||||
private var sleepTimerLength:Long = 0L
|
||||
private var sleepTimerElapsed:Long = 0L
|
||||
private var sleepTimerExtensionTime:Long = 0L
|
||||
private var sleepTimerFinishedAt:Long = 0L
|
||||
|
||||
@@ -45,13 +46,12 @@ class SleepTimerManager constructor(playerNotificationService:PlayerNotification
|
||||
}
|
||||
|
||||
private fun getSleepTimerTimeRemainingSeconds():Int {
|
||||
if (sleepTimerEndTime == 0L && sleepTimerLength > 0) { // For regular timer
|
||||
return ((sleepTimerLength - sleepTimerElapsed) / 1000).toDouble().roundToInt()
|
||||
}
|
||||
// For chapter end timer
|
||||
if (sleepTimerEndTime <= 0) return 0
|
||||
var sleepTimeRemaining = sleepTimerEndTime - getCurrentTime()
|
||||
return ((sleepTimeRemaining / 1000).toDouble()).roundToInt()
|
||||
}
|
||||
|
||||
fun getIsSleepTimerRunning():Boolean {
|
||||
return sleepTimerRunning
|
||||
return (((sleepTimerEndTime - getCurrentTime()) / 1000).toDouble()).roundToInt()
|
||||
}
|
||||
|
||||
fun setSleepTimer(time: Long, isChapterTime: Boolean) : Boolean {
|
||||
@@ -59,6 +59,7 @@ class SleepTimerManager constructor(playerNotificationService:PlayerNotification
|
||||
sleepTimerTask?.cancel()
|
||||
sleepTimerRunning = false
|
||||
sleepTimerFinishedAt = 0L
|
||||
sleepTimerElapsed = 0L
|
||||
|
||||
// Register shake sensor
|
||||
playerNotificationService.registerSensor()
|
||||
@@ -70,24 +71,36 @@ class SleepTimerManager constructor(playerNotificationService:PlayerNotification
|
||||
return false
|
||||
}
|
||||
sleepTimerEndTime = time
|
||||
sleepTimerLength = 0
|
||||
sleepTimerExtensionTime = SLEEP_EXTENSION_TIME
|
||||
|
||||
if (sleepTimerEndTime > getDuration()) {
|
||||
sleepTimerEndTime = getDuration()
|
||||
}
|
||||
} else {
|
||||
sleepTimerEndTime = currentTime + time
|
||||
sleepTimerLength = time
|
||||
sleepTimerEndTime = 0L
|
||||
sleepTimerExtensionTime = time
|
||||
|
||||
if (sleepTimerLength + getCurrentTime() > getDuration()) {
|
||||
sleepTimerLength = getDuration() - getCurrentTime()
|
||||
}
|
||||
}
|
||||
|
||||
if (sleepTimerEndTime > getDuration()) {
|
||||
sleepTimerEndTime = getDuration()
|
||||
}
|
||||
|
||||
playerNotificationService.listener?.onSleepTimerSet(sleepTimerEndTime)
|
||||
playerNotificationService.listener?.onSleepTimerSet(getSleepTimerTimeRemainingSeconds())
|
||||
|
||||
sleepTimerRunning = true
|
||||
sleepTimerTask = Timer("SleepTimer", false).schedule(0L, 1000L) {
|
||||
Handler(Looper.getMainLooper()).post() {
|
||||
if (getIsPlaying()) {
|
||||
sleepTimerElapsed += 1000L
|
||||
|
||||
var sleepTimeSecondsRemaining = getSleepTimerTimeRemainingSeconds()
|
||||
Log.d(tag, "Sleep TIMER time remaining $sleepTimeSecondsRemaining s")
|
||||
Log.d(tag, "Timer Elapsed $sleepTimerElapsed | Sleep TIMER time remaining $sleepTimeSecondsRemaining s")
|
||||
|
||||
if (sleepTimeSecondsRemaining > 0) {
|
||||
playerNotificationService.listener?.onSleepTimerSet(sleepTimeSecondsRemaining)
|
||||
}
|
||||
|
||||
if (sleepTimeSecondsRemaining <= 0) {
|
||||
Log.d(tag, "Sleep Timer Pausing Player on Chapter")
|
||||
@@ -129,9 +142,15 @@ class SleepTimerManager constructor(playerNotificationService:PlayerNotification
|
||||
private fun extendSleepTime() {
|
||||
if (!sleepTimerRunning) return
|
||||
setVolume(1F)
|
||||
sleepTimerEndTime += sleepTimerExtensionTime
|
||||
if (sleepTimerEndTime > getDuration()) sleepTimerEndTime = getDuration()
|
||||
playerNotificationService.listener?.onSleepTimerSet(sleepTimerEndTime)
|
||||
if (sleepTimerEndTime == 0L) {
|
||||
sleepTimerLength += sleepTimerExtensionTime
|
||||
if (sleepTimerLength + getCurrentTime() > getDuration()) sleepTimerLength = getDuration() - getCurrentTime()
|
||||
} else {
|
||||
sleepTimerEndTime += sleepTimerExtensionTime
|
||||
if (sleepTimerEndTime > getDuration()) sleepTimerEndTime = getDuration()
|
||||
}
|
||||
|
||||
playerNotificationService.listener?.onSleepTimerSet(getSleepTimerTimeRemainingSeconds())
|
||||
}
|
||||
|
||||
fun checkShouldExtendSleepTimer() {
|
||||
@@ -164,27 +183,42 @@ class SleepTimerManager constructor(playerNotificationService:PlayerNotification
|
||||
fun increaseSleepTime(time: Long) {
|
||||
Log.d(tag, "Increase Sleep time $time")
|
||||
if (!sleepTimerRunning) return
|
||||
var newSleepEndTime = sleepTimerEndTime + time
|
||||
sleepTimerEndTime = if (newSleepEndTime >= getDuration()) {
|
||||
getDuration()
|
||||
|
||||
if (sleepTimerEndTime == 0L) {
|
||||
sleepTimerLength += time
|
||||
if (sleepTimerLength + getCurrentTime() > getDuration()) sleepTimerLength = getDuration() - getCurrentTime()
|
||||
} else {
|
||||
newSleepEndTime
|
||||
var newSleepEndTime = sleepTimerEndTime + time
|
||||
sleepTimerEndTime = if (newSleepEndTime >= getDuration()) {
|
||||
getDuration()
|
||||
} else {
|
||||
newSleepEndTime
|
||||
}
|
||||
}
|
||||
|
||||
setVolume(1F)
|
||||
playerNotificationService.listener?.onSleepTimerSet(sleepTimerEndTime)
|
||||
playerNotificationService.listener?.onSleepTimerSet(getSleepTimerTimeRemainingSeconds())
|
||||
}
|
||||
|
||||
fun decreaseSleepTime(time: Long) {
|
||||
Log.d(tag, "Decrease Sleep time $time")
|
||||
if (!sleepTimerRunning) return
|
||||
var newSleepEndTime = sleepTimerEndTime - time
|
||||
sleepTimerEndTime = if (newSleepEndTime <= 1000) {
|
||||
// End sleep timer in 1 second
|
||||
getCurrentTime() + 1000
|
||||
|
||||
|
||||
if (sleepTimerEndTime == 0L) {
|
||||
sleepTimerLength -= time
|
||||
if (sleepTimerLength <= 0) sleepTimerLength = 1000L
|
||||
} else {
|
||||
newSleepEndTime
|
||||
var newSleepEndTime = sleepTimerEndTime - time
|
||||
sleepTimerEndTime = if (newSleepEndTime <= 1000) {
|
||||
// End sleep timer in 1 second
|
||||
getCurrentTime() + 1000
|
||||
} else {
|
||||
newSleepEndTime
|
||||
}
|
||||
}
|
||||
|
||||
setVolume(1F)
|
||||
playerNotificationService.listener?.onSleepTimerSet(sleepTimerEndTime)
|
||||
playerNotificationService.listener?.onSleepTimerSet(getSleepTimerTimeRemainingSeconds())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,7 +107,7 @@ export default {
|
||||
},
|
||||
loading: Boolean,
|
||||
sleepTimerRunning: Boolean,
|
||||
sleepTimerEndTime: Number
|
||||
sleepTimeRemaining: Number
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@@ -241,10 +241,10 @@ export default {
|
||||
if (!this.currentChapter) return 0
|
||||
return this.currentChapter.end - this.currentTime
|
||||
},
|
||||
sleepTimeRemaining() {
|
||||
if (!this.sleepTimerEndTime) return 0
|
||||
return Math.max(0, this.sleepTimerEndTime / 1000 - this.currentTime)
|
||||
},
|
||||
// sleepTimeRemaining() {
|
||||
// if (!this.sleepTimerEndTime) return 0
|
||||
// return Math.max(0, this.sleepTimerEndTime / 1000 - this.currentTime)
|
||||
// },
|
||||
sleepTimeRemainingPretty() {
|
||||
if (!this.sleepTimeRemaining) return '0s'
|
||||
var secondsRemaining = Math.round(this.sleepTimeRemaining)
|
||||
@@ -516,8 +516,8 @@ export default {
|
||||
calcSeekBackTime(lastUpdate) {
|
||||
var time = Date.now() - lastUpdate
|
||||
var seekback = 0
|
||||
if (time < 3000) seekback = 0
|
||||
else if (time < 60000) seekback = time / 6
|
||||
if (time < 60000) seekback = 0
|
||||
else if (time < 120000) seekback = 10000
|
||||
else if (time < 300000) seekback = 15000
|
||||
else if (time < 1800000) seekback = 20000
|
||||
else if (time < 3600000) seekback = 25000
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
:loading="isLoading"
|
||||
:bookmarks="bookmarks"
|
||||
:sleep-timer-running="isSleepTimerRunning"
|
||||
:sleep-timer-end-time="sleepTimerEndTime"
|
||||
:sleep-time-remaining="sleepTimeRemaining"
|
||||
@close="cancelStream"
|
||||
@sync="sync"
|
||||
@setTotalDuration="setTotalDuration"
|
||||
@@ -49,6 +49,7 @@ export default {
|
||||
currentTime: 0,
|
||||
isSleepTimerRunning: false,
|
||||
sleepTimerEndTime: 0,
|
||||
sleepTimerRemaining: 0,
|
||||
onSleepTimerEndedListener: null,
|
||||
onSleepTimerSetListener: null,
|
||||
sleepInterval: null,
|
||||
@@ -149,11 +150,11 @@ export default {
|
||||
return `${this.$store.state.serverUrl}/s/book/${this.audiobook.id}/${trelpath}?token=${this.userToken}`
|
||||
})
|
||||
return tracks
|
||||
},
|
||||
sleepTimeRemaining() {
|
||||
if (!this.sleepTimerEndTime) return 0
|
||||
return Math.max(0, this.sleepTimerEndTime / 1000 - this.currentTime)
|
||||
}
|
||||
// sleepTimeRemaining() {
|
||||
// if (!this.sleepTimerEndTime) return 0
|
||||
// return Math.max(0, this.sleepTimerEndTime / 1000 - this.currentTime)
|
||||
// }
|
||||
},
|
||||
methods: {
|
||||
showBookmarks() {
|
||||
@@ -175,16 +176,16 @@ export default {
|
||||
this.updateTime(currentTime)
|
||||
}
|
||||
},
|
||||
onSleepTimerSet({ value: sleepTimerEndTime }) {
|
||||
console.log('SLEEP TIMER SET', sleepTimerEndTime)
|
||||
if (sleepTimerEndTime === 0) {
|
||||
onSleepTimerSet({ value: sleepTimeRemaining }) {
|
||||
console.log('SLEEP TIMER SET', sleepTimeRemaining)
|
||||
if (sleepTimeRemaining === 0) {
|
||||
console.log('Sleep timer canceled')
|
||||
this.isSleepTimerRunning = false
|
||||
} else {
|
||||
this.isSleepTimerRunning = true
|
||||
}
|
||||
|
||||
this.sleepTimerEndTime = sleepTimerEndTime
|
||||
this.sleepTimeRemaining = sleepTimeRemaining
|
||||
},
|
||||
showSleepTimer() {
|
||||
if (this.currentChapter) {
|
||||
|
||||
@@ -319,7 +319,6 @@ export default {
|
||||
if (this.isFirstInit) return
|
||||
this.isFirstInit = true
|
||||
this.initSizeData()
|
||||
|
||||
await this.loadPage(0)
|
||||
var lastBookIndex = Math.min(this.totalEntities, this.shelvesPerPage * this.entitiesPerShelf)
|
||||
this.mountEntites(0, lastBookIndex)
|
||||
|
||||
+2
-1
@@ -56,7 +56,8 @@ export default {
|
||||
this.initSocketListeners()
|
||||
|
||||
// Load libraries
|
||||
this.$store.dispatch('libraries/load')
|
||||
await this.$store.dispatch('libraries/load')
|
||||
this.$eventBus.$emit('library-changed')
|
||||
this.$store.dispatch('libraries/fetch', this.currentLibraryId)
|
||||
} else {
|
||||
this.removeSocketListeners()
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "audiobookshelf-app",
|
||||
"version": "0.9.37-beta",
|
||||
"version": "0.9.40-beta",
|
||||
"author": "advplyr",
|
||||
"scripts": {
|
||||
"dev": "nuxt --hostname localhost --port 1337",
|
||||
|
||||
@@ -18,10 +18,7 @@
|
||||
<span class="material-icons text-error text-lg">cloud_off</span>
|
||||
<p class="pl-2 text-error text-sm">Audiobookshelf server not connected.</p>
|
||||
</div>
|
||||
<p class="px-4 text-center text-error absolute bottom-12 left-0 right-0 mx-auto">
|
||||
<strong>Important!</strong> This app requires that you are running
|
||||
<u>your own server</u> and does not provide any content.
|
||||
</p>
|
||||
<p class="px-4 text-center text-error absolute bottom-12 left-0 right-0 mx-auto"><strong>Important!</strong> This app requires that you are running <u>your own server</u> and does not provide any content.</p>
|
||||
</div>
|
||||
<div class="flex justify-center">
|
||||
<ui-btn v-if="!isSocketConnected" small @click="$router.push('/connect')" class="w-32">Connect</ui-btn>
|
||||
@@ -136,7 +133,7 @@ export default {
|
||||
this.shelves = categories
|
||||
},
|
||||
async socketInit(isConnected) {
|
||||
if (isConnected) {
|
||||
if (isConnected && this.currentLibraryId) {
|
||||
console.log('Connected - Load from server')
|
||||
await this.fetchCategories()
|
||||
} else {
|
||||
@@ -146,8 +143,7 @@ export default {
|
||||
this.loading = false
|
||||
},
|
||||
async libraryChanged(libid) {
|
||||
console.log('Library changed', libid)
|
||||
if (this.isSocketConnected) {
|
||||
if (this.isSocketConnected && this.currentLibraryId) {
|
||||
await this.fetchCategories()
|
||||
} else {
|
||||
this.shelves = this.downloadOnlyShelves
|
||||
@@ -246,7 +242,7 @@ export default {
|
||||
},
|
||||
mounted() {
|
||||
this.initListeners()
|
||||
if (this.$server.initialized) {
|
||||
if (this.$server.initialized && this.currentLibraryId) {
|
||||
this.fetchCategories()
|
||||
} else {
|
||||
this.shelves = this.downloadOnlyShelves
|
||||
|
||||
+32
-39
@@ -31,26 +31,22 @@
|
||||
<p>No Downloads</p>
|
||||
</div>
|
||||
<ul v-else class="h-full w-full" role="listbox" aria-labelledby="listbox-label">
|
||||
<template v-for="download in downloadsDownloading">
|
||||
<li :key="download.id" class="text-gray-400 select-none relative px-4 py-5 border-b border-white border-opacity-10 bg-black bg-opacity-10">
|
||||
<div class="flex items-center justify-center">
|
||||
<div class="w-3/4">
|
||||
<span class="text-xs">({{ downloadingProgress[download.id] || 0 }}%) {{ download.isPreparing ? 'Preparing' : 'Downloading' }}...</span>
|
||||
<p class="font-normal truncate text-sm">{{ download.audiobook.book.title }}</p>
|
||||
</div>
|
||||
<div class="flex-grow" />
|
||||
|
||||
<div class="shadow-sm text-white flex items-center justify-center rounded-full animate-spin">
|
||||
<span class="material-icons">refresh</span>
|
||||
</div>
|
||||
<li v-for="download in downloadsDownloading" :key="download.id" class="text-gray-400 select-none relative px-4 py-5 border-b border-white border-opacity-10 bg-black bg-opacity-10">
|
||||
<div class="flex items-center justify-center">
|
||||
<div class="w-3/4">
|
||||
<span class="text-xs">({{ downloadingProgress[download.id] || 0 }}%) {{ download.isPreparing ? 'Preparing' : 'Downloading' }}...</span>
|
||||
<p class="font-normal truncate text-sm">{{ download.audiobook.book.title }}</p>
|
||||
</div>
|
||||
</li>
|
||||
</template>
|
||||
<template v-for="download in downloadsReady">
|
||||
<li :key="download.id" class="text-gray-50 select-none relative pr-4 pl-2 py-5 border-b border-white border-opacity-10" @click="jumpToAudiobook(download)">
|
||||
<modals-downloads-download-item :download="download" @play="playDownload" @delete="clickDeleteDownload" />
|
||||
</li>
|
||||
</template>
|
||||
<div class="flex-grow" />
|
||||
|
||||
<div class="shadow-sm text-white flex items-center justify-center rounded-full animate-spin">
|
||||
<span class="material-icons">refresh</span>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li v-for="download in downloadsReady" :key="download.id" class="text-gray-50 select-none relative pr-4 pl-2 py-5 border-b border-white border-opacity-10" @click="jumpToAudiobook(download)">
|
||||
<modals-downloads-download-item :download="download" @play="playDownload" @delete="clickDeleteDownload" />
|
||||
</li>
|
||||
</ul>
|
||||
</template>
|
||||
<template v-else>
|
||||
@@ -62,29 +58,26 @@
|
||||
</div>
|
||||
<p v-if="isScanning" class="text-center my-8">Scanning Folder..</p>
|
||||
<p v-else-if="!mediaScanResults" class="text-center my-8">No Files Found</p>
|
||||
<template v-else>
|
||||
<template v-for="mediaFolder in mediaScanResults.folders">
|
||||
<div :key="mediaFolder.uri" class="w-full px-2 py-2">
|
||||
<div class="flex items-center">
|
||||
<span class="material-icons text-base text-white text-opacity-50">folder</span>
|
||||
<p class="ml-1 py-0.5">{{ mediaFolder.name }}</p>
|
||||
</div>
|
||||
<div v-for="mediaFile in mediaFolder.files" :key="mediaFile.uri" class="ml-3 flex items-center">
|
||||
<span class="material-icons text-base text-white text-opacity-50">{{ mediaFile.isAudio ? 'music_note' : 'image' }}</span>
|
||||
<p class="ml-1 py-0.5">{{ mediaFile.name }}</p>
|
||||
</div>
|
||||
<div v-else>
|
||||
<div v-for="mediaFolder in mediaScanResults.folders" :key="mediaFolder.uri" class="w-full px-2 py-2">
|
||||
<div class="flex items-center">
|
||||
<span class="material-icons text-base text-white text-opacity-50">folder</span>
|
||||
<p class="ml-1 py-0.5">{{ mediaFolder.name }}</p>
|
||||
</div>
|
||||
</template>
|
||||
<template v-for="mediaFile in mediaScanResults.files">
|
||||
<div :key="mediaFile.uri" class="w-full px-2 py-2">
|
||||
<div class="flex items-center">
|
||||
<span class="material-icons text-base text-white text-opacity-50">{{ mediaFile.isAudio ? 'music_note' : 'image' }}</span>
|
||||
<p class="ml-1 py-0.5">{{ mediaFile.name }}</p>
|
||||
</div>
|
||||
<div v-for="mediaFile in mediaFolder.files" :key="mediaFile.uri" class="ml-3 flex items-center">
|
||||
<span class="material-icons text-base text-white text-opacity-50">{{ mediaFile.isAudio ? 'music_note' : 'image' }}</span>
|
||||
<p class="ml-1 py-0.5">{{ mediaFile.name }}</p>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
</div>
|
||||
<div v-for="mediaFile in mediaScanResults.files" :key="mediaFile.uri" class="w-full px-2 py-2">
|
||||
<div class="flex items-center">
|
||||
<span class="material-icons text-base text-white text-opacity-50">{{ mediaFile.isAudio ? 'music_note' : 'image' }}</span>
|
||||
<p class="ml-1 py-0.5">{{ mediaFile.name }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -23,7 +23,6 @@ class StoreService {
|
||||
init() {
|
||||
this.platform = Capacitor.getPlatform()
|
||||
this.store = CapacitorDataStorageSqlite
|
||||
console.log('in init ', this.platform)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@ export const getters = {
|
||||
console.error('No book item id', bookItem)
|
||||
}
|
||||
if (process.env.NODE_ENV !== 'production') { // Testing
|
||||
return `http://localhost:3333/api/books/${bookItem.id}/cover?token=${userToken}&ts=${bookLastUpdate}`
|
||||
// return `http://localhost:3333/api/books/${bookItem.id}/cover?token=${userToken}&ts=${bookLastUpdate}`
|
||||
}
|
||||
|
||||
var url = new URL(`/api/books/${bookItem.id}/cover`, rootState.serverUrl)
|
||||
|
||||
+9
-3
@@ -2,7 +2,7 @@ export const state = () => ({
|
||||
libraries: [],
|
||||
lastLoad: 0,
|
||||
listeners: [],
|
||||
currentLibraryId: 'main',
|
||||
currentLibraryId: '',
|
||||
showModal: false,
|
||||
folders: [],
|
||||
folderLastUpdate: 0,
|
||||
@@ -65,17 +65,23 @@ export const actions = {
|
||||
return false
|
||||
}
|
||||
|
||||
this.$axios
|
||||
return this.$axios
|
||||
.$get(`/api/libraries`)
|
||||
.then((data) => {
|
||||
// Set current library
|
||||
if (data.length) {
|
||||
commit('setCurrentLibrary', data[0].id)
|
||||
}
|
||||
|
||||
commit('set', data)
|
||||
commit('setLastLoad')
|
||||
return true
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('Failed', error)
|
||||
commit('set', [])
|
||||
return false
|
||||
})
|
||||
return true
|
||||
},
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user