From 64aa4b3faf238126913e6dff7898f307ee25198e Mon Sep 17 00:00:00 2001 From: Cam Sweeney Date: Sun, 9 Jun 2024 18:42:10 -0700 Subject: [PATCH] get trending if no viewer --- README.md | 48 ++++++++++++++++++++++++++++++++++++----------- api/feed.go | 12 ++---------- go.sum | 2 ++ ui/app.go | 13 +++++-------- ui/feed.go | 14 ++++++++------ ui/keybindings.go | 4 ---- ui/splash.go | 17 +++++------------ 7 files changed, 59 insertions(+), 51 deletions(-) diff --git a/README.md b/README.md index 5e7d2fd..44fd79c 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,14 @@ # tofui -tofui (Terminally On Farcaster User Interface) is a TUI for [farcaster](https://www.farcaster.xyz/). +tofui (Terminally On Farcaster User Interface) is a TUI for +[farcaster](https://www.farcaster.xyz/). -It supports running locally using your own [Neynar](https://neynar.com/) application, or as a hosted SSH app using [wish](https://github.com/charmbracelet/wish). +It supports running locally using your own [Neynar](https://neynar.com/) +application, or as a hosted SSH app using +[wish](https://github.com/charmbracelet/wish). ![tofui screenshot](./media/screenshot.png) - ## Hosted version Use a hosted instance of tofui over ssh @@ -19,36 +21,51 @@ ssh -p 42069 tofui.xyz ### SSH Sessions, Authentication and Details -Each SSH session is authenticated via it's SSH public key. The session then receives it's own [Bubble Tea](https://github.com/charmbracelet/bubbletea) which provides the interface. +Each SSH session is authenticated via it's SSH public key. The session then +receives it's own [Bubble Tea](https://github.com/charmbracelet/bubbletea) which +provides the interface. -For authorization, the app directs you to create a signer via Neynar's [SIWN](https://docs.neynar.com/docs/how-to-let-users-connect-farcaster-accounts-with-write-access-for-free-using-sign-in-with-neynar-siwn). This signer is created and managed by Neynar, and is used to provide tofui access to your farcaster account via it's API. +For authorization, the app directs you to create a signer via Neynar's +[SIWN](https://docs.neynar.com/docs/how-to-let-users-connect-farcaster-accounts-with-write-access-for-free-using-sign-in-with-neynar-siwn). +This signer is created and managed by Neynar, and is used to provide tofui +access to your farcaster account via it's API. -This is done when both running locally and over SSH, and the signer is specific to whichever app credentials were used. This would be tofui over SSH, or your own app when running locally. +This is done when both running locally and over SSH, and the signer is specific +to whichever app credentials were used. This would be tofui over SSH, or your +own app when running locally. +the tofui instance (local or hosted) uses the configured Neynar app credentials +to obtain a signer via -the tofui instance (local or hosted) uses the configured Neynar app credentials to obtain a signer via ## Running Locally -Running locally requires your own Neynar application. After creating one, copy [config.yaml.example](./config.yaml.example) to config.yaml and updating with your app's values. +Running locally requires your own Neynar application. After creating one, copy +[config.yaml.example](./config.yaml.example) to config.yaml and updating with +your app's values. ### Install Install using go + ``` go install github.com/treethought/tofui@latest ``` -Or clone the repo and run +Or clone the repo and run + ``` make build ``` -Or download a binary from the [releases](https://github.com/treethought/tofui/releases) page +Or download a binary from the +[releases](https://github.com/treethought/tofui/releases) page Then start the TUI via `tofui` ## Keybindings +#### Navigation + | Key | Action | | --------- | ------------------------------------------- | | Tab | Toggle focus between sidebar and main panel | @@ -59,7 +76,16 @@ Then start the TUI via `tofui` | Enter | Select current item | | F
| Jump to your feed | | Ctrl-K | Open channel quick switcher
| -| P | Open publish form | | ? | Open help | | c | View channel of current item | | p | View profile of current item | + +#### Actions + +| Key | Action | +| ------ | ---------------------------------------------- | +| ctrl-d | Submit cast/reply in publish view | +| P | Open publish form | +| C | Open reply form when viewing cast | +| o | Open current cast in browser (local mode only) | +| l | Like current cast | diff --git a/api/feed.go b/api/feed.go index 96d6062..c4d1630 100644 --- a/api/feed.go +++ b/api/feed.go @@ -3,7 +3,6 @@ package api import ( "context" "fmt" - "log" ) type FeedRequest struct { @@ -42,16 +41,9 @@ func (r *FeedRequest) opts() []RequestOption { if r.Limit != 0 { opts = append(opts, WithQuery("limit", fmt.Sprintf("%d", r.Limit))) } - if r.ViewerFID == 0 { - if r.FID != 0 { - r.ViewerFID = r.FID - log.Println("using fid param for viewer for feed request: ", r.FID) - } else { - log.Println("using default viewer fid 3 for feed request") - r.ViewerFID = 3 - } + if r.ViewerFID != 0 { + opts = append(opts, WithQuery("viewer_fid", fmt.Sprintf("%d", r.ViewerFID))) } - opts = append(opts, WithQuery("viewer_fid", fmt.Sprintf("%d", r.ViewerFID))) return opts } diff --git a/go.sum b/go.sum index 004ee64..6f38253 100644 --- a/go.sum +++ b/go.sum @@ -24,6 +24,8 @@ github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UF github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/charmbracelet/bubbles v0.16.1 h1:6uzpAAaT9ZqKssntbvZMlksWHruQLNxg49H5WdeuYSY= github.com/charmbracelet/bubbles v0.16.1/go.mod h1:2QCp9LFlEsBQMvIYERr7Ww2H2bA7xen1idUDIzm/+Xc= +github.com/charmbracelet/bubbles v0.18.0 h1:PYv1A036luoBGroX6VWjQIE9Syf2Wby2oOl/39KLfy0= +github.com/charmbracelet/bubbles v0.18.0/go.mod h1:08qhZhtIwzgrtBjAcJnij1t1H0ZRjwHyGsy6AL11PSw= github.com/charmbracelet/bubbletea v0.26.4 h1:2gDkkzLZaTjMl/dQBpNVtnvcCxsh/FCkimep7FC9c40= github.com/charmbracelet/bubbletea v0.26.4/go.mod h1:P+r+RRA5qtI1DOHNFn0otoNwB4rn+zNAzSj/EXz6xU0= github.com/charmbracelet/glamour v0.7.0 h1:2BtKGZ4iVJCDfMF229EzbeR1QRKLWztO9dMtjmqZSng= diff --git a/ui/app.go b/ui/app.go index a9b90ff..7514d29 100644 --- a/ui/app.go +++ b/ui/app.go @@ -202,14 +202,9 @@ func (a *App) FocusPrev() tea.Cmd { } prev := a.GetModel(a.prev) if a.prev == "" || prev == nil { - a.SetNavName("feed") - if f, ok := a.GetModel("feed").(*FeedView); ok { - f.Clear() - return tea.Sequence(f.SetDefaultParams(), a.SetFocus("feed")) - } - - return a.SetFocus("feed") + return nil } + if m := a.GetModel(a.prev); m != nil { a.SetNavName(a.prevName) return a.SetFocus(a.prev) @@ -280,7 +275,9 @@ func (a *App) Update(msg tea.Msg) (tea.Model, tea.Cmd) { return a, cmd } feed := a.GetModel("feed").(*FeedView) - feed.Clear() + if a.focused == "feed" { + feed.Clear() + } focusCmd := a.SetFocus("feed") a.splash.SetInfo("loading channels...") return a, tea.Batch(feed.setItems(msg.Casts), focusCmd) diff --git a/ui/feed.go b/ui/feed.go index 91aec2d..28d5fea 100644 --- a/ui/feed.go +++ b/ui/feed.go @@ -31,7 +31,6 @@ type reactMsg struct { type FeedView struct { app *App - client *api.Client table table.Model items []*CastFeedItem loading *Loading @@ -148,10 +147,14 @@ func likeCastCmd(client *api.Client, signer *api.Signer, cast *api.Cast) tea.Cmd } func getDefaultFeedCmd(client *api.Client, signer *api.Signer) tea.Cmd { - req := &api.FeedRequest{FeedType: "following", Limit: 100} + req := &api.FeedRequest{Limit: 100} if signer != nil { req.FID = signer.FID req.ViewerFID = signer.FID + req.FeedType = "following" + } else { + req.FeedType = "filter" + req.FilterType = "global_trending" } return getFeedCmd(client, req) } @@ -284,18 +287,17 @@ func (m *FeedView) ViewCurrentChannel() tea.Cmd { if current.cast.ParentURL == "" { return nil } - m.Clear() cmds := []tea.Cmd{} - if c, err := m.client.GetChannelByParentUrl(current.cast.ParentURL); err == nil { + if c, err := m.app.client.GetChannelByParentUrl(current.cast.ParentURL); err == nil { cmds = append(cmds, navNameCmd(fmt.Sprintf("channel: %s", c.Name))) } cmds = append(cmds, - focusCmd("feed"), - getFeedCmd(m.client, &api.FeedRequest{ + getFeedCmd(m.app.client, &api.FeedRequest{ FeedType: "filter", FilterType: "parent_url", ParentURL: current.cast.ParentURL, Limit: 100}, ), + focusCmd("feed"), ) return tea.Sequence(cmds...) diff --git a/ui/keybindings.go b/ui/keybindings.go index 4d86a8f..aa8ba4c 100644 --- a/ui/keybindings.go +++ b/ui/keybindings.go @@ -142,10 +142,6 @@ func (k navKeymap) HandleMsg(a *App, msg tea.KeyMsg) tea.Cmd { // TODO cleanup // reset params for user's feed var cmd tea.Cmd - if f, ok := a.GetModel("feed").(*FeedView); ok { - f.Clear() - cmd = f.SetDefaultParams() - } a.SetNavName("feed") a.sidebar.SetActive(false) return tea.Sequence(cmd, a.SetFocus("feed")) diff --git a/ui/splash.go b/ui/splash.go index f4b3573..d9826dd 100644 --- a/ui/splash.go +++ b/ui/splash.go @@ -25,7 +25,6 @@ type SplashView struct { info *viewport.Model loading *Loading active bool - spinner *spinner.Model } func NewSplashView() *SplashView { @@ -39,7 +38,7 @@ func NewSplashView() *SplashView { s := spinner.New() s.Spinner = spinner.Dot s.Style = NewStyle().Foreground(lipgloss.Color("205")) - return &SplashView{vp: &vp, loading: l, info: &info, active: true, spinner: &s} + return &SplashView{vp: &vp, loading: l, info: &info, active: true} } func (m *SplashView) Active() bool { @@ -64,27 +63,21 @@ func (m *SplashView) SetSize(w, h int) { } func (m *SplashView) Init() tea.Cmd { - return tea.Batch(m.loading.Init(), m.spinner.Tick) + return tea.Batch(m.loading.Init()) } func (m *SplashView) Update(msg tea.Msg) (tea.Model, tea.Cmd) { if !m.active { return m, nil } - cmds := []tea.Cmd{} - _, lcmd := m.loading.Update(msg) - cmds = append(cmds, lcmd) - _, scmd := m.spinner.Update(msg) - cmds = append(cmds, scmd) - - cmds = append(cmds, m.spinner.Tick) - return m, tea.Batch(cmds...) + _, cmd := m.loading.Update(msg) + return m, cmd } func (m *SplashView) View() string { return splashStyle.Render( lipgloss.JoinVertical(lipgloss.Top, m.vp.View(), lipgloss.NewStyle().MarginTop(1).Render(m.loading.View()), - lipgloss.JoinHorizontal(lipgloss.Left, m.spinner.View(), " ", m.info.View()), + m.info.View(), ), ) }