Change: Bookmark UI #115

This commit is contained in:
advplyr 2021-11-03 17:45:47 -05:00
parent 76f28971a9
commit 908b9da112
6 changed files with 115 additions and 95 deletions

View File

@ -27,7 +27,7 @@
<audio-player ref="audioPlayer" :chapters="chapters" :loading="isLoading" :bookmarks="bookmarks" @close="cancelStream" @updateTime="updateTime" @loaded="(d) => (totalDuration = d)" @showBookmarks="showBookmarks" @hook:mounted="audioPlayerMounted" />
<modals-bookmarks-modal v-model="showBookmarksModal" :bookmarks="bookmarks" :audiobook-id="bookmarkAudiobookId" :current-time="bookmarkCurrentTime" @select="selectBookmark" @create="createBookmark" @update="updateBookmark" @delete="deleteBookmark" />
<modals-bookmarks-modal v-model="showBookmarksModal" :bookmarks="bookmarks" :audiobook-id="bookmarkAudiobookId" :current-time="bookmarkCurrentTime" @select="selectBookmark" />
</div>
</template>
@ -58,7 +58,7 @@ export default {
},
bookmarks() {
if (!this.userAudiobook) return []
return this.userAudiobook.bookmarks || []
return (this.userAudiobook.bookmarks || []).map((bm) => ({ ...bm })).sort((a, b) => a.time - b.time)
},
isLoading() {
if (!this.streamAudiobook) return false
@ -111,38 +111,12 @@ export default {
this.bookmarkCurrentTime = currentTime
this.showBookmarksModal = true
},
// bookmarkCreated(time) {
// if (time === this.bookmarkTimeProcessing) {
// this.bookmarkTimeProcessing = 0
// this.$toast.success(`${this.$secondsToTimestamp(time)} Bookmarked`)
// }
// },
createBookmark(bookmark) {
// this.bookmarkTimeProcessing = bookmark.time
this.$root.socket.emit('create_bookmark', bookmark)
this.showBookmarksModal = false
},
// bookmarkUpdated(time) {
// if (time === this.bookmarkTimeProcessing) {
// this.bookmarkTimeProcessing = 0
// this.$toast.success(`Bookmark @${this.$secondsToTimestamp(time)} Updated`)
// }
// },
updateBookmark(bookmark) {
// this.bookmarkTimeProcessing = bookmark.time
this.$root.socket.emit('update_bookmark', bookmark)
this.showBookmarksModal = false
},
selectBookmark(bookmark) {
if (this.$refs.audioPlayer) {
this.$refs.audioPlayer.selectBookmark(bookmark)
}
this.showBookmarksModal = false
},
deleteBookmark(bookmark) {
this.$root.socket.emit('delete_bookmark', bookmark)
this.showBookmarksModal = false
},
filterByAuthor() {
if (this.$route.name !== 'index') {
this.$router.push(`/library/${this.libraryId || this.$store.state.libraries.currentLibraryId}/bookshelf`)

View File

@ -1,38 +1,27 @@
<template>
<modals-modal v-model="show" name="bookmarks" :width="500" :height="'unset'">
<div ref="container" class="w-full rounded-lg bg-primary box-shadow-md overflow-y-auto overflow-x-hidden" style="max-height: 80vh">
<div class="w-full h-full px-6 py-6" v-show="showBookmarkTitleInput">
<div class="flex mb-4 items-center">
<div class="w-9 h-9 flex items-center justify-center rounded-full hover:bg-white hover:bg-opacity-10 cursor-pointer" @click="showBookmarkTitleInput = false">
<span class="material-icons text-3xl">arrow_back</span>
</div>
<p class="text-xl pl-2">{{ selectedBookmark ? 'Edit Bookmark' : 'New Bookmark' }}</p>
<div class="flex-grow" />
<p class="text-xl font-mono">
{{ this.$secondsToTimestamp(currentTime) }}
</p>
</div>
<form @submit.prevent="submitBookmark">
<ui-text-input-with-label v-model="newBookmarkTitle" label="Note" />
<div class="flex justify-end mt-6">
<ui-btn color="success" class="w-1/2" type="submit">{{ selectedBookmark ? 'Update' : 'Create' }} Bookmark</ui-btn>
</div>
</form>
</div>
<div class="w-full h-full" v-show="!showBookmarkTitleInput">
<div v-if="show" class="w-full h-full">
<template v-for="bookmark in bookmarks">
<modals-bookmarks-bookmark-item :key="bookmark.id" :highlight="currentTime === bookmark.time" :bookmark="bookmark" @click="clickBookmark" @edit="editBookmark" @delete="deleteBookmark" />
<modals-bookmarks-bookmark-item :key="bookmark.id" :highlight="currentTime === bookmark.time" :bookmark="bookmark" @click="clickBookmark" @update="submitUpdateBookmark" @delete="deleteBookmark" />
</template>
<div v-if="!bookmarks.length" class="flex h-32 items-center justify-center">
<p class="text-xl">No Bookmarks</p>
</div>
<div v-show="canCreateBookmark" class="flex px-4 py-2 items-center text-center justify-between border-b border-white border-opacity-10 bg-blue-500 bg-opacity-20 cursor-pointer text-white text-opacity-80 hover:bg-opacity-40 hover:text-opacity-100" @click="createBookmark">
<span class="material-icons">add</span>
<p class="text-base pl-2">Create Bookmark</p>
<p class="text-sm font-mono">
{{ this.$secondsToTimestamp(currentTime) }}
</p>
</div>
<div class="w-full h-px bg-white bg-opacity-10" />
<form @submit.prevent="submitCreateBookmark">
<div v-show="canCreateBookmark" class="flex px-4 py-2 items-center text-center border-b border-white border-opacity-10 text-white text-opacity-80">
<div class="w-16 text-center">
<p class="text-sm font-mono">
{{ this.$secondsToTimestamp(currentTime) }}
</p>
</div>
<div class="flex-grow px-2">
<ui-text-input v-model="newBookmarkTitle" placeholder="Note" class="w-full" />
</div>
<ui-btn type="submit" color="success" :padding-x="4" class="h-10"><span class="material-icons -mt-px">add</span></ui-btn>
</div>
</form>
</div>
</div>
</modals-modal>
@ -88,34 +77,34 @@ export default {
},
deleteBookmark(bm) {
var bookmark = { ...bm, audiobookId: this.audiobookId }
this.$emit('delete', bookmark)
this.$root.socket.emit('delete_bookmark', bookmark)
this.show = false
},
clickBookmark(bm) {
this.$emit('select', bm)
},
createBookmark() {
this.selectedBookmark = null
this.newBookmarkTitle = this.$formatDate(Date.now(), 'MMM dd, yyyy HH:mm')
this.showBookmarkTitleInput = true
submitUpdateBookmark(updatedBookmark) {
var bookmark = { ...updatedBookmark }
bookmark.audiobookId = this.audiobookId
this.$root.socket.emit('update_bookmark', bookmark)
this.show = false
},
submitBookmark() {
if (this.selectedBookmark) {
if (this.selectedBookmark.title !== this.newBookmarkTitle) {
var bookmark = { ...this.selectedBookmark }
bookmark.audiobookId = this.audiobookId
bookmark.title = this.newBookmarkTitle
this.$emit('update', bookmark)
}
} else {
var bookmark = {
audiobookId: this.audiobookId,
title: this.newBookmarkTitle,
time: this.currentTime
}
this.$emit('create', bookmark)
submitCreateBookmark() {
if (!this.newBookmarkTitle) {
this.newBookmarkTitle = this.$formatDate(Date.now(), 'MMM dd, yyyy HH:mm')
}
var bookmark = {
audiobookId: this.audiobookId,
title: this.newBookmarkTitle,
time: this.currentTime
}
this.$root.socket.emit('create_bookmark', bookmark)
this.newBookmarkTitle = ''
this.showBookmarkTitleInput = false
this.show = false
}
}
}

View File

@ -1,15 +1,30 @@
<template>
<div :key="bookmark.id" :id="`bookmark-row-${bookmark.id}`" class="flex items-center px-4 py-4 justify-start cursor-pointer hover:bg-bg relative" :class="highlight ? 'bg-bg bg-opacity-60' : ' bg-opacity-20'" @click="click" @mouseover="isHovering = true" @mouseleave="isHovering = false">
<span class="material-icons" :class="highlight ? 'text-success' : 'text-white text-opacity-60'">{{ highlight ? 'bookmark' : 'bookmark_border' }}</span>
<div :key="bookmark.id" :id="`bookmark-row-${bookmark.id}`" class="flex items-center px-4 py-4 justify-start relative hover:bg-bg" :class="wrapperClass" @click="click" @mouseover="mouseover" @mouseleave="mouseleave">
<!-- <span class="material-icons" :class="highlight ? 'text-success' : 'text-white text-opacity-80'">{{ highlight ? 'bookmark' : 'bookmark_border' }}</span> -->
<div class="w-12 min-w-12 text-center">
<p class="text-sm font-mono text-white text-opacity-80">
{{ this.$secondsToTimestamp(bookmark.time) }}
</p>
</div>
<div class="flex-grow overflow-hidden">
<p class="pl-2 pr-2 truncate">{{ bookmark.title }}</p>
<template v-if="isEditing">
<form @submit.prevent="submitUpdate">
<div class="flex items-center">
<div class="flex-grow pr-2">
<ui-text-input v-model="newBookmarkTitle" placeholder="Note" class="w-full" />
</div>
<ui-btn type="submit" color="success" :padding-x="4" class="h-10"><span class="material-icons -mt-px">forward</span></ui-btn>
<div class="pl-2 flex items-center">
<span class="material-icons text-3xl text-white text-opacity-70 hover:text-opacity-95 cursor-pointer" @click.stop.prevent="cancelEditing">close</span>
</div>
</div>
</form>
</template>
<p v-else class="pl-2 pr-2 truncate">{{ bookmark.title }}</p>
</div>
<div class="h-full flex items-center w-16 justify-end">
<span class="font-mono text-sm text-gray-300">{{ $secondsToTimestamp(bookmark.time) }}</span>
</div>
<div class="h-full flex items-center justify-end transform" :class="isHovering ? 'transition-transform translate-0 w-16' : 'translate-x-40 w-0'">
<span class="material-icons text-lg mr-2 text-gray-200 hover:text-yellow-400" @click.stop="editClick">edit</span>
<span class="material-icons text-lg text-gray-200 hover:text-error cursor-pointer" @click.stop="deleteClick">delete</span>
<div v-if="!isEditing" class="h-full flex items-center justify-end transform" :class="isHovering ? 'transition-transform translate-0 w-16' : 'translate-x-40 w-0'">
<span class="material-icons text-xl mr-2 text-gray-200 hover:text-yellow-400" @click.stop="editClick">edit</span>
<span class="material-icons text-xl text-gray-200 hover:text-error cursor-pointer" @click.stop="deleteClick">delete</span>
</div>
</div>
</template>
@ -25,19 +40,53 @@ export default {
},
data() {
return {
isHovering: false
isHovering: false,
isEditing: false,
newBookmarkTitle: null
}
},
computed: {
wrapperClass() {
var classes = []
if (this.highlight) classes.push('bg-bg bg-opacity-60')
if (!this.isEditing) classes.push('cursor-pointer')
return classes.join(' ')
}
},
computed: {},
methods: {
click() {
mouseover() {
if (this.isEditing) return
this.isHovering = true
},
mouseleave() {
this.isHovering = false
},
click(e) {
if (this.isEditing) {
if (e) e.stopPropagation()
return
}
this.$emit('click', this.bookmark)
},
deleteClick() {
if (this.isEditing) return
this.$emit('delete', this.bookmark)
},
editClick() {
this.$emit('edit', this.bookmark)
this.newBookmarkTitle = this.bookmark.title
this.isEditing = true
this.isHovering = false
},
cancelEditing() {
this.isEditing = false
},
submitUpdate() {
if (this.newBookmarkTitle === this.bookmark.title) {
return this.cancelEditing()
}
var bookmark = { ...this.bookmark }
bookmark.title = this.newBookmarkTitle
this.$emit('update', bookmark)
}
},
mounted() {}

8
package-lock.json generated
View File

@ -1,6 +1,6 @@
{
"name": "audiobookshelf",
"version": "1.4.13",
"version": "1.6.2",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@ -1222,9 +1222,9 @@
"integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw=="
},
"njodb": {
"version": "0.4.21",
"resolved": "https://registry.npmjs.org/njodb/-/njodb-0.4.21.tgz",
"integrity": "sha512-3qLMzwIZUgT1yq2PCzJlT6FFK/zfLHz71QnFeE9ec4KKJH9abY4SXnmHVaWP7wVq+lY77wW1F+EeKG9gm8j6WA==",
"version": "0.4.22",
"resolved": "https://registry.npmjs.org/njodb/-/njodb-0.4.22.tgz",
"integrity": "sha512-/paIiYKICyV/z540d27dF54y3Tv/DgY7MY/jQxcMLALyFpdYY/xSu+o78nko/3FpGBt34KPPlNOwnzLsy+WuxA==",
"requires": {
"proper-lockfile": "^4.1.2"
}

View File

@ -38,7 +38,7 @@
"ip": "^1.1.5",
"jsonwebtoken": "^8.5.1",
"libgen": "^2.1.0",
"njodb": "^0.4.21",
"njodb": "^0.4.22",
"node-cron": "^3.0.0",
"node-dir": "^0.1.17",
"node-stream-zip": "^1.15.0",
@ -48,4 +48,4 @@
"watcher": "^1.2.0"
},
"devDependencies": {}
}
}

View File

@ -170,7 +170,15 @@ class Db {
updateEntity(entityName, entity) {
var entityDb = this.getEntityDb(entityName)
return entityDb.update((record) => record.id === entity.id, () => entity).then((results) => {
var jsonEntity = entity
if (entity && entity.toJSON) {
jsonEntity = entity.toJSON()
} else {
console.log('Entity has no json', jsonEntity)
}
return entityDb.update((record) => record.id === entity.id, () => jsonEntity).then((results) => {
Logger.debug(`[DB] Updated entity ${entityName}: ${results.updated}`)
var arrayKey = this.getEntityArrayKey(entityName)
this[arrayKey] = this[arrayKey].map(e => {