mirror of
https://github.com/nkanaev/yarr.git
synced 2025-05-24 00:33:14 +00:00
add navigation and general keybindings
This commit is contained in:
parent
fc5da31acf
commit
4225e06db9
@ -161,7 +161,8 @@
|
|||||||
</button>
|
</button>
|
||||||
<div class="input-icon flex-grow-1">
|
<div class="input-icon flex-grow-1">
|
||||||
<span class="icon">{% inline "search.svg" %}</span>
|
<span class="icon">{% inline "search.svg" %}</span>
|
||||||
<input class="d-block toolbar-search" type="" v-model="itemSearch">
|
<!-- id used by keybindings -->
|
||||||
|
<input id="searchbar" class="d-block toolbar-search" type="" v-model="itemSearch">
|
||||||
</div>
|
</div>
|
||||||
<button class="toolbar-item ml-2"
|
<button class="toolbar-item ml-2"
|
||||||
@click="markItemsRead()"
|
@click="markItemsRead()"
|
||||||
|
@ -1,7 +1,87 @@
|
|||||||
const keybindings = {}
|
const helperFunctions = {
|
||||||
|
// navigation helper, navigate relative to selected item
|
||||||
|
navigateToItem: function(relativePosition) {
|
||||||
|
if(vm.itemSelected == null){
|
||||||
|
if(vm.items.length !== 0) {
|
||||||
|
// if no item is selected, select first
|
||||||
|
vm.itemSelected = vm.items[0].id
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const itemPosition = vm.items.findIndex(x=>x.id==vm.itemSelected)
|
||||||
|
if(itemPosition == -1){
|
||||||
|
// Item not found error
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const newPosition = itemPosition+relativePosition
|
||||||
|
if(newPosition < 0 || newPosition >= vm.items.length){
|
||||||
|
return
|
||||||
|
}
|
||||||
|
vm.itemSelected = vm.items[newPosition].id
|
||||||
|
},
|
||||||
|
// navigation helper, navigate relative to selected feed
|
||||||
|
navigateToFeed: function(relativePosition) {
|
||||||
|
// create a list with feed and folders guids, ignore feeds in collapsed folders
|
||||||
|
// Example result with folder 2 collapsed:
|
||||||
|
// ['folder:1','feed:1','feed:2','folder:2', 'folder:3','feed:3']
|
||||||
|
const navigationList = vm.foldersWithFeeds.map(
|
||||||
|
folder =>
|
||||||
|
folder.is_expanded
|
||||||
|
? ['folder:'+folder.id].concat(folder.feeds.map(feed=>'feed:'+feed.id))
|
||||||
|
: 'folder:'+folder.id
|
||||||
|
).flat()
|
||||||
|
const currentFeedPosition = navigationList.indexOf(vm.feedSelected)
|
||||||
|
if(currentFeedPosition== -1){
|
||||||
|
// feed not found error
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const newPosition = currentFeedPosition+relativePosition
|
||||||
|
if(newPosition < 0 || newPosition >= navigationList.length){
|
||||||
|
return
|
||||||
|
}
|
||||||
|
vm.feedSelected = navigationList[newPosition];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const shortcutFunctions = {
|
||||||
|
toggleItemRead: function() {
|
||||||
|
if(vm.itemSelected != null) {
|
||||||
|
vm.toggleItemRead(vm.itemSelectedDetails)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
toggleItemStarred: function() {
|
||||||
|
if(vm.itemSelected != null) {
|
||||||
|
vm.toggleItemStarred(vm.itemSelectedDetails)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
focusSearch: function() {
|
||||||
|
document.getElementById("searchbar").focus()
|
||||||
|
},
|
||||||
|
nextItem(){
|
||||||
|
helperFunctions.navigateToItem(+1)
|
||||||
|
},
|
||||||
|
previousItem() {
|
||||||
|
helperFunctions.navigateToItem(-1)
|
||||||
|
},
|
||||||
|
nextFeed(){
|
||||||
|
helperFunctions.navigateToFeed(+1)
|
||||||
|
},
|
||||||
|
previousFeed() {
|
||||||
|
helperFunctions.navigateToFeed(-1)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
const keybindings = {
|
||||||
|
"r": shortcutFunctions.toggleItemRead,
|
||||||
|
"s": shortcutFunctions.toggleItemStarred,
|
||||||
|
"?": shortcutFunctions.focusSearch,
|
||||||
|
"j": shortcutFunctions.nextItem,
|
||||||
|
"k": shortcutFunctions.previousItem,
|
||||||
|
"l": shortcutFunctions.nextFeed,
|
||||||
|
"h": shortcutFunctions.previousFeed,
|
||||||
|
}
|
||||||
|
|
||||||
function isTextBox(element) {
|
function isTextBox(element) {
|
||||||
var tagName = element.tagName.toLowerCase();
|
var tagName = element.tagName.toLowerCase()
|
||||||
// Input elements that aren't text
|
// Input elements that aren't text
|
||||||
const inputBlocklist = ['button','checkbox','color','file','hidden','image','radio','range','reset','search','submit']
|
const inputBlocklist = ['button','checkbox','color','file','hidden','image','radio','range','reset','search','submit']
|
||||||
|
|
||||||
@ -12,12 +92,14 @@ function isTextBox(element) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
document.addEventListener('keydown',function(event) {
|
document.addEventListener('keydown',function(event) {
|
||||||
if(isTextBox(event.target)) {
|
// Ignore while focused on text or
|
||||||
return;
|
// when using modifier keys (to not clash with browser behaviour)
|
||||||
|
if(isTextBox(event.target) || event.metaKey || event.ctrlKey) {
|
||||||
|
return
|
||||||
}
|
}
|
||||||
const keybindFunction = keybindings[event.key];
|
const keybindFunction = keybindings[event.key]
|
||||||
if(keybindFunction) {
|
if(keybindFunction) {
|
||||||
event.preventDefault();
|
event.preventDefault()
|
||||||
keybindFunction();
|
keybindFunction()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
Loading…
x
Reference in New Issue
Block a user