mirror of
https://github.com/makew0rld/amfora.git
synced 2024-11-23 14:19:12 +03:00
🐛 Capture all scrolling keys
This commit is contained in:
parent
4da7816a3a
commit
ed36eee83c
26
cache/page.go
vendored
26
cache/page.go
vendored
@ -13,7 +13,7 @@ var pages = make(map[string]*structs.Page) // The actual cache
|
||||
var urls = make([]string, 0) // Duplicate of the keys in the `pages` map, but in order of being added
|
||||
var maxPages = 0 // Max allowed number of pages in cache
|
||||
var maxSize = 0 // Max allowed cache size in bytes
|
||||
var lock = sync.RWMutex{}
|
||||
var mu = sync.RWMutex{}
|
||||
var timeout = time.Duration(0)
|
||||
|
||||
// SetMaxPages sets the max number of pages the cache can hold.
|
||||
@ -79,8 +79,8 @@ func AddPage(p *structs.Page) {
|
||||
RemovePage(urls[0])
|
||||
}
|
||||
|
||||
lock.Lock()
|
||||
defer lock.Unlock()
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
pages[p.URL] = p
|
||||
// Remove the URL if it was already there, then add it to the end
|
||||
removeURL(p.URL)
|
||||
@ -90,24 +90,24 @@ func AddPage(p *structs.Page) {
|
||||
// RemovePage will remove a page from the cache.
|
||||
// Even if the page doesn't exist there will be no error.
|
||||
func RemovePage(url string) {
|
||||
lock.Lock()
|
||||
defer lock.Unlock()
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
delete(pages, url)
|
||||
removeURL(url)
|
||||
}
|
||||
|
||||
// ClearPages removes all pages from the cache.
|
||||
func ClearPages() {
|
||||
lock.Lock()
|
||||
defer lock.Unlock()
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
pages = make(map[string]*structs.Page)
|
||||
urls = make([]string, 0)
|
||||
}
|
||||
|
||||
// SizePages returns the approx. current size of the cache in bytes.
|
||||
func SizePages() int {
|
||||
lock.RLock()
|
||||
defer lock.RUnlock()
|
||||
mu.RLock()
|
||||
defer mu.RUnlock()
|
||||
n := 0
|
||||
for _, page := range pages {
|
||||
n += page.Size()
|
||||
@ -116,16 +116,16 @@ func SizePages() int {
|
||||
}
|
||||
|
||||
func NumPages() int {
|
||||
lock.RLock()
|
||||
defer lock.RUnlock()
|
||||
mu.RLock()
|
||||
defer mu.RUnlock()
|
||||
return len(pages)
|
||||
}
|
||||
|
||||
// GetPage returns the page struct, and a bool indicating if the page was in the cache or not.
|
||||
// (nil, false) is returned if the page isn't in the cache.
|
||||
func GetPage(url string) (*structs.Page, bool) {
|
||||
lock.RLock()
|
||||
defer lock.RUnlock()
|
||||
mu.RLock()
|
||||
defer mu.RUnlock()
|
||||
|
||||
p, ok := pages[url]
|
||||
if ok && (timeout == 0 || time.Since(p.MadeAt) < timeout) {
|
||||
|
@ -248,6 +248,8 @@ func Init() error {
|
||||
viper.SetDefault("keybindings.bind_tab0", ")")
|
||||
viper.SetDefault("keybindings.bind_copy_page_url", "C")
|
||||
viper.SetDefault("keybindings.bind_copy_target_url", "c")
|
||||
viper.SetDefault("keybindings.bind_beginning", []string{"Home", "g"})
|
||||
viper.SetDefault("keybindings.bind_end", []string{"End", "G"})
|
||||
viper.SetDefault("keybindings.shift_numbers", "")
|
||||
viper.SetDefault("url-handlers.other", "off")
|
||||
viper.SetDefault("cache.max_size", 0)
|
||||
|
@ -164,6 +164,8 @@ scrollbar = "auto"
|
||||
# bind_add_sub
|
||||
# bind_copy_page_url
|
||||
# bind_copy_target_url
|
||||
# bind_beginning: moving to beginning of page (top left)
|
||||
# bind_end: same but the for the end (bottom left)
|
||||
|
||||
[url-handlers]
|
||||
# Allows setting the commands to run for various URL schemes.
|
||||
|
@ -59,6 +59,8 @@ const (
|
||||
CmdAddSub
|
||||
CmdCopyPageURL
|
||||
CmdCopyTargetURL
|
||||
CmdBeginning
|
||||
CmdEnd
|
||||
)
|
||||
|
||||
type keyBinding struct {
|
||||
@ -189,6 +191,8 @@ func KeyInit() {
|
||||
CmdAddSub: "keybindings.bind_add_sub",
|
||||
CmdCopyPageURL: "keybindings.bind_copy_page_url",
|
||||
CmdCopyTargetURL: "keybindings.bind_copy_target_url",
|
||||
CmdBeginning: "keybindings.bind_beginning",
|
||||
CmdEnd: "keybindings.bind_end",
|
||||
}
|
||||
// This is split off to allow shift_numbers to override bind_tab[1-90]
|
||||
// (This is needed for older configs so that the default bind_tab values
|
||||
@ -212,10 +216,15 @@ func KeyInit() {
|
||||
tcellKeys[kname] = k
|
||||
}
|
||||
|
||||
// Set cview navigation keys to use user-set ones
|
||||
cview.Keys.MoveUp2 = viper.GetStringSlice(configBindings[CmdMoveUp])
|
||||
cview.Keys.MoveDown2 = viper.GetStringSlice(configBindings[CmdMoveDown])
|
||||
cview.Keys.MoveLeft2 = viper.GetStringSlice(configBindings[CmdMoveLeft])
|
||||
cview.Keys.MoveRight2 = viper.GetStringSlice(configBindings[CmdMoveRight])
|
||||
cview.Keys.MoveFirst = viper.GetStringSlice(configBindings[CmdBeginning])
|
||||
cview.Keys.MoveFirst2 = nil
|
||||
cview.Keys.MoveLast = viper.GetStringSlice(configBindings[CmdEnd])
|
||||
cview.Keys.MoveLast2 = nil
|
||||
|
||||
for c, allb := range configBindings {
|
||||
for _, b := range viper.GetStringSlice(allb) {
|
||||
|
@ -161,6 +161,8 @@ scrollbar = "auto"
|
||||
# bind_add_sub
|
||||
# bind_copy_page_url
|
||||
# bind_copy_target_url
|
||||
# bind_beginning: moving to beginning of page (top left)
|
||||
# bind_end: same but the for the end (bottom left)
|
||||
|
||||
[url-handlers]
|
||||
# Allows setting the commands to run for various URL schemes.
|
||||
|
@ -9,7 +9,6 @@ import (
|
||||
"sync"
|
||||
|
||||
"code.rocketnine.space/tslocum/cview"
|
||||
"github.com/atotto/clipboard"
|
||||
"github.com/gdamore/tcell/v2"
|
||||
"github.com/makeworld-the-better-one/amfora/cache"
|
||||
"github.com/makeworld-the-better-one/amfora/config"
|
||||
@ -302,31 +301,6 @@ func Init(version, commit, builtBy string) {
|
||||
case config.CmdHome:
|
||||
URL(viper.GetString("a-general.home"))
|
||||
return nil
|
||||
case config.CmdBookmarks:
|
||||
Bookmarks(tabs[curTab])
|
||||
tabs[curTab].addToHistory("about:bookmarks")
|
||||
return nil
|
||||
case config.CmdAddBookmark:
|
||||
go addBookmark()
|
||||
return nil
|
||||
case config.CmdPgup:
|
||||
tabs[curTab].pageUp()
|
||||
return nil
|
||||
case config.CmdPgdn:
|
||||
tabs[curTab].pageDown()
|
||||
return nil
|
||||
case config.CmdSave:
|
||||
if tabs[curTab].hasContent() {
|
||||
savePath, err := downloadPage(tabs[curTab].page)
|
||||
if err != nil {
|
||||
Error("Download Error", fmt.Sprintf("Error saving page content: %v", err))
|
||||
} else {
|
||||
Info(fmt.Sprintf("Page content saved to %s. ", savePath))
|
||||
}
|
||||
} else {
|
||||
Info("The current page has no content, so it couldn't be downloaded.")
|
||||
}
|
||||
return nil
|
||||
case config.CmdBottom:
|
||||
// Space starts typing, like Bombadillo
|
||||
bottomBar.SetLabel("[::b]URL/Num./Search: [::-]")
|
||||
@ -340,58 +314,9 @@ func Init(version, commit, builtBy string) {
|
||||
bottomBar.SetText(tabs[curTab].page.URL)
|
||||
App.SetFocus(bottomBar)
|
||||
return nil
|
||||
case config.CmdBack:
|
||||
histBack(tabs[curTab])
|
||||
return nil
|
||||
case config.CmdForward:
|
||||
histForward(tabs[curTab])
|
||||
return nil
|
||||
case config.CmdSub:
|
||||
Subscriptions(tabs[curTab], "about:subscriptions")
|
||||
tabs[curTab].addToHistory("about:subscriptions")
|
||||
return nil
|
||||
case config.CmdAddSub:
|
||||
go addSubscription()
|
||||
return nil
|
||||
case config.CmdCopyPageURL:
|
||||
currentURL := tabs[curTab].page.URL
|
||||
err := clipboard.WriteAll(currentURL)
|
||||
if err != nil {
|
||||
Error("Copy Error", err.Error())
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
case config.CmdCopyTargetURL:
|
||||
currentURL := tabs[curTab].page.URL
|
||||
selectedURL := tabs[curTab].HighlightedURL()
|
||||
if selectedURL == "" {
|
||||
return nil
|
||||
}
|
||||
u, _ := url.Parse(currentURL)
|
||||
copiedURL, err := u.Parse(selectedURL)
|
||||
if err != nil {
|
||||
err := clipboard.WriteAll(selectedURL)
|
||||
if err != nil {
|
||||
Error("Copy Error", err.Error())
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
err = clipboard.WriteAll(copiedURL.String())
|
||||
if err != nil {
|
||||
Error("Copy Error", err.Error())
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Number key: 1-9, 0, LINK1-LINK10
|
||||
if cmd >= config.CmdLink1 && cmd <= config.CmdLink0 {
|
||||
if int(cmd) <= len(tabs[curTab].page.Links) {
|
||||
// It's a valid link number
|
||||
followLink(tabs[curTab], tabs[curTab].page.URL, tabs[curTab].page.Links[cmd-1])
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,8 +16,8 @@ var helpCells = strings.TrimSpace(
|
||||
"Arrow keys, %s(left)/%s(down)/%s(up)/%s(right)\tScroll and move a page.\n" +
|
||||
"%s\tGo up a page in document\n" +
|
||||
"%s\tGo down a page in document\n" +
|
||||
"g\tGo to top of document\n" +
|
||||
"G\tGo to bottom of document\n" +
|
||||
"%s\tGo to top of document\n" +
|
||||
"%s\tGo to bottom of document\n" +
|
||||
"Tab\tNavigate to the next item in a popup.\n" +
|
||||
"Shift-Tab\tNavigate to the previous item in a popup.\n" +
|
||||
"%s\tGo back in the history\n" +
|
||||
@ -86,6 +86,8 @@ func helpInit() {
|
||||
config.GetKeyBinding(config.CmdMoveRight),
|
||||
config.GetKeyBinding(config.CmdPgup),
|
||||
config.GetKeyBinding(config.CmdPgdn),
|
||||
config.GetKeyBinding(config.CmdBeginning),
|
||||
config.GetKeyBinding(config.CmdEnd),
|
||||
config.GetKeyBinding(config.CmdBack),
|
||||
config.GetKeyBinding(config.CmdForward),
|
||||
config.GetKeyBinding(config.CmdBottom),
|
||||
|
121
display/tab.go
121
display/tab.go
@ -1,10 +1,13 @@
|
||||
package display
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"code.rocketnine.space/tslocum/cview"
|
||||
"github.com/atotto/clipboard"
|
||||
"github.com/gdamore/tcell/v2"
|
||||
"github.com/makeworld-the-better-one/amfora/config"
|
||||
"github.com/makeworld-the-better-one/amfora/structs"
|
||||
@ -124,11 +127,96 @@ func makeNewTab() *tab {
|
||||
t.view.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
|
||||
// Capture scrolling and change the left margin size accordingly, see #197
|
||||
// This was also touched by #222
|
||||
// This also captures any tab-specific events now
|
||||
|
||||
if t.mode != tabModeDone {
|
||||
// Any events that should be caught when the tab is loading is handled in display.go
|
||||
return nil
|
||||
}
|
||||
|
||||
cmd := config.TranslateKeyEvent(event)
|
||||
|
||||
// Cmds that aren't single row/column scrolling
|
||||
switch cmd {
|
||||
case config.CmdBookmarks:
|
||||
Bookmarks(&t)
|
||||
t.addToHistory("about:bookmarks")
|
||||
return nil
|
||||
case config.CmdAddBookmark:
|
||||
go addBookmark()
|
||||
return nil
|
||||
case config.CmdPgup:
|
||||
t.pageUp()
|
||||
return nil
|
||||
case config.CmdPgdn:
|
||||
t.pageDown()
|
||||
return nil
|
||||
case config.CmdSave:
|
||||
if t.hasContent() {
|
||||
savePath, err := downloadPage(t.page)
|
||||
if err != nil {
|
||||
Error("Download Error", fmt.Sprintf("Error saving page content: %v", err))
|
||||
} else {
|
||||
Info(fmt.Sprintf("Page content saved to %s. ", savePath))
|
||||
}
|
||||
} else {
|
||||
Info("The current page has no content, so it couldn't be downloaded.")
|
||||
}
|
||||
return nil
|
||||
case config.CmdBack:
|
||||
histBack(&t)
|
||||
return nil
|
||||
case config.CmdForward:
|
||||
histForward(&t)
|
||||
return nil
|
||||
case config.CmdSub:
|
||||
Subscriptions(&t, "about:subscriptions")
|
||||
tabs[curTab].addToHistory("about:subscriptions")
|
||||
return nil
|
||||
case config.CmdCopyPageURL:
|
||||
currentURL := tabs[curTab].page.URL
|
||||
err := clipboard.WriteAll(currentURL)
|
||||
if err != nil {
|
||||
Error("Copy Error", err.Error())
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
case config.CmdCopyTargetURL:
|
||||
currentURL := t.page.URL
|
||||
selectedURL := t.HighlightedURL()
|
||||
if selectedURL == "" {
|
||||
return nil
|
||||
}
|
||||
u, _ := url.Parse(currentURL)
|
||||
copiedURL, err := u.Parse(selectedURL)
|
||||
if err != nil {
|
||||
err := clipboard.WriteAll(selectedURL)
|
||||
if err != nil {
|
||||
Error("Copy Error", err.Error())
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
err = clipboard.WriteAll(copiedURL.String())
|
||||
if err != nil {
|
||||
Error("Copy Error", err.Error())
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
// Number key: 1-9, 0, LINK1-LINK10
|
||||
if cmd >= config.CmdLink1 && cmd <= config.CmdLink0 {
|
||||
if int(cmd) <= len(t.page.Links) {
|
||||
// It's a valid link number
|
||||
followLink(&t, t.page.URL, t.page.Links[cmd-1])
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Scrolling stuff
|
||||
|
||||
key := event.Key()
|
||||
mod := event.Modifiers()
|
||||
cmd := config.TranslateKeyEvent(event)
|
||||
|
||||
height, width := t.view.GetBufferSize()
|
||||
_, _, boxW, boxH := t.view.GetInnerRect()
|
||||
|
||||
@ -175,6 +263,18 @@ func makeNewTab() *tab {
|
||||
t.page.Row++
|
||||
}
|
||||
return event
|
||||
} else if cmd == config.CmdBeginning {
|
||||
t.page.Row = 0
|
||||
// This is required because cview will also set the column (incorrectly)
|
||||
// if it handles this event itself
|
||||
t.applyScroll()
|
||||
App.Draw()
|
||||
return nil
|
||||
} else if cmd == config.CmdEnd {
|
||||
t.page.Row = height
|
||||
t.applyScroll()
|
||||
App.Draw()
|
||||
return nil
|
||||
} else {
|
||||
// Some other key, stop processing it
|
||||
return event
|
||||
@ -202,14 +302,23 @@ func (t *tab) addToHistory(u string) {
|
||||
|
||||
// pageUp scrolls up 75% of the height of the terminal, like Bombadillo.
|
||||
func (t *tab) pageUp() {
|
||||
row, col := t.view.GetScrollOffset()
|
||||
t.view.ScrollTo(row-(termH/4)*3, col)
|
||||
t.page.Row -= (termH / 4) * 3
|
||||
if t.page.Row < 0 {
|
||||
t.page.Row = 0
|
||||
}
|
||||
t.applyScroll()
|
||||
}
|
||||
|
||||
// pageDown scrolls down 75% of the height of the terminal, like Bombadillo.
|
||||
func (t *tab) pageDown() {
|
||||
row, col := t.view.GetScrollOffset()
|
||||
t.view.ScrollTo(row+(termH/4)*3, col)
|
||||
height, _ := t.view.GetBufferSize()
|
||||
|
||||
t.page.Row += (termH / 4) * 3
|
||||
if t.page.Row > height {
|
||||
t.page.Row = height
|
||||
}
|
||||
|
||||
t.applyScroll()
|
||||
}
|
||||
|
||||
// hasContent returns false when the tab's page is malformed,
|
||||
|
Loading…
Reference in New Issue
Block a user