mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2026-03-06 07:59:43 +00:00
Compare commits
4 commits
df45347690
...
bdeb22615e
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bdeb22615e | ||
|
|
257bf2ebe0 | ||
|
|
fc33da447a | ||
|
|
3cc527484d |
6 changed files with 19 additions and 159 deletions
|
|
@ -274,15 +274,10 @@ export default {
|
|||
isAuthorsPage() {
|
||||
return this.page === 'authors'
|
||||
},
|
||||
isAlbumsPage() {
|
||||
return this.page === 'albums'
|
||||
},
|
||||
numShowing() {
|
||||
return this.totalEntities
|
||||
},
|
||||
entityName() {
|
||||
if (this.isAlbumsPage) return 'Albums'
|
||||
|
||||
if (this.isPodcastLibrary) return this.$strings.LabelPodcasts
|
||||
if (!this.page) return this.$strings.LabelBooks
|
||||
if (this.isSeriesPage) return this.$strings.LabelSeries
|
||||
|
|
|
|||
|
|
@ -1,142 +0,0 @@
|
|||
<template>
|
||||
<div ref="card" :id="`album-card-${index}`" :style="{ width: cardWidth + 'px' }" class="absolute top-0 left-0 rounded-xs z-30 cursor-pointer" @mousedown.prevent @mouseup.prevent @mousemove.prevent @mouseover="mouseover" @mouseleave="mouseleave" @click="clickCard">
|
||||
<div class="relative" :style="{ height: coverHeight + 'px' }">
|
||||
<div class="absolute top-0 left-0 w-full box-shadow-book shadow-height" />
|
||||
<div class="w-full h-full bg-primary relative rounded-sm overflow-hidden">
|
||||
<covers-preview-cover ref="cover" :src="coverSrc" :width="cardWidth" :book-cover-aspect-ratio="bookCoverAspectRatio" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="relative w-full">
|
||||
<div v-if="!isAlternativeBookshelfView" class="categoryPlacard absolute z-30 left-0 right-0 mx-auto -bottom-6e h-6e rounded-md text-center" :style="{ width: Math.min(200, cardWidth) + 'px' }">
|
||||
<div class="w-full h-full shinyBlack flex items-center justify-center rounded-xs border" :style="{ padding: `0em ${0.5}em` }">
|
||||
<p class="truncate" :style="{ fontSize: labelFontSize + 'em' }">{{ title }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="absolute z-30 left-0 right-0 mx-auto -bottom-8e h-8e py-1e rounded-md text-center">
|
||||
<p class="truncate" :style="{ fontSize: labelFontSize + 'em' }">{{ title }}</p>
|
||||
<p class="truncate text-gray-400" :style="{ fontSize: 0.8 + 'em' }">{{ artist || ' ' }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
index: Number,
|
||||
width: Number,
|
||||
height: {
|
||||
type: Number,
|
||||
default: 192
|
||||
},
|
||||
bookshelfView: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
albumMount: {
|
||||
type: Object,
|
||||
default: () => null
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
album: null,
|
||||
isSelectionMode: false,
|
||||
selected: false,
|
||||
isHovering: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
bookCoverAspectRatio() {
|
||||
return this.store.getters['libraries/getBookCoverAspectRatio']
|
||||
},
|
||||
cardWidth() {
|
||||
return this.width || this.coverHeight
|
||||
},
|
||||
coverHeight() {
|
||||
return this.height * this.sizeMultiplier
|
||||
},
|
||||
/*
|
||||
cardHeight() {
|
||||
return this.coverHeight + this.bottomTextHeight
|
||||
},
|
||||
bottomTextHeight() {
|
||||
if (!this.isAlternativeBookshelfView) return 0
|
||||
const lineHeight = 1.5
|
||||
const remSize = 16
|
||||
const baseHeight = this.sizeMultiplier * lineHeight * remSize
|
||||
const titleHeight = this.labelFontSize * baseHeight
|
||||
const paddingHeight = 4 * 2 * this.sizeMultiplier // py-1
|
||||
return titleHeight + paddingHeight
|
||||
},
|
||||
*/
|
||||
coverSrc() {
|
||||
const config = this.$config || this.$nuxt.$config
|
||||
if (!this.album || !this.album.libraryItemId) return `${config.routerBasePath}/book_placeholder.jpg`
|
||||
return this.store.getters['globals/getLibraryItemCoverSrcById'](this.album.libraryItemId)
|
||||
},
|
||||
labelFontSize() {
|
||||
if (this.width < 160) return 0.75
|
||||
return 0.9
|
||||
},
|
||||
sizeMultiplier() {
|
||||
return this.store.getters['user/getSizeMultiplier']
|
||||
},
|
||||
title() {
|
||||
return this.album ? this.album.title : ''
|
||||
},
|
||||
artist() {
|
||||
return this.album ? this.album.artist : ''
|
||||
},
|
||||
store() {
|
||||
return this.$store || this.$nuxt.$store
|
||||
},
|
||||
currentLibraryId() {
|
||||
return this.store.state.libraries.currentLibraryId
|
||||
},
|
||||
isAlternativeBookshelfView() {
|
||||
const constants = this.$constants || this.$nuxt.$constants
|
||||
return this.bookshelfView == constants.BookshelfView.DETAIL
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
setEntity(album) {
|
||||
this.album = album
|
||||
},
|
||||
setSelectionMode(val) {
|
||||
this.isSelectionMode = val
|
||||
},
|
||||
mouseover() {
|
||||
this.isHovering = true
|
||||
},
|
||||
mouseleave() {
|
||||
this.isHovering = false
|
||||
},
|
||||
clickCard() {
|
||||
if (!this.album) return
|
||||
// const router = this.$router || this.$nuxt.$router
|
||||
// router.push(`/album/${this.$encode(this.title)}`)
|
||||
},
|
||||
clickEdit() {
|
||||
this.$emit('edit', this.album)
|
||||
},
|
||||
destroy() {
|
||||
// destroy the vue listeners, etc
|
||||
this.$destroy()
|
||||
|
||||
// remove the element from the DOM
|
||||
if (this.$el && this.$el.parentNode) {
|
||||
this.$el.parentNode.removeChild(this.$el)
|
||||
} else if (this.$el && this.$el.remove) {
|
||||
this.$el.remove()
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
if (this.albumMount) {
|
||||
this.setEntity(this.albumMount)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
@ -3,7 +3,6 @@ import LazyBookCard from '@/components/cards/LazyBookCard'
|
|||
import LazySeriesCard from '@/components/cards/LazySeriesCard'
|
||||
import LazyCollectionCard from '@/components/cards/LazyCollectionCard'
|
||||
import LazyPlaylistCard from '@/components/cards/LazyPlaylistCard'
|
||||
import LazyAlbumCard from '@/components/cards/LazyAlbumCard'
|
||||
import AuthorCard from '@/components/cards/AuthorCard'
|
||||
|
||||
export default {
|
||||
|
|
@ -20,7 +19,6 @@ export default {
|
|||
if (this.entityName === 'series') return Vue.extend(LazySeriesCard)
|
||||
if (this.entityName === 'collections') return Vue.extend(LazyCollectionCard)
|
||||
if (this.entityName === 'playlists') return Vue.extend(LazyPlaylistCard)
|
||||
if (this.entityName === 'albums') return Vue.extend(LazyAlbumCard)
|
||||
if (this.entityName === 'authors') return Vue.extend(AuthorCard)
|
||||
return Vue.extend(LazyBookCard)
|
||||
},
|
||||
|
|
@ -28,7 +26,6 @@ export default {
|
|||
if (this.entityName === 'series') return 'cards-lazy-series-card'
|
||||
if (this.entityName === 'collections') return 'cards-lazy-collection-card'
|
||||
if (this.entityName === 'playlists') return 'cards-lazy-playlist-card'
|
||||
if (this.entityName === 'albums') return 'cards-lazy-album-card'
|
||||
if (this.entityName === 'authors') return 'cards-author-card'
|
||||
return 'cards-lazy-book-card'
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<div id="page-wrapper" class="bg-bg page overflow-y-auto relative" :class="streamLibraryItem ? 'streaming' : ''">
|
||||
<div class="flex items-center py-4 px-2 md:px-0 max-w-7xl mx-auto">
|
||||
<div class="flex items-center py-4 px-4 max-w-7xl mx-auto">
|
||||
<nuxt-link :to="`/item/${libraryItem.id}`" class="hover:underline">
|
||||
<h1 class="text-lg lg:text-xl">{{ title }}</h1>
|
||||
</nuxt-link>
|
||||
|
|
@ -12,7 +12,7 @@
|
|||
<p class="text-base font-mono ml-4 hidden md:block">{{ $secondsToTimestamp(mediaDurationRounded) }}</p>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-wrap-reverse justify-center py-4 px-2">
|
||||
<div class="flex flex-wrap-reverse lg:flex-nowrap justify-center py-4 px-4">
|
||||
<div class="w-full max-w-3xl py-4">
|
||||
<div class="flex items-center">
|
||||
<div class="w-12 hidden lg:block" />
|
||||
|
|
@ -23,8 +23,8 @@
|
|||
</div>
|
||||
<div class="flex items-center mb-3 py-1 -mx-1">
|
||||
<div class="w-12 hidden lg:block" />
|
||||
<ui-btn v-if="chapters.length" color="bg-primary" small class="mx-1" @click.stop="removeAllChaptersClick">{{ $strings.ButtonRemoveAll }}</ui-btn>
|
||||
<ui-btn v-if="newChapters.length > 1" :color="showShiftTimes ? 'bg' : 'primary'" class="mx-1" small @click="showShiftTimes = !showShiftTimes">{{ $strings.ButtonShiftTimes }}</ui-btn>
|
||||
<ui-btn v-if="chapters.length" color="bg-primary" small class="mx-1 whitespace-nowrap" @click.stop="removeAllChaptersClick">{{ $strings.ButtonRemoveAll }}</ui-btn>
|
||||
<ui-btn v-if="newChapters.length > 1" :color="showShiftTimes ? 'bg-bg' : 'bg-primary'" class="mx-1 whitespace-nowrap" small @click="showShiftTimes = !showShiftTimes">{{ $strings.ButtonShiftTimes }}</ui-btn>
|
||||
<ui-btn color="bg-primary" small :class="{ 'mx-1': newChapters.length > 1 }" @click="showFindChaptersModal = true">{{ $strings.ButtonLookup }}</ui-btn>
|
||||
<div class="grow" />
|
||||
<ui-btn v-if="hasChanges" small class="mx-1" @click.stop="resetChapters">{{ $strings.ButtonReset }}</ui-btn>
|
||||
|
|
@ -65,7 +65,7 @@
|
|||
<ui-time-picker v-else class="text-xs" v-model="chapter.start" :show-three-digit-hour="mediaDuration >= 360000" @change="checkChapters" />
|
||||
</div>
|
||||
<div class="grow px-1">
|
||||
<ui-text-input v-model="chapter.title" @change="checkChapters" class="text-xs" />
|
||||
<ui-text-input v-model="chapter.title" @change="checkChapters" class="text-xs min-w-52" />
|
||||
</div>
|
||||
<div class="w-32 min-w-32 px-2 py-1">
|
||||
<div class="flex items-center">
|
||||
|
|
|
|||
|
|
@ -242,7 +242,7 @@ module.exports.recurseFiles = async (path, relPathToReplace = null) => {
|
|||
})
|
||||
.filter((item) => {
|
||||
// Filter out items in ignore directories
|
||||
if (directoriesToIgnore.some((dir) => item.fullname.startsWith(dir))) {
|
||||
if (directoriesToIgnore.some((dir) => item.fullname.startsWith(dir + '/'))) {
|
||||
Logger.debug(`[fileUtils] Ignoring path in dir with .ignore "${item.fullname}"`)
|
||||
return false
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ describe('fileUtils', () => {
|
|||
|
||||
// Mock file structure with normalized paths
|
||||
const mockDirContents = new Map([
|
||||
['/test', ['file1.mp3', 'subfolder', 'ignoreme', 'temp.mp3.tmp']],
|
||||
['/test', ['file1.mp3', 'subfolder', 'ignoreme', 'ignoremenot.mp3', 'temp.mp3.tmp']],
|
||||
['/test/subfolder', ['file2.m4b']],
|
||||
['/test/ignoreme', ['.ignore', 'ignored.mp3']]
|
||||
])
|
||||
|
|
@ -59,7 +59,8 @@ describe('fileUtils', () => {
|
|||
['/test/ignoreme', { isDirectory: () => true, size: 0, mtimeMs: Date.now(), ino: '4' }],
|
||||
['/test/ignoreme/.ignore', { isDirectory: () => false, size: 0, mtimeMs: Date.now(), ino: '5' }],
|
||||
['/test/ignoreme/ignored.mp3', { isDirectory: () => false, size: 1024, mtimeMs: Date.now(), ino: '6' }],
|
||||
['/test/temp.mp3.tmp', { isDirectory: () => false, size: 1024, mtimeMs: Date.now(), ino: '7' }]
|
||||
['/test/ignoremenot.mp3', { isDirectory: () => false, size: 1024, mtimeMs: Date.now(), ino: '7' }],
|
||||
['/test/temp.mp3.tmp', { isDirectory: () => false, size: 1024, mtimeMs: Date.now(), ino: '8' }]
|
||||
])
|
||||
|
||||
// Stub fs.readdir
|
||||
|
|
@ -103,7 +104,7 @@ describe('fileUtils', () => {
|
|||
it('should return filtered file list', async () => {
|
||||
const files = await fileUtils.recurseFiles('/test')
|
||||
expect(files).to.be.an('array')
|
||||
expect(files).to.have.lengthOf(2)
|
||||
expect(files).to.have.lengthOf(3)
|
||||
|
||||
expect(files[0]).to.deep.equal({
|
||||
name: 'file1.mp3',
|
||||
|
|
@ -115,6 +116,15 @@ describe('fileUtils', () => {
|
|||
})
|
||||
|
||||
expect(files[1]).to.deep.equal({
|
||||
name: 'ignoremenot.mp3',
|
||||
path: 'ignoremenot.mp3',
|
||||
reldirpath: '',
|
||||
fullpath: '/test/ignoremenot.mp3',
|
||||
extension: '.mp3',
|
||||
deep: 0
|
||||
})
|
||||
|
||||
expect(files[2]).to.deep.equal({
|
||||
name: 'file2.m4b',
|
||||
path: 'subfolder/file2.m4b',
|
||||
reldirpath: 'subfolder',
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue