2020-06-23 20:07:25 -04:00
|
|
|
package display
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
2022-01-28 12:18:28 -05:00
|
|
|
"regexp"
|
|
|
|
"strings"
|
2020-06-23 20:07:25 -04:00
|
|
|
|
2021-04-07 12:56:32 -04:00
|
|
|
"code.rocketnine.space/tslocum/cview"
|
2021-02-17 14:17:13 -05:00
|
|
|
"github.com/gdamore/tcell/v2"
|
2020-06-23 20:07:25 -04:00
|
|
|
"github.com/makeworld-the-better-one/amfora/bookmarks"
|
2020-07-28 16:58:32 -04:00
|
|
|
"github.com/makeworld-the-better-one/amfora/config"
|
2020-06-24 11:37:32 -04:00
|
|
|
"github.com/makeworld-the-better-one/amfora/renderer"
|
|
|
|
"github.com/makeworld-the-better-one/amfora/structs"
|
|
|
|
"github.com/spf13/viper"
|
2020-06-23 20:07:25 -04:00
|
|
|
)
|
|
|
|
|
|
|
|
// For adding and removing bookmarks, basically a clone of the input modal.
|
2020-07-28 16:58:32 -04:00
|
|
|
var bkmkModal = cview.NewModal()
|
2020-06-23 20:07:25 -04:00
|
|
|
|
2021-02-27 00:13:11 -05:00
|
|
|
type bkmkAction int
|
|
|
|
|
|
|
|
const (
|
|
|
|
add bkmkAction = iota
|
|
|
|
change
|
|
|
|
cancel
|
|
|
|
remove
|
|
|
|
)
|
|
|
|
|
2020-06-23 20:07:25 -04:00
|
|
|
// bkmkCh is for the user action
|
2021-02-27 00:13:11 -05:00
|
|
|
var bkmkCh = make(chan bkmkAction)
|
|
|
|
var bkmkModalText string // The current text of the input field in the modal
|
2020-06-23 20:07:25 -04:00
|
|
|
|
2022-01-28 12:18:28 -05:00
|
|
|
// Regex for extracting top level 1 heading. The title will extracted from the 1st submatch.
|
|
|
|
var topHeadingRegex = regexp.MustCompile(`(?m)^#[^#][\t ]*[^\s].*$`)
|
|
|
|
|
2020-06-23 20:07:25 -04:00
|
|
|
func bkmkInit() {
|
2021-12-07 20:18:08 -05:00
|
|
|
panels.AddPanel(PanelBookmarks, bkmkModal, false, false)
|
2021-02-17 14:17:13 -05:00
|
|
|
|
|
|
|
m := bkmkModal
|
2020-06-24 11:37:32 -04:00
|
|
|
if viper.GetBool("a-general.color") {
|
2021-02-17 14:17:13 -05:00
|
|
|
m.SetBackgroundColor(config.GetColor("bkmk_modal_bg"))
|
|
|
|
m.SetButtonBackgroundColor(config.GetColor("btn_bg"))
|
|
|
|
m.SetButtonTextColor(config.GetColor("btn_text"))
|
|
|
|
m.SetTextColor(config.GetColor("bkmk_modal_text"))
|
|
|
|
form := m.GetForm()
|
|
|
|
form.SetLabelColor(config.GetColor("bkmk_modal_label"))
|
|
|
|
form.SetFieldBackgroundColor(config.GetColor("bkmk_modal_field_bg"))
|
|
|
|
form.SetFieldTextColor(config.GetColor("bkmk_modal_field_text"))
|
2021-08-10 15:03:34 -04:00
|
|
|
form.SetFieldBackgroundColorFocused(config.GetColor("bkmk_modal_field_text"))
|
|
|
|
form.SetFieldTextColorFocused(config.GetTextColor("bkmk_modal_field_bg", "bkmk_modal_field_text"))
|
2021-02-17 14:17:13 -05:00
|
|
|
form.SetButtonBackgroundColorFocused(config.GetColor("btn_text"))
|
2021-08-10 15:03:34 -04:00
|
|
|
form.SetButtonTextColorFocused(config.GetTextColor("btn_bg", "btn_text"))
|
2021-02-17 14:17:13 -05:00
|
|
|
frame := m.GetFrame()
|
|
|
|
frame.SetBorderColor(config.GetColor("bkmk_modal_text"))
|
|
|
|
frame.SetTitleColor(config.GetColor("bkmk_modal_text"))
|
2020-06-24 11:37:32 -04:00
|
|
|
} else {
|
2021-02-17 14:17:13 -05:00
|
|
|
m.SetBackgroundColor(tcell.ColorBlack)
|
|
|
|
m.SetButtonBackgroundColor(tcell.ColorWhite)
|
|
|
|
m.SetButtonTextColor(tcell.ColorBlack)
|
|
|
|
m.SetTextColor(tcell.ColorWhite)
|
|
|
|
form := m.GetForm()
|
|
|
|
form.SetLabelColor(tcell.ColorWhite)
|
|
|
|
form.SetFieldBackgroundColor(tcell.ColorWhite)
|
|
|
|
form.SetFieldTextColor(tcell.ColorBlack)
|
|
|
|
form.SetButtonBackgroundColorFocused(tcell.ColorBlack)
|
|
|
|
form.SetButtonTextColorFocused(tcell.ColorWhite)
|
|
|
|
frame := m.GetFrame()
|
|
|
|
frame.SetBorderColor(tcell.ColorWhite)
|
|
|
|
frame.SetTitleColor(tcell.ColorWhite)
|
2020-06-24 11:37:32 -04:00
|
|
|
}
|
|
|
|
|
2021-02-17 14:17:13 -05:00
|
|
|
m.SetBorder(true)
|
|
|
|
frame := m.GetFrame()
|
|
|
|
frame.SetTitleAlign(cview.AlignCenter)
|
|
|
|
frame.SetTitle(" Add Bookmark ")
|
|
|
|
m.SetDoneFunc(func(buttonIndex int, buttonLabel string) {
|
2020-06-23 20:07:25 -04:00
|
|
|
switch buttonLabel {
|
|
|
|
case "Add":
|
2021-02-27 00:13:11 -05:00
|
|
|
bkmkCh <- add
|
2020-06-23 20:07:25 -04:00
|
|
|
case "Change":
|
2021-02-27 00:13:11 -05:00
|
|
|
bkmkCh <- change
|
2020-06-23 20:07:25 -04:00
|
|
|
case "Remove":
|
2021-02-27 00:13:11 -05:00
|
|
|
bkmkCh <- remove
|
2020-06-23 20:07:25 -04:00
|
|
|
case "Cancel":
|
2021-02-27 00:13:11 -05:00
|
|
|
bkmkCh <- cancel
|
2021-02-04 17:30:32 -05:00
|
|
|
case "":
|
2021-02-27 00:13:11 -05:00
|
|
|
bkmkCh <- cancel
|
2020-06-23 20:07:25 -04:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
// Bkmk displays the "Add a bookmark" modal.
|
|
|
|
// It accepts the default value for the bookmark name that will be displayed, but can be changed by the user.
|
|
|
|
// It also accepts a bool indicating whether this page already has a bookmark.
|
2021-02-27 00:13:11 -05:00
|
|
|
// It returns the bookmark name and the bookmark action.
|
|
|
|
func openBkmkModal(name string, exists bool) (string, bkmkAction) {
|
2020-06-23 20:07:25 -04:00
|
|
|
// Basically a copy of Input()
|
|
|
|
|
2020-06-29 13:30:20 -04:00
|
|
|
// Reset buttons before input field, to make sure the input is in focus
|
2020-06-23 20:07:25 -04:00
|
|
|
bkmkModal.ClearButtons()
|
|
|
|
if exists {
|
|
|
|
bkmkModal.SetText("Change or remove the bookmark for the current page?")
|
|
|
|
bkmkModal.AddButtons([]string{"Change", "Remove", "Cancel"})
|
|
|
|
} else {
|
|
|
|
bkmkModal.SetText("Create a bookmark for the current page?")
|
|
|
|
bkmkModal.AddButtons([]string{"Add", "Cancel"})
|
|
|
|
}
|
2020-06-29 13:30:20 -04:00
|
|
|
|
|
|
|
// Remove and re-add input field - to clear the old text
|
|
|
|
bkmkModal.GetForm().Clear(false)
|
2021-02-22 17:41:48 -05:00
|
|
|
|
2020-11-04 19:54:58 -05:00
|
|
|
bkmkModalText = name
|
2020-06-29 13:30:20 -04:00
|
|
|
bkmkModal.GetForm().AddInputField("Name: ", name, 0, nil,
|
|
|
|
func(text string) {
|
|
|
|
// Store for use later
|
|
|
|
bkmkModalText = text
|
|
|
|
})
|
|
|
|
|
2021-12-07 20:18:08 -05:00
|
|
|
panels.ShowPanel(PanelBookmarks)
|
|
|
|
panels.SendToFront(PanelBookmarks)
|
2020-06-23 20:07:25 -04:00
|
|
|
App.SetFocus(bkmkModal)
|
|
|
|
App.Draw()
|
|
|
|
|
|
|
|
action := <-bkmkCh
|
2021-12-07 20:18:08 -05:00
|
|
|
panels.HidePanel(PanelBookmarks)
|
2020-07-28 18:09:36 -04:00
|
|
|
App.SetFocus(tabs[curTab].view)
|
|
|
|
App.Draw()
|
2020-06-23 20:07:25 -04:00
|
|
|
|
|
|
|
return bkmkModalText, action
|
|
|
|
}
|
|
|
|
|
|
|
|
// Bookmarks displays the bookmarks page on the current tab.
|
2020-07-07 21:13:45 -04:00
|
|
|
func Bookmarks(t *tab) {
|
2020-11-19 11:39:08 -05:00
|
|
|
bkmkPageRaw := "# Bookmarks\r\n\r\n"
|
|
|
|
|
2020-06-23 20:07:25 -04:00
|
|
|
// Gather bookmarks
|
2021-05-14 18:45:41 -04:00
|
|
|
names, urls := bookmarks.All()
|
|
|
|
for i := range names {
|
|
|
|
bkmkPageRaw += fmt.Sprintf("=> %s %s\r\n", urls[i], names[i])
|
2020-06-23 20:07:25 -04:00
|
|
|
}
|
|
|
|
// Render and display
|
2021-02-27 21:18:03 -05:00
|
|
|
content, links := renderer.RenderGemini(bkmkPageRaw, textWidth(), false)
|
2020-07-02 23:55:24 -04:00
|
|
|
page := structs.Page{
|
2021-02-27 21:18:03 -05:00
|
|
|
Raw: bkmkPageRaw,
|
|
|
|
Content: content,
|
|
|
|
Links: links,
|
|
|
|
URL: "about:bookmarks",
|
|
|
|
TermWidth: termW,
|
|
|
|
Mediatype: structs.TextGemini,
|
2020-07-02 23:55:24 -04:00
|
|
|
}
|
2020-07-07 21:13:45 -04:00
|
|
|
setPage(t, &page)
|
|
|
|
t.applyBottomBar()
|
2020-06-23 20:07:25 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
// addBookmark goes through the process of adding a bookmark for the current page.
|
|
|
|
// It is the high-level way of doing it. It should be called in a goroutine.
|
|
|
|
// It can also be called to edit an existing bookmark.
|
|
|
|
func addBookmark() {
|
2020-10-01 19:08:26 -04:00
|
|
|
t := tabs[curTab]
|
|
|
|
p := t.page
|
|
|
|
|
2021-05-13 16:38:53 -04:00
|
|
|
if !t.hasContent() || t.isAnAboutPage() {
|
2020-10-01 19:08:26 -04:00
|
|
|
// It's an about: page, or a malformed one
|
2020-06-23 20:07:25 -04:00
|
|
|
return
|
|
|
|
}
|
2020-10-01 19:08:26 -04:00
|
|
|
name, exists := bookmarks.Get(p.URL)
|
2022-01-28 12:18:28 -05:00
|
|
|
|
|
|
|
// Retrieve & use top level 1 heading for name if bookmark does not already exist.
|
|
|
|
if !exists {
|
|
|
|
match := topHeadingRegex.FindString(p.Raw)
|
|
|
|
if match != "" {
|
|
|
|
name = strings.TrimSpace(match[1:])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-23 20:07:25 -04:00
|
|
|
// Open a bookmark modal with the current name of the bookmark, if it exists
|
2022-01-28 12:18:28 -05:00
|
|
|
// otherwise use the top level 1 heading as a suggested name
|
2021-02-22 17:41:48 -05:00
|
|
|
newName, action := openBkmkModal(name, exists)
|
2021-02-27 00:17:11 -05:00
|
|
|
|
|
|
|
//nolint:exhaustive
|
2020-06-23 20:07:25 -04:00
|
|
|
switch action {
|
2021-02-27 00:13:11 -05:00
|
|
|
case add:
|
|
|
|
bookmarks.Add(p.URL, newName)
|
|
|
|
case change:
|
|
|
|
bookmarks.Change(p.URL, newName)
|
|
|
|
case remove:
|
2020-10-01 19:08:26 -04:00
|
|
|
bookmarks.Remove(p.URL)
|
2020-06-23 20:07:25 -04:00
|
|
|
}
|
2021-02-27 00:13:11 -05:00
|
|
|
// Other case is action == cancel, so nothing needs to happen
|
2020-06-23 20:07:25 -04:00
|
|
|
}
|