Fix episodeId download issue, add draggable for local tracks

This commit is contained in:
advplyr 2022-04-13 20:24:54 -05:00
parent 331a3b4a1a
commit ccba8dc3c7
11 changed files with 150 additions and 15 deletions

View file

@ -5,10 +5,7 @@ import com.audiobookshelf.app.MainActivity
import com.audiobookshelf.app.device.DeviceManager
import com.audiobookshelf.app.server.ApiHandler
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
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 kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
@ -202,6 +199,27 @@ class AbsDatabase : Plugin() {
}
}
@PluginMethod
fun updateLocalTrackOrder(call:PluginCall) {
var localLibraryItemId = call.getString("localLibraryItemId", "") ?: ""
var localLibraryItem = DeviceManager.dbManager.getLocalLibraryItem(localLibraryItemId)
if (localLibraryItem == null) {
call.resolve()
return
}
var tracks:JSArray = call.getArray("tracks") ?: JSArray()
Log.d(tag, "updateLocalTrackOrder $tracks")
for (i in 0..tracks.length()) {
var track = tracks.getJSONObject(i)
var localFileId = track.getString("localFileId")
Log.d(tag, "LOCAL FILE ID $localFileId")
}
call.resolve()
}
//
// Generic Webview calls to db
//

View file

@ -100,8 +100,9 @@ class AbsDownloader : Plugin() {
fun downloadLibraryItem(call: PluginCall) {
var libraryItemId = call.data.getString("libraryItemId").toString()
var episodeId = call.data.getString("episodeId").toString()
if (episodeId == "null") episodeId = ""
var localFolderId = call.data.getString("localFolderId").toString()
Log.d(tag, "Download library item $libraryItemId to folder $localFolderId")
Log.d(tag, "Download library item $libraryItemId to folder $localFolderId / episode: $episodeId")
var downloadId = if (episodeId.isNullOrEmpty()) libraryItemId else "$libraryItemId-$episodeId"
if (downloadQueue.find { it.id == downloadId } != null) {

View file

@ -42,11 +42,9 @@
</div>
<!-- Error widget -->
<ui-tooltip v-if="showError" :text="errorText" class="absolute bottom-4 left-0 z-10">
<div :style="{ height: 1.5 * sizeMultiplier + 'rem', width: 2.5 * sizeMultiplier + 'rem' }" class="bg-error rounded-r-full shadow-md flex items-center justify-end border-r border-b border-red-300">
<div v-if="showError" :style="{ height: 1.5 * sizeMultiplier + 'rem', width: 2.5 * sizeMultiplier + 'rem' }" class="bg-error rounded-r-full shadow-md flex items-center justify-end border-r border-b border-red-300">
<span class="material-icons text-red-100 pr-1" :style="{ fontSize: 0.875 * sizeMultiplier + 'rem' }">priority_high</span>
</div>
</ui-tooltip>
<!-- Volume number -->
<div v-if="seriesSequence && showSequence && !isSelectionMode" class="absolute rounded-lg bg-black bg-opacity-90 box-shadow-md z-10" :style="{ top: 0.375 * sizeMultiplier + 'rem', right: 0.375 * sizeMultiplier + 'rem', padding: `${0.1 * sizeMultiplier}rem ${0.25 * sizeMultiplier}rem` }">

View file

@ -24,6 +24,11 @@ export default {
{ hid: 'description', name: 'description', content: '' },
{ name: 'format-detection', content: 'telephone=no' }
],
script: [
{
src: '/libs/sortable.js'
}
],
link: [
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' },
{ rel: 'stylesheet', href: 'https://fonts.googleapis.com/css2?family=Ubuntu+Mono&family=Source+Sans+Pro:wght@300;400;600' },

13
package-lock.json generated
View file

@ -11775,6 +11775,11 @@
}
}
},
"sortablejs": {
"version": "1.10.2",
"resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.10.2.tgz",
"integrity": "sha512-YkPGufevysvfwn5rfdlGyrGjt7/CRHwvRPogD/lC+TnvcN29jDpCifKP+rBqf+LRldfXSTh+0CGLcSg0VIxq3A=="
},
"source-list-map": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz",
@ -13190,6 +13195,14 @@
"resolved": "https://registry.npmjs.org/vue-toastification/-/vue-toastification-1.7.14.tgz",
"integrity": "sha512-khZR8t3NWZ/JJ2MZxXLbesHrRJ8AKa75PY5Zq8yMifF9x8lHq8ljYkC0d2PD9yahooygQB5tcFyRDkbbIPx8hw=="
},
"vuedraggable": {
"version": "2.24.3",
"resolved": "https://registry.npmjs.org/vuedraggable/-/vuedraggable-2.24.3.tgz",
"integrity": "sha512-6/HDXi92GzB+Hcs9fC6PAAozK1RLt1ewPTLjK0anTYguXLAeySDmcnqE8IC0xa7shvSzRjQXq3/+dsZ7ETGF3g==",
"requires": {
"sortablejs": "1.10.2"
}
},
"vuex": {
"version": "3.6.2",
"resolved": "https://registry.npmjs.org/vuex/-/vuex-3.6.2.tgz",

View file

@ -28,7 +28,8 @@
"libarchive.js": "^1.3.0",
"nuxt": "^2.15.7",
"socket.io-client": "^4.1.3",
"vue-toastification": "^1.7.11"
"vue-toastification": "^1.7.11",
"vuedraggable": "^2.24.3"
},
"devDependencies": {
"@babel/core": "7.13.15",

View file

@ -18,10 +18,36 @@
<div v-if="isScanning" class="w-full text-center p-4">
<p>Scanning...</p>
</div>
<div v-else class="w-full media-item-container overflow-y-auto">
<div v-else class="w-full max-w-full media-item-container overflow-y-auto overflow-x-hidden relative">
<div v-if="!isPodcast" class="w-full">
<p class="text-base mb-2">Audio Tracks ({{ audioTracks.length }})</p>
<template v-for="track in audioTracks">
<draggable v-model="audioTracksCopy" v-bind="dragOptions" handle=".drag-handle" draggable=".item" tag="div" @start="drag = true" @end="drag = false" @update="draggableUpdate">
<transition-group type="transition" :name="!drag ? 'dragtrack' : null">
<template v-for="track in audioTracksCopy">
<div :key="track.localFileId" class="flex items-center my-1 item">
<div class="w-8 h-12 flex items-center justify-center" style="min-width: 32px">
<span class="material-icons drag-handle text-lg text-white text-opacity-50 hover:text-opacity-100">menu</span>
</div>
<div class="w-8 h-12 flex items-center justify-center" style="min-width: 32px">
<p class="font-mono font-bold text-xl">{{ track.index }}</p>
</div>
<div class="flex-grow px-2">
<p class="text-xs">{{ track.title }}</p>
</div>
<div class="w-20 text-center text-gray-300" style="min-width: 80px">
<p class="text-xs">{{ track.mimeType }}</p>
<p class="text-sm">{{ $elapsedPretty(track.duration) }}</p>
</div>
<div class="w-12 h-12 flex items-center justify-center" style="min-width: 48px">
<span class="material-icons" @click="showTrackDialog(track)">more_vert</span>
</div>
</div>
</template>
</transition-group>
</draggable>
<!-- <template v-for="track in audioTracks">
<div :key="track.localFileId" class="flex items-center my-1">
<div class="w-10 h-12 flex items-center justify-center" style="min-width: 48px">
<p class="font-mono font-bold text-xl">{{ track.index }}</p>
@ -37,7 +63,7 @@
<span class="material-icons" @click="showTrackDialog(track)">more_vert</span>
</div>
</div>
</template>
</template> -->
</div>
<div v-else class="w-full">
<p class="text-base mb-2">Episodes ({{ audioTracks.length }})</p>
@ -87,11 +113,16 @@
</template>
<script>
import draggable from 'vuedraggable'
import { Capacitor } from '@capacitor/core'
import { Dialog } from '@capacitor/dialog'
import { AbsFileSystem } from '@/plugins/capacitor'
export default {
components: {
draggable
},
asyncData({ params }) {
return {
localLibraryItemId: params.id
@ -99,8 +130,16 @@ export default {
},
data() {
return {
drag: false,
dragOptions: {
animation: 200,
group: 'description',
delay: 40,
delayOnTouchOnly: true
},
failed: false,
localLibraryItem: null,
audioTracksCopy: [],
removingItem: false,
folderId: null,
folder: null,
@ -187,6 +226,15 @@ export default {
}
},
methods: {
draggableUpdate() {
console.log('Draggable update', this.audioTracksCopy)
// var copyOfCopy = this.audioTracksCopy.map((at) => ({ ...at }))
// const payload = {
// localLibraryItemId: this.localLibraryItemId,
// tracks: copyOfCopy
// }
// this.$db.updateLocalTrackOrder(payload)
},
showItemDialog() {
this.selectedAudioTrack = null
this.showDialog = true
@ -322,6 +370,8 @@ export default {
return
}
this.audioTracksCopy = this.audioTracks.map((at) => ({ ...at }))
this.folderId = this.localLibraryItem.folderId
this.folder = await this.$db.getLocalFolder(this.folderId)
}
@ -332,9 +382,21 @@ export default {
}
</script>
<style scoped>
<style>
.media-item-container {
height: calc(100vh - 200px);
max-height: calc(100vh - 200px);
}
.sortable-ghost {
opacity: 0.5;
}
.dragtrack-enter-from,
.dragtrack-leave-to {
opacity: 0;
transform: translateX(30px);
}
.dragtrack-leave-active {
position: absolute;
}
</style>

View file

@ -111,6 +111,30 @@ class AbsDatabaseWeb extends WebPlugin {
isLocal: true,
localFileId: 'lf1',
audioProbeResult: {}
},
{
index: 2,
startOffset: 0,
duration: 15000,
title: 'Track Title 2',
contentUrl: 'test2',
mimeType: 'audio/mpeg',
metadata: null,
isLocal: true,
localFileId: 'lf2',
audioProbeResult: {}
},
{
index: 3,
startOffset: 0,
duration: 20000,
title: 'Track Title 3',
contentUrl: 'test3',
mimeType: 'audio/mpeg',
metadata: null,
isLocal: true,
localFileId: 'lf3',
audioProbeResult: {}
}
]
},
@ -170,6 +194,10 @@ class AbsDatabaseWeb extends WebPlugin {
async syncLocalMediaProgressWithServer() {
return null
}
async updateLocalTrackOrder({ localLibraryItemId, tracks }) {
return []
}
}
const AbsDatabase = registerPlugin('AbsDatabase', {

View file

@ -92,6 +92,10 @@ class DbService {
syncLocalMediaProgressWithServer() {
return AbsDatabase.syncLocalMediaProgressWithServer()
}
updateLocalTrackOrder(payload) {
return AbsDatabase.updateLocalTrackOrder(payload)
}
}
export default ({ app, store }, inject) => {

2
static/lib/sortable.js Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long