Change: UI to display correctly on mobile #162

This commit is contained in:
advplyr 2021-11-04 17:35:59 -05:00
parent b0ea2f8008
commit b827667a72
30 changed files with 239 additions and 102 deletions

View File

@ -14,6 +14,11 @@
#bookshelf {
height: calc(100% - 40px);
}
@media (max-width: 768px) {
#bookshelf {
height: calc(100% - 80px);
}
}
/* width */
::-webkit-scrollbar {

View File

@ -8,21 +8,21 @@
<p class="font-mono text-sm text-gray-100 pointer-events-auto">{{ timeRemainingPretty }}</p>
</div>
<div v-if="chapters.length" class="absolute right-20 top-0 bottom-0 h-full flex items-end">
<div v-if="chapters.length" class="hidden md:flex absolute right-20 top-0 bottom-0 h-full items-end">
<div class="cursor-pointer text-gray-300" @mousedown.prevent @mouseup.prevent @click.stop="showChapters">
<span class="material-icons text-3xl">format_list_bulleted</span>
</div>
</div>
<div class="absolute top-0 bottom-0 h-full flex items-end" :class="chapters.length ? ' right-32' : 'right-20'">
<div class="absolute top-0 bottom-0 h-full hidden md:flex items-end" :class="chapters.length ? ' right-32' : 'right-20'">
<div class="cursor-pointer text-gray-300" @mousedown.prevent @mouseup.prevent @click.stop="showBookmarks">
<span class="material-icons" style="font-size: 1.7rem">{{ bookmarks.length ? 'bookmarks' : 'bookmark_border' }}</span>
</div>
</div>
<div class="absolute top-0 bottom-0 h-full flex items-end" :class="chapters.length ? ' right-44' : 'right-32'">
<div class="absolute top-0 bottom-0 h-full hidden md:flex items-end" :class="chapters.length ? ' right-44' : 'right-32'">
<controls-volume-control ref="volumeControl" v-model="volume" @input="updateVolume" />
</div>
<div class="flex pb-2">
<div class="flex pb-8 sm:pb-4 md:pb-2">
<div class="flex-grow" />
<template v-if="!loading">
<div class="cursor-pointer flex items-center justify-center text-gray-300 mr-8" @mousedown.prevent @mouseup.prevent @click.stop="restart">

View File

@ -1,33 +1,33 @@
<template>
<div class="w-full h-16 bg-primary relative">
<div id="appbar" class="absolute top-0 bottom-0 left-0 w-full h-full px-6 py-1 z-40">
<div id="appbar" class="absolute top-0 bottom-0 left-0 w-full h-full px-2 md:px-6 py-1 z-40">
<div class="flex h-full items-center">
<img v-if="!showBack" src="/Logo48.png" class="w-12 h-12 mr-4" />
<img v-if="!showBack" src="/Logo48.png" class="w-10 h-10 md:w-12 md:h-12 mr-4" />
<a v-if="showBack" @click="back" class="rounded-full h-12 w-12 flex items-center justify-center hover:bg-white hover:bg-opacity-10 mr-4 cursor-pointer">
<span class="material-icons text-4xl text-white">arrow_back</span>
</a>
<h1 class="text-2xl font-book mr-6">audiobookshelf</h1>
<h1 class="text-2xl font-book mr-6 hidden lg:block">audiobookshelf</h1>
<ui-libraries-dropdown />
<controls-global-search />
<controls-global-search class="hidden md:block" />
<div class="flex-grow" />
<span v-if="showExperimentalFeatures" class="material-icons text-4xl text-warning pr-4">logo_dev</span>
<span v-if="showExperimentalFeatures" class="material-icons text-4xl text-warning pr-0 sm:pr-2 md:pr-4">logo_dev</span>
<nuxt-link v-if="userCanUpload" to="/upload" class="outline-none hover:text-gray-200 cursor-pointer w-8 h-8 flex items-center justify-center">
<span class="material-icons">upload</span>
</nuxt-link>
<nuxt-link v-if="isRootUser" to="/config" class="outline-none hover:text-gray-200 cursor-pointer w-8 h-8 flex items-center justify-center ml-4">
<nuxt-link v-if="isRootUser" to="/config" class="outline-none hover:text-gray-200 cursor-pointer w-8 h-8 flex items-center justify-center ml-0 sm:ml-2 md:ml-4">
<span class="material-icons">settings</span>
</nuxt-link>
<nuxt-link to="/account" class="relative w-32 bg-fg border border-gray-500 rounded shadow-sm ml-5 pl-3 pr-10 py-2 text-left focus:outline-none sm:text-sm cursor-pointer hover:bg-bg hover:bg-opacity-40" aria-haspopup="listbox" aria-expanded="true">
<span class="flex items-center">
<nuxt-link to="/account" class="relative w-9 h-9 md:w-32 bg-fg border border-gray-500 rounded shadow-sm ml-1.5 sm:ml-3 md:ml-5 md:pl-3 md:pr-10 py-2 text-left focus:outline-none sm:text-sm cursor-pointer hover:bg-bg hover:bg-opacity-40" aria-haspopup="listbox" aria-expanded="true">
<span class="items-center hidden md:flex">
<span class="block truncate">{{ username }}</span>
</span>
<span class="ml-3 absolute inset-y-0 right-0 flex items-center pr-2 pointer-events-none">
<span class="h-full md:ml-3 md:absolute inset-y-0 md:right-0 flex items-center justify-center md:pr-2 pointer-events-none">
<span class="material-icons text-gray-100">person</span>
</span>
</nuxt-link>

View File

@ -1,5 +1,5 @@
<template>
<div class="bookshelf overflow-hidden relative block max-h-full">
<div id="bookshelf" class="bookshelf overflow-hidden relative block max-h-full">
<div ref="wrapper" class="h-full w-full relative" :class="isGridMode ? 'overflow-y-scroll' : 'overflow-hidden'">
<!-- Cover size widget -->
<div v-show="!isSelectionMode && isGridMode" class="fixed bottom-2 right-4 z-30">
@ -362,9 +362,16 @@ export default {
<style>
.bookshelf {
height: calc(100% - 40px);
/* height: calc(100% - 40px); */
width: calc(100vw - 80px);
}
@media (max-width: 768px) {
.bookshelf {
/* height: calc(100% - 80px); */
width: 100vw;
}
}
.bookshelfRow {
background-image: url(/wood_panels.jpg);
}

View File

@ -16,7 +16,7 @@
<ui-btn color="success" class="w-52" @click="scan">Scan Audiobooks</ui-btn>
</div>
</div>
<div v-else id="bookshelf" class="w-full flex flex-col items-center">
<div v-else class="w-full flex flex-col items-center">
<template v-for="(shelf, index) in shelves">
<app-book-shelf-row :key="index" :index="index" :shelf="shelf" :size-multiplier="sizeMultiplier" :book-cover-width="bookCoverWidth" />
</template>

View File

@ -1,6 +1,6 @@
<template>
<div class="relative">
<div ref="shelf" class="w-full max-w-full bookshelfRowCategorized relative overflow-x-scroll overflow-y-hidden z-10" :style="{ paddingLeft: 2.5 * sizeMultiplier + 'rem' }" @scroll="scrolled">
<div ref="shelf" class="w-full max-w-full categorizedBookshelfRow relative overflow-x-scroll overflow-y-hidden z-10" :style="{ paddingLeft: paddingLeft * sizeMultiplier + 'rem' }" @scroll="scrolled">
<div class="w-full h-full" :style="{ marginTop: sizeMultiplier + 'rem' }">
<div v-if="shelf.books" class="flex items-center -mb-2">
<template v-for="entity in shelf.books">
@ -22,7 +22,7 @@
</div>
</div>
<div class="absolute text-center categoryPlacard font-book transform z-30 bottom-0.5 left-8 w-36 rounded-md" style="height: 22px">
<div class="absolute text-center categoryPlacard font-book transform z-30 bottom-0.5 left-4 md:left-8 w-36 rounded-md" style="height: 22px">
<div class="w-full h-full shinyBlack flex items-center justify-center rounded-sm border">
<p class="transform text-sm">{{ shelf.label }}</p>
</div>
@ -62,6 +62,10 @@ export default {
computed: {
userAudiobooks() {
return this.$store.state.user.user ? this.$store.state.user.user.audiobooks || {} : {}
},
paddingLeft() {
if (window.innerWidth < 768) return 1
return 2.5
}
},
methods: {
@ -117,11 +121,17 @@ export default {
</script>
<style>
.bookshelfRowCategorized {
.categorizedBookshelfRow {
scroll-behavior: smooth;
width: calc(100vw - 80px);
background-image: url(/wood_panels.jpg);
}
@media (max-width: 768px) {
.categorizedBookshelfRow {
width: 100vw;
}
}
.bookshelfDividerCategorized {
background: rgb(149, 119, 90);
/* background: linear-gradient(180deg, rgba(149, 119, 90, 1) 0%, rgba(103, 70, 37, 1) 17%, rgba(103, 70, 37, 1) 88%, rgba(71, 48, 25, 1) 100%); */

View File

@ -1,9 +1,20 @@
<template>
<div class="w-full h-10 relative">
<div id="toolbar" class="absolute top-0 left-0 w-full h-full z-20 flex items-center px-8">
<div class="w-full h-20 md:h-10 relative">
<div class="flex md:hidden h-10 items-center">
<nuxt-link :to="`/library/${currentLibraryId}`" class="flex-grow h-full flex justify-center items-center" :class="homePage ? 'bg-primary bg-opacity-80' : 'bg-primary bg-opacity-40'">
<p>Home</p>
</nuxt-link>
<nuxt-link :to="`/library/${currentLibraryId}/bookshelf`" class="flex-grow h-full flex justify-center items-center" :class="showLibrary ? 'bg-primary bg-opacity-80' : 'bg-primary bg-opacity-40'">
<p>Library</p>
</nuxt-link>
<nuxt-link :to="`/library/${currentLibraryId}/bookshelf/series`" class="flex-grow h-full flex justify-center items-center" :class="paramId === 'series' ? 'bg-primary bg-opacity-80' : 'bg-primary bg-opacity-40'">
<p>Series</p>
</nuxt-link>
</div>
<div id="toolbar" class="absolute top-10 md:top-0 left-0 w-full h-10 md:h-full z-20 flex items-center px-2 md:px-8">
<template v-if="page !== 'search' && !isHome">
<p v-if="!selectedSeries" class="font-book">{{ numShowing }} {{ entityName }}</p>
<div v-else class="flex items-center">
<p v-if="!selectedSeries" class="font-book hidden md:block">{{ numShowing }} {{ entityName }}</p>
<div v-else class="items-center hidden md:flex">
<div @click="seriesBackArrow" class="rounded-full h-9 w-9 flex items-center justify-center hover:bg-white hover:bg-opacity-10 cursor-pointer">
<span class="material-icons text-2xl text-white">west</span>
</div>
@ -15,12 +26,12 @@
<span class="font-mono">{{ numShowing }}</span>
</div>
</div>
<div class="flex-grow" />
<div class="flex-grow hidden md:inline-block" />
<ui-text-input v-show="!selectedSeries" v-model="_keywordFilter" placeholder="Keyword Filter" :padding-y="1.5" clearable class="text-xs w-40" />
<ui-text-input v-show="!selectedSeries" v-model="_keywordFilter" placeholder="Keyword Filter" :padding-y="1.5" clearable class="text-xs w-40 hidden md:block" />
<controls-filter-select v-show="showSortFilters" v-model="settings.filterBy" class="w-48 h-7.5 ml-4" @change="updateFilter" />
<controls-order-select v-show="showSortFilters" v-model="settings.orderBy" :descending.sync="settings.orderDesc" class="w-48 h-7.5 ml-4" @change="updateOrder" />
<div class="h-7 ml-4 flex border border-white border-opacity-25 rounded-md">
<div v-show="showSortFilters" class="h-7 ml-4 flex border border-white border-opacity-25 rounded-md">
<div class="h-full px-2 text-white flex items-center rounded-l-md hover:bg-primary hover:bg-opacity-75 cursor-pointer" :class="isGridMode ? 'bg-primary' : 'text-opacity-70'" @click="$emit('update:viewMode', 'grid')">
<span class="material-icons" style="font-size: 1.4rem">view_module</span>
</div>
@ -98,8 +109,20 @@ export default {
this.$store.commit('audiobooks/setKeywordFilter', val)
}
},
paramId() {
return this.$route.params ? this.$route.params.id || '' : ''
},
currentLibraryId() {
return this.$store.state.libraries.currentLibraryId
},
homePage() {
return this.$route.name === 'library-library'
},
libraryBookshelfPage() {
return this.$route.name === 'library-library-bookshelf-id'
},
showLibrary() {
return this.libraryBookshelfPage && this.paramId === '' && !this.showingIssues
}
},
methods: {

View File

@ -1,5 +1,8 @@
<template>
<div class="w-44 fixed left-0 top-16 z-40 h-full bg-bg bg-opacity-70 shadow-lg border-r border-white border-opacity-5 py-4">
<div class="w-44 fixed left-0 top-16 z-40 h-full bg-bg bg-opacity-100 md:bg-opacity-70 shadow-lg border-r border-white border-opacity-5 py-4 transform transition-transform" :class="drawerOpen ? 'translate-x-0' : '-translate-x-44'" v-click-outside="clickOutside">
<div class="md:hidden flex items-center justify-end py-2 px-4 mb-1" @click="closeDrawer">
<span class="material-icons text-2xl">arrow_back</span>
</div>
<nuxt-link to="/config" class="w-full px-4 h-12 border-b border-opacity-0 flex items-center cursor-pointer relative" :class="routeName === 'config' ? 'bg-primary bg-opacity-70' : 'hover:bg-primary hover:bg-opacity-30'">
<p>Settings</p>
<div v-show="routeName === 'config'" class="h-full w-0.5 bg-yellow-400 absolute top-0 left-0" />
@ -30,10 +33,19 @@
<script>
export default {
props: {
isOpen: Boolean
},
data() {
return {}
return {
windowWidth: 0
}
},
computed: {
drawerOpen() {
if (this.windowWidth < 758) return this.isOpen
return true
},
routeName() {
return this.$route.name
},
@ -50,7 +62,24 @@ export default {
return this.versionData.githubTagUrl
}
},
methods: {},
mounted() {}
methods: {
clickOutside() {
if (!this.isOpen) return
this.closeDrawer()
},
closeDrawer() {
this.$emit('update:isOpen', false)
},
resize() {
this.windowWidth = window.innerWidth
}
},
mounted() {
window.addEventListener('resize', this.resize)
this.windowWidth = this.resize
},
beforeDestroy() {
window.removeEventListener('resize', this.resize)
}
}
</script>

View File

@ -85,9 +85,6 @@ export default {
currentLibraryId() {
return this.$store.state.libraries.currentLibraryId
},
selectedClassName() {
return ''
},
homePage() {
return this.$route.name === 'library-library'
},

View File

@ -1,19 +1,19 @@
<template>
<div v-if="streamAudiobook" id="streamContainer" class="w-full fixed bottom-0 left-0 right-0 h-40 z-40 bg-primary px-4 pb-4 pt-2">
<div v-if="streamAudiobook" id="streamContainer" class="w-full fixed bottom-0 left-0 right-0 h-48 sm:h-44 md:h-40 z-40 bg-primary px-4 pb-4 pt-2">
<nuxt-link :to="`/audiobook/${streamAudiobook.id}`" class="absolute -top-16 left-4 cursor-pointer">
<cards-book-cover :audiobook="streamAudiobook" :width="88" />
<cards-book-cover :audiobook="streamAudiobook" :width="bookCoverWidth" />
</nuxt-link>
<div class="flex items-start pl-24">
<div class="flex items-start pl-24 mb-6 md:mb-0">
<div>
<nuxt-link :to="`/audiobook/${streamAudiobook.id}`" class="hover:underline cursor-pointer text-lg">
<nuxt-link :to="`/audiobook/${streamAudiobook.id}`" class="hover:underline cursor-pointer text-base sm:text-lg">
{{ title }} <span v-if="stream && $isDev" class="text-xs text-gray-400">({{ stream.id }})</span>
</nuxt-link>
<div class="text-gray-400 flex items-center">
<span class="material-icons text-sm">person</span>
<p v-if="authorFL" class="pl-1.5 text-base">
<p v-if="authorFL" class="pl-1.5 text-sm sm:text-base">
<nuxt-link v-for="(author, index) in authorsList" :key="index" :to="`/library/${libraryId}/bookshelf?filter=authors.${$encode(author)}`" class="hover:underline">{{ author }}<span v-if="index < authorsList.length - 1">,&nbsp;</span></nuxt-link>
</p>
<p v-else class="text-base cursor-pointer pl-2">Unknown</p>
<p v-else class="text-sm sm:text-base cursor-pointer pl-2">Unknown</p>
</div>
<div class="text-gray-400 flex items-center">
@ -45,6 +45,9 @@ export default {
}
},
computed: {
bookCoverWidth() {
return 88
},
cover() {
if (this.streamAudiobook && this.streamAudiobook.cover) return this.streamAudiobook.cover
return 'Logo.png'

View File

@ -13,7 +13,8 @@
<div class="w-full relative box-shadow-book" :style="{ height: height + 'px' }" @click="clickCard" @mouseover="isHovering = true" @mouseleave="isHovering = false">
<cards-book-cover :audiobook="audiobook" :author-override="authorFormat" :width="width" />
<div v-show="isHovering || isSelectionMode" class="absolute top-0 left-0 w-full h-full bg-black rounded" :class="overlayWrapperClasslist">
<!-- Hidden SM and DOWN -->
<div v-show="isHovering || isSelectionMode" class="absolute top-0 left-0 w-full h-full bg-black rounded hidden md:block" :class="overlayWrapperClasslist">
<div v-show="showPlayButton" class="h-full flex items-center justify-center">
<div class="hover:text-gray-200 hover:scale-110 transform duration-200" @click.stop.prevent="play">
<span class="material-icons" :style="{ fontSize: playIconFontSize + 'rem' }">play_circle_filled</span>

View File

@ -29,7 +29,8 @@ export default {
offsetIncrement: 0,
isFannedOut: false,
isDetached: false,
isAttaching: false
isAttaching: false,
windowWidth: 0
}
},
watch: {
@ -49,14 +50,17 @@ export default {
},
showExperimentalFeatures() {
return this.$store.state.showExperimentalFeatures
},
showCoverFan() {
return this.showExperimentalFeatures && this.windowWidth > 1024
}
},
methods: {
mouseoverCover() {
if (this.showExperimentalFeatures) this.setHover(true)
if (this.showCoverFan) this.setHover(true)
},
mouseleaveCover() {
if (this.showExperimentalFeatures) this.setHover(false)
if (this.showCoverFan) this.setHover(false)
},
detchCoverWrapper() {
if (!this.coverWrapperEl || !this.$refs.wrapper || this.isDetached) return
@ -82,7 +86,7 @@ export default {
this.coverWrapperEl.style.width = this.$refs.wrapper.clientWidth + 'px'
this.$refs.wrapper.appendChild(this.coverWrapperEl)
console.log('Appended to wrapper', this.$refs.wrapper.children)
this.isDetached = false
},
updatePosition() {
@ -310,7 +314,7 @@ export default {
coverImageEls.push(img)
}
if (this.showExperimentalFeatures) {
if (this.showCoverFan) {
var seriesNameCover = this.createSeriesNameCover(offsetLeft)
outerdiv.appendChild(seriesNameCover)
coverImageEls.push(seriesNameCover)
@ -324,7 +328,9 @@ export default {
}
}
},
mounted() {},
mounted() {
this.windowWidth = window.innerWidth
},
beforeDestroy() {
if (this.coverWrapperEl) this.coverWrapperEl.remove()
}

View File

@ -7,7 +7,7 @@
</template>
<div class="absolute -top-10 left-0 w-full flex">
<template v-for="tab in availableTabs">
<div :key="tab.id" class="w-28 rounded-t-lg flex items-center justify-center mr-1 cursor-pointer hover:bg-bg font-book border-t border-l border-r border-black-300 tab" :class="selectedTab === tab.id ? 'tab-selected bg-bg pb-px' : 'bg-primary text-gray-400'" @click="selectTab(tab.id)">{{ tab.title }}</div>
<div :key="tab.id" class="w-28 rounded-t-lg flex items-center justify-center mr-1 cursor-pointer hover:bg-bg font-book border-t border-l border-r border-black-300 tab text-xs sm:text-base" :class="selectedTab === tab.id ? 'tab-selected bg-bg pb-px' : 'bg-primary text-gray-400'" @click="selectTab(tab.id)">{{ tab.title }}</div>
</template>
</div>

View File

@ -58,7 +58,7 @@
<div class="flex-grow" />
<ui-tooltip v-if="!isMissing" text="(Root User Only) Save a NFO metadata file in your audiobooks directory" direction="bottom" class="mr-4">
<ui-tooltip v-if="!isMissing" text="(Root User Only) Save a NFO metadata file in your audiobooks directory" direction="bottom" class="mr-4 hidden sm:block">
<ui-btn v-if="isRootUser" :loading="savingMetadata" color="bg" type="button" class="h-full" small @click.stop.prevent="saveMetadata">Save Metadata</ui-btn>
</ui-tooltip>

View File

@ -6,7 +6,7 @@
<span class="text-sm font-mono">{{ tracks.length }}</span>
</div>
<div class="flex-grow" />
<ui-btn small :color="showFullPath ? 'gray-600' : 'primary'" class="mr-2" @click.stop="showFullPath = !showFullPath">Full Path</ui-btn>
<ui-btn small :color="showFullPath ? 'gray-600' : 'primary'" class="mr-2 hidden md:block" @click.stop="showFullPath = !showFullPath">Full Path</ui-btn>
<nuxt-link v-if="userCanUpdate" :to="`/audiobook/${audiobook.id}/edit`" class="mr-4">
<ui-btn small color="primary">Manage Tracks</ui-btn>
</nuxt-link>

View File

@ -1,15 +1,15 @@
<template>
<div class="w-full my-2">
<div class="w-full bg-primary px-6 py-2 flex items-center cursor-pointer" @click.stop="clickBar">
<p class="pr-4">Other Files</p>
<div class="h-7 w-7 rounded-full bg-white bg-opacity-10 flex items-center justify-center">
<div class="w-full bg-primary px-4 md:px-6 py-2 flex items-center cursor-pointer" @click.stop="clickBar">
<p class="pr-2 md:pr-4">Other Files</p>
<div class="h-5 md:h-7 w-5 md:w-7 rounded-full bg-white bg-opacity-10 flex items-center justify-center">
<span class="text-sm font-mono">{{ files.length }}</span>
</div>
<div class="flex-grow" />
<!-- <nuxt-link :to="`/audiobook/${audiobookId}/edit`" class="mr-4">
<ui-btn small color="primary">Manage Tracks</ui-btn>
</nuxt-link> -->
<ui-btn small :color="showFullPath ? 'gray-600' : 'primary'" class="mr-2" @click.stop="showFullPath = !showFullPath">Full Path</ui-btn>
<ui-btn small :color="showFullPath ? 'gray-600' : 'primary'" class="mr-2 hidden md:block" @click.stop="showFullPath = !showFullPath">Full Path</ui-btn>
<div class="cursor-pointer h-10 w-10 rounded-full hover:bg-black-400 flex justify-center items-center duration-500" :class="showFiles ? 'transform rotate-180' : ''">
<span class="material-icons text-4xl">expand_more</span>
</div>

View File

@ -1,14 +1,14 @@
<template>
<div class="w-full my-2">
<div class="w-full bg-primary px-6 py-2 flex items-center cursor-pointer" @click.stop="clickBar">
<p class="pr-4">Audio Tracks</p>
<div class="h-7 w-7 rounded-full bg-white bg-opacity-10 flex items-center justify-center">
<div class="w-full bg-primary px-4 md:px-6 py-2 flex items-center cursor-pointer" @click.stop="clickBar">
<p class="pr-2 md:pr-4">Audio Tracks</p>
<div class="h-5 md:h-7 w-5 md:w-7 rounded-full bg-white bg-opacity-10 flex items-center justify-center">
<span class="text-sm font-mono">{{ tracks.length }}</span>
</div>
<!-- <span class="bg-black-400 rounded-xl py-1 px-2 text-sm font-mono">{{ tracks.length }}</span> -->
<div class="flex-grow" />
<ui-btn small :color="showFullPath ? 'gray-600' : 'primary'" class="mr-2" @click.stop="showFullPath = !showFullPath">Full Path</ui-btn>
<nuxt-link v-if="userCanUpdate" :to="`/audiobook/${audiobookId}/edit`" class="mr-4">
<ui-btn small :color="showFullPath ? 'gray-600' : 'primary'" class="mr-2 hidden md:block" @click.stop="showFullPath = !showFullPath">Full Path</ui-btn>
<nuxt-link v-if="userCanUpdate" :to="`/audiobook/${audiobookId}/edit`" class="mr-2 md:mr-4">
<ui-btn small color="primary">Manage Tracks</ui-btn>
</nuxt-link>
<div class="cursor-pointer h-10 w-10 rounded-full hover:bg-black-400 flex justify-center items-center duration-500" :class="showTracks ? 'transform rotate-180' : ''">

View File

@ -12,9 +12,9 @@
<tr>
<th>Username</th>
<th class="w-20">Type</th>
<th>Activity</th>
<th class="w-32">Last Seen</th>
<th class="w-32">Created</th>
<th class="hidden lg:table-cell">Activity</th>
<th class="w-32 hidden sm:table-cell">Last Seen</th>
<th class="w-32 hidden sm:table-cell">Created</th>
<th class="w-32"></th>
</tr>
<tr v-for="user in users" :key="user.id" class="cursor-pointer" :class="user.isActive ? '' : 'bg-error bg-opacity-20'" @click="$router.push(`/config/users/${user.id}`)">
@ -25,7 +25,7 @@
</div>
</td>
<td class="text-sm">{{ user.type }}</td>
<td>
<td class="hidden lg:table-cell">
<div v-if="usersOnline[user.id] && usersOnline[user.id].stream && usersOnline[user.id].stream.audiobook && usersOnline[user.id].stream.audiobook.book">
<p class="truncate text-xs">Reading: {{ usersOnline[user.id].stream.audiobook.book.title || '' }}</p>
</div>
@ -33,12 +33,12 @@
<p class="truncate text-xs">Last: {{ getLastRead(user.audiobooks) }}</p>
</div>
</td>
<td class="text-xs font-mono">
<td class="text-xs font-mono hidden sm:table-cell">
<ui-tooltip v-if="user.lastSeen" direction="top" :text="$formatDate(user.lastSeen, 'MMMM do, yyyy HH:mm')">
{{ $dateDistanceFromNow(user.lastSeen) }}
</ui-tooltip>
</td>
<td class="text-xs font-mono">
<td class="text-xs font-mono hidden sm:table-cell">
<ui-tooltip direction="top" :text="$formatDate(user.createdAt, 'MMMM do, yyyy HH:mm')">
{{ $formatDate(user.createdAt, 'MMM d, yyyy') }}
</ui-tooltip>

View File

@ -1,6 +1,6 @@
{
"name": "audiobookshelf-client",
"version": "1.6.4",
"version": "1.6.5",
"description": "Audiobook manager and player",
"main": "index.js",
"scripts": {

View File

@ -1,5 +1,5 @@
<template>
<div class="w-full h-full p-8">
<div id="page-wrapper" class="page p-6 overflow-y-auto relative" :class="streamAudiobook ? 'streaming' : ''">
<div class="w-full max-w-xl mx-auto">
<h1 class="text-2xl">Account</h1>
@ -46,6 +46,9 @@ export default {
}
},
computed: {
streamAudiobook() {
return this.$store.state.streamAudiobook
},
user() {
return this.$store.state.user.user || null
},

View File

@ -1,29 +1,31 @@
<template>
<div id="page-wrapper" class="bg-bg page overflow-hidden" :class="streamAudiobook ? 'streaming' : ''">
<div class="w-full h-full overflow-y-auto p-8">
<div class="flex max-w-6xl mx-auto">
<div class="w-52" style="min-width: 208px">
<div class="relative">
<cards-book-cover :audiobook="audiobook" :width="208" />
<div class="w-full h-full overflow-y-auto px-2 py-6 md:p-8">
<div class="flex flex-col sm:flex-row max-w-6xl mx-auto">
<div class="w-full flex justify-center md:block sm:w-32 md:w-52" style="min-width: 208px">
<div class="relative" style="height: fit-content">
<cards-book-cover :audiobook="audiobook" :width="bookCoverWidth" />
<div class="absolute bottom-0 left-0 h-1.5 bg-yellow-400 shadow-sm" :class="userIsRead ? 'bg-success' : 'bg-yellow-400'" :style="{ width: 208 * progressPercent + 'px' }"></div>
</div>
</div>
<div class="flex-grow px-10">
<div class="flex-grow px-2 py-6 md:py-0 md:px-10">
<div class="flex">
<div class="mb-4">
<div class="flex items-end">
<h1 class="text-3xl font-sans">
<div class="flex sm:items-end flex-col sm:flex-row">
<h1 class="text-2xl md:text-3xl font-sans">
{{ title }}
</h1>
<p v-if="subtitle" class="ml-4 text-gray-400 text-2xl">{{ subtitle }}</p>
<p v-if="subtitle" class="sm:ml-4 text-gray-400 text-xl md:text-2xl">{{ subtitle }}</p>
</div>
<p v-if="authorFL" class="mb-2 mt-0.5 text-gray-200 text-xl">
<!-- <p v-if="subtitle" class="ml-4 text-gray-400 text-2xl block sm:hidden">{{ subtitle }}</p> -->
<p v-if="authorFL" class="mb-2 mt-0.5 text-gray-200 text-lg md:text-xl">
by <nuxt-link v-for="(author, index) in authorsList" :key="index" :to="`/library/${libraryId}/bookshelf?filter=authors.${$encode(author)}`" class="hover:underline">{{ author }}<span v-if="index < authorsList.length - 1">,&nbsp;</span></nuxt-link>
</p>
<p v-else class="mb-2 mt-0.5 text-gray-200 text-xl">by Unknown</p>
<nuxt-link v-if="series" :to="`/library/${libraryId}/bookshelf/series?series=${$encode(series)}`" class="hover:underline font-sans text-gray-300 text-lg leading-7 mb-4"> {{ seriesText }}</nuxt-link>
<nuxt-link v-if="series" :to="`/library/${libraryId}/bookshelf/series?series=${$encode(series)}`" class="hover:underline font-sans text-gray-300 text-lg leading-7"> {{ seriesText }}</nuxt-link>
<div v-if="narrator" class="flex py-0.5">
<div v-if="narrator" class="flex py-0.5 mt-4">
<div class="w-32">
<span class="text-white text-opacity-60 uppercase text-sm">Narrated By</span>
</div>
@ -168,7 +170,8 @@ export default {
return {
isRead: false,
resettingProgress: false,
isProcessingReadUpdate: false
isProcessingReadUpdate: false,
windowWidth: 0
}
},
watch: {
@ -180,6 +183,9 @@ export default {
}
},
computed: {
bookCoverWidth() {
return this.windowWidth < 800 ? 176 : 208
},
isDeveloperMode() {
return this.$store.state.developerMode
},
@ -426,9 +432,13 @@ export default {
},
downloadClick() {
this.$store.commit('showEditModalOnTab', { audiobook: this.audiobook, tab: 'download' })
},
resize() {
this.windowWidth = window.innerWidth
}
},
mounted() {
window.addEventListener('resize', this.resize)
this.$store.commit('audiobooks/addListener', { id: 'audiobook', audiobookId: this.audiobookId, meth: this.audiobookUpdated })
// If a library has not yet been loaded, use this audiobooks library id as the current
@ -437,6 +447,7 @@ export default {
}
},
beforeDestroy() {
window.removeEventListener('resize', this.resize)
this.$store.commit('audiobooks/removeListener', 'audiobook')
}
}

View File

@ -1,7 +1,11 @@
<template>
<div id="page-wrapper" class="page p-6 overflow-y-auto relative" :class="streamAudiobook ? 'streaming' : ''">
<app-config-side-nav />
<div class="w-full max-w-4xl mx-auto">
<app-config-side-nav :is-open.sync="sideDrawerOpen" />
<div class="configContent">
<div class="w-full pb-4 px-2 flex md:hidden border-b border-white border-opacity-10 mb-2">
<span class="material-icons cursor-pointer" @click.stop.prevent="showMore">more_vert</span>
<p class="pl-3 capitalize">{{ currentPage }}</p>
</div>
<nuxt-child />
</div>
<div class="fixed bottom-0 right-0 w-10 h-10" @dblclick="setDeveloperMode"></div>
@ -16,14 +20,32 @@ export default {
}
},
data() {
return {}
return {
sideDrawerOpen: false
}
},
watch: {
currentPage: {
handler() {
this.sideDrawerOpen = false
}
}
},
computed: {
streamAudiobook() {
return this.$store.state.streamAudiobook
},
currentPage() {
if (!this.$route.name) return 'Settings'
var routeName = this.$route.name.split('-')
if (routeName.length > 0) return routeName[1]
return 'Settings'
}
},
methods: {
showMore() {
this.sideDrawerOpen = true
},
setDeveloperMode() {
var value = !this.$store.state.developerMode
this.$store.commit('setDeveloperMode', value)
@ -43,3 +65,23 @@ export default {
mounted() {}
}
</script>
<style>
.configContent {
margin: auto;
width: 900px;
max-width: calc(100% - 176px);
}
@media (max-width: 1024px) {
.configContent {
margin-left: 176px;
}
}
@media (max-width: 768px) {
.configContent {
margin-left: 0px;
width: 100%;
max-width: 100%;
}
}
</style>

View File

@ -32,7 +32,7 @@
<div class="h-0.5 bg-primary bg-opacity-30 w-full" />
<div class="flex items-center py-4">
<ui-btn color="bg" small :padding-x="4" :loading="isResettingAudiobooks" @click="resetAudiobooks">Reset All Audiobooks</ui-btn>
<ui-btn color="bg" small :padding-x="4" class="hidden lg:block" :loading="isResettingAudiobooks" @click="resetAudiobooks">Reset All Audiobooks</ui-btn>
<div class="flex-grow" />
<p class="pr-2 text-sm font-book text-yellow-400">Report bugs, request features, provide feedback, and contribute on <a class="underline" href="https://github.com/advplyr/audiobookshelf" target="_blank">github</a>.</p>
<a href="https://github.com/advplyr/audiobookshelf" target="_blank" class="text-white hover:text-gray-200 hover:scale-150 hover:rotate-6 transform duration-500">
@ -56,7 +56,7 @@
</ui-tooltip>
</div>
</div>
<div>
<div class="hidden md:block">
<a href="https://github.com/advplyr/audiobookshelf/discussions/75#discussion-3604812" target="_blank" class="text-blue-500 hover:text-blue-300 underline">Join the discussion</a>
</div>
</div>

View File

@ -1,7 +1,7 @@
<template>
<div class="w-full h-full">
<div class="bg-bg rounded-md shadow-lg border border-white border-opacity-5 p-4 mb-8">
<nuxt-link to="/config/users" class="text-white text-opacity-70 hover:text-opacity-100 hover:bg-white hover:bg-opacity-5 cursor-pointer rounded-full">
<div class="bg-bg rounded-md shadow-lg border border-white border-opacity-5 p-0 sm:p-4 mb-8">
<nuxt-link to="/config/users" class="text-white text-opacity-70 hover:text-opacity-100 hover:bg-white hover:bg-opacity-5 cursor-pointer rounded-full px-2 sm:px-0">
<div class="flex items-center">
<div class="h-10 w-10 flex items-center justify-center">
<span class="material-icons text-2xl">arrow_back</span>
@ -9,20 +9,20 @@
<p class="pl-1">All Users</p>
</div>
</nuxt-link>
<div class="flex items-center mb-2 mt-4">
<div class="flex items-center mb-2 mt-4 px-2 sm:px-0">
<widgets-online-indicator :value="!!userOnline" />
<h1 class="text-xl pl-2">{{ username }}</h1>
</div>
<div class="w-full h-px bg-white bg-opacity-10 my-2" />
<div class="py-2">
<h1 class="text-lg mb-2 text-white text-opacity-90">Reading Progress</h1>
<h1 class="text-lg mb-2 text-white text-opacity-90 px-2 sm:px-0">Reading Progress</h1>
<table v-if="userAudiobooks.length" class="userAudiobooksTable">
<tr class="bg-primary bg-opacity-40">
<th class="w-16 text-left">Book</th>
<th class="text-left"></th>
<th class="w-32">Progress</th>
<th class="w-40">Started At</th>
<th class="w-40">Last Update</th>
<th class="w-40 hidden sm:table-cell">Started At</th>
<th class="w-40 hidden sm:table-cell">Last Update</th>
</tr>
<tr v-for="ab in userAudiobooks" :key="ab.audiobookId" :class="!ab.isRead ? '' : 'isRead'">
<td>
@ -33,12 +33,12 @@
<p v-if="ab.book && ab.book.author" class="text-white text-opacity-50 text-sm font-sans">by {{ ab.book.author }}</p>
</td>
<td class="text-center">{{ Math.floor(ab.progress * 100) }}%</td>
<td class="text-center">
<td class="text-center hidden sm:table-cell">
<ui-tooltip v-if="ab.startedAt" direction="top" :text="$formatDate(ab.startedAt, 'MMMM do, yyyy HH:mm')">
<p class="text-sm">{{ $dateDistanceFromNow(ab.startedAt) }}</p>
</ui-tooltip>
</td>
<td class="text-center">
<td class="text-center hidden sm:table-cell">
<ui-tooltip v-if="ab.lastUpdate" direction="top" :text="$formatDate(ab.lastUpdate, 'MMMM do, yyyy HH:mm')">
<p class="text-sm">{{ $dateDistanceFromNow(ab.lastUpdate) }}</p>
</ui-tooltip>

View File

@ -1,12 +1,12 @@
<template>
<div class="page" :class="streamAudiobook ? 'streaming' : ''">
<div class="flex h-full">
<app-side-rail />
<!-- <div class="flex h-full">
<app-side-rail class="hidden md:block" />
<div class="flex-grow">
<app-book-shelf-toolbar is-home />
<app-book-shelf-categorized />
</div>
</div>
</div> -->
</div>
</template>

View File

@ -1,7 +1,7 @@
<template>
<div class="page" :class="streamAudiobook ? 'streaming' : ''">
<div class="flex h-full">
<app-side-rail />
<app-side-rail class="hidden md:block" />
<div class="flex-grow">
<app-book-shelf-toolbar :page="id || ''" :search-results="searchResults" :search-query="searchQuery" :selected-series.sync="selectedSeries" :view-mode.sync="viewMode" />
<app-book-shelf :page="id || ''" :search-results="searchResults" :search-query="searchQuery" :selected-series.sync="selectedSeries" :view-mode="viewMode" />

View File

@ -1,7 +1,7 @@
<template>
<div class="page" :class="streamAudiobook ? 'streaming' : ''">
<div class="flex h-full">
<app-side-rail />
<app-side-rail class="hidden md:block" />
<div class="flex-grow">
<app-book-shelf-toolbar is-home />
<app-book-shelf-categorized />

View File

@ -1,7 +1,7 @@
<template>
<div id="page-wrapper" class="page p-6" :class="streamAudiobook ? 'streaming' : ''">
<main class="container mx-auto h-full max-w-screen-lg p-6">
<article class="max-h-full overflow-y-auto relative flex flex-col rounded-md" @drop="drop" @dragover="dragover" @dragleave="dragleave" @dragenter="dragenter">
<div id="page-wrapper" class="page p-0 sm:p-6 overflow-y-auto" :class="streamAudiobook ? 'streaming' : ''">
<main class="md:container mx-auto md:h-full max-w-screen-lg p-0 md:p-6">
<article class="max-h-full md:overflow-y-auto relative flex flex-col rounded-md" @drop="drop" @dragover="dragover" @dragleave="dragleave" @dragenter="dragenter">
<h1 class="text-xl font-book px-8 pt-4 pb-2">Audiobook Uploader</h1>
<div class="flex my-2 px-6">

View File

@ -1,6 +1,6 @@
{
"name": "audiobookshelf",
"version": "1.6.4",
"version": "1.6.5",
"description": "Self-hosted audiobook server for managing and playing audiobooks",
"main": "index.js",
"scripts": {

View File

@ -305,4 +305,4 @@ class Db {
return allTags
}
}
module.exports = Db
module.exports = Db