2020-06-18 23:54:48 +03:00
|
|
|
package display
|
|
|
|
|
2021-12-23 01:09:47 +03:00
|
|
|
// This file contains the functions that aren't part of the public API.
|
|
|
|
// The funcs are for network and displaying.
|
|
|
|
|
2020-06-18 23:54:48 +03:00
|
|
|
import (
|
|
|
|
"net/url"
|
2020-08-05 20:31:59 +03:00
|
|
|
"strconv"
|
2020-06-18 23:54:48 +03:00
|
|
|
"strings"
|
|
|
|
|
|
|
|
"github.com/makeworld-the-better-one/amfora/renderer"
|
|
|
|
"github.com/makeworld-the-better-one/amfora/structs"
|
|
|
|
)
|
|
|
|
|
2021-12-23 01:09:47 +03:00
|
|
|
// followLink should be used when the user "clicks" a link on a page,
|
|
|
|
// but not when a URL is opened on a new tab for the first time.
|
|
|
|
//
|
|
|
|
// It will handle updating the bottomBar.
|
|
|
|
//
|
|
|
|
// It should be called with the `go` keyword to spawn a new goroutine if
|
|
|
|
// it would otherwise block the UI loop, such as when called from an input
|
|
|
|
// handler.
|
|
|
|
//
|
|
|
|
// It blocks until navigation is finished, and we've completed any user
|
|
|
|
// interaction related to loading the URL (such as info, error modals)
|
2020-07-08 04:13:45 +03:00
|
|
|
func followLink(t *tab, prev, next string) {
|
2020-12-06 04:35:15 +03:00
|
|
|
if strings.HasPrefix(next, "about:") {
|
2021-12-23 01:09:47 +03:00
|
|
|
goURL(t, next)
|
2020-06-24 03:07:25 +03:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2021-05-13 23:38:53 +03:00
|
|
|
if t.hasContent() && !t.isAnAboutPage() {
|
2020-07-08 04:13:45 +03:00
|
|
|
nextURL, err := resolveRelLink(t, prev, next)
|
2020-06-24 03:07:25 +03:00
|
|
|
if err != nil {
|
2020-07-01 20:39:13 +03:00
|
|
|
Error("URL Error", err.Error())
|
2020-06-24 03:07:25 +03:00
|
|
|
return
|
|
|
|
}
|
2021-12-23 01:09:47 +03:00
|
|
|
goURL(t, nextURL)
|
2020-06-24 03:07:25 +03:00
|
|
|
return
|
|
|
|
}
|
|
|
|
// No content on current tab, so the "prev" URL is not valid.
|
|
|
|
// An example is the about:newtab page
|
|
|
|
_, err := url.Parse(next)
|
2020-06-18 23:54:48 +03:00
|
|
|
if err != nil {
|
2020-06-19 21:05:05 +03:00
|
|
|
Error("URL Error", "Link URL could not be parsed")
|
2020-06-18 23:54:48 +03:00
|
|
|
return
|
|
|
|
}
|
2021-12-23 01:09:47 +03:00
|
|
|
goURL(t, next)
|
2020-06-18 23:54:48 +03:00
|
|
|
}
|
|
|
|
|
2020-07-03 06:55:24 +03:00
|
|
|
// reformatPage will take the raw page content and reformat it according to the current terminal dimensions.
|
|
|
|
// It should be called when the terminal size changes.
|
|
|
|
// It will not waste resources if the passed page is already fitted to the current terminal width, and can be
|
|
|
|
// called safely even when the page might be already formatted properly.
|
|
|
|
func reformatPage(p *structs.Page) {
|
2021-02-28 02:17:49 +03:00
|
|
|
if p.TermWidth == termW {
|
2020-07-03 06:55:24 +03:00
|
|
|
// No changes to make
|
|
|
|
return
|
2020-06-22 00:15:21 +03:00
|
|
|
}
|
2020-07-04 00:28:56 +03:00
|
|
|
|
2020-08-26 02:17:06 +03:00
|
|
|
// TODO: Setup a renderer.RenderFromMediatype func so this isn't needed
|
|
|
|
|
2020-07-04 00:28:56 +03:00
|
|
|
var rendered string
|
2020-08-26 02:17:06 +03:00
|
|
|
switch p.Mediatype {
|
|
|
|
case structs.TextGemini:
|
2020-07-04 00:28:56 +03:00
|
|
|
// Links are not recorded because they won't change
|
2020-09-01 23:41:30 +03:00
|
|
|
proxied := true
|
2020-11-23 00:25:20 +03:00
|
|
|
if strings.HasPrefix(p.URL, "gemini") ||
|
|
|
|
strings.HasPrefix(p.URL, "about") ||
|
|
|
|
strings.HasPrefix(p.URL, "file") {
|
2020-09-01 23:41:30 +03:00
|
|
|
proxied = false
|
|
|
|
}
|
2021-02-28 05:18:03 +03:00
|
|
|
rendered, _ = renderer.RenderGemini(p.Raw, textWidth(), proxied)
|
2020-08-26 02:17:06 +03:00
|
|
|
case structs.TextPlain:
|
2021-02-17 22:17:13 +03:00
|
|
|
rendered = renderer.RenderPlainText(p.Raw)
|
2020-08-26 02:17:06 +03:00
|
|
|
case structs.TextAnsi:
|
2021-02-17 22:17:13 +03:00
|
|
|
rendered = renderer.RenderANSI(p.Raw)
|
2020-08-26 02:17:06 +03:00
|
|
|
default:
|
2020-07-04 00:28:56 +03:00
|
|
|
// Rendering this type is not implemented
|
|
|
|
return
|
|
|
|
}
|
2020-07-03 06:55:24 +03:00
|
|
|
p.Content = rendered
|
2021-02-28 02:17:49 +03:00
|
|
|
p.TermWidth = termW
|
2020-07-03 06:55:24 +03:00
|
|
|
}
|
|
|
|
|
2020-07-04 18:32:11 +03:00
|
|
|
// reformatPageAndSetView is for reformatting a page that is already being displayed.
|
2020-07-03 06:55:24 +03:00
|
|
|
// setPage should be used when a page is being loaded for the first time.
|
2020-07-08 04:13:45 +03:00
|
|
|
func reformatPageAndSetView(t *tab, p *structs.Page) {
|
2021-02-28 02:17:49 +03:00
|
|
|
if p.TermWidth == termW {
|
2020-07-26 18:50:18 +03:00
|
|
|
// No changes to make
|
|
|
|
return
|
|
|
|
}
|
2020-07-03 19:22:44 +03:00
|
|
|
reformatPage(p)
|
2020-07-08 04:13:45 +03:00
|
|
|
t.view.SetText(p.Content)
|
|
|
|
t.applyScroll() // Go back to where you were, roughly
|
2021-02-17 22:17:13 +03:00
|
|
|
|
|
|
|
App.Draw()
|
2020-06-22 00:15:21 +03:00
|
|
|
}
|
|
|
|
|
2020-07-08 04:13:45 +03:00
|
|
|
// setPage displays a Page on the passed tab number.
|
|
|
|
// The bottomBar is not actually changed in this func
|
|
|
|
func setPage(t *tab, p *structs.Page) {
|
|
|
|
if !isValidTab(t) {
|
|
|
|
// Don't waste time reformatting an invalid tab
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-07-03 06:55:24 +03:00
|
|
|
// Make sure the page content is fitted to the terminal every time it's displayed
|
|
|
|
reformatPage(p)
|
2020-06-29 01:09:52 +03:00
|
|
|
|
2020-07-08 04:13:45 +03:00
|
|
|
t.page = p
|
2020-08-05 20:31:59 +03:00
|
|
|
|
|
|
|
// Change page on screen
|
2020-07-08 04:13:45 +03:00
|
|
|
t.view.SetText(p.Content)
|
|
|
|
t.view.Highlight("") // Turn off highlights, other funcs may restore if necessary
|
|
|
|
t.view.ScrollToBeginning()
|
2021-02-28 02:17:49 +03:00
|
|
|
// Reset page left margin
|
2021-02-17 22:17:13 +03:00
|
|
|
tabNum := tabNumber(t)
|
2021-02-28 02:17:49 +03:00
|
|
|
browser.AddTab(
|
|
|
|
strconv.Itoa(tabNum),
|
2021-12-29 00:39:42 +03:00
|
|
|
t.label(),
|
2021-02-28 02:17:49 +03:00
|
|
|
makeContentLayout(t.view, leftMargin()),
|
|
|
|
)
|
2021-02-17 22:17:13 +03:00
|
|
|
App.Draw()
|
|
|
|
|
2020-06-18 23:54:48 +03:00
|
|
|
// Setup display
|
2020-07-08 04:13:45 +03:00
|
|
|
App.SetFocus(t.view)
|
|
|
|
|
2020-07-10 21:37:18 +03:00
|
|
|
// Save bottom bar for the tab - other funcs will apply/display it
|
2020-07-08 04:13:45 +03:00
|
|
|
t.barLabel = ""
|
2020-08-26 04:03:21 +03:00
|
|
|
t.barText = p.URL
|
2020-07-08 04:13:45 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// goURL is like handleURL, but takes care of history and the bottomBar.
|
|
|
|
// It should be preferred over handleURL in most cases.
|
|
|
|
// It has no return values to be processed.
|
|
|
|
//
|
|
|
|
// It should be called in a goroutine.
|
|
|
|
func goURL(t *tab, u string) {
|
2021-12-27 00:22:29 +03:00
|
|
|
// Update page cache in history for #122
|
|
|
|
t.historyCachePage()
|
|
|
|
|
2020-08-28 01:55:42 +03:00
|
|
|
final, displayed := handleURL(t, u, 0)
|
2020-07-08 04:13:45 +03:00
|
|
|
if displayed {
|
|
|
|
t.addToHistory(final)
|
2021-12-08 03:54:54 +03:00
|
|
|
} else if t.page.URL == "" {
|
|
|
|
// The tab is showing interstitial or no content. Let's go to about:newtab.
|
|
|
|
handleAbout(t, "about:newtab")
|
2020-07-08 04:13:45 +03:00
|
|
|
}
|
|
|
|
if t == tabs[curTab] {
|
|
|
|
// Display the bottomBar state that handleURL set
|
|
|
|
t.applyBottomBar()
|
|
|
|
}
|
2020-06-18 23:54:48 +03:00
|
|
|
}
|