mirror of
https://github.com/sudoxnym/audiobookshelf-atv.git
synced 2026-04-15 12:06:57 +00:00
Initial android auto support, fix bug saving user settings
This commit is contained in:
parent
e124d3858f
commit
9c5f79d54f
12 changed files with 273 additions and 49 deletions
|
|
@ -13,8 +13,8 @@ android {
|
|||
applicationId "com.audiobookshelf.app"
|
||||
minSdkVersion rootProject.ext.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
versionCode 15
|
||||
versionName "0.9.0-beta"
|
||||
versionCode 16
|
||||
versionName "0.9.1-beta"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
aaptOptions {
|
||||
// Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps.
|
||||
|
|
|
|||
|
|
@ -6,9 +6,8 @@
|
|||
<!-- Permissions -->
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<!-- <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />-->
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
|
|
@ -31,18 +30,25 @@
|
|||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
|
||||
</activity>
|
||||
|
||||
<provider
|
||||
android:name="androidx.core.content.FileProvider"
|
||||
android:authorities="${applicationId}.fileprovider"
|
||||
android:exported="false"
|
||||
android:grantUriPermissions="true">
|
||||
<meta-data
|
||||
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||
android:resource="@xml/file_paths" />
|
||||
</provider>
|
||||
<!--Used by Android Auto-->
|
||||
<meta-data android:name="com.google.android.gms.car.notification.SmallIcon"
|
||||
android:resource="@drawable/icon" />
|
||||
<meta-data
|
||||
android:name="com.google.android.gms.car.application"
|
||||
android:resource="@xml/automotive_app_desc"/>
|
||||
|
||||
<!-- TODO: Can remove in future -->
|
||||
<!-- <provider-->
|
||||
<!-- android:name="androidx.core.content.FileProvider"-->
|
||||
<!-- android:authorities="${applicationId}.fileprovider"-->
|
||||
<!-- android:exported="false"-->
|
||||
<!-- android:grantUriPermissions="true">-->
|
||||
<!-- <meta-data-->
|
||||
<!-- android:name="android.support.FILE_PROVIDER_PATHS"-->
|
||||
<!-- android:resource="@xml/file_paths" />-->
|
||||
<!-- </provider>-->
|
||||
|
||||
<receiver android:name="androidx.media.session.MediaButtonReceiver" >
|
||||
<intent-filter>
|
||||
|
|
@ -51,8 +57,12 @@
|
|||
</receiver>
|
||||
|
||||
<service
|
||||
android:exported="true"
|
||||
android:enabled="true"
|
||||
android:name=".PlayerNotificationService">
|
||||
<intent-filter>
|
||||
<action android:name="android.media.browse.MediaBrowserService"/>
|
||||
</intent-filter>
|
||||
</service>
|
||||
|
||||
</application>
|
||||
|
|
|
|||
|
|
@ -34,9 +34,19 @@ class Audiobook {
|
|||
cover = jsondata.getString("cover", "").toString()
|
||||
playlistUrl = jsondata.getString("playlistUrl", "").toString()
|
||||
playWhenReady = jsondata.getBoolean("playWhenReady", false) == true
|
||||
startTime = jsondata.getString("startTime", "0")!!.toLong()
|
||||
playbackSpeed = jsondata.getDouble("playbackSpeed")!!.toFloat()
|
||||
duration = jsondata.getString("duration", "0")!!.toLong()
|
||||
|
||||
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
|
||||
|
|
|
|||
|
|
@ -60,12 +60,12 @@ class MainActivity : BridgeActivity() {
|
|||
|
||||
mConnection = object : ServiceConnection {
|
||||
override fun onServiceDisconnected(name: ComponentName) {
|
||||
Log.w(tag, "Service Disconnected")
|
||||
Log.w(tag, "Service Disconnected $name")
|
||||
mBounded = false
|
||||
}
|
||||
|
||||
override fun onServiceConnected(name: ComponentName, service: IBinder) {
|
||||
Log.d(tag, "Service Connected")
|
||||
Log.d(tag, "Service Connected $name")
|
||||
|
||||
|
||||
mBounded = true
|
||||
|
|
|
|||
|
|
@ -5,11 +5,9 @@ import android.os.Handler
|
|||
import android.os.Looper
|
||||
import android.util.Log
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.getcapacitor.JSObject
|
||||
import com.getcapacitor.Plugin
|
||||
import com.getcapacitor.PluginCall
|
||||
import com.getcapacitor.PluginMethod
|
||||
import com.getcapacitor.*
|
||||
import com.getcapacitor.annotation.CapacitorPlugin
|
||||
import org.json.JSONObject
|
||||
|
||||
@CapacitorPlugin(name = "MyNativeAudio")
|
||||
class MyNativeAudio : Plugin() {
|
||||
|
|
@ -31,6 +29,13 @@ class MyNativeAudio : Plugin() {
|
|||
override fun onMetadata(metadata:JSObject) {
|
||||
notifyListeners("onMetadata", metadata)
|
||||
}
|
||||
override fun onPrepare(audiobookId:String, playWhenReady:Boolean) {
|
||||
var jsobj = JSObject()
|
||||
jsobj.put("audiobookId", audiobookId)
|
||||
jsobj.put("playWhenReady", playWhenReady)
|
||||
notifyListeners("onPrepareMedia", jsobj)
|
||||
}
|
||||
override fun onCar() {}
|
||||
})
|
||||
}
|
||||
mainActivity.pluginCallback = foregroundServiceReady
|
||||
|
|
@ -141,4 +146,37 @@ class MyNativeAudio : Plugin() {
|
|||
call.resolve()
|
||||
}
|
||||
}
|
||||
|
||||
@PluginMethod
|
||||
fun setAudiobooks(call: PluginCall) {
|
||||
var audiobooks = call.getArray("audiobooks", JSArray())
|
||||
if (audiobooks == null) {
|
||||
Log.w(tag, "setAudiobooks IS NULL")
|
||||
call.resolve()
|
||||
return
|
||||
}
|
||||
|
||||
var audiobookObjs = mutableListOf<Audiobook>()
|
||||
|
||||
var len = audiobooks.length()
|
||||
(0 until len).forEach { _it ->
|
||||
var jsonobj = audiobooks.get(_it) as JSONObject
|
||||
|
||||
var _names = Array(jsonobj.names().length()) {
|
||||
jsonobj.names().getString(it)
|
||||
}
|
||||
var jsobj = JSObject(jsonobj, _names)
|
||||
|
||||
if (jsobj.has("duration")) {
|
||||
var dur = jsobj.getDouble("duration")
|
||||
var duration = Math.floor(dur * 1000L).toLong()
|
||||
jsobj.put("duration", duration)
|
||||
}
|
||||
|
||||
var audiobook = Audiobook(jsobj)
|
||||
audiobookObjs.add(audiobook)
|
||||
}
|
||||
Log.d(tag, "Setting Audiobooks ${audiobookObjs.size}")
|
||||
playerNotificationService.setAudiobooks(audiobookObjs)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,17 +6,18 @@ import android.content.Intent
|
|||
import android.graphics.Bitmap
|
||||
import android.graphics.Color
|
||||
import android.net.Uri
|
||||
import android.os.Binder
|
||||
import android.os.Build
|
||||
import android.os.IBinder
|
||||
import android.provider.MediaStore
|
||||
import android.os.*
|
||||
import android.support.v4.media.MediaBrowserCompat
|
||||
import android.support.v4.media.MediaDescriptionCompat
|
||||
import android.support.v4.media.MediaMetadataCompat
|
||||
import android.support.v4.media.session.MediaControllerCompat
|
||||
import android.support.v4.media.session.MediaSessionCompat
|
||||
import android.support.v4.media.session.PlaybackStateCompat
|
||||
import android.util.Log
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.core.app.NotificationCompat
|
||||
import androidx.media.MediaBrowserServiceCompat
|
||||
import androidx.media.utils.MediaConstants
|
||||
import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
||||
import com.bumptech.glide.request.RequestOptions
|
||||
|
|
@ -25,20 +26,17 @@ import com.google.android.exoplayer2.*
|
|||
import com.google.android.exoplayer2.audio.AudioAttributes
|
||||
import com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector
|
||||
import com.google.android.exoplayer2.ext.mediasession.TimelineQueueNavigator
|
||||
import com.google.android.exoplayer2.source.DefaultMediaSourceFactory
|
||||
import com.google.android.exoplayer2.source.MediaSource
|
||||
import com.google.android.exoplayer2.source.ProgressiveMediaExtractor
|
||||
import com.google.android.exoplayer2.source.ProgressiveMediaSource
|
||||
import com.google.android.exoplayer2.source.hls.HlsMediaSource
|
||||
import com.google.android.exoplayer2.ui.PlayerNotificationManager
|
||||
import com.google.android.exoplayer2.upstream.*
|
||||
import kotlinx.coroutines.*
|
||||
import java.io.File
|
||||
|
||||
|
||||
const val NOTIFICATION_LARGE_ICON_SIZE = 144 // px
|
||||
|
||||
class PlayerNotificationService : Service() {
|
||||
class PlayerNotificationService : MediaBrowserServiceCompat() {
|
||||
|
||||
companion object {
|
||||
var isStarted = false
|
||||
|
|
@ -47,6 +45,8 @@ class PlayerNotificationService : Service() {
|
|||
interface MyCustomObjectListener {
|
||||
fun onPlayingUpdate(isPlaying: Boolean)
|
||||
fun onMetadata(metadata: JSObject)
|
||||
fun onPrepare(audiobookId:String, playWhenReady:Boolean)
|
||||
fun onCar()
|
||||
}
|
||||
|
||||
private val tag = "PlayerService"
|
||||
|
|
@ -71,6 +71,8 @@ class PlayerNotificationService : Service() {
|
|||
|
||||
private var currentAudiobook:Audiobook? = null
|
||||
|
||||
private var audiobooks = mutableListOf<Audiobook>()
|
||||
|
||||
fun setCustomObjectListener(mylistener: MyCustomObjectListener) {
|
||||
listener = mylistener
|
||||
}
|
||||
|
|
@ -78,8 +80,14 @@ class PlayerNotificationService : Service() {
|
|||
/*
|
||||
Service related stuff
|
||||
*/
|
||||
override fun onBind(intent: Intent?): IBinder? {
|
||||
override fun onBind(intent: Intent): IBinder? {
|
||||
Log.d(tag, "onBind")
|
||||
|
||||
// Android Auto Media Browser Service
|
||||
if (SERVICE_INTERFACE.equals(intent.getAction())) {
|
||||
Log.d(tag, "Is Media Browser Service")
|
||||
return super.onBind(intent);
|
||||
}
|
||||
return binder
|
||||
}
|
||||
|
||||
|
|
@ -97,11 +105,13 @@ class PlayerNotificationService : Service() {
|
|||
Log.d(tag, "onStartCommand $startId")
|
||||
isStarted = true
|
||||
|
||||
|
||||
|
||||
return START_STICKY
|
||||
}
|
||||
|
||||
override fun onStart(intent: Intent?, startId: Int) {
|
||||
Log.d(tag, "onStart $startId" )
|
||||
}
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.O)
|
||||
private fun createNotificationChannel(channelId: String, channelName: String): String{
|
||||
val chan = NotificationChannel(channelId,
|
||||
|
|
@ -166,6 +176,9 @@ class PlayerNotificationService : Service() {
|
|||
|
||||
val mediaController = MediaControllerCompat(ctx, mediaSession.sessionToken)
|
||||
|
||||
// This is for Media Browser
|
||||
sessionToken = mediaSession.sessionToken
|
||||
|
||||
val builder = PlayerNotificationManager.Builder(
|
||||
ctx,
|
||||
notificationId,
|
||||
|
|
@ -232,7 +245,53 @@ class PlayerNotificationService : Service() {
|
|||
return builder.build()
|
||||
}
|
||||
}
|
||||
|
||||
val myPlaybackPreparer:MediaSessionConnector.PlaybackPreparer = object :MediaSessionConnector.PlaybackPreparer {
|
||||
override fun onCommand(player: Player, controlDispatcher: ControlDispatcher, command: String, extras: Bundle?, cb: ResultReceiver?): Boolean {
|
||||
Log.d(tag, "ON COMMAND $command")
|
||||
return false
|
||||
}
|
||||
|
||||
override fun getSupportedPrepareActions(): Long {
|
||||
Log.d(tag, "GET SUPORTED ACITONS")
|
||||
return PlaybackStateCompat.ACTION_PREPARE_FROM_MEDIA_ID or
|
||||
PlaybackStateCompat.ACTION_PLAY_FROM_MEDIA_ID or
|
||||
PlaybackStateCompat.ACTION_PREPARE_FROM_SEARCH or
|
||||
PlaybackStateCompat.ACTION_PLAY_FROM_SEARCH
|
||||
}
|
||||
|
||||
override fun onPrepare(playWhenReady: Boolean) {
|
||||
Log.d(tag, "ON PREPARE $playWhenReady")
|
||||
|
||||
var audiobook = audiobooks[0]
|
||||
if (audiobook == null) {
|
||||
Log.e(tag, "Audiobook NOT FOUND")
|
||||
return
|
||||
}
|
||||
listener.onPrepare(audiobook.id, playWhenReady)
|
||||
}
|
||||
|
||||
override fun onPrepareFromMediaId(mediaId: String, playWhenReady: Boolean, extras: Bundle?) {
|
||||
Log.d(tag, "ON PREPARE FROM MEDIA ID $mediaId $playWhenReady")
|
||||
var audiobook = audiobooks.find { it.id == mediaId }
|
||||
if (audiobook == null) {
|
||||
Log.e(tag, "Audiobook NOT FOUND")
|
||||
return
|
||||
}
|
||||
listener.onPrepare(audiobook.id, playWhenReady)
|
||||
}
|
||||
|
||||
override fun onPrepareFromSearch(query: String, playWhenReady: Boolean, extras: Bundle?) {
|
||||
Log.d(tag, "ON PREPARE FROM SEARCH $query")
|
||||
}
|
||||
|
||||
override fun onPrepareFromUri(uri: Uri, playWhenReady: Boolean, extras: Bundle?) {
|
||||
Log.d(tag, "ON PREPARE FROM URI $uri")
|
||||
}
|
||||
|
||||
}
|
||||
mediaSessionConnector.setQueueNavigator(queueNavigator)
|
||||
mediaSessionConnector.setPlaybackPreparer(myPlaybackPreparer)
|
||||
mediaSessionConnector.setPlayer(mPlayer)
|
||||
|
||||
//attach player to playerNotificationManager
|
||||
|
|
@ -286,9 +345,6 @@ class PlayerNotificationService : Service() {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
private fun setPlayerListeners() {
|
||||
mPlayer.addListener(object : Player.Listener {
|
||||
override fun onPlayerError(error: PlaybackException) {
|
||||
|
|
@ -451,4 +507,81 @@ class PlayerNotificationService : Service() {
|
|||
metadata.put("stateName", stateName)
|
||||
if (listener != null) listener.onMetadata(metadata)
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// MEDIA BROWSER STUFF (ANDROID AUTO)
|
||||
//
|
||||
private val MY_MEDIA_ROOT_ID = "audiobookshelf"
|
||||
|
||||
fun setAudiobooks(_audiobooks:MutableList<Audiobook>) {
|
||||
audiobooks = _audiobooks
|
||||
}
|
||||
|
||||
private fun isValid(packageName:String, uid:Int) : Boolean {
|
||||
Log.d(tag, "Check package $packageName is valid with uid $uid")
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onGetRoot(clientPackageName: String, clientUid: Int, rootHints: Bundle?): BrowserRoot? {
|
||||
// Verify that the specified package is allowed to access your
|
||||
// content! You'll need to write your own logic to do this.
|
||||
return if (!isValid(clientPackageName, clientUid)) {
|
||||
// If the request comes from an untrusted package, return null.
|
||||
// No further calls will be made to other media browsing methods.
|
||||
null
|
||||
} else {
|
||||
listener.onCar()
|
||||
|
||||
val extras = Bundle()
|
||||
extras.putInt(
|
||||
MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_BROWSABLE,
|
||||
MediaConstants.DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_GRID_ITEM)
|
||||
extras.putInt(
|
||||
MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_PLAYABLE,
|
||||
MediaConstants.DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_GRID_ITEM)
|
||||
MediaBrowserServiceCompat.BrowserRoot(MY_MEDIA_ROOT_ID, extras)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onLoadChildren(parentMediaId: String, result: Result<MutableList<MediaBrowserCompat.MediaItem>>) {
|
||||
val mediaItems: MutableList<MediaBrowserCompat.MediaItem> = mutableListOf()
|
||||
|
||||
if (audiobooks.size == 0) {
|
||||
result.sendResult(mediaItems)
|
||||
return
|
||||
}
|
||||
|
||||
audiobooks.forEach {
|
||||
var builder = MediaDescriptionCompat.Builder()
|
||||
.setMediaId(it.id)
|
||||
.setTitle(it.title)
|
||||
.setSubtitle(it.author)
|
||||
.setMediaUri(it.playlistUri)
|
||||
.setIconUri(it.coverUri)
|
||||
|
||||
// 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 newMediaItem = MediaBrowserCompat.MediaItem(mediaDescription, MediaBrowserCompat.MediaItem.FLAG_PLAYABLE)
|
||||
mediaItems.add(newMediaItem)
|
||||
}
|
||||
|
||||
// Check if this is the root menu:
|
||||
if (MY_MEDIA_ROOT_ID == parentMediaId) {
|
||||
// build the MediaItem objects for the top level,
|
||||
// and put them in the mediaItems list
|
||||
} else {
|
||||
|
||||
// examine the passed parentMediaId to see which submenu we're at,
|
||||
// and put the children of that menu in the mediaItems list
|
||||
}
|
||||
result.sendResult(mediaItems)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
3
android/app/src/main/res/xml/automotive_app_desc.xml
Normal file
3
android/app/src/main/res/xml/automotive_app_desc.xml
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
<automotiveApp>
|
||||
<uses name="media" />
|
||||
</automotiveApp>
|
||||
|
|
@ -10,11 +10,11 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import Path from 'path'
|
||||
import { Capacitor } from '@capacitor/core'
|
||||
import { Network } from '@capacitor/network'
|
||||
import { AppUpdate } from '@robingenz/capacitor-app-update'
|
||||
import AudioDownloader from '@/plugins/audio-downloader'
|
||||
import MyNativeAudio from '@/plugins/my-native-audio'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
|
|
@ -248,6 +248,7 @@ export default {
|
|||
}
|
||||
|
||||
this.checkLoadCurrent()
|
||||
this.$store.dispatch('audiobooks/setNativeAudiobooks')
|
||||
},
|
||||
selectDownload(download) {
|
||||
this.$store.commit('setPlayOnLoad', true)
|
||||
|
|
@ -373,6 +374,25 @@ export default {
|
|||
this.checkForUpdate()
|
||||
this.initMediaStore()
|
||||
}
|
||||
|
||||
// For Testing Android Auto
|
||||
MyNativeAudio.addListener('onPrepareMedia', (data) => {
|
||||
var audiobookId = data.audiobookId
|
||||
var playWhenReady = data.playWhenReady
|
||||
|
||||
var audiobook = this.$store.getters['audiobooks/getAudiobook'](audiobookId)
|
||||
|
||||
var download = this.$store.getters['downloads/getDownloadIfReady'](audiobookId)
|
||||
this.$store.commit('setPlayOnLoad', playWhenReady)
|
||||
if (!download) {
|
||||
// Stream
|
||||
this.$store.commit('setStreamAudiobook', audiobook)
|
||||
this.$server.socket.emit('open_stream', audiobook.id)
|
||||
} else {
|
||||
// Local
|
||||
this.$store.commit('setPlayingDownload', download)
|
||||
}
|
||||
})
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (!this.$server) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "audiobookshelf-app",
|
||||
"version": "v0.9.0-beta",
|
||||
"version": "v0.9.1-beta",
|
||||
"author": "advplyr",
|
||||
"scripts": {
|
||||
"dev": "nuxt --hostname localhost --port 1337",
|
||||
|
|
|
|||
|
|
@ -46,7 +46,6 @@
|
|||
<script>
|
||||
import Path from 'path'
|
||||
import { Dialog } from '@capacitor/dialog'
|
||||
import { Capacitor } from '@capacitor/core'
|
||||
import AudioDownloader from '@/plugins/audio-downloader'
|
||||
|
||||
export default {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import MyNativeAudio from '@/plugins/my-native-audio'
|
||||
import { sort } from '@/assets/fastSort'
|
||||
import { decode } from '@/plugins/init.client'
|
||||
|
||||
|
|
@ -60,12 +61,13 @@ export const getters = {
|
|||
}
|
||||
|
||||
export const actions = {
|
||||
load({ commit }) {
|
||||
load({ commit, dispatch }) {
|
||||
return this.$axios
|
||||
.$get(`/api/audiobooks`)
|
||||
.then((data) => {
|
||||
console.log('Audiobooks request data', data)
|
||||
commit('set', data)
|
||||
dispatch('setNativeAudiobooks')
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('Failed', error)
|
||||
|
|
@ -73,6 +75,21 @@ export const actions = {
|
|||
},
|
||||
useDownloaded({ commit, rootGetters }) {
|
||||
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 })
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
import Vue from 'vue'
|
||||
|
||||
export const state = () => ({
|
||||
user: null,
|
||||
localUserAudiobooks: {},
|
||||
|
|
@ -31,15 +29,13 @@ export const getters = {
|
|||
|
||||
export const actions = {
|
||||
async updateUserSettings({ commit }, payload) {
|
||||
|
||||
if (Vue.prototype.$server.connected) {
|
||||
if (this.$server.connected) {
|
||||
var updatePayload = {
|
||||
...payload
|
||||
}
|
||||
return this.$axios.$patch('/api/user/settings', updatePayload).then((result) => {
|
||||
if (result.success) {
|
||||
commit('setSettings', result.settings)
|
||||
console.log('Settings updated', result.settings)
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
|
|
@ -80,9 +76,7 @@ export const mutations = {
|
|||
}
|
||||
}
|
||||
if (hasChanges) {
|
||||
console.log('Update settings in local storage')
|
||||
this.$localStore.setUserSettings({ ...state.settings })
|
||||
|
||||
state.settingsListeners.forEach((listener) => {
|
||||
listener.meth(state.settings)
|
||||
})
|
||||
|
|
|
|||
Loading…
Reference in a new issue