mirror of
https://github.com/advplyr/audiobookshelf-app.git
synced 2025-07-22 03:34:27 +02:00
feat: add haptic feedback to all action buttons
This commit is contained in:
parent
96dde8cf31
commit
1aa6a441f3
16 changed files with 113 additions and 42 deletions
|
@ -118,6 +118,7 @@
|
|||
<script>
|
||||
import { Capacitor } from '@capacitor/core'
|
||||
import { AbsAudioPlayer } from '@/plugins/capacitor'
|
||||
import { Haptics, ImpactStyle } from '@capacitor/haptics';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
|
@ -335,15 +336,18 @@ export default {
|
|||
this.showFullscreen = false
|
||||
}
|
||||
},
|
||||
touchstartTrack(e) {
|
||||
async touchstartTrack(e) {
|
||||
await Haptics.impact({ style: ImpactStyle.Medium });
|
||||
if (!e || !e.touches || !this.$refs.track || !this.showFullscreen || this.lockUi) return
|
||||
this.touchTrackStart = true
|
||||
},
|
||||
selectChapter(chapter) {
|
||||
async selectChapter(chapter) {
|
||||
await Haptics.impact({ style: ImpactStyle.Medium });
|
||||
this.seek(chapter.start)
|
||||
this.showChapterModal = false
|
||||
},
|
||||
castClick() {
|
||||
async castClick() {
|
||||
await Haptics.impact({ style: ImpactStyle.Medium });
|
||||
if (this.isLocalPlayMethod) {
|
||||
this.$eventBus.$emit('cast-local-item')
|
||||
return
|
||||
|
@ -362,12 +366,14 @@ export default {
|
|||
this.showFullscreen = false
|
||||
this.forceCloseDropdownMenu()
|
||||
},
|
||||
jumpNextChapter() {
|
||||
async jumpNextChapter() {
|
||||
await Haptics.impact({ style: ImpactStyle.Medium });
|
||||
if (this.isLoading) return
|
||||
if (!this.nextChapter) return
|
||||
this.seek(this.nextChapter.start)
|
||||
},
|
||||
jumpChapterStart() {
|
||||
async jumpChapterStart() {
|
||||
await Haptics.impact({ style: ImpactStyle.Medium });
|
||||
if (this.isLoading) return
|
||||
if (!this.currentChapter) {
|
||||
return this.restart()
|
||||
|
@ -387,7 +393,8 @@ export default {
|
|||
showSleepTimerModal() {
|
||||
this.$emit('showSleepTimer')
|
||||
},
|
||||
setPlaybackSpeed(speed) {
|
||||
async setPlaybackSpeed(speed) {
|
||||
await Haptics.impact({ style: ImpactStyle.Medium });
|
||||
console.log(`[AudioPlayer] Set Playback Rate: ${speed}`)
|
||||
this.currentPlaybackRate = speed
|
||||
AbsAudioPlayer.setPlaybackSpeed({ value: speed })
|
||||
|
@ -395,11 +402,13 @@ export default {
|
|||
restart() {
|
||||
this.seek(0)
|
||||
},
|
||||
jumpBackwards() {
|
||||
async jumpBackwards() {
|
||||
await Haptics.impact({ style: ImpactStyle.Medium });
|
||||
if (this.isLoading) return
|
||||
AbsAudioPlayer.seekBackward({ value: this.jumpBackwardsTime })
|
||||
},
|
||||
jumpForward() {
|
||||
async jumpForward() {
|
||||
await Haptics.impact({ style: ImpactStyle.Medium });
|
||||
if (this.isLoading) return
|
||||
AbsAudioPlayer.seekForward({ value: this.jumpForwardTime })
|
||||
},
|
||||
|
@ -539,6 +548,7 @@ export default {
|
|||
this.seek(time)
|
||||
},
|
||||
async playPauseClick() {
|
||||
await Haptics.impact({ style: ImpactStyle.Medium });
|
||||
if (this.isLoading) return
|
||||
|
||||
this.isPlaying = !!((await AbsAudioPlayer.playPause()) || {}).playing
|
||||
|
@ -641,7 +651,8 @@ export default {
|
|||
ts.innerText = currTimeStr
|
||||
}
|
||||
},
|
||||
clickMenuAction(action) {
|
||||
async clickMenuAction(action) {
|
||||
await Haptics.impact({ style: ImpactStyle.Medium });
|
||||
this.showMoreMenuDialog = false
|
||||
this.$nextTick(() => {
|
||||
if (action === 'lock') {
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
|
||||
<script>
|
||||
import TouchEvent from '@/objects/TouchEvent'
|
||||
import { Haptics, ImpactStyle } from '@capacitor/haptics';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
|
@ -137,6 +138,7 @@ export default {
|
|||
this.show = false
|
||||
},
|
||||
async logout() {
|
||||
await Haptics.impact({ style: ImpactStyle.Medium });
|
||||
if (this.user) {
|
||||
await this.$axios.$post('/logout').catch((error) => {
|
||||
console.error(error)
|
||||
|
|
|
@ -70,6 +70,7 @@
|
|||
|
||||
<script>
|
||||
import { Capacitor } from '@capacitor/core'
|
||||
import { Haptics, ImpactStyle } from '@capacitor/haptics';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
|
@ -401,12 +402,13 @@ export default {
|
|||
// Server books may have a local library item
|
||||
this.localLibraryItem = localLibraryItem
|
||||
},
|
||||
clickCard(e) {
|
||||
async clickCard(e) {
|
||||
if (this.isSelectionMode) {
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
this.selectBtnClick()
|
||||
} else if (this.recentEpisode) {
|
||||
await Haptics.impact({ style: ImpactStyle.Medium });
|
||||
var eventBus = this.$eventBus || this.$nuxt.$eventBus
|
||||
if (this.streamIsPlaying) {
|
||||
eventBus.$emit('pause-item')
|
||||
|
|
|
@ -77,6 +77,7 @@
|
|||
|
||||
<script>
|
||||
import { Dialog } from '@capacitor/dialog'
|
||||
import { Haptics, ImpactStyle } from '@capacitor/haptics';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
|
@ -132,6 +133,7 @@ export default {
|
|||
}
|
||||
},
|
||||
async connectToServer(config) {
|
||||
await Haptics.impact({ style: ImpactStyle.Medium });
|
||||
console.log('[ServerConnectForm] connectToServer', config.address)
|
||||
this.processing = true
|
||||
this.serverConfig = {
|
||||
|
@ -159,6 +161,7 @@ export default {
|
|||
},
|
||||
async removeServerConfigClick() {
|
||||
if (!this.serverConfig.id) return
|
||||
await Haptics.impact({ style: ImpactStyle.Medium });
|
||||
|
||||
const { value } = await Dialog.confirm({
|
||||
title: 'Confirm',
|
||||
|
@ -189,7 +192,8 @@ export default {
|
|||
this.showForm = true
|
||||
this.showAuth = true
|
||||
},
|
||||
newServerConfigClick() {
|
||||
async newServerConfigClick() {
|
||||
await Haptics.impact({ style: ImpactStyle.Medium });
|
||||
this.serverConfig = {
|
||||
address: '',
|
||||
userId: '',
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
<p v-show="!selectedSeriesName" class="font-book pt-1">{{ totalEntities }} {{ entityTitle }}</p>
|
||||
<p v-show="selectedSeriesName" class="ml-2 font-book pt-1">{{ selectedSeriesName }} ({{ totalEntities }})</p>
|
||||
<div class="flex-grow" />
|
||||
<span v-if="page == 'library' || seriesBookPage" class="material-icons px-2" @click="bookshelfListView = !bookshelfListView">{{ !bookshelfListView ? 'view_list' : 'grid_view' }}</span>
|
||||
<span v-if="page == 'library' || seriesBookPage" class="material-icons px-2" @click="changeView()">{{ !bookshelfListView ? 'view_list' : 'grid_view' }}</span>
|
||||
<template v-if="page === 'library'">
|
||||
<div class="relative flex items-center px-2">
|
||||
<span class="material-icons" @click="showFilterModal = true">filter_alt</span>
|
||||
|
@ -25,6 +25,8 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { Haptics, ImpactStyle } from '@capacitor/haptics';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
|
@ -102,6 +104,10 @@ export default {
|
|||
},
|
||||
setTotalEntities(total) {
|
||||
this.totalEntities = total
|
||||
},
|
||||
async changeView() {
|
||||
this.bookshelfListView = !this.bookshelfListView
|
||||
await Haptics.impact({ style: ImpactStyle.Medium });
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
|
|
|
@ -46,6 +46,8 @@
|
|||
|
||||
<script>
|
||||
import { Dialog } from '@capacitor/dialog'
|
||||
import { Haptics, ImpactStyle } from '@capacitor/haptics';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
value: Boolean,
|
||||
|
@ -94,6 +96,7 @@ export default {
|
|||
this.showBookmarkTitleInput = true
|
||||
},
|
||||
async deleteBookmark(bm) {
|
||||
await Haptics.impact({ style: ImpactStyle.Medium });
|
||||
const { value } = await Dialog.confirm({
|
||||
title: 'Remove Bookmark',
|
||||
message: `Are you sure you want to remove bookmark?`
|
||||
|
@ -111,7 +114,8 @@ export default {
|
|||
})
|
||||
this.show = false
|
||||
},
|
||||
clickBookmark(bm) {
|
||||
async clickBookmark(bm) {
|
||||
await Haptics.impact({ style: ImpactStyle.Medium });
|
||||
this.$emit('select', bm)
|
||||
},
|
||||
submitUpdateBookmark(updatedBookmark) {
|
||||
|
@ -155,7 +159,8 @@ export default {
|
|||
this.newBookmarkTitle = this.$formatDate(Date.now(), 'MMM dd, yyyy HH:mm')
|
||||
this.showBookmarkTitleInput = true
|
||||
},
|
||||
submitBookmark() {
|
||||
async submitBookmark() {
|
||||
await Haptics.impact({ style: ImpactStyle.Medium });
|
||||
if (this.selectedBookmark) {
|
||||
var updatePayload = {
|
||||
...this.selectedBookmark,
|
||||
|
|
|
@ -48,6 +48,8 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { Haptics, ImpactStyle } from '@capacitor/haptics';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
value: Boolean,
|
||||
|
@ -196,7 +198,8 @@ export default {
|
|||
}
|
||||
},
|
||||
methods: {
|
||||
clearSelected() {
|
||||
async clearSelected() {
|
||||
await Haptics.impact({ style: ImpactStyle.Medium });
|
||||
this.selected = 'all'
|
||||
this.show = false
|
||||
this.$nextTick(() => this.$emit('change', 'all'))
|
||||
|
@ -204,7 +207,7 @@ export default {
|
|||
clickedSublistOption(item) {
|
||||
this.clickedOption({ value: `${this.sublist}.${item}` })
|
||||
},
|
||||
clickedOption(option) {
|
||||
async clickedOption(option) {
|
||||
if (option.sublist) {
|
||||
this.sublist = option.value
|
||||
return
|
||||
|
@ -215,6 +218,7 @@ export default {
|
|||
this.show = false
|
||||
return
|
||||
}
|
||||
await Haptics.impact({ style: ImpactStyle.Medium });
|
||||
this.selected = val
|
||||
this.show = false
|
||||
this.$nextTick(() => this.$emit('change', val))
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { Haptics, ImpactStyle } from '@capacitor/haptics';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
|
@ -49,6 +51,7 @@ export default {
|
|||
},
|
||||
methods: {
|
||||
async clickedOption(lib) {
|
||||
await Haptics.impact({ style: ImpactStyle.Medium });
|
||||
this.show = false
|
||||
if (lib.id === this.currentLibraryId) return
|
||||
await this.$store.dispatch('libraries/fetch', lib.id)
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { Haptics, ImpactStyle } from '@capacitor/haptics';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
value: Boolean,
|
||||
|
@ -126,7 +128,8 @@ export default {
|
|||
}
|
||||
},
|
||||
methods: {
|
||||
clickedOption(val) {
|
||||
async clickedOption(val) {
|
||||
await Haptics.impact({ style: ImpactStyle.Medium });
|
||||
if (this.selected === val) {
|
||||
this.selectedDesc = !this.selectedDesc
|
||||
} else {
|
||||
|
|
|
@ -59,6 +59,8 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { Haptics, ImpactStyle } from '@capacitor/haptics';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
value: Boolean,
|
||||
|
@ -89,30 +91,37 @@ export default {
|
|||
}
|
||||
},
|
||||
methods: {
|
||||
clickedChapterOption() {
|
||||
async clickedChapterOption() {
|
||||
await Haptics.impact({ style: ImpactStyle.Medium });
|
||||
this.show = false
|
||||
this.$nextTick(() => this.$emit('change', { time: this.currentEndOfChapterTime * 1000, isChapterTime: true }))
|
||||
},
|
||||
clickedOption(timeoutMin) {
|
||||
async clickedOption(timeoutMin) {
|
||||
await Haptics.impact({ style: ImpactStyle.Medium });
|
||||
var timeout = timeoutMin * 1000 * 60
|
||||
this.show = false
|
||||
this.manualTimerModal = false
|
||||
this.$nextTick(() => this.$emit('change', { time: timeout, isChapterTime: false }))
|
||||
},
|
||||
cancelSleepTimer() {
|
||||
async cancelSleepTimer() {
|
||||
await Haptics.impact({ style: ImpactStyle.Medium });
|
||||
this.$emit('cancel')
|
||||
this.show = false
|
||||
},
|
||||
increaseSleepTime() {
|
||||
async increaseSleepTime() {
|
||||
await Haptics.impact({ style: ImpactStyle.Medium });
|
||||
this.$emit('increase')
|
||||
},
|
||||
decreaseSleepTime() {
|
||||
async decreaseSleepTime() {
|
||||
await Haptics.impact({ style: ImpactStyle.Medium });
|
||||
this.$emit('decrease')
|
||||
},
|
||||
increaseManualTimeout() {
|
||||
async increaseManualTimeout() {
|
||||
await Haptics.impact({ style: ImpactStyle.Medium });
|
||||
this.manualTimeoutMin++
|
||||
},
|
||||
decreaseManualTimeout() {
|
||||
async decreaseManualTimeout() {
|
||||
await Haptics.impact({ style: ImpactStyle.Medium });
|
||||
if (this.manualTimeoutMin > 1) this.manualTimeoutMin--
|
||||
}
|
||||
},
|
||||
|
|
|
@ -39,6 +39,8 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { Haptics, ImpactStyle } from '@capacitor/haptics';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
libraryItemId: String
|
||||
|
@ -114,7 +116,8 @@ export default {
|
|||
this.loading = false
|
||||
})
|
||||
},
|
||||
clickPlaylist(playlist) {
|
||||
async clickPlaylist(playlist) {
|
||||
await Haptics.impact({ style: ImpactStyle.Medium });
|
||||
if (playlist.isItemIncluded) {
|
||||
this.removeFromPlaylist(playlist)
|
||||
} else {
|
||||
|
@ -163,7 +166,8 @@ export default {
|
|||
this.newPlaylistName = ''
|
||||
this.showPlaylistNameInput = true
|
||||
},
|
||||
submitCreatePlaylist() {
|
||||
async submitCreatePlaylist() {
|
||||
await Haptics.impact({ style: ImpactStyle.Medium });
|
||||
if (!this.newPlaylistName || !this.selectedPlaylistItems.length) {
|
||||
return
|
||||
}
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
<script>
|
||||
import { Dialog } from '@capacitor/dialog'
|
||||
import { AbsFileSystem, AbsDownloader } from '@/plugins/capacitor'
|
||||
import { Haptics, ImpactStyle } from '@capacitor/haptics';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
|
@ -148,8 +149,9 @@ export default {
|
|||
}
|
||||
return folderObj
|
||||
},
|
||||
downloadClick() {
|
||||
async downloadClick() {
|
||||
if (this.downloadItem) return
|
||||
await Haptics.impact({ style: ImpactStyle.Medium });
|
||||
if (this.isIos) {
|
||||
// no local folders on iOS
|
||||
this.startDownload()
|
||||
|
@ -209,7 +211,8 @@ export default {
|
|||
this.$toast.error(errorMsg)
|
||||
}
|
||||
},
|
||||
playClick() {
|
||||
async playClick() {
|
||||
await Haptics.impact({ style: ImpactStyle.Medium });
|
||||
if (this.streamIsPlaying) {
|
||||
this.$eventBus.$emit('pause-item')
|
||||
} else {
|
||||
|
@ -231,6 +234,7 @@ export default {
|
|||
}
|
||||
},
|
||||
async toggleFinished() {
|
||||
await Haptics.impact({ style: ImpactStyle.Medium });
|
||||
this.isProcessingReadUpdate = true
|
||||
if (this.isLocal || this.localEpisode) {
|
||||
var isFinished = !this.userIsFinished
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { Haptics, ImpactStyle } from '@capacitor/haptics';
|
||||
|
||||
export default {
|
||||
asyncData({ redirect, store }) {
|
||||
if (!store.state.socketConnected) {
|
||||
|
@ -53,6 +55,7 @@ export default {
|
|||
},
|
||||
methods: {
|
||||
async logout() {
|
||||
await Haptics.impact({ style: ImpactStyle.Medium });
|
||||
if (this.user) {
|
||||
await this.$axios.$post('/logout').catch((error) => {
|
||||
console.error(error)
|
||||
|
|
|
@ -142,6 +142,8 @@
|
|||
<script>
|
||||
import { Dialog } from '@capacitor/dialog'
|
||||
import { AbsFileSystem, AbsDownloader } from '@/plugins/capacitor'
|
||||
import { Haptics, ImpactStyle } from '@capacitor/haptics';
|
||||
|
||||
|
||||
export default {
|
||||
async asyncData({ store, params, redirect, app }) {
|
||||
|
@ -406,8 +408,9 @@ export default {
|
|||
readBook() {
|
||||
this.$store.commit('openReader', this.libraryItem)
|
||||
},
|
||||
playClick() {
|
||||
async playClick() {
|
||||
var episodeId = null
|
||||
await Haptics.impact({ style: ImpactStyle.Medium });
|
||||
|
||||
if (this.isPodcast) {
|
||||
this.episodes.sort((a, b) => {
|
||||
|
@ -461,6 +464,7 @@ export default {
|
|||
this.$eventBus.$emit('play-item', { libraryItemId: this.libraryItemId, episodeId })
|
||||
},
|
||||
async clearProgressClick() {
|
||||
await Haptics.impact({ style: ImpactStyle.Medium });
|
||||
const { value } = await Dialog.confirm({
|
||||
title: 'Confirm',
|
||||
message: 'Are you sure you want to reset your progress?'
|
||||
|
@ -506,13 +510,14 @@ export default {
|
|||
this.showSelectLocalFolder = false
|
||||
this.download(localFolder)
|
||||
},
|
||||
downloadClick() {
|
||||
async downloadClick() {
|
||||
if (this.downloadItem) {
|
||||
return
|
||||
}
|
||||
if (!this.numTracks) {
|
||||
return
|
||||
}
|
||||
await Haptics.impact({ style: ImpactStyle.Medium });
|
||||
if (this.isIos) {
|
||||
// no local folders on iOS
|
||||
this.startDownload()
|
||||
|
@ -580,6 +585,7 @@ export default {
|
|||
}
|
||||
},
|
||||
async toggleFinished() {
|
||||
await Haptics.impact({ style: ImpactStyle.Medium });
|
||||
this.isProcessingReadUpdate = true
|
||||
if (this.isLocal) {
|
||||
var isFinished = !this.userIsFinished
|
||||
|
|
|
@ -105,6 +105,7 @@ import draggable from 'vuedraggable'
|
|||
import { Capacitor } from '@capacitor/core'
|
||||
import { Dialog } from '@capacitor/dialog'
|
||||
import { AbsFileSystem } from '@/plugins/capacitor'
|
||||
import { Haptics, ImpactStyle } from '@capacitor/haptics';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
|
@ -255,14 +256,16 @@ export default {
|
|||
}
|
||||
this.showDialog = true
|
||||
},
|
||||
play() {
|
||||
async play() {
|
||||
await Haptics.impact({ style: ImpactStyle.Medium });
|
||||
this.$eventBus.$emit('play-item', { libraryItemId: this.localLibraryItemId })
|
||||
},
|
||||
getCapImageSrc(contentUrl) {
|
||||
return Capacitor.convertFileSrc(contentUrl)
|
||||
},
|
||||
dialogAction(action) {
|
||||
async dialogAction(action) {
|
||||
console.log('Dialog action', action)
|
||||
await Haptics.impact({ style: ImpactStyle.Medium });
|
||||
if (action == 'scan') {
|
||||
this.scanItem()
|
||||
} else if (action == 'rescan') {
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
|
||||
<script>
|
||||
import { Dialog } from '@capacitor/dialog'
|
||||
import { Haptics, ImpactStyle } from '@capacitor/haptics';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
|
@ -149,6 +150,7 @@ export default {
|
|||
this.saveSettings()
|
||||
},
|
||||
async saveSettings() {
|
||||
await Haptics.impact({ style: ImpactStyle.Medium });
|
||||
const updatedDeviceData = await this.$db.updateDeviceSettings({ ...this.settings })
|
||||
console.log('Saved device data', updatedDeviceData)
|
||||
if (updatedDeviceData) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue