mirror of
https://github.com/advplyr/audiobookshelf-app.git
synced 2026-08-31 15:47:13 +02:00
Change: laying the groundwork for android auto
This commit is contained in:
@@ -39,16 +39,18 @@ repositories {
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation "com.anggrayudi:storage:0.13.0"
|
implementation "com.anggrayudi:storage:0.13.0"
|
||||||
implementation fileTree(include: ['*.jar'], dir: 'libs')
|
implementation fileTree(include: ['*.jar'], dir: 'libs')
|
||||||
implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion"
|
implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion"
|
||||||
implementation project(':capacitor-android')
|
implementation project(':capacitor-android')
|
||||||
|
|
||||||
implementation 'androidx.coordinatorlayout:coordinatorlayout:1.1.0'
|
implementation 'androidx.coordinatorlayout:coordinatorlayout:1.1.0'
|
||||||
|
|
||||||
|
implementation 'com.squareup.okhttp3:okhttp:4.9.2'
|
||||||
|
|
||||||
testImplementation "junit:junit:$junitVersion"
|
testImplementation "junit:junit:$junitVersion"
|
||||||
androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion"
|
androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion"
|
||||||
androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion"
|
androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion"
|
||||||
implementation project(':capacitor-cordova-android-plugins')
|
implementation project(':capacitor-cordova-android-plugins')
|
||||||
|
|
||||||
implementation "androidx.core:core-ktx:1.6.0"
|
implementation "androidx.core:core-ktx:1.6.0"
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||||
|
|||||||
@@ -38,9 +38,9 @@
|
|||||||
android:resource="@drawable/icon" />
|
android:resource="@drawable/icon" />
|
||||||
|
|
||||||
<!-- Android auto rejected the update, removing this so it can be published on the store -->
|
<!-- Android auto rejected the update, removing this so it can be published on the store -->
|
||||||
<!-- <meta-data-->
|
<meta-data
|
||||||
<!-- android:name="com.google.android.gms.car.application"-->
|
android:name="com.google.android.gms.car.application"
|
||||||
<!-- android:resource="@xml/automotive_app_desc"/>-->
|
android:resource="@xml/automotive_app_desc"/>
|
||||||
|
|
||||||
<!-- TODO: Can remove in future -->
|
<!-- TODO: Can remove in future -->
|
||||||
<!-- <provider-->
|
<!-- <provider-->
|
||||||
|
|||||||
@@ -4,66 +4,42 @@ import android.net.Uri
|
|||||||
import com.getcapacitor.JSObject
|
import com.getcapacitor.JSObject
|
||||||
|
|
||||||
class Audiobook {
|
class Audiobook {
|
||||||
var id:String = "audiobook"
|
var id:String
|
||||||
var token:String = ""
|
var ino:String
|
||||||
var playlistUrl:String = ""
|
var libraryId:String
|
||||||
var title:String = "No Title"
|
var folderId:String
|
||||||
var author:String = "Unknown"
|
var book:Book
|
||||||
var series:String = ""
|
var duration:Float
|
||||||
var cover:String = ""
|
var size:Long
|
||||||
var playWhenReady:Boolean = false
|
var numTracks:Int
|
||||||
var startTime:Long = 0
|
var isMissing:Boolean
|
||||||
var playbackSpeed:Float = 1f
|
var isInvalid:Boolean
|
||||||
var duration:Long = 0
|
var path:String
|
||||||
|
|
||||||
var isLocal:Boolean = false
|
var fallbackCover:Uri
|
||||||
var contentUrl:String = ""
|
var fallbackUri:Uri
|
||||||
|
|
||||||
var hasPlayerLoaded:Boolean = false
|
constructor(jsobj: JSObject) {
|
||||||
|
id = jsobj.getString("id", "").toString()
|
||||||
|
ino = jsobj.getString("ino", "").toString()
|
||||||
|
libraryId = jsobj.getString("libraryId", "").toString()
|
||||||
|
folderId = jsobj.getString("folderId", "").toString()
|
||||||
|
|
||||||
var playlistUri:Uri = Uri.EMPTY
|
var bookJsObj = jsobj.getJSObject("book")
|
||||||
var coverUri:Uri = Uri.EMPTY
|
book = bookJsObj?.let { Book(it) }!!
|
||||||
var contentUri:Uri = Uri.EMPTY // For Local only
|
|
||||||
|
|
||||||
constructor(jsondata:JSObject) {
|
duration = jsobj.getDouble("duration").toFloat()
|
||||||
id = jsondata.getString("id", "audiobook").toString()
|
size = jsobj.getLong("size")
|
||||||
title = jsondata.getString("title", "No Title").toString()
|
numTracks = jsobj.getInteger("numTracks")!!
|
||||||
token = jsondata.getString("token", "").toString()
|
isMissing = jsobj.getBoolean("isMissing")
|
||||||
author = jsondata.getString("author", "Unknown").toString()
|
isInvalid = jsobj.getBoolean("isInvalid")
|
||||||
series = jsondata.getString("series", "").toString()
|
path = jsobj.getString("path", "").toString()
|
||||||
cover = jsondata.getString("cover", "").toString()
|
|
||||||
playlistUrl = jsondata.getString("playlistUrl", "").toString()
|
|
||||||
playWhenReady = jsondata.getBoolean("playWhenReady", false) == true
|
|
||||||
|
|
||||||
if (jsondata.has("startTime")) {
|
fallbackUri = Uri.parse("http://fallback.com/run.mp3")
|
||||||
startTime = jsondata.getString("startTime", "0")!!.toLong()
|
fallbackCover = Uri.parse("android.resource://com.audiobookshelf.app/" + R.drawable.icon)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (jsondata.has("duration")) {
|
fun getCover(serverUrl:String, token:String):Uri {
|
||||||
duration = jsondata.getString("duration", "0")!!.toLong()
|
return Uri.parse("$serverUrl/${book.cover}?token=$token")
|
||||||
}
|
|
||||||
|
|
||||||
if (jsondata.has("playbackSpeed")) {
|
|
||||||
playbackSpeed = jsondata.getDouble("playbackSpeed")!!.toFloat()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Local data
|
|
||||||
isLocal = jsondata.getBoolean("isLocal", false) == true
|
|
||||||
contentUrl = jsondata.getString("contentUrl", "").toString()
|
|
||||||
|
|
||||||
if (playlistUrl != "") {
|
|
||||||
playlistUri = Uri.parse(playlistUrl)
|
|
||||||
}
|
|
||||||
if (cover != "") {
|
|
||||||
coverUri = Uri.parse(cover)
|
|
||||||
} else {
|
|
||||||
coverUri = Uri.parse("android.resource://com.audiobookshelf.app/" + R.drawable.icon)
|
|
||||||
cover = coverUri.toString()
|
|
||||||
}
|
|
||||||
|
|
||||||
if (contentUrl != "") {
|
|
||||||
contentUri = Uri.parse(contentUrl)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,105 @@
|
|||||||
|
package com.audiobookshelf.app
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import android.content.Context
|
||||||
|
import android.os.Handler
|
||||||
|
import android.os.Looper
|
||||||
|
import android.support.v4.media.MediaBrowserCompat
|
||||||
|
import android.support.v4.media.MediaDescriptionCompat
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
|
import androidx.media.MediaBrowserServiceCompat
|
||||||
|
import com.getcapacitor.JSArray
|
||||||
|
import com.getcapacitor.JSObject
|
||||||
|
import com.jeep.plugin.capacitor.capacitordatastoragesqlite.CapacitorDataStorageSqlite
|
||||||
|
import okhttp3.*
|
||||||
|
import java.io.IOException
|
||||||
|
import java.net.URL
|
||||||
|
|
||||||
|
class AudiobookManager {
|
||||||
|
var tag = "AudiobookManager"
|
||||||
|
|
||||||
|
var hasLoaded = false
|
||||||
|
var ctx: Context
|
||||||
|
var serverUrl = ""
|
||||||
|
var token = ""
|
||||||
|
private var client:OkHttpClient
|
||||||
|
|
||||||
|
var audiobooks:MutableList<Audiobook> = mutableListOf()
|
||||||
|
|
||||||
|
constructor(_ctx:Context, _client:OkHttpClient) {
|
||||||
|
ctx = _ctx
|
||||||
|
client = _client
|
||||||
|
}
|
||||||
|
|
||||||
|
fun init() {
|
||||||
|
var sharedPreferences = ctx.getSharedPreferences("CapacitorStorage", Activity.MODE_PRIVATE)
|
||||||
|
serverUrl = sharedPreferences.getString("serverUrl", null).toString()
|
||||||
|
Log.d(tag, "SHARED PREF SERVERURL $serverUrl")
|
||||||
|
token = sharedPreferences.getString("token", null).toString()
|
||||||
|
Log.d(tag, "SHARED PREF TOKEN $token")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun fetchAudiobooks(result: MediaBrowserServiceCompat.Result<MutableList<MediaBrowserCompat.MediaItem>>) {
|
||||||
|
var url = "$serverUrl/api/library/main/audiobooks"
|
||||||
|
Log.d(tag, "RUNNING SAMPLER $url")
|
||||||
|
val request = Request.Builder()
|
||||||
|
.url(url).addHeader("Authorization", "Bearer $token")
|
||||||
|
.build()
|
||||||
|
|
||||||
|
client.newCall(request).enqueue(object : Callback {
|
||||||
|
override fun onFailure(call: Call, e: IOException) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResponse(call: Call, response: Response) {
|
||||||
|
response.use {
|
||||||
|
if (!response.isSuccessful) throw IOException("Unexpected code $response")
|
||||||
|
// for ((name, value) in response.headers) {
|
||||||
|
// Log.d(tag, "HEADER $name: $value")
|
||||||
|
// }
|
||||||
|
|
||||||
|
var bodyString = response.body!!.string()
|
||||||
|
var json = JSArray(bodyString)
|
||||||
|
var totalBooks = json.length() - 1
|
||||||
|
for (i in 0..totalBooks) {
|
||||||
|
var abobj = json.get(i)
|
||||||
|
var jsobj = JSObject(abobj.toString())
|
||||||
|
var audiobook = Audiobook(jsobj)
|
||||||
|
audiobooks.add(audiobook)
|
||||||
|
Log.d(tag, "Audiobook: ${audiobook.toString()}")
|
||||||
|
}
|
||||||
|
Log.d(tag, "Audiobooks Loaded")
|
||||||
|
|
||||||
|
val mediaItems: MutableList<MediaBrowserCompat.MediaItem> = mutableListOf()
|
||||||
|
audiobooks.forEach {
|
||||||
|
var builder = MediaDescriptionCompat.Builder()
|
||||||
|
.setMediaId(it.id)
|
||||||
|
.setTitle(it.book.title)
|
||||||
|
.setSubtitle(it.book.authorFL)
|
||||||
|
.setMediaUri(it.fallbackUri)
|
||||||
|
.setIconUri(it.fallbackCover)
|
||||||
|
|
||||||
|
var mediaDescription = builder.build()
|
||||||
|
var newMediaItem = MediaBrowserCompat.MediaItem(mediaDescription, MediaBrowserCompat.MediaItem.FLAG_PLAYABLE)
|
||||||
|
mediaItems.add(newMediaItem)
|
||||||
|
|
||||||
|
}
|
||||||
|
Log.d(tag, "AudiobookManager: Sending ${mediaItems.size} Aduiobooks")
|
||||||
|
result.sendResult(mediaItems)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fun load() {
|
||||||
|
hasLoaded = true
|
||||||
|
|
||||||
|
var db = CapacitorDataStorageSqlite(ctx)
|
||||||
|
db.openStore("storage", "downloads", false, "no-encryption", 1)
|
||||||
|
Log.d(tag, "CHECK IF DB IS OPEN ${db.isStoreOpen("storage")}")
|
||||||
|
var keyvalues = db.keysvalues()
|
||||||
|
Log.d(tag, "KEY VALUES $keyvalues")
|
||||||
|
keyvalues.forEach { Log.d(tag, "keyvalue ${it.getString("key")} | ${it.getString("value")}") }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
package com.audiobookshelf.app
|
||||||
|
|
||||||
|
import android.net.Uri
|
||||||
|
import com.getcapacitor.JSObject
|
||||||
|
|
||||||
|
class AudiobookStreamData {
|
||||||
|
var id:String = "audiobook"
|
||||||
|
var token:String = ""
|
||||||
|
var playlistUrl:String = ""
|
||||||
|
var title:String = "No Title"
|
||||||
|
var author:String = "Unknown"
|
||||||
|
var series:String = ""
|
||||||
|
var cover:String = ""
|
||||||
|
var playWhenReady:Boolean = false
|
||||||
|
var startTime:Long = 0
|
||||||
|
var playbackSpeed:Float = 1f
|
||||||
|
var duration:Long = 0
|
||||||
|
|
||||||
|
var isLocal:Boolean = false
|
||||||
|
var contentUrl:String = ""
|
||||||
|
|
||||||
|
var hasPlayerLoaded:Boolean = false
|
||||||
|
|
||||||
|
var playlistUri:Uri = Uri.EMPTY
|
||||||
|
var coverUri:Uri = Uri.EMPTY
|
||||||
|
var contentUri:Uri = Uri.EMPTY // For Local only
|
||||||
|
|
||||||
|
constructor(jsondata:JSObject) {
|
||||||
|
id = jsondata.getString("id", "audiobook").toString()
|
||||||
|
title = jsondata.getString("title", "No Title").toString()
|
||||||
|
token = jsondata.getString("token", "").toString()
|
||||||
|
author = jsondata.getString("author", "Unknown").toString()
|
||||||
|
series = jsondata.getString("series", "").toString()
|
||||||
|
cover = jsondata.getString("cover", "").toString()
|
||||||
|
playlistUrl = jsondata.getString("playlistUrl", "").toString()
|
||||||
|
playWhenReady = jsondata.getBoolean("playWhenReady", false) == true
|
||||||
|
|
||||||
|
if (jsondata.has("startTime")) {
|
||||||
|
startTime = jsondata.getString("startTime", "0")!!.toLong()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (jsondata.has("duration")) {
|
||||||
|
duration = jsondata.getString("duration", "0")!!.toLong()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (jsondata.has("playbackSpeed")) {
|
||||||
|
playbackSpeed = jsondata.getDouble("playbackSpeed")!!.toFloat()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Local data
|
||||||
|
isLocal = jsondata.getBoolean("isLocal", false) == true
|
||||||
|
contentUrl = jsondata.getString("contentUrl", "").toString()
|
||||||
|
|
||||||
|
if (playlistUrl != "") {
|
||||||
|
playlistUri = Uri.parse(playlistUrl)
|
||||||
|
}
|
||||||
|
if (cover != "") {
|
||||||
|
coverUri = Uri.parse(cover)
|
||||||
|
} else {
|
||||||
|
coverUri = Uri.parse("android.resource://com.audiobookshelf.app/" + R.drawable.icon)
|
||||||
|
cover = coverUri.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (contentUrl != "") {
|
||||||
|
contentUri = Uri.parse(contentUrl)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package com.audiobookshelf.app
|
||||||
|
|
||||||
|
import com.getcapacitor.JSObject
|
||||||
|
|
||||||
|
class Book {
|
||||||
|
var title:String
|
||||||
|
var subtitle:String
|
||||||
|
var author:String
|
||||||
|
var authorFL:String
|
||||||
|
var narrator:String
|
||||||
|
var series:String
|
||||||
|
var volumeNumber:String
|
||||||
|
var publisher:String
|
||||||
|
var description:String
|
||||||
|
var publishYear:String
|
||||||
|
var language:String
|
||||||
|
var cover:String
|
||||||
|
var coverFullPath:String
|
||||||
|
var genres:String
|
||||||
|
var lastUpdate:Long
|
||||||
|
|
||||||
|
constructor(jsobj: JSObject) {
|
||||||
|
title = jsobj.getString("title", "").toString()
|
||||||
|
subtitle = jsobj.getString("subtitle", "").toString()
|
||||||
|
author = jsobj.getString("author", "").toString()
|
||||||
|
authorFL = jsobj.getString("authorFL", "").toString()
|
||||||
|
narrator = jsobj.getString("narrator", "").toString()
|
||||||
|
series = jsobj.getString("series", "").toString()
|
||||||
|
volumeNumber = jsobj.getString("volumeNumber", "").toString()
|
||||||
|
publisher = jsobj.getString("publisher", "").toString()
|
||||||
|
description = jsobj.getString("description", "").toString()
|
||||||
|
publishYear = jsobj.getString("publishYear", "").toString()
|
||||||
|
language = jsobj.getString("language", "").toString()
|
||||||
|
cover = jsobj.getString("cover", "").toString()
|
||||||
|
coverFullPath = jsobj.getString("coverFullPath", "").toString()
|
||||||
|
genres = jsobj.getString("genres", "").toString()
|
||||||
|
lastUpdate = jsobj.getLong("lastUpdate")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.audiobookshelf.app
|
package com.audiobookshelf.app
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
import android.app.DownloadManager
|
import android.app.DownloadManager
|
||||||
import android.content.*
|
import android.content.*
|
||||||
import android.os.*
|
import android.os.*
|
||||||
@@ -7,6 +8,11 @@ import android.util.Log
|
|||||||
import com.anggrayudi.storage.SimpleStorage
|
import com.anggrayudi.storage.SimpleStorage
|
||||||
import com.anggrayudi.storage.SimpleStorageHelper
|
import com.anggrayudi.storage.SimpleStorageHelper
|
||||||
import com.getcapacitor.BridgeActivity
|
import com.getcapacitor.BridgeActivity
|
||||||
|
import com.getcapacitor.JSObject
|
||||||
|
import com.jeep.plugin.capacitor.capacitordatastoragesqlite.CapacitorDataStorageSqlite
|
||||||
|
import okhttp3.OkHttpClient
|
||||||
|
import okhttp3.Request
|
||||||
|
import java.net.URL
|
||||||
|
|
||||||
|
|
||||||
class MainActivity : BridgeActivity() {
|
class MainActivity : BridgeActivity() {
|
||||||
@@ -40,6 +46,13 @@ class MainActivity : BridgeActivity() {
|
|||||||
public override fun onCreate(savedInstanceState: Bundle?) {
|
public override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
|
// REMOVE FOR TESTING
|
||||||
|
Log.d(tag, "STARTING UP APP")
|
||||||
|
// var client: OkHttpClient = OkHttpClient()
|
||||||
|
// var abManager = AudiobookManager(this, client)
|
||||||
|
// abManager.init()
|
||||||
|
// abManager.fetchAudiobooks()
|
||||||
|
|
||||||
Log.d(tag, "onCreate")
|
Log.d(tag, "onCreate")
|
||||||
registerPlugin(MyNativeAudio::class.java)
|
registerPlugin(MyNativeAudio::class.java)
|
||||||
registerPlugin(AudioDownloader::class.java)
|
registerPlugin(AudioDownloader::class.java)
|
||||||
|
|||||||
@@ -8,8 +8,6 @@ import androidx.core.content.ContextCompat
|
|||||||
import com.getcapacitor.*
|
import com.getcapacitor.*
|
||||||
import com.getcapacitor.annotation.CapacitorPlugin
|
import com.getcapacitor.annotation.CapacitorPlugin
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
import java.util.*
|
|
||||||
import kotlin.concurrent.schedule
|
|
||||||
|
|
||||||
@CapacitorPlugin(name = "MyNativeAudio")
|
@CapacitorPlugin(name = "MyNativeAudio")
|
||||||
class MyNativeAudio : Plugin() {
|
class MyNativeAudio : Plugin() {
|
||||||
@@ -64,8 +62,8 @@ class MyNativeAudio : Plugin() {
|
|||||||
}
|
}
|
||||||
var jsobj = JSObject()
|
var jsobj = JSObject()
|
||||||
|
|
||||||
var audiobook:Audiobook = Audiobook(call.data)
|
var audiobookStreamData:AudiobookStreamData = AudiobookStreamData(call.data)
|
||||||
if (audiobook.playlistUrl == "" && audiobook.contentUrl == "") {
|
if (audiobookStreamData.playlistUrl == "" && audiobookStreamData.contentUrl == "") {
|
||||||
Log.e(tag, "Invalid URL for init audio player")
|
Log.e(tag, "Invalid URL for init audio player")
|
||||||
|
|
||||||
jsobj.put("success", false)
|
jsobj.put("success", false)
|
||||||
@@ -73,7 +71,7 @@ class MyNativeAudio : Plugin() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Handler(Looper.getMainLooper()).post() {
|
Handler(Looper.getMainLooper()).post() {
|
||||||
playerNotificationService.initPlayer(audiobook)
|
playerNotificationService.initPlayer(audiobookStreamData)
|
||||||
jsobj.put("success", true)
|
jsobj.put("success", true)
|
||||||
call.resolve(jsobj)
|
call.resolve(jsobj)
|
||||||
}
|
}
|
||||||
@@ -174,38 +172,38 @@ class MyNativeAudio : Plugin() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@PluginMethod
|
// @PluginMethod
|
||||||
fun setAudiobooks(call: PluginCall) {
|
// fun setAudiobooks(call: PluginCall) {
|
||||||
var audiobooks = call.getArray("audiobooks", JSArray())
|
// var audiobooks = call.getArray("audiobooks", JSArray())
|
||||||
if (audiobooks == null) {
|
// if (audiobooks == null) {
|
||||||
Log.w(tag, "setAudiobooks IS NULL")
|
// Log.w(tag, "setAudiobooks IS NULL")
|
||||||
call.resolve()
|
// call.resolve()
|
||||||
return
|
// return
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
var audiobookObjs = mutableListOf<Audiobook>()
|
// var audiobookObjs = mutableListOf<AudiobookStreamData>()
|
||||||
|
//
|
||||||
var len = audiobooks.length()
|
// var len = audiobooks.length()
|
||||||
(0 until len).forEach { _it ->
|
// (0 until len).forEach { _it ->
|
||||||
var jsonobj = audiobooks.get(_it) as JSONObject
|
// var jsonobj = audiobooks.get(_it) as JSONObject
|
||||||
|
//
|
||||||
var _names = Array(jsonobj.names().length()) {
|
// var _names = Array(jsonobj.names().length()) {
|
||||||
jsonobj.names().getString(it)
|
// jsonobj.names().getString(it)
|
||||||
}
|
// }
|
||||||
var jsobj = JSObject(jsonobj, _names)
|
// var jsobj = JSObject(jsonobj, _names)
|
||||||
|
//
|
||||||
if (jsobj.has("duration")) {
|
// if (jsobj.has("duration")) {
|
||||||
var dur = jsobj.getDouble("duration")
|
// var dur = jsobj.getDouble("duration")
|
||||||
var duration = Math.floor(dur * 1000L).toLong()
|
// var duration = Math.floor(dur * 1000L).toLong()
|
||||||
jsobj.put("duration", duration)
|
// jsobj.put("duration", duration)
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
var audiobook = Audiobook(jsobj)
|
// var audiobook = AudiobookStreamData(jsobj)
|
||||||
audiobookObjs.add(audiobook)
|
// audiobookObjs.add(audiobook)
|
||||||
}
|
// }
|
||||||
Log.d(tag, "Setting Audiobooks ${audiobookObjs.size}")
|
// Log.d(tag, "Setting Audiobooks ${audiobookObjs.size}")
|
||||||
playerNotificationService.setAudiobooks(audiobookObjs)
|
// playerNotificationService.setAudiobooks(audiobookObjs)
|
||||||
}
|
// }
|
||||||
|
|
||||||
@PluginMethod
|
@PluginMethod
|
||||||
fun setSleepTimer(call: PluginCall) {
|
fun setSleepTimer(call: PluginCall) {
|
||||||
|
|||||||
@@ -33,10 +33,10 @@ import com.google.android.exoplayer2.ui.PlayerNotificationManager
|
|||||||
import com.google.android.exoplayer2.upstream.*
|
import com.google.android.exoplayer2.upstream.*
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
import android.view.KeyEvent
|
import android.view.KeyEvent
|
||||||
import java.io.File
|
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.concurrent.schedule
|
import kotlin.concurrent.schedule
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
|
import okhttp3.OkHttpClient
|
||||||
|
|
||||||
|
|
||||||
const val NOTIFICATION_LARGE_ICON_SIZE = 144 // px
|
const val NOTIFICATION_LARGE_ICON_SIZE = 144 // px
|
||||||
@@ -74,9 +74,9 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
|
|||||||
private var channelId = "audiobookshelf_channel"
|
private var channelId = "audiobookshelf_channel"
|
||||||
private var channelName = "Audiobookshelf Channel"
|
private var channelName = "Audiobookshelf Channel"
|
||||||
|
|
||||||
private var currentAudiobook:Audiobook? = null
|
private var currentAudiobookStreamData:AudiobookStreamData? = null
|
||||||
|
|
||||||
private var audiobooks = mutableListOf<Audiobook>()
|
// private var audiobooks = mutableListOf<AudiobookStreamData>()
|
||||||
|
|
||||||
private var mediaButtonClickCount: Int = 0
|
private var mediaButtonClickCount: Int = 0
|
||||||
var mediaButtonClickTimeout: Long = 1000 //ms
|
var mediaButtonClickTimeout: Long = 1000 //ms
|
||||||
@@ -88,6 +88,8 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
|
|||||||
private var sleepTimerTask:TimerTask? = null
|
private var sleepTimerTask:TimerTask? = null
|
||||||
private var sleepChapterTime:Long = 0L
|
private var sleepChapterTime:Long = 0L
|
||||||
|
|
||||||
|
private lateinit var audiobookManager:AudiobookManager
|
||||||
|
|
||||||
fun setCustomObjectListener(mylistener: MyCustomObjectListener) {
|
fun setCustomObjectListener(mylistener: MyCustomObjectListener) {
|
||||||
listener = mylistener
|
listener = mylistener
|
||||||
}
|
}
|
||||||
@@ -160,6 +162,9 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
|
|||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
ctx = this
|
ctx = this
|
||||||
|
var client: OkHttpClient = OkHttpClient()
|
||||||
|
audiobookManager = AudiobookManager(ctx, client)
|
||||||
|
audiobookManager.init()
|
||||||
|
|
||||||
channelId = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
channelId = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
createNotificationChannel(channelId, channelName)
|
createNotificationChannel(channelId, channelName)
|
||||||
@@ -252,11 +257,11 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
|
|||||||
val queueNavigator: TimelineQueueNavigator = object : TimelineQueueNavigator(mediaSession) {
|
val queueNavigator: TimelineQueueNavigator = object : TimelineQueueNavigator(mediaSession) {
|
||||||
override fun getMediaDescription(player: Player, windowIndex: Int): MediaDescriptionCompat {
|
override fun getMediaDescription(player: Player, windowIndex: Int): MediaDescriptionCompat {
|
||||||
var builder = MediaDescriptionCompat.Builder()
|
var builder = MediaDescriptionCompat.Builder()
|
||||||
.setMediaId(currentAudiobook!!.id)
|
.setMediaId(currentAudiobookStreamData!!.id)
|
||||||
.setTitle(currentAudiobook!!.title)
|
.setTitle(currentAudiobookStreamData!!.title)
|
||||||
.setSubtitle(currentAudiobook!!.author)
|
.setSubtitle(currentAudiobookStreamData!!.author)
|
||||||
.setMediaUri(currentAudiobook!!.playlistUri)
|
.setMediaUri(currentAudiobookStreamData!!.playlistUri)
|
||||||
.setIconUri(currentAudiobook!!.coverUri)
|
.setIconUri(currentAudiobookStreamData!!.coverUri)
|
||||||
return builder.build()
|
return builder.build()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -277,7 +282,7 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
|
|||||||
override fun onPrepare(playWhenReady: Boolean) {
|
override fun onPrepare(playWhenReady: Boolean) {
|
||||||
Log.d(tag, "ON PREPARE $playWhenReady")
|
Log.d(tag, "ON PREPARE $playWhenReady")
|
||||||
|
|
||||||
var audiobook = audiobooks[0]
|
var audiobook = audiobookManager.audiobooks[0]
|
||||||
if (audiobook == null) {
|
if (audiobook == null) {
|
||||||
Log.e(tag, "Audiobook NOT FOUND")
|
Log.e(tag, "Audiobook NOT FOUND")
|
||||||
return
|
return
|
||||||
@@ -287,7 +292,7 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
|
|||||||
|
|
||||||
override fun onPrepareFromMediaId(mediaId: String, playWhenReady: Boolean, extras: Bundle?) {
|
override fun onPrepareFromMediaId(mediaId: String, playWhenReady: Boolean, extras: Bundle?) {
|
||||||
Log.d(tag, "ON PREPARE FROM MEDIA ID $mediaId $playWhenReady")
|
Log.d(tag, "ON PREPARE FROM MEDIA ID $mediaId $playWhenReady")
|
||||||
var audiobook = audiobooks.find { it.id == mediaId }
|
var audiobook = audiobookManager.audiobooks.find { it.id == mediaId }
|
||||||
if (audiobook == null) {
|
if (audiobook == null) {
|
||||||
Log.e(tag, "Audiobook NOT FOUND")
|
Log.e(tag, "Audiobook NOT FOUND")
|
||||||
return
|
return
|
||||||
@@ -391,7 +396,7 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
|
|||||||
mPlayer.seekTo(currentAudiobook!!.startTime)
|
mPlayer.seekTo(currentAudiobook!!.startTime)
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
currentAudiobook!!.hasPlayerLoaded = true
|
currentAudiobookStreamData!!.hasPlayerLoaded = true
|
||||||
if (lastPauseTime == 0L) {
|
if (lastPauseTime == 0L) {
|
||||||
sendClientMetadata("ready_no_sync")
|
sendClientMetadata("ready_no_sync")
|
||||||
lastPauseTime = -1;
|
lastPauseTime = -1;
|
||||||
@@ -448,27 +453,27 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// fun initPlayer(token: String, playlistUri: String, playWhenReady: Boolean, currentTime: Long, title: String, artist: String, albumArt: String) {
|
// fun initPlayer(token: String, playlistUri: String, playWhenReady: Boolean, currentTime: Long, title: String, artist: String, albumArt: String) {
|
||||||
fun initPlayer(audiobook: Audiobook) {
|
fun initPlayer(audiobookStreamData: AudiobookStreamData) {
|
||||||
currentAudiobook = audiobook
|
currentAudiobookStreamData = audiobookStreamData
|
||||||
|
|
||||||
Log.d(tag, "Init Player Audiobook ${currentAudiobook!!.playlistUrl} | ${currentAudiobook!!.title} | ${currentAudiobook!!.author}")
|
Log.d(tag, "Init Player Audiobook ${currentAudiobookStreamData!!.playlistUrl} | ${currentAudiobookStreamData!!.title} | ${currentAudiobookStreamData!!.author}")
|
||||||
|
|
||||||
if (mPlayer.isPlaying) {
|
if (mPlayer.isPlaying) {
|
||||||
Log.d(tag, "Init Player audiobook already playing")
|
Log.d(tag, "Init Player audiobook already playing")
|
||||||
}
|
}
|
||||||
|
|
||||||
var metadataBuilder = MediaMetadataCompat.Builder()
|
var metadataBuilder = MediaMetadataCompat.Builder()
|
||||||
.putString(MediaMetadataCompat.METADATA_KEY_TITLE, currentAudiobook!!.title)
|
.putString(MediaMetadataCompat.METADATA_KEY_TITLE, currentAudiobookStreamData!!.title)
|
||||||
.putString(MediaMetadataCompat.METADATA_KEY_DISPLAY_TITLE, currentAudiobook!!.title)
|
.putString(MediaMetadataCompat.METADATA_KEY_DISPLAY_TITLE, currentAudiobookStreamData!!.title)
|
||||||
.putString(MediaMetadataCompat.METADATA_KEY_DISPLAY_SUBTITLE, currentAudiobook!!.author)
|
.putString(MediaMetadataCompat.METADATA_KEY_DISPLAY_SUBTITLE, currentAudiobookStreamData!!.author)
|
||||||
.putString(MediaMetadataCompat.METADATA_KEY_AUTHOR, currentAudiobook!!.author)
|
.putString(MediaMetadataCompat.METADATA_KEY_AUTHOR, currentAudiobookStreamData!!.author)
|
||||||
.putString(MediaMetadataCompat.METADATA_KEY_ARTIST, currentAudiobook!!.author)
|
.putString(MediaMetadataCompat.METADATA_KEY_ARTIST, currentAudiobookStreamData!!.author)
|
||||||
.putString(MediaMetadataCompat.METADATA_KEY_ALBUM, currentAudiobook!!.series)
|
.putString(MediaMetadataCompat.METADATA_KEY_ALBUM, currentAudiobookStreamData!!.series)
|
||||||
.putString(MediaMetadataCompat.METADATA_KEY_MEDIA_ID, currentAudiobook!!.id)
|
.putString(MediaMetadataCompat.METADATA_KEY_MEDIA_ID, currentAudiobookStreamData!!.id)
|
||||||
|
|
||||||
if (currentAudiobook!!.cover != "") {
|
if (currentAudiobookStreamData!!.cover != "") {
|
||||||
metadataBuilder.putString(MediaMetadataCompat.METADATA_KEY_ART_URI, currentAudiobook!!.cover)
|
metadataBuilder.putString(MediaMetadataCompat.METADATA_KEY_ART_URI, currentAudiobookStreamData!!.cover)
|
||||||
metadataBuilder.putString(MediaMetadataCompat.METADATA_KEY_ALBUM_ART_URI, currentAudiobook!!.cover)
|
metadataBuilder.putString(MediaMetadataCompat.METADATA_KEY_ALBUM_ART_URI, currentAudiobookStreamData!!.cover)
|
||||||
}
|
}
|
||||||
|
|
||||||
var metadata = metadataBuilder.build()
|
var metadata = metadataBuilder.build()
|
||||||
@@ -478,27 +483,27 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
|
|||||||
|
|
||||||
|
|
||||||
var mediaSource:MediaSource
|
var mediaSource:MediaSource
|
||||||
if (currentAudiobook!!.isLocal) {
|
if (currentAudiobookStreamData!!.isLocal) {
|
||||||
Log.d(tag, "Playing Local File")
|
Log.d(tag, "Playing Local File")
|
||||||
var mediaItem = MediaItem.Builder().setUri(currentAudiobook!!.contentUri).setMediaMetadata(mediaMetadata).build()
|
var mediaItem = MediaItem.Builder().setUri(currentAudiobookStreamData!!.contentUri).setMediaMetadata(mediaMetadata).build()
|
||||||
var dataSourceFactory = DefaultDataSourceFactory(ctx, channelId)
|
var dataSourceFactory = DefaultDataSourceFactory(ctx, channelId)
|
||||||
mediaSource = ProgressiveMediaSource.Factory(dataSourceFactory).createMediaSource(mediaItem)
|
mediaSource = ProgressiveMediaSource.Factory(dataSourceFactory).createMediaSource(mediaItem)
|
||||||
} else {
|
} else {
|
||||||
Log.d(tag, "Playing HLS File")
|
Log.d(tag, "Playing HLS File")
|
||||||
var mediaItem = MediaItem.Builder().setUri(currentAudiobook!!.playlistUri).setMediaMetadata(mediaMetadata).build()
|
var mediaItem = MediaItem.Builder().setUri(currentAudiobookStreamData!!.playlistUri).setMediaMetadata(mediaMetadata).build()
|
||||||
var dataSourceFactory = DefaultHttpDataSource.Factory()
|
var dataSourceFactory = DefaultHttpDataSource.Factory()
|
||||||
dataSourceFactory.setUserAgent(channelId)
|
dataSourceFactory.setUserAgent(channelId)
|
||||||
dataSourceFactory.setDefaultRequestProperties(hashMapOf("Authorization" to "Bearer ${currentAudiobook!!.token}"))
|
dataSourceFactory.setDefaultRequestProperties(hashMapOf("Authorization" to "Bearer ${currentAudiobookStreamData!!.token}"))
|
||||||
|
|
||||||
mediaSource = HlsMediaSource.Factory(dataSourceFactory).createMediaSource(mediaItem)
|
mediaSource = HlsMediaSource.Factory(dataSourceFactory).createMediaSource(mediaItem)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//mPlayer.setMediaSource(mediaSource, true)
|
//mPlayer.setMediaSource(mediaSource, true)
|
||||||
mPlayer.setMediaSource(mediaSource, currentAudiobook!!.startTime)
|
mPlayer.setMediaSource(mediaSource, currentAudiobookStreamData!!.startTime)
|
||||||
mPlayer.prepare()
|
mPlayer.prepare()
|
||||||
mPlayer.playWhenReady = currentAudiobook!!.playWhenReady
|
mPlayer.playWhenReady = currentAudiobookStreamData!!.playWhenReady
|
||||||
mPlayer.setPlaybackSpeed(audiobook.playbackSpeed)
|
mPlayer.setPlaybackSpeed(audiobookStreamData.playbackSpeed)
|
||||||
|
|
||||||
lastPauseTime = 0
|
lastPauseTime = 0
|
||||||
}
|
}
|
||||||
@@ -534,7 +539,7 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun getCurrentAudiobookId() : String {
|
fun getCurrentAudiobookId() : String {
|
||||||
return currentAudiobook?.id.toString()
|
return currentAudiobookStreamData?.id.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun play() {
|
fun play() {
|
||||||
@@ -569,7 +574,7 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
|
|||||||
if (mPlayer.playbackState == Player.STATE_READY) {
|
if (mPlayer.playbackState == Player.STATE_READY) {
|
||||||
mPlayer.clearMediaItems()
|
mPlayer.clearMediaItems()
|
||||||
}
|
}
|
||||||
currentAudiobook?.id = ""
|
currentAudiobookStreamData?.id = ""
|
||||||
lastPauseTime = 0
|
lastPauseTime = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -589,9 +594,6 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
|
|||||||
//
|
//
|
||||||
private val MY_MEDIA_ROOT_ID = "audiobookshelf"
|
private val MY_MEDIA_ROOT_ID = "audiobookshelf"
|
||||||
|
|
||||||
fun setAudiobooks(_audiobooks:MutableList<Audiobook>) {
|
|
||||||
audiobooks = _audiobooks
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun isValid(packageName:String, uid:Int) : Boolean {
|
private fun isValid(packageName:String, uid:Int) : Boolean {
|
||||||
Log.d(tag, "Check package $packageName is valid with uid $uid")
|
Log.d(tag, "Check package $packageName is valid with uid $uid")
|
||||||
@@ -620,25 +622,27 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
|
|||||||
override fun onLoadChildren(parentMediaId: String, result: Result<MutableList<MediaBrowserCompat.MediaItem>>) {
|
override fun onLoadChildren(parentMediaId: String, result: Result<MutableList<MediaBrowserCompat.MediaItem>>) {
|
||||||
val mediaItems: MutableList<MediaBrowserCompat.MediaItem> = mutableListOf()
|
val mediaItems: MutableList<MediaBrowserCompat.MediaItem> = mutableListOf()
|
||||||
|
|
||||||
if (audiobooks.size == 0) {
|
if (!audiobookManager.hasLoaded) {
|
||||||
|
Log.d(tag, "audiobook manager loading")
|
||||||
|
result.detach()
|
||||||
|
audiobookManager.load()
|
||||||
|
audiobookManager.fetchAudiobooks(result)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (audiobookManager.audiobooks.size == 0) {
|
||||||
|
Log.d(tag, "AudiobookManager: Sending no items")
|
||||||
result.sendResult(mediaItems)
|
result.sendResult(mediaItems)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
audiobooks.forEach {
|
audiobookManager.audiobooks.forEach {
|
||||||
var builder = MediaDescriptionCompat.Builder()
|
var builder = MediaDescriptionCompat.Builder()
|
||||||
.setMediaId(it.id)
|
.setMediaId(it.id)
|
||||||
.setTitle(it.title)
|
.setTitle(it.book.title)
|
||||||
.setSubtitle(it.author)
|
.setSubtitle(it.book.authorFL)
|
||||||
.setMediaUri(it.playlistUri)
|
.setMediaUri(it.fallbackUri)
|
||||||
.setIconUri(it.coverUri)
|
.setIconUri(it.getCover(audiobookManager.serverUrl, audiobookManager.token))
|
||||||
|
|
||||||
// val extras = Bundle()
|
|
||||||
// var startsWithA = it.title.toLowerCase().startsWith("a")
|
|
||||||
// var groupTitle = "test group
|
|
||||||
// extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, groupTitle)
|
|
||||||
// builder.setExtras(extras)\
|
|
||||||
// Log.d(tag, "Load Media Item for AUTO ${it.title} - ${it.author}")
|
|
||||||
|
|
||||||
var mediaDescription = builder.build()
|
var mediaDescription = builder.build()
|
||||||
var newMediaItem = MediaBrowserCompat.MediaItem(mediaDescription, MediaBrowserCompat.MediaItem.FLAG_PLAYABLE)
|
var newMediaItem = MediaBrowserCompat.MediaItem(mediaDescription, MediaBrowserCompat.MediaItem.FLAG_PLAYABLE)
|
||||||
@@ -654,6 +658,7 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
|
|||||||
// examine the passed parentMediaId to see which submenu we're at,
|
// examine the passed parentMediaId to see which submenu we're at,
|
||||||
// and put the children of that menu in the mediaItems list
|
// and put the children of that menu in the mediaItems list
|
||||||
}
|
}
|
||||||
|
Log.d(tag, "AudiobookManager: Sending ${mediaItems.size} Aduiobooks")
|
||||||
result.sendResult(mediaItems)
|
result.sendResult(mediaItems)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+66
-10
@@ -7,7 +7,6 @@ class StoreService {
|
|||||||
isService = false
|
isService = false
|
||||||
platform
|
platform
|
||||||
isOpen = false
|
isOpen = false
|
||||||
tableName = 'downloads'
|
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.init()
|
this.init()
|
||||||
@@ -323,31 +322,75 @@ class StoreService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async getDownload(id) {
|
async setServerConfig(config) {
|
||||||
if (!this.isOpen) {
|
if (!this.isOpen) {
|
||||||
var success = await this.openStore('storage', this.tableName)
|
var success = await this.openStore('storage', 'serverConfig')
|
||||||
if (!success) {
|
if (!success) {
|
||||||
console.error('Store failed to open')
|
console.error('Store failed to open')
|
||||||
return null
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
var value = await this.getItem(id)
|
await this.setTable('serverConfig')
|
||||||
return JSON.parse(value)
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to get download from store', error)
|
console.error('Failed to set table', error)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await this.setItem('config', JSON.stringify(config))
|
||||||
|
console.log(`[STORE] Set Server Config`)
|
||||||
|
return true
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to set server config in store', error)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async getServerConfig() {
|
||||||
|
if (!this.isOpen) {
|
||||||
|
var success = await this.openStore('storage', 'serverConfig')
|
||||||
|
if (!success) {
|
||||||
|
console.error('Store failed to open')
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
await this.setTable('serverConfig')
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to set table', error)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
var configVal = await this.getItem('config')
|
||||||
|
if (!configVal) {
|
||||||
|
console.log(`[STORE] server config not available`)
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
var config = JSON.parse(configVal)
|
||||||
|
console.log(`[STORE] Got Server Config`, JSON.stringify(config))
|
||||||
|
return config
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to set server config in store', error)
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async setDownload(download) {
|
async setDownload(download) {
|
||||||
if (!this.isOpen) {
|
if (!this.isOpen) {
|
||||||
var success = await this.openStore('storage', this.tableName)
|
var success = await this.openStore('storage', 'downloads')
|
||||||
if (!success) {
|
if (!success) {
|
||||||
console.error('Store failed to open')
|
console.error('Store failed to open')
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
|
await this.setTable('downloads')
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to set table', error)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await this.setItem(download.id, JSON.stringify(download))
|
await this.setItem(download.id, JSON.stringify(download))
|
||||||
@@ -361,12 +404,18 @@ class StoreService {
|
|||||||
|
|
||||||
async removeDownload(id) {
|
async removeDownload(id) {
|
||||||
if (!this.isOpen) {
|
if (!this.isOpen) {
|
||||||
var success = await this.openStore('storage', this.tableName)
|
var success = await this.openStore('storage', 'downloads')
|
||||||
if (!success) {
|
if (!success) {
|
||||||
console.error('Store failed to open')
|
console.error('Store failed to open')
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
|
await this.setTable('downloads')
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to set table', error)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await this.removeItem(id)
|
await this.removeItem(id)
|
||||||
@@ -380,12 +429,19 @@ class StoreService {
|
|||||||
|
|
||||||
async getAllDownloads() {
|
async getAllDownloads() {
|
||||||
if (!this.isOpen) {
|
if (!this.isOpen) {
|
||||||
var success = await this.openStore('storage', this.tableName)
|
var success = await this.openStore('storage', 'downloads')
|
||||||
if (!success) {
|
if (!success) {
|
||||||
console.error('Store failed to open')
|
console.error('Store failed to open')
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
|
await this.setTable('downloads')
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to set table', error)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
var keysvalues = await this.getAllKeysValues()
|
var keysvalues = await this.getAllKeysValues()
|
||||||
var downloads = []
|
var downloads = []
|
||||||
|
|
||||||
|
|||||||
@@ -145,21 +145,6 @@ export const actions = {
|
|||||||
},
|
},
|
||||||
useDownloaded({ commit, rootGetters }) {
|
useDownloaded({ commit, rootGetters }) {
|
||||||
commit('set', rootGetters['downloads/getAudiobooks'])
|
commit('set', rootGetters['downloads/getAudiobooks'])
|
||||||
},
|
|
||||||
setNativeAudiobooks({ state }) {
|
|
||||||
var audiobooks = state.audiobooks.map(ab => {
|
|
||||||
var _book = ab.book
|
|
||||||
return {
|
|
||||||
id: ab.id,
|
|
||||||
title: _book.title,
|
|
||||||
author: _book.author,
|
|
||||||
duration: ab.duration,
|
|
||||||
size: ab.size,
|
|
||||||
cover: _book.cover || '',
|
|
||||||
series: _book.series || ''
|
|
||||||
}
|
|
||||||
})
|
|
||||||
MyNativeAudio.setAudiobooks({ audiobooks: audiobooks })
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user