Compare commits

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