From f90a49a30602ad1464c4dc0da2e17f2e3becfe83 Mon Sep 17 00:00:00 2001 From: Engin Date: Sun, 1 Sep 2024 19:51:46 +0300 Subject: [PATCH 1/4] Render widgets efficient --- widget.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/widget.go b/widget.go index 76f46be..42c5053 100644 --- a/widget.go +++ b/widget.go @@ -279,9 +279,9 @@ func (w *widget) View() string { line := strings.Repeat("─", requiredLineCount) line = lipgloss.NewStyle().Foreground(lipgloss.Color(w.properties.borderColor)).Render(line) - var renderedWidgets []string - for _, wgt := range w.widgets { - renderedWidgets = append(renderedWidgets, w.properties.widgetStyle.Render(wgt.Value)) + var renderedWidgets = make([]string, len(w.widgets)) + for i, wgt := range w.widgets { + renderedWidgets[i] = w.properties.widgetStyle.Render(wgt.Value) } leftCorner := lipgloss.JoinVertical(lipgloss.Top, "│", "╰") From 71e0662b92a818a99038cd1c1e67d161a570d4b9 Mon Sep 17 00:00:00 2001 From: Engin Date: Sun, 1 Sep 2024 19:52:09 +0300 Subject: [PATCH 2/4] Remove unused code --- header.go | 1 - 1 file changed, 1 deletion(-) diff --git a/header.go b/header.go index b6d1e4d..eb0e735 100644 --- a/header.go +++ b/header.go @@ -103,7 +103,6 @@ type commonHeader struct { func (h *header) Init() tea.Cmd { return h.Listen() - //return nil } func (h *header) Update(msg tea.Msg) (*header, tea.Cmd) { From 15a8cb42b74200cadf58e4657dc752f3aae57d56 Mon Sep 17 00:00:00 2001 From: Engin Date: Sun, 1 Sep 2024 19:54:36 +0300 Subject: [PATCH 3/4] Listen only needed situations --- header.go | 6 ++++-- skeleton.go | 46 +++++++++++++++++++++++++++------------------- widget.go | 9 +++++---- 3 files changed, 36 insertions(+), 25 deletions(-) diff --git a/header.go b/header.go index eb0e735..fa83a93 100644 --- a/header.go +++ b/header.go @@ -118,6 +118,8 @@ func (h *header) Update(msg tea.Msg) (*header, tea.Cmd) { h.viewport.Height = msg.Height h.calculateTitleLength() + + cmds = append(cmds, h.Listen()) case tea.KeyMsg: switch { case key.Matches(msg, h.keyMap.SwitchTabLeft): @@ -129,9 +131,9 @@ func (h *header) Update(msg tea.Msg) (*header, tea.Cmd) { h.currentTab = min(h.currentTab+1, len(h.headers)-1) } } - } - cmds = append(cmds, h.Listen()) + cmds = append(cmds, h.Listen()) + } return h, tea.Batch(cmds...) } diff --git a/skeleton.go b/skeleton.go index b952947..6b0e3e8 100644 --- a/skeleton.go +++ b/skeleton.go @@ -364,6 +364,20 @@ func (s *Skeleton) IAMActivePageCmd() tea.Cmd { } } +func (s *Skeleton) updateSkeleton(msg tea.Msg, cmd tea.Cmd, cmds []tea.Cmd) []tea.Cmd { + s.header, cmd = s.header.Update(msg) + cmds = append(cmds, cmd) + + s.widget, cmd = s.widget.Update(msg) + cmds = append(cmds, cmd) + + s.pages[s.currentTab], cmd = s.pages[s.currentTab].Update(msg) + cmds = append(cmds, cmd) + + cmds = append(cmds, s.Listen()) // listen to the update channel + return cmds +} + func (s *Skeleton) Init() tea.Cmd { if len(s.pages) == 0 { panic("skeleton: no pages added, please add at least one page") @@ -387,47 +401,41 @@ func (s *Skeleton) Update(msg tea.Msg) (tea.Model, tea.Cmd) { } s.viewport.Width = msg.Width s.viewport.Height = msg.Height + + cmds = s.updateSkeleton(msg, cmd, cmds) case tea.KeyMsg: switch { case key.Matches(msg, s.KeyMap.Quit): return s, tea.Quit case key.Matches(msg, s.KeyMap.SwitchTabLeft): - if !s.IsTabsLocked() { - s.currentTab = max(s.currentTab-1, 0) - cmds = append(cmds, s.IAMActivePageCmd()) - } + cmds = s.switchPage(cmds, "left") case key.Matches(msg, s.KeyMap.SwitchTabRight): - if !s.IsTabsLocked() { - s.currentTab = min(s.currentTab+1, len(s.pages)-1) - cmds = append(cmds, s.IAMActivePageCmd()) - } + cmds = s.switchPage(cmds, "right") } + cmds = s.updateSkeleton(msg, cmd, cmds) case AddPage: cmds = append(cmds, msg.Page.Init()) // init the page + cmds = s.updateSkeleton(msg, cmd, cmds) case UpdatePageTitle: s.updatePageTitle(msg.Key, msg.Title) + cmds = s.updateSkeleton(msg, cmd, cmds) case DeletePage: s.deletePage(msg.Key) cmds = append(cmds, s.IAMActivePageCmd()) + cmds = s.updateSkeleton(msg, cmd, cmds) case DummyMsg: // do nothing, just to trigger the update + cmds = s.updateSkeleton(msg, cmd, cmds) case HeaderSizeMsg: s.termSizeNotEnoughToHandleHeaders = msg.NotEnoughToHandleHeaders case WidgetSizeMsg: s.termSizeNotEnoughToHandleWidgets = msg.NotEnoughToHandleWidgets + case AddNewWidget, UpdateWidgetContent, DeleteWidget: + cmds = s.updateSkeleton(msg, cmd, cmds) + default: + cmds = s.updateSkeleton(msg, cmd, cmds) } - s.header, cmd = s.header.Update(msg) - cmds = append(cmds, cmd) - - s.widget, cmd = s.widget.Update(msg) - cmds = append(cmds, cmd) - - s.pages[s.currentTab], cmd = s.pages[s.currentTab].Update(msg) - cmds = append(cmds, cmd) - - cmds = append(cmds, s.Listen()) // listen to the update channel - return s, tea.Batch(cmds...) } diff --git a/widget.go b/widget.go index 42c5053..c8ad934 100644 --- a/widget.go +++ b/widget.go @@ -231,18 +231,19 @@ func (w *widget) Update(msg tea.Msg) (*widget, tea.Cmd) { w.viewport.Height = msg.Height w.calculateWidgetLength() + + cmds = append(cmds, w.Listen()) case AddNewWidget: w.addNewWidget(msg.Key, msg.Value) - + cmds = append(cmds, w.Listen()) case UpdateWidgetContent: w.updateWidgetContent(msg.Key, msg.Value) - + cmds = append(cmds, w.Listen()) case DeleteWidget: w.deleteWidget(msg.Key) + cmds = append(cmds, w.Listen()) } - cmds = append(cmds, w.Listen()) - return w, tea.Batch(cmds...) } From 21194c4b10d9c76679c3584ce5c13ad90bd318e6 Mon Sep 17 00:00:00 2001 From: Engin Date: Sun, 1 Sep 2024 19:55:36 +0300 Subject: [PATCH 4/4] Refactor the code --- skeleton.go | 47 ++++++++++++++++++++++++++++++++++++++++------- widget.go | 28 ---------------------------- 2 files changed, 40 insertions(+), 35 deletions(-) diff --git a/skeleton.go b/skeleton.go index 6b0e3e8..7bae9e5 100644 --- a/skeleton.go +++ b/skeleton.go @@ -308,25 +308,41 @@ func (s *Skeleton) deletePage(key string) { // AddWidget adds a new widget to the Skeleton. func (s *Skeleton) AddWidget(key string, value string) *Skeleton { - s.widget.AddWidget(key, value) + go func() { + s.updateChan <- AddNewWidget{ + Key: key, + Value: value, + } + }() return s } // UpdateWidgetValue updates the Value content by the given key. // Adds the widget if it doesn't exist. func (s *Skeleton) UpdateWidgetValue(key string, value string) *Skeleton { - // if widget not exists, add it - if s.widget.GetWidget(key) == nil { - s.widget.AddWidget(key, value) - } + go func() { + // if widget not exists, add it + if s.widget.GetWidget(key) == nil { + s.AddWidget(key, value) + } + + s.updateChan <- UpdateWidgetContent{ + Key: key, + Value: value, + } + }() - s.widget.UpdateWidgetValue(key, value) return s } // DeleteWidget deletes the Value by the given key. func (s *Skeleton) DeleteWidget(key string) *Skeleton { - s.widget.DeleteWidget(key) + go func() { + s.updateChan <- DeleteWidget{ + Key: key, + } + }() + return s } @@ -364,6 +380,23 @@ func (s *Skeleton) IAMActivePageCmd() tea.Cmd { } } +func (s *Skeleton) switchPage(cmds []tea.Cmd, position string) []tea.Cmd { + switch position { + case "left": + if !s.IsTabsLocked() { + s.currentTab = max(s.currentTab-1, 0) + cmds = append(cmds, s.IAMActivePageCmd()) + } + case "right": + if !s.IsTabsLocked() { + s.currentTab = min(s.currentTab+1, len(s.pages)-1) + cmds = append(cmds, s.IAMActivePageCmd()) + } + } + + return cmds +} + func (s *Skeleton) updateSkeleton(msg tea.Msg, cmd tea.Cmd, cmds []tea.Cmd) []tea.Cmd { s.header, cmd = s.header.Update(msg) cmds = append(cmds, cmd) diff --git a/widget.go b/widget.go index c8ad934..63c59e0 100644 --- a/widget.go +++ b/widget.go @@ -102,15 +102,6 @@ func (w *widget) SetRightPadding(padding int) *widget { return w } -func (w *widget) AddWidget(key string, value string) { - go func() { - w.updateChan <- AddNewWidget{ - Key: key, - Value: value, - } - }() -} - // GetWidget returns the Value by the given key. func (w *widget) GetWidget(key string) *commonWidget { for _, widget := range w.widgets { @@ -122,25 +113,6 @@ func (w *widget) GetWidget(key string) *commonWidget { return nil } -// UpdateWidgetValue updates the Value content by the given key. -func (w *widget) UpdateWidgetValue(key string, value string) { - go func() { - w.updateChan <- UpdateWidgetContent{ - Key: key, - Value: value, - } - }() -} - -// DeleteWidget deletes the Value by the given key. -func (w *widget) DeleteWidget(key string) { - go func() { - w.updateChan <- DeleteWidget{ - Key: key, - } - }() -} - // DeleteAllWidgets deletes all the widgets. func (w *widget) DeleteAllWidgets() { w.widgets = nil