170 lines
4.0 KiB
Go
170 lines
4.0 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"net/url"
|
|
"os/exec"
|
|
"runtime"
|
|
"strconv"
|
|
|
|
"github.com/gdamore/tcell/v2"
|
|
"github.com/gelembjuk/articletext"
|
|
"github.com/rivo/tview"
|
|
)
|
|
|
|
func createArticleList(articles []Article) *tview.List {
|
|
list := tview.NewList().ShowSecondaryText(true).SetSecondaryTextColor(tcell.ColorGray)
|
|
for _, article := range articles {
|
|
title := article.Title
|
|
if article.Comments > 50 { // TODO: configurable
|
|
title = "🔥 " + title
|
|
}
|
|
|
|
commentsText := strconv.Itoa(article.Comments) + " comments"
|
|
list.AddItem(title, extractDomain(article.Link)+" "+commentsText, 0, nil)
|
|
}
|
|
|
|
return list
|
|
}
|
|
|
|
func extractDomain(link string) string {
|
|
u, err := url.Parse(link)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
return u.Host
|
|
}
|
|
|
|
func createInputHandler(app *tview.Application, list *tview.List, articles []Article, pages *tview.Pages) func(event *tcell.EventKey) *tcell.EventKey {
|
|
|
|
return func(event *tcell.EventKey) *tcell.EventKey {
|
|
switch event.Key() {
|
|
case tcell.KeyCtrlC:
|
|
app.Stop()
|
|
return nil
|
|
case tcell.KeyRight:
|
|
nextPage(pages, app, articles, list)
|
|
return nil
|
|
case tcell.KeyLeft:
|
|
backPage(pages)
|
|
return nil
|
|
case tcell.KeyRune:
|
|
switch event.Rune() {
|
|
case 'q':
|
|
app.Stop()
|
|
return nil
|
|
case 'j':
|
|
return tcell.NewEventKey(tcell.KeyDown, 0, tcell.ModNone)
|
|
case 'k':
|
|
return tcell.NewEventKey(tcell.KeyUp, 0, tcell.ModNone)
|
|
case 'l':
|
|
nextPage(pages, app, articles, list)
|
|
return nil
|
|
case 'h':
|
|
backPage(pages)
|
|
return nil
|
|
case ' ':
|
|
openURL(articles[list.GetCurrentItem()].Link)
|
|
return nil
|
|
case 'c':
|
|
openURL(hackerNewsURL + articles[list.GetCurrentItem()].CommentsLink)
|
|
return nil
|
|
|
|
}
|
|
}
|
|
|
|
return event
|
|
}
|
|
}
|
|
|
|
func backPage(pages *tview.Pages) {
|
|
// TODO: navigation flow will become configurable
|
|
currentPage, _ := pages.GetFrontPage()
|
|
if currentPage == "comments" {
|
|
pages.SwitchToPage("homepage")
|
|
}
|
|
if currentPage == "article" {
|
|
pages.SwitchToPage("comments")
|
|
}
|
|
}
|
|
|
|
func nextPage(pages *tview.Pages, app *tview.Application, articles []Article, list *tview.List) {
|
|
currentPage, _ := pages.GetFrontPage()
|
|
if currentPage == "comments" {
|
|
openArticle(app, articles[list.GetCurrentItem()].Link, pages)
|
|
} else {
|
|
openComments(app, articles[list.GetCurrentItem()].CommentsLink, pages)
|
|
}
|
|
}
|
|
|
|
func openComments(app *tview.Application, commentsLink string, pages *tview.Pages) {
|
|
u, err := url.Parse(commentsLink)
|
|
if err != nil {
|
|
fmt.Println("Error parsing URL:", err) // TODO maybe alert dialogbox
|
|
return
|
|
}
|
|
story_id := u.Query().Get("id")
|
|
|
|
articleStringList := fetchComments(story_id)
|
|
commentsText := ""
|
|
for _, articleString := range articleStringList {
|
|
commentsText += articleString + "\n"
|
|
}
|
|
displayComments(app, pages, commentsText)
|
|
}
|
|
|
|
func openArticle(app *tview.Application, articleLink string, pages *tview.Pages) {
|
|
articleText := getArticleTextFromLink(articleLink)
|
|
displayArticle(app, pages, articleText)
|
|
}
|
|
|
|
func getArticleTextFromLink(url string) string {
|
|
article, err := articletext.GetArticleTextFromUrl(url)
|
|
if err != nil {
|
|
fmt.Printf("Failed to parse %s, %v\n", url, err)
|
|
}
|
|
return article
|
|
}
|
|
|
|
func displayArticle(app *tview.Application, pages *tview.Pages, text string) {
|
|
articleTextView := tview.NewTextView().
|
|
SetText(text).
|
|
SetDynamicColors(true).
|
|
SetScrollable(true)
|
|
|
|
pages.AddPage("article", articleTextView, true, true)
|
|
if err := app.SetRoot(pages, true).Run(); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
}
|
|
|
|
func displayComments(app *tview.Application, pages *tview.Pages, text string) {
|
|
commentsTextView := tview.NewTextView().
|
|
SetText(text).
|
|
SetDynamicColors(true).
|
|
SetScrollable(true)
|
|
|
|
pages.AddPage("comments", commentsTextView, true, true)
|
|
if err := app.SetRoot(pages, true).Run(); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
}
|
|
|
|
func openURL(url string) {
|
|
var cmd string
|
|
var args []string
|
|
|
|
switch runtime.GOOS {
|
|
case "windows":
|
|
cmd = "cmd"
|
|
args = []string{"/c", "start"}
|
|
case "darwin":
|
|
cmd = "open"
|
|
default: // "linux", "freebsd", "openbsd", "netbsd"
|
|
cmd = "xdg-open"
|
|
}
|
|
args = append(args, url)
|
|
exec.Command(cmd, args...).Start()
|
|
}
|