From 02ea07428b32876d199372f5c136af370ceedb28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=83=9E=E3=83=AA=E3=82=A6=E3=82=B9?= Date: Tue, 3 Jan 2023 13:19:21 -0500 Subject: [PATCH] Fixed caching, focusing --- ui/ui.go | 23 ++- ui/views/posts/posts.go | 230 ++++++---------------------- ui/views/posts/view.go | 209 ------------------------- ui/windows/postcreate/postcreate.go | 61 ++++---- ui/windows/postshow/postshow.go | 28 ++-- 5 files changed, 110 insertions(+), 441 deletions(-) delete mode 100644 ui/views/posts/view.go diff --git a/ui/ui.go b/ui/ui.go index 2822143..06d5ef1 100644 --- a/ui/ui.go +++ b/ui/ui.go @@ -51,6 +51,7 @@ type Model struct { ctx *ctx.Ctx viewcache string + viewcacheID string renderOnlyFocused bool } @@ -82,6 +83,8 @@ func (m Model) Init() tea.Cmd { func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { cmds := make([]tea.Cmd, 0) + m.viewcacheID = m.wm.Focused() + switch msg := msg.(type) { case tea.KeyMsg: @@ -129,14 +132,13 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { ) case postcreate.WIN_ID: m.ctx.Logger.Debugln("received WinOpen") - m.viewcache = m.buildView(false) - m.renderOnlyFocused = true ccmds = m.wm.Open( msg.Target, postcreate.NewModel(m.ctx), [4]int{6, int(m.ctx.Content[1] / 3), 8, 4}, &msg, ) + m.viewcache = m.buildView(false) } m.ctx.Logger.Debugf("got back ccmds: %v\n", ccmds) @@ -144,7 +146,6 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { switch msg.Target { case postcreate.WIN_ID: m.ctx.Logger.Debugln("received WinClose") - m.renderOnlyFocused = false } case cmd.WMCloseWin: @@ -162,10 +163,10 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { ) default: - if msg.Call < cmd.ViewFocus { - m.ctx.Logger.Debugf("updating all with cmd: %v\n", msg) - ccmds = m.wm.UpdateAll(msg) - } + // if msg.Call < cmd.ViewFocus { + m.ctx.Logger.Debugf("updating all with cmd: %v\n", msg) + ccmds = m.wm.UpdateAll(msg) + // } } cmds = append(cmds, ccmds...) @@ -197,9 +198,15 @@ func (m Model) buildView(cached bool) string { s := strings.Builder{} var tmp string = "" - if m.viewcache != "" && m.renderOnlyFocused { + m.ctx.Logger.Debugf("viewcacheID: %s\n", m.viewcacheID) + if cached && m.viewcache != "" && m.viewcacheID == m.wm.Focused() && + m.viewcacheID == postcreate.WIN_ID { + m.ctx.Logger.Debug("hitting UI viewcache") tmp = m.viewcache + m.renderOnlyFocused = true } else { + m.ctx.Logger.Debug("generating UI viewcache") + m.renderOnlyFocused = false s.WriteString(m.header.View() + "\n") s.WriteString(m.views[m.currentView].View()) tmp = s.String() diff --git a/ui/views/posts/posts.go b/ui/views/posts/posts.go index 2236151..abdfc71 100644 --- a/ui/views/posts/posts.go +++ b/ui/views/posts/posts.go @@ -2,17 +2,14 @@ package posts import ( "fmt" + "strings" "github.com/charmbracelet/bubbles/key" "github.com/charmbracelet/bubbles/list" - "github.com/charmbracelet/bubbles/textarea" - "github.com/charmbracelet/bubbles/viewport" tea "github.com/charmbracelet/bubbletea" - "github.com/charmbracelet/glamour" "github.com/charmbracelet/lipgloss" "github.com/mrusme/gobbs/aggregator" "github.com/mrusme/gobbs/models/post" - "github.com/mrusme/gobbs/models/reply" "github.com/mrusme/gobbs/ui/cmd" "github.com/mrusme/gobbs/ui/ctx" "github.com/mrusme/gobbs/ui/windows/postshow" @@ -20,22 +17,11 @@ import ( var ( VIEW_ID = "posts" - - viewportStyle = lipgloss.NewStyle(). - Margin(0, 0, 0, 0). - Padding(0, 0). - BorderTop(false). - BorderLeft(false). - BorderRight(false). - BorderBottom(false) ) type KeyMap struct { Refresh key.Binding Select key.Binding - // Esc key.Binding - // Quit key.Binding - Reply key.Binding } var DefaultKeyMap = KeyMap{ @@ -47,47 +33,23 @@ var DefaultKeyMap = KeyMap{ key.WithKeys("r", "enter"), key.WithHelp("r/enter", "read"), ), - // Esc: key.NewBinding( - // key.WithKeys("esc"), - // key.WithHelp("esc", "close"), - // ), - // Quit: key.NewBinding( - // key.WithKeys("q"), - // ), - Reply: key.NewBinding( - key.WithKeys("ctrl+s"), - key.WithHelp("ctrl+s", "reply"), - ), } type Model struct { - ctx *ctx.Ctx - keymap KeyMap - focused bool - list list.Model - items []list.Item - viewport viewport.Model - textarea textarea.Model + ctx *ctx.Ctx + keymap KeyMap + focused bool - a *aggregator.Aggregator - glam *glamour.TermRenderer + list list.Model + items []list.Item - // wm []string - - buffer string - replyIDs []string - - activePost *post.Post - allReplies []*reply.Reply - activeReply *reply.Reply + a *aggregator.Aggregator viewcache string viewcacheTextareaXY []int } func (m Model) Init() tea.Cmd { - // TODO: Doesn't seem to be working - // return m.refresh() return nil } @@ -97,11 +59,6 @@ func NewModel(c *ctx.Ctx) Model { keymap: DefaultKeyMap, focused: false, - // wm: []string{WM_ROOT_ID}, - - buffer: "", - replyIDs: []string{}, - viewcache: "", viewcacheTextareaXY: []int{0, 0, 0, 0}, } @@ -118,10 +75,6 @@ func NewModel(c *ctx.Ctx) Model { m.list.SetShowTitle(false) m.list.SetShowStatusBar(false) - // m.textarea = textarea.New() - // m.textarea.Placeholder = "Type in your reply ..." - // m.textarea.Prompt = "" - m.a, _ = aggregator.New(m.ctx) return m @@ -135,19 +88,12 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { switch { case key.Matches(msg, m.keymap.Refresh): - // if m.WMisFocused("list") { m.ctx.Loading = true cmds = append(cmds, m.refresh()) - // } case key.Matches(msg, m.keymap.Select): - // switch m.WMFocused() { - // - // case "list": i, ok := m.list.SelectedItem().(post.Post) if ok { - // m.ctx.Loading = true - // cmds = append(cmds, m.loadItem(&i)) m.viewcache = m.buildView(false) cmd := cmd.New(cmd.WinOpen, postshow.WIN_ID, cmd.Arg{ Name: "post", @@ -155,103 +101,11 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { }) cmds = append(cmds, cmd.Tea()) } - // - // case "post": - // if m.buffer != "" { - // replyToID, err := strconv.Atoi(m.buffer) - // if err != nil { - // // TODO: Handle error - // } - // - // if replyToID >= len(m.replyIDs) { - // // TODO: Handle error - // } - // } - // m.WMOpen("reply") - // - // m.ctx.Logger.Debugln("caching view") - // m.ctx.Logger.Debugf("buffer: %s", m.buffer) - // m.viewcache = m.buildView(false) - // - // return m, m.textarea.Focus() - // } - - // case key.Matches(msg, m.keymap.Esc), key.Matches(msg, m.keymap.Quit): - // switch m.WMFocused() { - // - // case "list": - // return m, tea.Quit - // - // case "post": - // // Let's make sure we reset the texarea - // m.textarea.Reset() - // m.WMClose("post") - // return m, nil - // - // case "reply": - // if key.Matches(msg, m.keymap.Esc) { - // m.buffer = "" - // m.WMClose("reply") - // return m, nil - // } - // } - - case key.Matches(msg, m.keymap.Reply): - // if m.WMisFocused("reply") { - // replyToIdx, _ := strconv.Atoi(m.buffer) - // - // m.ctx.Logger.Debugf("replyToIdx: %d", replyToIdx) - // - // var irtID string = "" - // var irtIRT string = "" - // var irtSysIDX int = 0 - // - // if replyToIdx == 0 { - // irtID = m.activePost.ID - // irtSysIDX = m.activePost.SysIDX - // } else { - // irt := m.allReplies[(replyToIdx - 1)] - // irtID = strconv.Itoa(replyToIdx + 1) - // irtIRT = irt.InReplyTo - // irtSysIDX = irt.SysIDX - // } - // - // r := reply.Reply{ - // ID: irtID, - // InReplyTo: irtIRT, - // Body: m.textarea.Value(), - // SysIDX: irtSysIDX, - // } - // err := m.a.CreateReply(&r) - // if err != nil { - // m.ctx.Logger.Error(err) - // } - // - // m.textarea.Reset() - // m.buffer = "" - // m.WMClose("reply") - // return m, nil - // } - - // default: - // switch msg.String() { - // case "1", "2", "3", "4", "5", "6", "7", "8", "9", "0": - // if m.WMisFocused("post") { - // m.buffer += msg.String() - // return m, nil - // } - // default: - // if m.WMFocused() != "reply" { - // m.buffer = "" - // } - // } } case tea.WindowSizeMsg: listWidth := m.ctx.Content[0] - 2 listHeight := m.ctx.Content[1] - 1 - // viewportWidth := m.ctx.Content[0] - 9 - // viewportHeight := m.ctx.Content[1] - 10 m.ctx.Theme.PostsList.List.Focused.Width(listWidth) m.ctx.Theme.PostsList.List.Blurred.Width(listWidth) @@ -262,31 +116,18 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { listHeight-2, ) - // viewportStyle.Width(viewportWidth) - // viewportStyle.Height(viewportHeight) - // m.viewport = viewport.New(viewportWidth-4, viewportHeight-4) - // m.viewport.Width = viewportWidth - 4 - // m.viewport.Height = viewportHeight + 1 - // // cmds = append(cmds, viewport.Sync(m.viewport)) - - // case *post.Post: - // m.viewport.SetContent(m.renderViewport(msg)) - // m.WMOpen("post") - // m.ctx.Loading = false - // return m, nil - case cmd.Command: switch msg.Call { case cmd.ViewFocus: if msg.Target == VIEW_ID || msg.Target == "*" { - m.focused = true + m.Focus() } return m, nil case cmd.ViewBlur: if msg.Target == VIEW_ID || msg.Target == "*" { - m.focused = false + m.Blur() } return m, nil case cmd.ViewRefreshData: @@ -308,18 +149,7 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { } var lcmd tea.Cmd - - // switch m.WMFocused() { - // case "list": m.list, lcmd = m.list.Update(msg) - // case "post": - // m.viewport, lcmd = m.viewport.Update(msg) - // case "reply": - // if !m.textarea.Focused() { - // cmds = append(cmds, m.textarea.Focus()) - // } - // m.textarea, lcmd = m.textarea.Update(msg) - // } cmds = append(cmds, lcmd) return m, tea.Batch(cmds...) @@ -347,9 +177,41 @@ func (m *Model) refresh() tea.Cmd { } } -func (m *Model) loadItem(p *post.Post) tea.Cmd { - return func() tea.Msg { - m.a.LoadPost(p) - return p - } +func (m *Model) Focus() { + m.focused = true + m.viewcache = m.buildView(false) +} + +func (m *Model) Blur() { + m.focused = false + m.viewcache = m.buildView(false) +} + +func (m Model) View() string { + return m.buildView(true) +} + +func (m Model) buildView(cached bool) string { + var view strings.Builder = strings.Builder{} + + if cached && m.focused == false && m.viewcache != "" { + m.ctx.Logger.Debugln("Cached View()") + + return m.viewcache + } + + m.ctx.Logger.Debugln("Posts.View()") + var l string = "" + if m.focused { + l = m.ctx.Theme.PostsList.List.Focused.Render(m.list.View()) + } else { + l = m.ctx.Theme.PostsList.List.Blurred.Render(m.list.View()) + } + view.WriteString(lipgloss.JoinHorizontal( + lipgloss.Top, + l, + )) + + m.viewcache = view.String() + return m.viewcache } diff --git a/ui/views/posts/view.go b/ui/views/posts/view.go deleted file mode 100644 index c271a40..0000000 --- a/ui/views/posts/view.go +++ /dev/null @@ -1,209 +0,0 @@ -package posts - -import ( - "strings" - - "github.com/charmbracelet/lipgloss" -) - -func (m Model) View() string { - return m.buildView(true) -} - -func (m Model) buildView(cached bool) string { - var view strings.Builder = strings.Builder{} - - if cached && m.focused == false && m.viewcache != "" { - m.ctx.Logger.Debugln("Cached View()") - - return m.viewcache - } - - m.ctx.Logger.Debugln("Posts.View()") - var l string = "" - if m.focused { - l = m.ctx.Theme.PostsList.List.Focused.Render(m.list.View()) - } else { - l = m.ctx.Theme.PostsList.List.Blurred.Render(m.list.View()) - } - view.WriteString(lipgloss.JoinHorizontal( - lipgloss.Top, - l, - )) - - // if m.WMisOpen("post") { - // var style lipgloss.Style - // if m.WMisFocused("post") { - // style = m.ctx.Theme.DialogBox.Titlebar.Focused - // } else { - // style = m.ctx.Theme.DialogBox.Titlebar.Blurred - // } - // titlebar := style.Align(lipgloss.Center). - // Width(m.viewport.Width + 4). - // Render("Post") - // - // bottombar := m.ctx.Theme.DialogBox.Bottombar. - // Width(m.viewport.Width + 4). - // Render("[#]r reply · esc close") - // - // ui := lipgloss.JoinVertical( - // lipgloss.Center, - // titlebar, - // viewportStyle.Render(m.viewport.View()), - // bottombar, - // ) - // - // var tmp string - // if m.WMisFocused("post") { - // tmp = helpers.PlaceOverlay(3, 2, - // m.ctx.Theme.DialogBox.Window.Focused.Render(ui), - // view.String(), true) - // } else { - // tmp = helpers.PlaceOverlay(3, 2, - // m.ctx.Theme.DialogBox.Window.Blurred.Render(ui), - // view.String(), true) - // } - // - // view = strings.Builder{} - // view.WriteString(tmp) - // } - // - // if m.WMisOpen("reply") { - // title := "Reply" - // if m.buffer != "" && m.buffer != "0" { - // title += " to reply #" + m.buffer - // } - // titlebar := m.ctx.Theme.DialogBox.Titlebar.Focused. - // Align(lipgloss.Center). - // Width(m.viewport.Width - 2). - // Render(title) - // - // textareaWidth := m.viewport.Width - 2 - // textareaHeight := 6 - // m.textarea.SetWidth(textareaWidth) - // m.textarea.SetHeight(textareaHeight) - // - // bottombar := m.ctx.Theme.DialogBox.Bottombar. - // Width(m.viewport.Width - 2). - // Render("ctrl+enter reply · esc close") - // - // replyWindow := lipgloss.JoinVertical( - // lipgloss.Center, - // titlebar, - // m.textarea.View(), - // bottombar, - // ) - // - // replyWindowX := 5 - // replyWindowY := m.ctx.Screen[1] - 21 - // - // tmp := helpers.PlaceOverlay(replyWindowX, replyWindowY, - // m.ctx.Theme.DialogBox.Window.Focused.Render(replyWindow), - // view.String(), true) - // - // m.viewcacheTextareaXY[0] = replyWindowX + 1 - // m.viewcacheTextareaXY[1] = replyWindowY + 2 - // m.viewcacheTextareaXY[2] = textareaWidth - // m.viewcacheTextareaXY[3] = textareaHeight - // - // view = strings.Builder{} - // view.WriteString(tmp) - // } - - m.viewcache = view.String() - return m.viewcache -} - -// func (m *Model) renderViewport(p *post.Post) string { -// var out string = "" -// -// var err error -// m.glam, err = glamour.NewTermRenderer( -// glamour.WithAutoStyle(), -// glamour.WithWordWrap(m.viewport.Width), -// ) -// if err != nil { -// m.ctx.Logger.Error(err) -// m.glam = nil -// } -// -// adj := "writes" -// if p.Subject[len(p.Subject)-1:] == "?" { -// adj = "asks" -// } -// -// body, err := m.glam.Render(p.Body) -// if err != nil { -// m.ctx.Logger.Error(err) -// body = p.Body -// } -// out += fmt.Sprintf( -// " %s\n\n %s\n%s", -// m.ctx.Theme.Post.Author.Render( -// fmt.Sprintf("%s %s:", p.Author.Name, adj), -// ), -// m.ctx.Theme.Post.Subject.Render(p.Subject), -// body, -// ) -// -// m.replyIDs = []string{p.ID} -// m.activePost = p -// out += m.renderReplies(0, p.Author.Name, &p.Replies) -// -// return out -// } -// -// func (m *Model) renderReplies( -// level int, -// inReplyTo string, -// replies *[]reply.Reply, -// ) string { -// var out string = "" -// -// if replies == nil { -// return "" -// } -// -// for ri, re := range *replies { -// var err error = nil -// var body string = "" -// var author string = "" -// -// if re.Deleted { -// body = "\n DELETED\n\n" -// author = "DELETED" -// } else { -// body, err = m.glam.Render(re.Body) -// if err != nil { -// m.ctx.Logger.Error(err) -// body = re.Body -// } -// -// author = re.Author.Name -// } -// -// m.replyIDs = append(m.replyIDs, re.ID) -// m.allReplies = append(m.allReplies, &(*replies)[ri]) -// idx := len(m.replyIDs) - 1 -// -// out += fmt.Sprintf( -// "\n\n %s %s%s%s\n%s", -// m.ctx.Theme.Reply.Author.Render( -// author, -// ), -// lipgloss.NewStyle(). -// Foreground(m.ctx.Theme.Reply.Author.GetBackground()). -// Render(fmt.Sprintf("writes in reply to %s:", inReplyTo)), -// strings.Repeat(" ", (m.viewport.Width-len(author)-len(inReplyTo)-28)), -// lipgloss.NewStyle(). -// Foreground(lipgloss.Color("#777777")). -// Render(fmt.Sprintf("#%d", idx)), -// body, -// ) -// -// idx++ -// out += m.renderReplies(level+1, re.Author.Name, &re.Replies) -// } -// -// return out -// } diff --git a/ui/windows/postcreate/postcreate.go b/ui/windows/postcreate/postcreate.go index b18f2e8..42ac248 100644 --- a/ui/windows/postcreate/postcreate.go +++ b/ui/windows/postcreate/postcreate.go @@ -9,7 +9,6 @@ import ( "github.com/charmbracelet/bubbles/key" "github.com/charmbracelet/bubbles/textarea" tea "github.com/charmbracelet/bubbletea" - "github.com/charmbracelet/glamour" "github.com/charmbracelet/lipgloss" "github.com/mrusme/gobbs/aggregator" "github.com/mrusme/gobbs/models/post" @@ -39,15 +38,15 @@ var DefaultKeyMap = KeyMap{ } type Model struct { - ctx *ctx.Ctx - keymap KeyMap - wh [2]int - focused bool - xywh [4]int + ctx *ctx.Ctx + keymap KeyMap + wh [2]int + focused bool + xywh [4]int + textarea textarea.Model - a *aggregator.Aggregator - glam *glamour.TermRenderer + a *aggregator.Aggregator replyToIdx int replyTo string @@ -61,14 +60,6 @@ func (m Model) Init() tea.Cmd { return nil } -func (m Model) Focus() { - m.focused = true -} - -func (m Model) Blur() { - m.focused = false -} - func NewModel(c *ctx.Ctx) Model { m := Model{ ctx: c, @@ -164,14 +155,13 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { case cmd.WinFocus: if msg.Target == WIN_ID || msg.Target == "*" { - m.focused = true - m.viewcache = m.buildView(false) + m.Focus() } return m, nil case cmd.WinBlur: if msg.Target == WIN_ID || msg.Target == "*" { - m.focused = false + m.Blur() } return m, nil default: @@ -196,14 +186,14 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { return m, tea.Batch(cmds...) } -func (m *Model) loadPost(p *post.Post) tea.Cmd { - return func() tea.Msg { - m.ctx.Logger.Debug("------ EXECUTED -----") - if err := m.a.LoadPost(p); err != nil { - m.ctx.Logger.Error(err) - } - return p - } +func (m *Model) Focus() { + m.focused = true + m.viewcache = m.buildView(false) +} + +func (m *Model) Blur() { + m.focused = false + m.viewcache = m.buildView(false) } func (m Model) View() string { @@ -229,8 +219,14 @@ func (m Model) buildView(cached bool) string { if m.replyToIdx != 0 { title += fmt.Sprintf(" to reply #%d", m.replyToIdx) } - titlebar := m.ctx.Theme.DialogBox.Titlebar.Focused. - Align(lipgloss.Center). + + var style lipgloss.Style + if m.focused { + style = m.ctx.Theme.DialogBox.Titlebar.Focused + } else { + style = m.ctx.Theme.DialogBox.Titlebar.Blurred + } + titlebar := style.Align(lipgloss.Center). Width(m.wh[0]). Render(title) @@ -250,7 +246,12 @@ func (m Model) buildView(cached bool) string { bottombar, ) - tmp := m.ctx.Theme.DialogBox.Window.Focused.Render(replyWindow) + var tmp string + if m.focused { + tmp = m.ctx.Theme.DialogBox.Window.Focused.Render(replyWindow) + } else { + tmp = m.ctx.Theme.DialogBox.Window.Blurred.Render(replyWindow) + } m.viewcacheTextareaXY[0] = 1 m.viewcacheTextareaXY[1] = 2 diff --git a/ui/windows/postshow/postshow.go b/ui/windows/postshow/postshow.go index f65df8f..b0b39c6 100644 --- a/ui/windows/postshow/postshow.go +++ b/ui/windows/postshow/postshow.go @@ -65,14 +65,6 @@ func (m Model) Init() tea.Cmd { return nil } -func (m Model) Focus() { - m.focused = true -} - -func (m Model) Blur() { - m.focused = false -} - func NewModel(c *ctx.Ctx) Model { m := Model{ ctx: c, @@ -179,14 +171,18 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { case cmd.WinFocus: if msg.Target == WIN_ID || msg.Target == "*" { - m.focused = true + m.ctx.Logger.Debug("got WinFocus") + m.Focus() } + m.ctx.Logger.Debugf("focused: %v", m.focused) return m, nil case cmd.WinBlur: if msg.Target == WIN_ID || msg.Target == "*" { - m.focused = false + m.ctx.Logger.Debug("got WinBlur") + m.Blur() } + m.ctx.Logger.Debugf("focused: %v", m.focused) return m, nil case cmd.WinFreshData: if msg.Target == WIN_ID || @@ -235,6 +231,16 @@ func (m *Model) loadPost(p *post.Post) tea.Cmd { } } +func (m *Model) Focus() { + m.focused = true + m.viewcache = m.buildView(false) +} + +func (m *Model) Blur() { + m.focused = false + m.viewcache = m.buildView(false) +} + func (m Model) View() string { return m.buildView(true) } @@ -247,6 +253,8 @@ func (m Model) buildView(cached bool) string { return m.viewcache } + m.ctx.Logger.Debugln("View()") + m.ctx.Logger.Debug(m.focused) var style lipgloss.Style if m.focused {