mirror of
https://github.com/advplyr/audiobookshelf-app.git
synced 2026-07-25 14:08:35 +02:00
Compare commits
8
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bad8d10a18 | ||
|
|
a4412da3ed | ||
|
|
870774b408 | ||
|
|
d7dcaa22a6 | ||
|
|
cc0b2943dd | ||
|
|
50ee0b2265 | ||
|
|
910b3a2a17 | ||
|
|
916da91ccb |
@@ -29,8 +29,8 @@ android {
|
||||
applicationId "com.audiobookshelf.app"
|
||||
minSdkVersion rootProject.ext.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
versionCode 77
|
||||
versionName "0.9.47-beta"
|
||||
versionCode 80
|
||||
versionName "0.9.49-beta"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
aaptOptions {
|
||||
// Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps.
|
||||
|
||||
@@ -26,4 +26,9 @@ object DeviceManager {
|
||||
fun getBase64Id(id:String):String {
|
||||
return android.util.Base64.encodeToString(id.toByteArray(), android.util.Base64.URL_SAFE or android.util.Base64.NO_WRAP)
|
||||
}
|
||||
|
||||
fun getServerConnectionConfig(id:String?):ServerConnectionConfig? {
|
||||
if (id == null) return null
|
||||
return deviceData.serverConnectionConfigs.find { it.id == id }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,7 +105,7 @@ class FolderScanner(var ctx: Context) {
|
||||
var coverContentUrl:String? = null
|
||||
var coverAbsolutePath:String? = null
|
||||
|
||||
val filesInFolder = itemFolder.search(false, DocumentFileType.FILE, arrayOf("audio/*", "image/*", "video/mp4"))
|
||||
val filesInFolder = itemFolder.search(false, DocumentFileType.FILE, arrayOf("audio/*", "image/*", "video/mp4", "application/octet-stream"))
|
||||
|
||||
val existingLocalFilesRemoved = existingLocalFiles.filter { elf ->
|
||||
filesInFolder.find { fif -> DeviceManager.getBase64Id(fif.id) == elf.id } == null // File was not found in media item folder
|
||||
@@ -248,7 +248,7 @@ class FolderScanner(var ctx: Context) {
|
||||
|
||||
val localLibraryItemId = getLocalLibraryItemId(itemFolderId)
|
||||
Log.d(tag, "scanDownloadItem starting for ${downloadItem.itemFolderPath} | ${df.uri} | Item Folder Id:$itemFolderId | LLI Id:$localLibraryItemId")
|
||||
|
||||
|
||||
// Search for files in media item folder
|
||||
// m4b files showing as mimeType application/octet-stream on Android 10 and earlier see #154
|
||||
val filesFound = df.search(false, DocumentFileType.FILE, arrayOf("audio/*", "image/*", "video/mp4", "application/octet-stream"))
|
||||
@@ -378,7 +378,7 @@ class FolderScanner(var ctx: Context) {
|
||||
var wasUpdated = false
|
||||
|
||||
// Search for files in media item folder
|
||||
val filesFound = df.search(false, DocumentFileType.FILE, arrayOf("audio/*", "image/*", "video/mp4"))
|
||||
val filesFound = df.search(false, DocumentFileType.FILE, arrayOf("audio/*", "image/*", "video/mp4", "application/octet-stream"))
|
||||
Log.d(tag, "scanLocalLibraryItem ${filesFound.size} files found in ${localLibraryItem.absolutePath}")
|
||||
|
||||
filesFound.forEach {
|
||||
|
||||
@@ -8,6 +8,10 @@ import com.audiobookshelf.app.device.DeviceManager
|
||||
import com.audiobookshelf.app.server.ApiHandler
|
||||
import java.util.*
|
||||
import io.paperdb.Paper
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlin.coroutines.resume
|
||||
import kotlin.coroutines.suspendCoroutine
|
||||
|
||||
class MediaManager(var apiHandler: ApiHandler, var ctx: Context) {
|
||||
val tag = "MediaManager"
|
||||
@@ -137,6 +141,48 @@ class MediaManager(var apiHandler: ApiHandler, var ctx: Context) {
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun checkServerConnection(config:ServerConnectionConfig) : Boolean {
|
||||
var successfulPing = false
|
||||
suspendCoroutine<Boolean> { cont ->
|
||||
apiHandler.pingServer(config) {
|
||||
Log.d(tag, "checkServerConnection: Checked server conn for ${config.address} result = $it")
|
||||
successfulPing = it
|
||||
cont.resume(it)
|
||||
}
|
||||
}
|
||||
return successfulPing
|
||||
}
|
||||
|
||||
fun checkSetValidServerConnectionConfig(cb: (Boolean) -> Unit) = runBlocking {
|
||||
if (!apiHandler.isOnline()) cb(false)
|
||||
else {
|
||||
coroutineScope {
|
||||
var hasValidConn = false
|
||||
|
||||
// First check if the current selected config is pingable
|
||||
DeviceManager.serverConnectionConfig?.let {
|
||||
hasValidConn = checkServerConnection(it)
|
||||
Log.d(tag, "checkSetValidServerConnectionConfig: Current config ${DeviceManager.serverAddress} is pingable? $hasValidConn")
|
||||
}
|
||||
|
||||
if (!hasValidConn) {
|
||||
// Loop through available configs and check if can connect
|
||||
for (config: ServerConnectionConfig in DeviceManager.deviceData.serverConnectionConfigs) {
|
||||
val result = checkServerConnection(config)
|
||||
|
||||
if (result) {
|
||||
hasValidConn = true
|
||||
DeviceManager.serverConnectionConfig = config
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cb(hasValidConn)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Load currently listening category for local items
|
||||
fun loadLocalCategory():List<LibraryCategory> {
|
||||
val localBooks = DeviceManager.dbManager.getLocalLibraryItems("book")
|
||||
@@ -158,35 +204,32 @@ class MediaManager(var apiHandler: ApiHandler, var ctx: Context) {
|
||||
val localCategories = loadLocalCategory()
|
||||
cats.addAll(localCategories)
|
||||
|
||||
// Connected to server and has internet - load other cats
|
||||
if (apiHandler.isOnline() && (DeviceManager.isConnectedToServer || DeviceManager.hasLastServerConnectionConfig)) {
|
||||
if (!DeviceManager.isConnectedToServer) {
|
||||
DeviceManager.serverConnectionConfig = DeviceManager.deviceData.getLastServerConnectionConfig()
|
||||
Log.d(tag, "Not connected to server, set last server \"${DeviceManager.serverAddress}\"")
|
||||
}
|
||||
// Check if any valid server connection if not use locally downloaded books
|
||||
checkSetValidServerConnectionConfig { isConnected ->
|
||||
if (isConnected) {
|
||||
serverConfigIdUsed = DeviceManager.serverConnectionConfigId
|
||||
|
||||
serverConfigIdUsed = DeviceManager.serverConnectionConfigId
|
||||
loadLibraries { libraries ->
|
||||
val library = libraries[0]
|
||||
Log.d(tag, "Loading categories for library ${library.name} - ${library.id} - ${library.mediaType}")
|
||||
|
||||
loadLibraries { libraries ->
|
||||
val library = libraries[0]
|
||||
Log.d(tag, "Loading categories for library ${library.name} - ${library.id} - ${library.mediaType}")
|
||||
loadLibraryCategories(library.id) { libraryCategories ->
|
||||
|
||||
loadLibraryCategories(library.id) { libraryCategories ->
|
||||
|
||||
// Only using book or podcast library categories for now
|
||||
libraryCategories.forEach {
|
||||
// Log.d(tag, "Found library category ${it.label} with type ${it.type}")
|
||||
if (it.type == library.mediaType) {
|
||||
// Log.d(tag, "Using library category ${it.id}")
|
||||
cats.add(it)
|
||||
// Only using book or podcast library categories for now
|
||||
libraryCategories.forEach {
|
||||
// Log.d(tag, "Found library category ${it.label} with type ${it.type}")
|
||||
if (it.type == library.mediaType) {
|
||||
// Log.d(tag, "Using library category ${it.id}")
|
||||
cats.add(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cb(cats)
|
||||
cb(cats)
|
||||
}
|
||||
}
|
||||
} else { // Not connected/no internet sent downloaded cats only
|
||||
cb(cats)
|
||||
}
|
||||
} else { // Not connected/no internet sent downloaded cats only
|
||||
cb(cats)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import com.audiobookshelf.app.data.PlayerState
|
||||
import com.google.android.exoplayer2.PlaybackException
|
||||
import com.google.android.exoplayer2.Player
|
||||
|
||||
const val PAUSE_LEN_BEFORE_RECHECK = 60000 // 1 minute
|
||||
const val PAUSE_LEN_BEFORE_RECHECK = 30000 // 30 seconds
|
||||
|
||||
class PlayerListener(var playerNotificationService:PlayerNotificationService) : Player.Listener {
|
||||
var tag = "PlayerListener"
|
||||
@@ -85,7 +85,8 @@ class PlayerListener(var playerNotificationService:PlayerNotificationService) :
|
||||
}
|
||||
|
||||
// Check if playback session still exists or sync media progress if updated
|
||||
if (lastPauseTime > PAUSE_LEN_BEFORE_RECHECK) {
|
||||
val pauseLength: Long = System.currentTimeMillis() - lastPauseTime
|
||||
if (pauseLength > PAUSE_LEN_BEFORE_RECHECK) {
|
||||
val shouldCarryOn = playerNotificationService.checkCurrentSessionProgress()
|
||||
if (!shouldCarryOn) return
|
||||
}
|
||||
|
||||
+11
-2
@@ -509,10 +509,19 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
|
||||
}
|
||||
|
||||
if (playbackSession.isLocal) {
|
||||
|
||||
// Make sure this connection config exists
|
||||
val serverConnectionConfig = DeviceManager.getServerConnectionConfig(playbackSession.serverConnectionConfigId)
|
||||
if (serverConnectionConfig == null) {
|
||||
Log.d(tag, "checkCurrentSessionProgress: Local library item server connection config is not saved ${playbackSession.serverConnectionConfigId}")
|
||||
return true // carry on
|
||||
}
|
||||
|
||||
// Local playback session check if server has updated media progress
|
||||
Log.d(tag, "checkCurrentSessionProgress: Checking if local media progress was updated on server")
|
||||
apiHandler.getMediaProgress(playbackSession.libraryItemId!!, playbackSession.episodeId) { mediaProgress ->
|
||||
if (mediaProgress.lastUpdate > playbackSession.updatedAt && mediaProgress.currentTime != playbackSession.currentTime) {
|
||||
apiHandler.getMediaProgress(playbackSession.libraryItemId!!, playbackSession.episodeId, serverConnectionConfig) { mediaProgress ->
|
||||
|
||||
if (mediaProgress != null && mediaProgress.lastUpdate > playbackSession.updatedAt && mediaProgress.currentTime != playbackSession.currentTime) {
|
||||
Log.d(tag, "checkCurrentSessionProgress: Media progress was updated since last play time updating from ${playbackSession.currentTime} to ${mediaProgress.currentTime}")
|
||||
mediaProgressSyncer.syncFromServerProgress(mediaProgress)
|
||||
|
||||
|
||||
@@ -19,11 +19,13 @@ import okhttp3.MediaType.Companion.toMediaType
|
||||
import okhttp3.RequestBody.Companion.toRequestBody
|
||||
import org.json.JSONObject
|
||||
import java.io.IOException
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
class ApiHandler(var ctx:Context) {
|
||||
val tag = "ApiHandler"
|
||||
|
||||
private var client = OkHttpClient()
|
||||
private var defaultClient = OkHttpClient()
|
||||
private var pingClient = OkHttpClient.Builder().callTimeout(3, TimeUnit.SECONDS).build()
|
||||
var jacksonMapper = jacksonObjectMapper().enable(JsonReadFeature.ALLOW_UNESCAPED_CONTROL_CHARS.mappedFeature())
|
||||
|
||||
var storageSharedPreferences: SharedPreferences? = null
|
||||
@@ -33,11 +35,14 @@ class ApiHandler(var ctx:Context) {
|
||||
data class MediaProgressSyncResponsePayload(val numServerProgressUpdates:Int, val localProgressUpdates:List<LocalMediaProgress>)
|
||||
data class LocalMediaProgressSyncResultsPayload(var numLocalMediaProgressForServer:Int, var numServerProgressUpdates:Int, var numLocalProgressUpdates:Int)
|
||||
|
||||
fun getRequest(endpoint:String, cb: (JSObject) -> Unit) {
|
||||
fun getRequest(endpoint:String, httpClient:OkHttpClient?, config:ServerConnectionConfig?, cb: (JSObject) -> Unit) {
|
||||
val address = config?.address ?: DeviceManager.serverAddress
|
||||
val token = config?.token ?: DeviceManager.token
|
||||
|
||||
val request = Request.Builder()
|
||||
.url("${DeviceManager.serverAddress}$endpoint").addHeader("Authorization", "Bearer ${DeviceManager.token}")
|
||||
.url("${address}$endpoint").addHeader("Authorization", "Bearer $token")
|
||||
.build()
|
||||
makeRequest(request, cb)
|
||||
makeRequest(request, httpClient, cb)
|
||||
}
|
||||
|
||||
fun postRequest(endpoint:String, payload: JSObject, cb: (JSObject) -> Unit) {
|
||||
@@ -46,7 +51,7 @@ class ApiHandler(var ctx:Context) {
|
||||
val request = Request.Builder().post(requestBody)
|
||||
.url("${DeviceManager.serverAddress}$endpoint").addHeader("Authorization", "Bearer ${DeviceManager.token}")
|
||||
.build()
|
||||
makeRequest(request, cb)
|
||||
makeRequest(request, null, cb)
|
||||
}
|
||||
|
||||
fun patchRequest(endpoint:String, payload: JSObject, cb: (JSObject) -> Unit) {
|
||||
@@ -55,7 +60,7 @@ class ApiHandler(var ctx:Context) {
|
||||
val request = Request.Builder().patch(requestBody)
|
||||
.url("${DeviceManager.serverAddress}$endpoint").addHeader("Authorization", "Bearer ${DeviceManager.token}")
|
||||
.build()
|
||||
makeRequest(request, cb)
|
||||
makeRequest(request, null, cb)
|
||||
}
|
||||
|
||||
fun isOnline(): Boolean {
|
||||
@@ -76,18 +81,21 @@ class ApiHandler(var ctx:Context) {
|
||||
return false
|
||||
}
|
||||
|
||||
fun makeRequest(request:Request, cb: (JSObject) -> Unit) {
|
||||
fun makeRequest(request:Request, httpClient:OkHttpClient?, cb: (JSObject) -> Unit) {
|
||||
val client = httpClient ?: defaultClient
|
||||
client.newCall(request).enqueue(object : Callback {
|
||||
override fun onFailure(call: Call, e: IOException) {
|
||||
Log.d(tag, "FAILURE TO CONNECT")
|
||||
e.printStackTrace()
|
||||
cb(JSObject())
|
||||
|
||||
val jsobj = JSObject()
|
||||
jsobj.put("error", "Failed to connect")
|
||||
cb(jsobj)
|
||||
}
|
||||
|
||||
override fun onResponse(call: Call, response: Response) {
|
||||
response.use {
|
||||
if (!it.isSuccessful) {
|
||||
// throw IOException("Unexpected code $response")
|
||||
val jsobj = JSObject()
|
||||
jsobj.put("error", "Unexpected code $response")
|
||||
cb(jsobj)
|
||||
@@ -114,7 +122,7 @@ class ApiHandler(var ctx:Context) {
|
||||
|
||||
fun getLibraries(cb: (List<Library>) -> Unit) {
|
||||
val mapper = jacksonMapper
|
||||
getRequest("/api/libraries") {
|
||||
getRequest("/api/libraries", null,null) {
|
||||
val libraries = mutableListOf<Library>()
|
||||
if (it.has("value")) {
|
||||
val array = it.getJSONArray("value")
|
||||
@@ -128,7 +136,7 @@ class ApiHandler(var ctx:Context) {
|
||||
}
|
||||
|
||||
fun getLibraryItem(libraryItemId:String, cb: (LibraryItem) -> Unit) {
|
||||
getRequest("/api/items/$libraryItemId?expanded=1") {
|
||||
getRequest("/api/items/$libraryItemId?expanded=1", null, null) {
|
||||
val libraryItem = jacksonMapper.readValue<LibraryItem>(it.toString())
|
||||
cb(libraryItem)
|
||||
}
|
||||
@@ -137,14 +145,14 @@ class ApiHandler(var ctx:Context) {
|
||||
fun getLibraryItemWithProgress(libraryItemId:String, episodeId:String?, cb: (LibraryItem) -> Unit) {
|
||||
var requestUrl = "/api/items/$libraryItemId?expanded=1&include=progress"
|
||||
if (!episodeId.isNullOrEmpty()) requestUrl += "&episode=$episodeId"
|
||||
getRequest(requestUrl) {
|
||||
getRequest(requestUrl, null, null) {
|
||||
val libraryItem = jacksonMapper.readValue<LibraryItem>(it.toString())
|
||||
cb(libraryItem)
|
||||
}
|
||||
}
|
||||
|
||||
fun getLibraryItems(libraryId:String, cb: (List<LibraryItem>) -> Unit) {
|
||||
getRequest("/api/libraries/$libraryId/items?limit=100&minified=1") {
|
||||
getRequest("/api/libraries/$libraryId/items?limit=100&minified=1", null, null) {
|
||||
val items = mutableListOf<LibraryItem>()
|
||||
if (it.has("results")) {
|
||||
val array = it.getJSONArray("results")
|
||||
@@ -158,7 +166,7 @@ class ApiHandler(var ctx:Context) {
|
||||
}
|
||||
|
||||
fun getLibraryCategories(libraryId:String, cb: (List<LibraryCategory>) -> Unit) {
|
||||
getRequest("/api/libraries/$libraryId/personalized") {
|
||||
getRequest("/api/libraries/$libraryId/personalized", null, null) {
|
||||
val items = mutableListOf<LibraryCategory>()
|
||||
if (it.has("value")) {
|
||||
val array = it.getJSONArray("value")
|
||||
@@ -263,17 +271,24 @@ class ApiHandler(var ctx:Context) {
|
||||
}
|
||||
}
|
||||
|
||||
fun getMediaProgress(libraryItemId:String, episodeId:String?, cb: (MediaProgress) -> Unit) {
|
||||
fun getMediaProgress(libraryItemId:String, episodeId:String?, serverConnectionConfig:ServerConnectionConfig?, cb: (MediaProgress?) -> Unit) {
|
||||
val endpoint = if(episodeId.isNullOrEmpty()) "/api/me/progress/$libraryItemId" else "/api/me/progress/$libraryItemId/$episodeId"
|
||||
getRequest(endpoint) {
|
||||
val progress = jacksonMapper.readValue<MediaProgress>(it.toString())
|
||||
cb(progress)
|
||||
|
||||
// TODO: Using ping client here allows for shorter timeout (3 seconds), maybe rename or make diff client for requests requiring quicker response
|
||||
getRequest(endpoint, pingClient, serverConnectionConfig) {
|
||||
if (it.has("error")) {
|
||||
Log.e(tag, "getMediaProgress: Failed to get progress")
|
||||
cb(null)
|
||||
} else {
|
||||
val progress = jacksonMapper.readValue<MediaProgress>(it.toString())
|
||||
cb(progress)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getPlaybackSession(playbackSessionId:String, cb: (PlaybackSession?) -> Unit) {
|
||||
val endpoint = "/api/session/$playbackSessionId"
|
||||
getRequest(endpoint) {
|
||||
getRequest(endpoint, null, null) {
|
||||
val err = it.getString("error")
|
||||
if (!err.isNullOrEmpty()) {
|
||||
cb(null)
|
||||
@@ -282,4 +297,18 @@ class ApiHandler(var ctx:Context) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun pingServer(config:ServerConnectionConfig, cb: (Boolean) -> Unit) {
|
||||
Log.d(tag, "pingServer: Pinging ${config.address}")
|
||||
getRequest("/ping", pingClient, config) {
|
||||
val success = it.getString("success")
|
||||
if (success.isNullOrEmpty()) {
|
||||
Log.d(tag, "pingServer: Ping ${config.address} Failed")
|
||||
cb(false)
|
||||
} else {
|
||||
Log.d(tag, "pingServer: Ping ${config.address} Successful")
|
||||
cb(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,11 +122,15 @@ export default {
|
||||
this.show = false
|
||||
},
|
||||
async logout() {
|
||||
await this.$axios.$post('/logout').catch((error) => {
|
||||
console.error(error)
|
||||
})
|
||||
if (this.user) {
|
||||
await this.$axios.$post('/logout').catch((error) => {
|
||||
console.error(error)
|
||||
})
|
||||
}
|
||||
|
||||
this.$socket.logout()
|
||||
await this.$db.logout()
|
||||
this.$localStore.removeLastLibraryId()
|
||||
this.$store.commit('user/logout')
|
||||
this.$router.push('/connect')
|
||||
},
|
||||
|
||||
@@ -382,7 +382,7 @@ export default {
|
||||
this.resetEntities()
|
||||
}
|
||||
},
|
||||
libraryChanged(libid) {
|
||||
libraryChanged() {
|
||||
if (this.hasFilter) {
|
||||
this.clearFilter()
|
||||
} else {
|
||||
|
||||
@@ -51,7 +51,7 @@ export default {
|
||||
async clickedOption(lib) {
|
||||
this.show = false
|
||||
await this.$store.dispatch('libraries/fetch', lib.id)
|
||||
this.$eventBus.$emit('library-changed', lib.id)
|
||||
this.$eventBus.$emit('library-changed')
|
||||
this.$localStore.setLastLibraryId(lib.id)
|
||||
}
|
||||
},
|
||||
|
||||
+6
-6
@@ -9,12 +9,12 @@ install! 'cocoapods', :disable_input_output_paths => true
|
||||
def capacitor_pods
|
||||
pod 'Capacitor', :path => '../../node_modules/@capacitor/ios'
|
||||
pod 'CapacitorCordova', :path => '../../node_modules/@capacitor/ios'
|
||||
pod 'CapacitorApp', :path => '../../node_modules/@capacitor/app'
|
||||
pod 'CapacitorDialog', :path => '../../node_modules/@capacitor/dialog'
|
||||
pod 'CapacitorHaptics', :path => '../../node_modules/@capacitor/haptics'
|
||||
pod 'CapacitorNetwork', :path => '../../node_modules/@capacitor/network'
|
||||
pod 'CapacitorStatusBar', :path => '../../node_modules/@capacitor/status-bar'
|
||||
pod 'CapacitorStorage', :path => '../../node_modules/@capacitor/storage'
|
||||
pod 'CapacitorApp', :path => '..\..\node_modules\@capacitor\app'
|
||||
pod 'CapacitorDialog', :path => '..\..\node_modules\@capacitor\dialog'
|
||||
pod 'CapacitorHaptics', :path => '..\..\node_modules\@capacitor\haptics'
|
||||
pod 'CapacitorNetwork', :path => '..\..\node_modules\@capacitor\network'
|
||||
pod 'CapacitorStatusBar', :path => '..\..\node_modules\@capacitor\status-bar'
|
||||
pod 'CapacitorStorage', :path => '..\..\node_modules\@capacitor\storage'
|
||||
end
|
||||
|
||||
target 'App' do
|
||||
|
||||
+1
-1
@@ -170,8 +170,8 @@ export default {
|
||||
this.inittingLibraries = true
|
||||
await this.$store.dispatch('libraries/load')
|
||||
console.log(`[default] initLibraries loaded ${this.currentLibraryId}`)
|
||||
await this.$store.dispatch('libraries/fetch', this.currentLibraryId)
|
||||
this.$eventBus.$emit('library-changed')
|
||||
this.$store.dispatch('libraries/fetch', this.currentLibraryId)
|
||||
this.inittingLibraries = false
|
||||
},
|
||||
async syncLocalMediaProgress() {
|
||||
|
||||
Generated
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "audiobookshelf-app",
|
||||
"version": "0.9.47-beta",
|
||||
"version": "0.9.49-beta",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "audiobookshelf-app",
|
||||
"version": "0.9.47-beta",
|
||||
"version": "0.9.49-beta",
|
||||
"author": "advplyr",
|
||||
"scripts": {
|
||||
"dev": "nuxt --hostname 0.0.0.0 --port 1337",
|
||||
|
||||
+10
-4
@@ -53,10 +53,16 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
async logout() {
|
||||
await this.$axios.$post('/logout').catch((error) => {
|
||||
console.error(error)
|
||||
})
|
||||
this.$server.logout()
|
||||
if (this.user) {
|
||||
await this.$axios.$post('/logout').catch((error) => {
|
||||
console.error(error)
|
||||
})
|
||||
}
|
||||
|
||||
this.$socket.logout()
|
||||
await this.$db.logout()
|
||||
this.$localStore.removeLastLibraryId()
|
||||
this.$store.commit('user/logout')
|
||||
this.$router.push('/connect')
|
||||
}
|
||||
},
|
||||
|
||||
@@ -4,10 +4,6 @@
|
||||
<home-bookshelf-toolbar v-show="!isHome" />
|
||||
<div id="bookshelf-wrapper" class="main-content overflow-y-auto overflow-x-hidden relative" :class="isHome ? 'home-page' : ''">
|
||||
<nuxt-child />
|
||||
|
||||
<!-- <div v-if="isLoading" class="absolute top-0 left-0 w-full h-full flex items-center justify-center">
|
||||
<ui-loading-indicator />
|
||||
</div>-->
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -135,7 +135,7 @@ export default {
|
||||
}
|
||||
this.loading = false
|
||||
},
|
||||
async libraryChanged(libid) {
|
||||
async libraryChanged() {
|
||||
if (this.currentLibraryId) {
|
||||
await this.fetchCategories()
|
||||
}
|
||||
|
||||
+1
-1
@@ -71,7 +71,7 @@
|
||||
</div>
|
||||
|
||||
<div v-if="isLocal" class="flex mt-4">
|
||||
<ui-btn color="success" :disabled="isPlaying" class="flex items-center justify-center flex-grow mr-2" :padding-x="4" @click="playClick">
|
||||
<ui-btn v-if="showPlay" color="success" :disabled="isPlaying" class="flex items-center justify-center flex-grow mr-2" :padding-x="4" @click="playClick">
|
||||
<span v-show="!isPlaying" class="material-icons">play_arrow</span>
|
||||
<span class="px-1 text-sm">{{ isPlaying ? 'Playing' : 'Play' }}</span>
|
||||
</ui-btn>
|
||||
|
||||
+10
-1
@@ -83,7 +83,16 @@ class LocalStorage {
|
||||
await Storage.set({ key: 'lastLibraryId', value: libraryId })
|
||||
console.log('[LocalStorage] Set Last Library Id', libraryId)
|
||||
} catch (error) {
|
||||
console.error('[LocalStorage] Failed to set current library', error)
|
||||
console.error('[LocalStorage] Failed to set last library id', error)
|
||||
}
|
||||
}
|
||||
|
||||
async removeLastLibraryId() {
|
||||
try {
|
||||
await Storage.remove({ key: 'lastLibraryId' })
|
||||
console.log('[LocalStorage] Remove Last Library Id')
|
||||
} catch (error) {
|
||||
console.error('[LocalStorage] Failed to remove last library id', error)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+4
-1
@@ -22,13 +22,16 @@ export const getters = {
|
||||
if (media.coverPath.startsWith('http:') || media.coverPath.startsWith('https:')) return media.coverPath
|
||||
|
||||
var userToken = rootGetters['user/getToken']
|
||||
var serverAddress = rootGetters['user/getServerAddress']
|
||||
if (!userToken || !serverAddress) return placeholder
|
||||
|
||||
var 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}`
|
||||
}
|
||||
|
||||
var url = new URL(`/api/items/${libraryItem.id}/cover`, rootGetters['user/getServerAddress'])
|
||||
var url = new URL(`/api/items/${libraryItem.id}/cover`, serverAddress)
|
||||
return `${url}?token=${userToken}&ts=${lastUpdate}`
|
||||
},
|
||||
getLocalMediaProgressById: (state) => (localLibraryItemId, episodeId = null) => {
|
||||
|
||||
@@ -90,6 +90,7 @@ export const mutations = {
|
||||
},
|
||||
reset(state) {
|
||||
state.lastLoad = 0
|
||||
state.currentLibraryId = null
|
||||
state.libraries = []
|
||||
},
|
||||
setCurrentLibrary(state, val) {
|
||||
|
||||
Reference in New Issue
Block a user