mirror of
https://github.com/gotson/komga.git
synced 2025-12-21 16:03:03 +01:00
feat(webui): change internals for shortcuts. add new shortcuts for settings
Closes #172
This commit is contained in:
parent
5e30e9dcd5
commit
b402817edb
2 changed files with 151 additions and 47 deletions
105
komga-webui/src/functions/shortcuts.ts
Normal file
105
komga-webui/src/functions/shortcuts.ts
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
import { ReadingDirection } from '@/types/enum-books'
|
||||
|
||||
enum Shortcut {
|
||||
// Navigation
|
||||
SEEK_FORWARD = 'seekForward',
|
||||
SEEK_BACKWARD = 'seekBackward',
|
||||
// Vertical mode
|
||||
SEEK_UP = 'seekUp',
|
||||
SEEK_DOWN = 'seekDown',
|
||||
SEEK_BEGIN = 'seekBegin',
|
||||
SEEK_END = 'seekEnd',
|
||||
// SETTINGS
|
||||
DIR_LTR = 'directionLTR',
|
||||
DIR_RTL = 'directionRTL',
|
||||
DIR_VRT = 'directionVRT',
|
||||
TOGGLE_DOUBLE_PAGE = 'toggleDoublePage',
|
||||
CYCLE_SCALE = 'cycleScale',
|
||||
// OTHER
|
||||
TOGGLE_TOOLBAR = 'toggleToolbar',
|
||||
TOGGLE_MENU = 'toggleMenu',
|
||||
TOGGLE_THUMBNAIL_EXPLORER = 'toggleExplorer',
|
||||
ESCAPE = 'escape'
|
||||
}
|
||||
|
||||
interface KeyMapping {
|
||||
[key: string]: Shortcut
|
||||
}
|
||||
|
||||
type Action = (ctx: any) => void
|
||||
|
||||
interface Shortcuts {
|
||||
[key: string]: Action
|
||||
}
|
||||
|
||||
// consider making this configurable on the server side?
|
||||
const keyMapping = {
|
||||
'PageUp': Shortcut.SEEK_FORWARD,
|
||||
'ArrowRight': Shortcut.SEEK_FORWARD,
|
||||
'PageDown': Shortcut.SEEK_BACKWARD,
|
||||
'ArrowLeft': Shortcut.SEEK_BACKWARD,
|
||||
'ArrowDown': Shortcut.SEEK_DOWN,
|
||||
'ArrowUp': Shortcut.SEEK_UP,
|
||||
'Home': Shortcut.SEEK_BEGIN,
|
||||
'End': Shortcut.SEEK_END,
|
||||
'm': Shortcut.TOGGLE_TOOLBAR,
|
||||
's': Shortcut.TOGGLE_MENU,
|
||||
't': Shortcut.TOGGLE_THUMBNAIL_EXPLORER,
|
||||
'Escape': Shortcut.ESCAPE,
|
||||
'l': Shortcut.DIR_LTR,
|
||||
'r': Shortcut.DIR_RTL,
|
||||
'v': Shortcut.DIR_VRT,
|
||||
'd': Shortcut.TOGGLE_DOUBLE_PAGE,
|
||||
'f': Shortcut.CYCLE_SCALE,
|
||||
} as KeyMapping
|
||||
|
||||
const shortcuts = {
|
||||
[Shortcut.SEEK_FORWARD]: (ctx: any) => {
|
||||
ctx.flipDirection ? ctx.prev() : ctx.next()
|
||||
},
|
||||
[Shortcut.SEEK_BACKWARD]: (ctx: any) => {
|
||||
ctx.flipDirection ? ctx.next() : ctx.prev()
|
||||
},
|
||||
[Shortcut.SEEK_UP]: (ctx: any) => { if (ctx.vertical) ctx.prev() },
|
||||
[Shortcut.SEEK_DOWN]: (ctx: any) => { if (ctx.vertical) ctx.next() },
|
||||
[Shortcut.SEEK_BEGIN]: (ctx: any) => { ctx.goToFirst() },
|
||||
[Shortcut.SEEK_END]: (ctx: any) => { ctx.goToLast() },
|
||||
[Shortcut.TOGGLE_TOOLBAR]: (ctx: any) => { ctx.toolbar = !ctx.toolbar },
|
||||
[Shortcut.TOGGLE_MENU]: (ctx: any) => { ctx.menu = !ctx.menu },
|
||||
[Shortcut.TOGGLE_THUMBNAIL_EXPLORER]: (ctx: any) => { ctx.showThumbnailsExplorer = !ctx.showThumbnailsExplorer },
|
||||
[Shortcut.TOGGLE_DOUBLE_PAGE]: (ctx: any) => ctx.toggleDoublePages(),
|
||||
[Shortcut.CYCLE_SCALE]: (ctx: any) => ctx.cycleScale(),
|
||||
[Shortcut.DIR_LTR]: (ctx: any) => ctx.changeReadingDir(ReadingDirection.LEFT_TO_RIGHT),
|
||||
[Shortcut.DIR_RTL]: (ctx: any) => ctx.changeReadingDir(ReadingDirection.RIGHT_TO_LEFT),
|
||||
[Shortcut.DIR_VRT]: (ctx: any) => ctx.changeReadingDir(ReadingDirection.VERTICAL),
|
||||
[Shortcut.ESCAPE]: (ctx: any) => {
|
||||
if (ctx.showThumbnailsExplorer) {
|
||||
ctx.showThumbnailsExplorer = false
|
||||
return
|
||||
}
|
||||
if (ctx.menu) {
|
||||
ctx.menu = false
|
||||
return
|
||||
}
|
||||
if (ctx.toolbar) {
|
||||
ctx.toolbar = false
|
||||
return
|
||||
}
|
||||
ctx.closeBook()
|
||||
},
|
||||
} as Shortcuts
|
||||
|
||||
export function executeShortcut (ctx: any, e: KeyboardEvent): boolean {
|
||||
let k: string = e.key
|
||||
if (k in keyMapping) {
|
||||
let s: Shortcut = keyMapping[k]
|
||||
if (s in shortcuts) {
|
||||
let action: Action = shortcuts[s]
|
||||
if (action) {
|
||||
action(ctx)
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
|
@ -249,6 +249,20 @@
|
|||
Dismiss
|
||||
</v-btn>
|
||||
</v-snackbar>
|
||||
|
||||
<v-snackbar
|
||||
v-model="notification.enabled"
|
||||
class="mb-12"
|
||||
color="rgba(0, 0, 0, 0.8)"
|
||||
multi-line
|
||||
vertical
|
||||
centered
|
||||
:timeout="notification.timeout"
|
||||
>
|
||||
<div class="title pa-2">
|
||||
{{ notification.message }}
|
||||
</div>
|
||||
</v-snackbar>
|
||||
</v-container>
|
||||
</template>
|
||||
|
||||
|
|
@ -260,6 +274,7 @@ import { getBookTitleCompact } from '@/functions/book-title'
|
|||
import { checkWebpFeature } from '@/functions/check-webp'
|
||||
import { bookPageUrl } from '@/functions/urls'
|
||||
import { ReadingDirection } from '@/types/enum-books'
|
||||
import { executeShortcut } from '@/functions/shortcuts'
|
||||
import Vue from 'vue'
|
||||
|
||||
const cookieFit = 'webreader.fit'
|
||||
|
|
@ -301,11 +316,17 @@ export default Vue.extend({
|
|||
settings: {
|
||||
doublePages: false,
|
||||
swipe: true,
|
||||
imageFits: Object.values(ImageFit),
|
||||
fit: ImageFit.HEIGHT,
|
||||
readingDirection: ReadingDirection.LEFT_TO_RIGHT,
|
||||
animations: true,
|
||||
backgroundColor: 'black',
|
||||
imageFits: Object.values(ImageFit),
|
||||
readingDirs: Object.values(ReadingDirection),
|
||||
},
|
||||
notification: {
|
||||
enabled: false,
|
||||
message: '',
|
||||
timeout: 4000,
|
||||
},
|
||||
readingDirs: [
|
||||
{ text: 'Left to right', value: ReadingDirection.LEFT_TO_RIGHT },
|
||||
|
|
@ -494,52 +515,7 @@ export default Vue.extend({
|
|||
},
|
||||
methods: {
|
||||
keyPressed (e: KeyboardEvent) {
|
||||
switch (e.key) {
|
||||
case 'PageUp':
|
||||
case 'ArrowRight':
|
||||
this.flipDirection ? this.prev() : this.next()
|
||||
break
|
||||
case 'PageDown':
|
||||
case 'ArrowLeft':
|
||||
this.flipDirection ? this.next() : this.prev()
|
||||
break
|
||||
case 'ArrowDown':
|
||||
if (this.vertical) this.next()
|
||||
break
|
||||
case 'ArrowUp':
|
||||
if (this.vertical) this.prev()
|
||||
break
|
||||
case 'Home':
|
||||
this.goToFirst()
|
||||
break
|
||||
case 'End':
|
||||
this.goToLast()
|
||||
break
|
||||
case 'm':
|
||||
this.toolbar = !this.toolbar
|
||||
break
|
||||
case 's':
|
||||
this.menu = !this.menu
|
||||
break
|
||||
case 't':
|
||||
this.showThumbnailsExplorer = !this.showThumbnailsExplorer
|
||||
break
|
||||
case 'Escape':
|
||||
if (this.showThumbnailsExplorer) {
|
||||
this.showThumbnailsExplorer = false
|
||||
break
|
||||
}
|
||||
if (this.menu) {
|
||||
this.menu = false
|
||||
break
|
||||
}
|
||||
if (this.toolbar) {
|
||||
this.toolbar = false
|
||||
break
|
||||
}
|
||||
this.closeBook()
|
||||
break
|
||||
}
|
||||
executeShortcut(this, e)
|
||||
},
|
||||
async setup (bookId: number, page: number) {
|
||||
this.book = await this.$komgaBooks.getBook(bookId)
|
||||
|
|
@ -686,6 +662,29 @@ export default Vue.extend({
|
|||
setter(value)
|
||||
}
|
||||
},
|
||||
changeReadingDir (dir: ReadingDirection) {
|
||||
this.readingDirection = dir
|
||||
let i = this.settings.readingDirs.indexOf(this.readingDirection)
|
||||
let text = this.readingDirs[i].text
|
||||
this.sendNotification(`Changing Reading Direction to: ${text}`)
|
||||
},
|
||||
cycleScale () {
|
||||
let fit: ImageFit = this.settings.fit
|
||||
let i = (this.settings.imageFits.indexOf(fit) + 1) % (this.settings.imageFits.length)
|
||||
this.settings.fit = this.settings.imageFits[i]
|
||||
let text = this.imageFits[i].text
|
||||
// The text here only works cause this.imageFits has the same index structure as the ImageFit enum
|
||||
this.sendNotification(`Cycling Scale: ${text}`)
|
||||
},
|
||||
toggleDoublePages () {
|
||||
this.doublePages = !this.doublePages
|
||||
this.sendNotification(`${this.doublePages ? 'Enabled' : 'Disabled'} Double Pages`)
|
||||
},
|
||||
sendNotification (message:string, timeout: number = 4000) {
|
||||
this.notification.timeout = 4000
|
||||
this.notification.message = message
|
||||
this.notification.enabled = true
|
||||
},
|
||||
async markProgress (page: number) {
|
||||
this.$komgaBooks.updateReadProgress(this.bookId, { page: page })
|
||||
},
|
||||
|
|
|
|||
Loading…
Reference in a new issue