mirror of
https://github.com/advplyr/audiobookshelf-app.git
synced 2026-08-31 15:47:13 +02:00
New data model in android: Adding jackson for JSON deserialization, adding data classes, setting up API caller
This commit is contained in:
@@ -85,6 +85,9 @@ dependencies {
|
|||||||
|
|
||||||
// OK HTTP
|
// OK HTTP
|
||||||
implementation 'com.squareup.okhttp3:okhttp:4.9.2'
|
implementation 'com.squareup.okhttp3:okhttp:4.9.2'
|
||||||
|
|
||||||
|
// Jackson for JSON
|
||||||
|
implementation 'com.fasterxml.jackson.module:jackson-module-kotlin:2.12.1'
|
||||||
}
|
}
|
||||||
|
|
||||||
apply from: 'capacitor.build.gradle'
|
apply from: 'capacitor.build.gradle'
|
||||||
|
|||||||
@@ -5,7 +5,9 @@ import android.os.Handler
|
|||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
|
import com.audiobookshelf.app.server.ApiHandler
|
||||||
import com.capacitorjs.plugins.app.AppPlugin
|
import com.capacitorjs.plugins.app.AppPlugin
|
||||||
|
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
|
||||||
import com.getcapacitor.*
|
import com.getcapacitor.*
|
||||||
import com.getcapacitor.annotation.CapacitorPlugin
|
import com.getcapacitor.annotation.CapacitorPlugin
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
@@ -15,10 +17,12 @@ class MyNativeAudio : Plugin() {
|
|||||||
private val tag = "MyNativeAudio"
|
private val tag = "MyNativeAudio"
|
||||||
|
|
||||||
lateinit var mainActivity:MainActivity
|
lateinit var mainActivity:MainActivity
|
||||||
|
lateinit var apiHandler:ApiHandler
|
||||||
lateinit var playerNotificationService: PlayerNotificationService
|
lateinit var playerNotificationService: PlayerNotificationService
|
||||||
|
|
||||||
override fun load() {
|
override fun load() {
|
||||||
mainActivity = (activity as MainActivity)
|
mainActivity = (activity as MainActivity)
|
||||||
|
apiHandler = ApiHandler(mainActivity)
|
||||||
|
|
||||||
var foregroundServiceReady : () -> Unit = {
|
var foregroundServiceReady : () -> Unit = {
|
||||||
playerNotificationService = mainActivity.foregroundService
|
playerNotificationService = mainActivity.foregroundService
|
||||||
@@ -59,6 +63,37 @@ class MyNativeAudio : Plugin() {
|
|||||||
notifyListeners(evtName, ret)
|
notifyListeners(evtName, ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PluginMethod
|
||||||
|
fun prepareLibraryItem(call: PluginCall) {
|
||||||
|
var libraryItemId = call.getString("libraryItemId", "").toString()
|
||||||
|
var mediaEntityId = call.getString("mediaEntityId", "").toString()
|
||||||
|
|
||||||
|
apiHandler.playLibraryItem(libraryItemId) {
|
||||||
|
|
||||||
|
Handler(Looper.getMainLooper()).post() {
|
||||||
|
Log.d(tag, "Preparing Player TEST ${jacksonObjectMapper().writeValueAsString(it)}")
|
||||||
|
playerNotificationService.preparePlayer(it)
|
||||||
|
}
|
||||||
|
|
||||||
|
call.resolve(JSObject(jacksonObjectMapper().writeValueAsString(it)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@PluginMethod
|
||||||
|
fun getLibraryItems(call: PluginCall) {
|
||||||
|
var libraryId = call.getString("libraryId", "").toString()
|
||||||
|
apiHandler.getLibraryItems(libraryId) {
|
||||||
|
val mapper = jacksonObjectMapper()
|
||||||
|
var jsobj = JSObject()
|
||||||
|
var libarray = JSArray()
|
||||||
|
it.map {
|
||||||
|
libarray.put(JSObject(mapper.writeValueAsString(it)))
|
||||||
|
}
|
||||||
|
jsobj.put("value", libarray)
|
||||||
|
call.resolve(jsobj)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@PluginMethod
|
@PluginMethod
|
||||||
fun initPlayer(call: PluginCall) {
|
fun initPlayer(call: PluginCall) {
|
||||||
if (!PlayerNotificationService.isStarted) {
|
if (!PlayerNotificationService.isStarted) {
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import androidx.media.MediaBrowserServiceCompat
|
|||||||
import androidx.media.utils.MediaConstants
|
import androidx.media.utils.MediaConstants
|
||||||
import com.anggrayudi.storage.file.isExternalStorageDocument
|
import com.anggrayudi.storage.file.isExternalStorageDocument
|
||||||
import com.audiobookshelf.app.data.DbManager
|
import com.audiobookshelf.app.data.DbManager
|
||||||
|
import com.audiobookshelf.app.data.PlaybackSession
|
||||||
import com.getcapacitor.Bridge
|
import com.getcapacitor.Bridge
|
||||||
import com.getcapacitor.JSObject
|
import com.getcapacitor.JSObject
|
||||||
import com.google.android.exoplayer2.*
|
import com.google.android.exoplayer2.*
|
||||||
@@ -85,6 +86,7 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
|
|||||||
private var channelName = "Audiobookshelf Channel"
|
private var channelName = "Audiobookshelf Channel"
|
||||||
|
|
||||||
private var currentAudiobookStreamData:AudiobookStreamData? = null
|
private var currentAudiobookStreamData:AudiobookStreamData? = null
|
||||||
|
private var currentPlaybackSession:PlaybackSession? = null
|
||||||
|
|
||||||
private var mediaButtonClickCount: Int = 0
|
private var mediaButtonClickCount: Int = 0
|
||||||
var mediaButtonClickTimeout: Long = 1000 //ms
|
var mediaButtonClickTimeout: Long = 1000 //ms
|
||||||
@@ -376,11 +378,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(currentAudiobookStreamData!!.id)
|
.setMediaId(currentPlaybackSession!!.id)
|
||||||
.setTitle(currentAudiobookStreamData!!.title)
|
.setTitle(currentPlaybackSession!!.getTitle())
|
||||||
.setSubtitle(currentAudiobookStreamData!!.author)
|
.setSubtitle(currentPlaybackSession!!.getAuthor())
|
||||||
.setMediaUri(currentAudiobookStreamData!!.playlistUri)
|
// .setMediaUri(currentPlaybackSession!!.getContentUri())
|
||||||
.setIconUri(currentAudiobookStreamData!!.coverUri)
|
// .setIconUri(currentAudiobookStreamData!!.)
|
||||||
return builder.build()
|
return builder.build()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -600,7 +602,7 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
|
|||||||
if (currentPlayer.playbackState == Player.STATE_READY) {
|
if (currentPlayer.playbackState == Player.STATE_READY) {
|
||||||
Log.d(tag, "STATE_READY : " + mPlayer.duration.toString())
|
Log.d(tag, "STATE_READY : " + mPlayer.duration.toString())
|
||||||
|
|
||||||
currentAudiobookStreamData!!.hasPlayerLoaded = true
|
// currentAudiobookStreamData!!.hasPlayerLoaded = true
|
||||||
if (lastPauseTime == 0L) {
|
if (lastPauseTime == 0L) {
|
||||||
sendClientMetadata("ready_no_sync")
|
sendClientMetadata("ready_no_sync")
|
||||||
lastPauseTime = -1;
|
lastPauseTime = -1;
|
||||||
@@ -664,6 +666,23 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
|
|||||||
/*
|
/*
|
||||||
User callable methods
|
User callable methods
|
||||||
*/
|
*/
|
||||||
|
fun preparePlayer(playbackSession: PlaybackSession) {
|
||||||
|
currentPlaybackSession = playbackSession
|
||||||
|
var metadata = playbackSession.getMediaMetadataCompat()
|
||||||
|
mediaSession.setMetadata(metadata)
|
||||||
|
var mediaMetadata = playbackSession.getMediaMetadata()
|
||||||
|
var mediaUrl = playbackSession.getContentUri()
|
||||||
|
var mimeType = playbackSession.getMimeType()
|
||||||
|
Log.d(tag, "Media URL $mediaUrl")
|
||||||
|
var mediaUri = Uri.parse(mediaUrl)
|
||||||
|
var mediaItem = MediaItem.Builder().setUri(mediaUri).setMediaMetadata(mediaMetadata).setMimeType(mimeType).build()
|
||||||
|
var dataSourceFactory = DefaultDataSourceFactory(ctx, channelId)
|
||||||
|
var mediaSource = ProgressiveMediaSource.Factory(dataSourceFactory).createMediaSource(mediaItem)
|
||||||
|
mPlayer.setMediaSource(mediaSource, 0L)
|
||||||
|
mPlayer.prepare()
|
||||||
|
mPlayer.playWhenReady = true
|
||||||
|
}
|
||||||
|
|
||||||
fun initPlayer(audiobookStreamData: AudiobookStreamData) {
|
fun initPlayer(audiobookStreamData: AudiobookStreamData) {
|
||||||
currentAudiobookStreamData = audiobookStreamData
|
currentAudiobookStreamData = audiobookStreamData
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,211 @@
|
|||||||
|
package com.audiobookshelf.app.data
|
||||||
|
|
||||||
|
import android.net.Uri
|
||||||
|
import android.support.v4.media.MediaMetadataCompat
|
||||||
|
import com.fasterxml.jackson.annotation.*
|
||||||
|
import com.google.android.exoplayer2.MediaMetadata
|
||||||
|
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
data class LibraryItem(
|
||||||
|
var id:String,
|
||||||
|
var ino:String,
|
||||||
|
var libraryId:String,
|
||||||
|
var folderId:String,
|
||||||
|
var path:String,
|
||||||
|
var relPath:String,
|
||||||
|
var mtimeMs:Long,
|
||||||
|
var ctimeMs:Long,
|
||||||
|
var birthtimeMs:Long,
|
||||||
|
var addedAt:Long,
|
||||||
|
var updatedAt:Long,
|
||||||
|
var lastScan:Long?,
|
||||||
|
var scanVersion:String?,
|
||||||
|
var isMissing:Boolean,
|
||||||
|
var isInvalid:Boolean,
|
||||||
|
var mediaType:String,
|
||||||
|
var media:MediaEntity,
|
||||||
|
var libraryFiles:MutableList<LibraryFile>
|
||||||
|
)
|
||||||
|
|
||||||
|
// This auto-detects whether it is a Book or Podcast
|
||||||
|
@JsonTypeInfo(use=JsonTypeInfo.Id.DEDUCTION)
|
||||||
|
@JsonSubTypes(
|
||||||
|
JsonSubTypes.Type(Book::class),
|
||||||
|
JsonSubTypes.Type(Podcast::class)
|
||||||
|
)
|
||||||
|
open class MediaEntity {}
|
||||||
|
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
data class Podcast(
|
||||||
|
var metadata:PodcastMetadata,
|
||||||
|
var coverPath:String?,
|
||||||
|
var tags:MutableList<String>,
|
||||||
|
var episodes:MutableList<PodcastEpisode>,
|
||||||
|
var autoDownloadEpisodes:Boolean
|
||||||
|
) : MediaEntity()
|
||||||
|
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
data class Book(
|
||||||
|
var metadata:BookMetadata,
|
||||||
|
var coverPath:String?,
|
||||||
|
var tags:MutableList<String>,
|
||||||
|
var audiobooks:MutableList<Audiobook>
|
||||||
|
) : MediaEntity()
|
||||||
|
|
||||||
|
// This auto-detects whether it is a Book or Podcast
|
||||||
|
@JsonTypeInfo(use=JsonTypeInfo.Id.DEDUCTION)
|
||||||
|
@JsonSubTypes(
|
||||||
|
JsonSubTypes.Type(BookMetadata::class),
|
||||||
|
JsonSubTypes.Type(PodcastMetadata::class)
|
||||||
|
)
|
||||||
|
open class MediaEntityMetadata {}
|
||||||
|
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
data class BookMetadata(
|
||||||
|
var title:String,
|
||||||
|
var subtitle:String?,
|
||||||
|
var authors:MutableList<Author>
|
||||||
|
) : MediaEntityMetadata()
|
||||||
|
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
data class PodcastMetadata(
|
||||||
|
var title:String,
|
||||||
|
var author:String?,
|
||||||
|
var feedUrl:String,
|
||||||
|
var genres:MutableList<String>
|
||||||
|
) : MediaEntityMetadata()
|
||||||
|
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
data class Author(
|
||||||
|
var id:String,
|
||||||
|
var name:String,
|
||||||
|
var coverPath:String?
|
||||||
|
)
|
||||||
|
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
data class Audiobook(
|
||||||
|
var id:String,
|
||||||
|
var index:Int,
|
||||||
|
var name:String,
|
||||||
|
var audioFiles:MutableList<AudioFile>
|
||||||
|
)
|
||||||
|
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
data class PodcastEpisode(
|
||||||
|
var id:String,
|
||||||
|
var index:Int,
|
||||||
|
var episode:String?,
|
||||||
|
var episodeType:String?,
|
||||||
|
var title:String?,
|
||||||
|
var subtitle:String?,
|
||||||
|
var description:String?,
|
||||||
|
var audioFile:AudioFile
|
||||||
|
)
|
||||||
|
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
data class LibraryFile(
|
||||||
|
var ino:String,
|
||||||
|
var metadata:FileMetadata
|
||||||
|
)
|
||||||
|
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
data class FileMetadata(
|
||||||
|
var filename:String,
|
||||||
|
var ext:String,
|
||||||
|
var path:String,
|
||||||
|
var relPath:String
|
||||||
|
)
|
||||||
|
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
data class AudioFile(
|
||||||
|
var index:Int,
|
||||||
|
var ino:String,
|
||||||
|
var metadata:FileMetadata
|
||||||
|
)
|
||||||
|
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
data class Library(
|
||||||
|
var id:String,
|
||||||
|
var name:String,
|
||||||
|
var folders:MutableList<Folder>,
|
||||||
|
var icon:String,
|
||||||
|
var mediaType:String
|
||||||
|
)
|
||||||
|
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
data class Folder(
|
||||||
|
var id:String,
|
||||||
|
var fullPath:String
|
||||||
|
)
|
||||||
|
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
class PlaybackSession(
|
||||||
|
var id:String,
|
||||||
|
var userId:String,
|
||||||
|
var libraryItemId:String,
|
||||||
|
var mediaEntityId:String,
|
||||||
|
var mediaType:String,
|
||||||
|
var mediaMetadata:MediaEntityMetadata,
|
||||||
|
var duration:Double,
|
||||||
|
var playMethod:Int,
|
||||||
|
var audioTracks:MutableList<AudioTrack>,
|
||||||
|
var currentTime:Double,
|
||||||
|
var serverUrl:String,
|
||||||
|
var token:String
|
||||||
|
) {
|
||||||
|
fun getTitle():String {
|
||||||
|
var metadata = mediaMetadata as BookMetadata
|
||||||
|
return metadata.title
|
||||||
|
}
|
||||||
|
fun getAuthor():String {
|
||||||
|
var metadata = mediaMetadata as BookMetadata
|
||||||
|
return metadata.authors.joinToString(",") { it.name }
|
||||||
|
}
|
||||||
|
fun getContentUri():String {
|
||||||
|
// TODO: Using Uri.parse here is throwing error with jackson
|
||||||
|
var audioTrack = audioTracks[0]
|
||||||
|
return "$serverUrl${audioTrack.contentUrl}?token=$token"
|
||||||
|
}
|
||||||
|
fun getMimeType():String {
|
||||||
|
var audioTrack = audioTracks[0]
|
||||||
|
return audioTrack.mimeType
|
||||||
|
}
|
||||||
|
fun getMediaMetadataCompat(): MediaMetadataCompat {
|
||||||
|
var metadata = mediaMetadata as BookMetadata
|
||||||
|
|
||||||
|
var metadataBuilder = MediaMetadataCompat.Builder()
|
||||||
|
.putString(MediaMetadataCompat.METADATA_KEY_TITLE, metadata.title)
|
||||||
|
.putString(MediaMetadataCompat.METADATA_KEY_DISPLAY_TITLE, metadata.title)
|
||||||
|
.putString(MediaMetadataCompat.METADATA_KEY_DISPLAY_SUBTITLE, metadata.authors.joinToString(",") { it.name })
|
||||||
|
.putString(MediaMetadataCompat.METADATA_KEY_AUTHOR, metadata.authors.joinToString(",") { it.name })
|
||||||
|
.putString(MediaMetadataCompat.METADATA_KEY_ARTIST, metadata.authors.joinToString(",") { it.name })
|
||||||
|
.putString(MediaMetadataCompat.METADATA_KEY_ALBUM, "series")
|
||||||
|
.putString(MediaMetadataCompat.METADATA_KEY_MEDIA_ID, id)
|
||||||
|
return metadataBuilder.build()
|
||||||
|
}
|
||||||
|
fun getMediaMetadata(): MediaMetadata {
|
||||||
|
var metadata = mediaMetadata as BookMetadata
|
||||||
|
var authorName = metadata.authors.joinToString(",") { it.name }
|
||||||
|
var metadataBuilder = MediaMetadata.Builder()
|
||||||
|
.setTitle(metadata.title)
|
||||||
|
.setDisplayTitle(metadata.title)
|
||||||
|
.setArtist(authorName)
|
||||||
|
.setAlbumArtist(authorName)
|
||||||
|
.setSubtitle(authorName)
|
||||||
|
|
||||||
|
// var contentUri = this.getContentUri()
|
||||||
|
// metadataBuilder.setMediaUri(contentUri)
|
||||||
|
|
||||||
|
return metadataBuilder.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
data class AudioTrack(
|
||||||
|
var index:Int,
|
||||||
|
var startOffset:Double,
|
||||||
|
var duration:Double,
|
||||||
|
var title:String,
|
||||||
|
var contentUrl:String,
|
||||||
|
var mimeType:String
|
||||||
|
)
|
||||||
@@ -0,0 +1,124 @@
|
|||||||
|
package com.audiobookshelf.app.server
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.SharedPreferences
|
||||||
|
import android.util.Log
|
||||||
|
import com.audiobookshelf.app.data.Library
|
||||||
|
import com.audiobookshelf.app.data.LibraryItem
|
||||||
|
import com.audiobookshelf.app.data.PlaybackSession
|
||||||
|
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
|
||||||
|
import com.fasterxml.jackson.module.kotlin.readValue
|
||||||
|
import com.getcapacitor.JSArray
|
||||||
|
import com.getcapacitor.JSObject
|
||||||
|
import okhttp3.*
|
||||||
|
import okhttp3.MediaType.Companion.toMediaType
|
||||||
|
import okhttp3.RequestBody.Companion.toRequestBody
|
||||||
|
import java.io.IOException
|
||||||
|
|
||||||
|
class ApiHandler {
|
||||||
|
val tag = "ApiHandler"
|
||||||
|
private var client = OkHttpClient()
|
||||||
|
var ctx: Context
|
||||||
|
var serverUrl = ""
|
||||||
|
var token = ""
|
||||||
|
var storageSharedPreferences: SharedPreferences? = null
|
||||||
|
|
||||||
|
constructor(_ctx: Context) {
|
||||||
|
ctx = _ctx
|
||||||
|
init()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun init() {
|
||||||
|
storageSharedPreferences = ctx.getSharedPreferences("CapacitorStorage", Activity.MODE_PRIVATE)
|
||||||
|
serverUrl = storageSharedPreferences?.getString("serverUrl", "").toString()
|
||||||
|
Log.d(tag, "SHARED PREF SERVERURL $serverUrl")
|
||||||
|
token = storageSharedPreferences?.getString("token", "").toString()
|
||||||
|
Log.d(tag, "SHARED PREF TOKEN $token")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getRequest(endpoint:String, cb: (JSObject) -> Unit) {
|
||||||
|
val request = Request.Builder()
|
||||||
|
.url("$serverUrl$endpoint").addHeader("Authorization", "Bearer $token")
|
||||||
|
.build()
|
||||||
|
makeRequest(request, cb)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun postRequest(endpoint:String, payload: JSObject, cb: (JSObject) -> Unit) {
|
||||||
|
val mediaType = "application/json; charset=utf-8".toMediaType()
|
||||||
|
val requestBody = payload.toString().toRequestBody(mediaType)
|
||||||
|
val request = Request.Builder().post(requestBody)
|
||||||
|
.url("$serverUrl$endpoint").addHeader("Authorization", "Bearer $token")
|
||||||
|
.build()
|
||||||
|
makeRequest(request, cb)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun makeRequest(request:Request, cb: (JSObject) -> Unit) {
|
||||||
|
client.newCall(request).enqueue(object : Callback {
|
||||||
|
override fun onFailure(call: Call, e: IOException) {
|
||||||
|
Log.d(tag, "FAILURE TO CONNECT")
|
||||||
|
e.printStackTrace()
|
||||||
|
cb(JSObject())
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResponse(call: Call, response: Response) {
|
||||||
|
response.use {
|
||||||
|
if (!response.isSuccessful) throw IOException("Unexpected code $response")
|
||||||
|
var bodyString = response.body!!.string()
|
||||||
|
var jsonObj = JSObject()
|
||||||
|
if (bodyString.startsWith("[")) {
|
||||||
|
var array = JSArray(bodyString)
|
||||||
|
jsonObj.put("value", array)
|
||||||
|
} else {
|
||||||
|
jsonObj = JSObject(bodyString)
|
||||||
|
}
|
||||||
|
cb(jsonObj)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getLibraries(cb: (List<Library>) -> Unit) {
|
||||||
|
val mapper = jacksonObjectMapper()
|
||||||
|
getRequest("/api/libraries") {
|
||||||
|
val libraries = mutableListOf<Library>()
|
||||||
|
if (it.has("value")) {
|
||||||
|
var array = it.getJSONArray("value")!!
|
||||||
|
for (i in 0 until array.length()) {
|
||||||
|
val library = mapper.readValue<Library>(array.get(i).toString())
|
||||||
|
libraries.add(library)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cb(libraries)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getLibraryItems(libraryId:String, cb: (List<LibraryItem>) -> Unit) {
|
||||||
|
val mapper = jacksonObjectMapper()
|
||||||
|
getRequest("/api/libraries/$libraryId/items") {
|
||||||
|
val items = mutableListOf<LibraryItem>()
|
||||||
|
if (it.has("results")) {
|
||||||
|
var array = it.getJSONArray("results")
|
||||||
|
for (i in 0 until array.length()) {
|
||||||
|
val item = mapper.readValue<LibraryItem>(array.get(i).toString())
|
||||||
|
items.add(item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cb(items)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun playLibraryItem(libraryItemId:String, cb: (PlaybackSession) -> Unit) {
|
||||||
|
val mapper = jacksonObjectMapper()
|
||||||
|
var payload = JSObject()
|
||||||
|
payload.put("mediaPlayer", "exo-player")
|
||||||
|
payload.put("forceDirectPlay", true)
|
||||||
|
|
||||||
|
postRequest("/api/items/$libraryItemId/play", payload) {
|
||||||
|
it.put("serverUrl", serverUrl)
|
||||||
|
it.put("token", token)
|
||||||
|
val playbackSession = mapper.readValue<PlaybackSession>(it.toString())
|
||||||
|
cb(playbackSession)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -479,6 +479,12 @@ export default {
|
|||||||
this.$store.commit('setLibraryItemStream', libraryItem)
|
this.$store.commit('setLibraryItemStream', libraryItem)
|
||||||
|
|
||||||
// TODO: Call load library item in native
|
// TODO: Call load library item in native
|
||||||
|
console.log('TEST prepare library item', libraryItemId)
|
||||||
|
MyNativeAudio.prepareLibraryItem({ libraryItemId }).then((data) => {
|
||||||
|
console.log('TEST library item play response', JSON.stringify(data))
|
||||||
|
}).catch((error) => {
|
||||||
|
console.error('TEST failed', error)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
|
|||||||
@@ -26,12 +26,16 @@
|
|||||||
|
|
||||||
<ui-btn v-if="!isUpdateAvailable || immediateUpdateAllowed" class="w-full my-4" color="primary" @click="openAppStore">Open app store</ui-btn>
|
<ui-btn v-if="!isUpdateAvailable || immediateUpdateAllowed" class="w-full my-4" color="primary" @click="openAppStore">Open app store</ui-btn>
|
||||||
|
|
||||||
|
<!-- Used for testing API -->
|
||||||
|
<ui-btn @click="testCall">Test Call</ui-btn>
|
||||||
|
|
||||||
<p class="text-xs text-gray-400">UA: {{ updateAvailability }} | Avail: {{ availableVersion }} | Curr: {{ currentVersion }} | ImmedAllowed: {{ immediateUpdateAllowed }}</p>
|
<p class="text-xs text-gray-400">UA: {{ updateAvailability }} | Avail: {{ availableVersion }} | Curr: {{ currentVersion }} | ImmedAllowed: {{ immediateUpdateAllowed }}</p>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { AppUpdate } from '@robingenz/capacitor-app-update'
|
import { AppUpdate } from '@robingenz/capacitor-app-update'
|
||||||
|
import MyNativeAudio from '@/plugins/my-native-audio'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
asyncData({ redirect, store }) {
|
asyncData({ redirect, store }) {
|
||||||
@@ -74,6 +78,14 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
testCall() {
|
||||||
|
// Used for testing API
|
||||||
|
console.log('Making Test call')
|
||||||
|
var libraryId = this.$store.state.libraries.currentLibraryId
|
||||||
|
MyNativeAudio.getLibraryItems({ libraryId }).then((res) => {
|
||||||
|
console.log('TEST CALL response', JSON.stringify(res))
|
||||||
|
})
|
||||||
|
},
|
||||||
async logout() {
|
async logout() {
|
||||||
await this.$axios.$post('/logout').catch((error) => {
|
await this.$axios.$post('/logout').catch((error) => {
|
||||||
console.error(error)
|
console.error(error)
|
||||||
|
|||||||
Reference in New Issue
Block a user