From 8a8423d33fd3cd8f90f14d123c24a53b755cd686 Mon Sep 17 00:00:00 2001 From: diamondburned Date: Sun, 25 Oct 2020 19:28:29 -0700 Subject: [PATCH] action menu fix; server list retry fix --- internal/ui/primitives/actions/menu.go | 13 +++- internal/ui/primitives/actions/stateful.go | 5 ++ .../service/session/server/button/button.go | 20 +----- internal/ui/service/session/server/server.go | 62 +++++++++++++------ internal/ui/service/session/session.go | 9 +-- 5 files changed, 66 insertions(+), 43 deletions(-) diff --git a/internal/ui/primitives/actions/menu.go b/internal/ui/primitives/actions/menu.go index 02445cd..fb1252f 100644 --- a/internal/ui/primitives/actions/menu.go +++ b/internal/ui/primitives/actions/menu.go @@ -39,7 +39,18 @@ func (m *Menu) InsertActionGroup(w ActionGroupInserter) { w.InsertActionGroup(m.prefix, m) } -func (m *Menu) Popover(relative gtk.IWidget) *gtk.Popover { +// Popup pops up the menu popover. It does not pop up anything if there are no +// menu items. +func (m *Menu) Popup(relative gtk.IWidget) { + p := m.popover(relative) + if p == nil || m.Len() == 0 { + return + } + + p.Popup() +} + +func (m *Menu) popover(relative gtk.IWidget) *gtk.Popover { _, model := m.MenuModel() p, _ := gtk.PopoverNewFromModel(relative, model) diff --git a/internal/ui/primitives/actions/stateful.go b/internal/ui/primitives/actions/stateful.go index 31e0b3e..9e7c048 100644 --- a/internal/ui/primitives/actions/stateful.go +++ b/internal/ui/primitives/actions/stateful.go @@ -30,6 +30,11 @@ func (s *Stateful) Reset() { s.labels = nil } +// Len returns the number of menu entries. +func (s *Stateful) Len() int { + return len(s.labels) +} + func (s *Stateful) AddAction(label string, call func()) { sa := glib.SimpleActionNew(ActionName(label), nil) sa.Connect("activate", call) diff --git a/internal/ui/service/session/server/button/button.go b/internal/ui/service/session/server/button/button.go index 9613cdb..e575692 100644 --- a/internal/ui/service/session/server/button/button.go +++ b/internal/ui/service/session/server/button/button.go @@ -4,7 +4,6 @@ import ( "github.com/diamondburned/cchat" "github.com/diamondburned/cchat-gtk/internal/gts" "github.com/diamondburned/cchat-gtk/internal/ui/primitives" - "github.com/diamondburned/cchat-gtk/internal/ui/primitives/menu" "github.com/diamondburned/cchat-gtk/internal/ui/rich" "github.com/diamondburned/cchat/text" ) @@ -16,9 +15,6 @@ const UnreadColorDefs = ` type ToggleButtonImage struct { *rich.ToggleButtonImage - extraMenu []menu.Item - menu *menu.LazyMenu - clicked func(bool) readcss primitives.ClassEnum @@ -67,7 +63,6 @@ func WrapToggleButtonImage(b *rich.ToggleButtonImage) *ToggleButtonImage { ToggleButtonImage: b, clicked: func(bool) {}, - menu: menu.NewLazyMenu(b.ToggleButton), } tb.Connect("clicked", func() { tb.clicked(tb.GetActive()) }) serverButtonCSS(tb) @@ -104,14 +99,9 @@ func (b *ToggleButtonImage) SetClickedIfTrue(clickedIfTrue func()) { } } -func (b *ToggleButtonImage) SetNormalExtraMenu(items []menu.Item) { - b.extraMenu = items - b.SetNormal() -} - func (b *ToggleButtonImage) SetNormal() { b.SetLabelUnsafe(b.GetLabel()) - b.menu.SetItems(b.extraMenu) + // b.menu.SetItems(b.extraMenu) if b.icon != "" { b.Image.SetPlaceholderIcon(b.icon, b.Image.Size()) @@ -121,9 +111,6 @@ func (b *ToggleButtonImage) SetNormal() { func (b *ToggleButtonImage) SetLoading() { b.SetLabelUnsafe(b.GetLabel()) - // Reset the menu. - b.menu.SetItems(b.extraMenu) - if b.icon != "" { b.Image.SetPlaceholderIcon("content-loading-symbolic", b.Image.Size()) } @@ -132,11 +119,6 @@ func (b *ToggleButtonImage) SetLoading() { func (b *ToggleButtonImage) SetFailed(err error, retry func()) { b.Label.SetMarkup(rich.MakeRed(b.GetLabel())) - // Add a retry button, if any. - b.menu.Reset() - b.menu.AddItems(menu.SimpleItem("Retry", retry)) - b.menu.AddItems(b.extraMenu...) - // If we have an icon set, then we can use the failed icon. if b.icon != "" { b.Image.SetPlaceholderIcon("computer-fail-symbolic", b.Image.Size()) diff --git a/internal/ui/service/session/server/server.go b/internal/ui/service/session/server/server.go index 7dd6d6f..0ee19c1 100644 --- a/internal/ui/service/session/server/server.go +++ b/internal/ui/service/session/server/server.go @@ -6,7 +6,6 @@ import ( "github.com/diamondburned/cchat-gtk/internal/log" "github.com/diamondburned/cchat-gtk/internal/ui/primitives" "github.com/diamondburned/cchat-gtk/internal/ui/primitives/actions" - "github.com/diamondburned/cchat-gtk/internal/ui/primitives/menu" "github.com/diamondburned/cchat-gtk/internal/ui/primitives/roundimage" "github.com/diamondburned/cchat-gtk/internal/ui/rich" "github.com/diamondburned/cchat-gtk/internal/ui/service/savepath" @@ -125,6 +124,10 @@ func (r *ServerRow) Init() { r.Box.PackStart(r.Button, false, false, 0) serverCSS(r.Box) + // Make the Actions menu. + r.ActionsMenu = actions.NewMenu("server") + r.ActionsMenu.InsertActionGroup(r) + // Ensure errors are displayed. r.childrenSetErr(r.childrenErr) @@ -137,10 +140,6 @@ func (r *ServerRow) Init() { // Restore the read state. r.Button.SetUnreadUnsafe(r.unread, r.mentioned) // update with state - // Make the Actions menu. - r.ActionsMenu = actions.NewMenu("server") - r.ActionsMenu.InsertActionGroup(r) - if cmder := r.Server.AsCommander(); cmder != nil { r.cmder = commander.NewBuffer(r.Server.Name().String(), cmder) r.ActionsMenu.AddAction("Command Prompt", r.cmder.ShowDialog) @@ -149,7 +148,7 @@ func (r *ServerRow) Init() { // Bind right clicks and show a popover menu on such event. r.Button.Connect("button-press-event", func(_ gtk.IWidget, ev *gdk.Event) { if gts.EventIsRightClick(ev) { - r.ActionsMenu.Popover(r).Popup() + r.ActionsMenu.Popup(r) } }) @@ -223,12 +222,28 @@ func (r *ServerRow) IsHollow() bool { // recursively create func (r *ServerRow) SetHollowServerList(list cchat.Lister, ctrl Controller) { r.serverList = list - r.children = NewHollowChildren(r, ctrl) - r.children.setLoading() + r.load(func(error) {}) +} + +// load calls finish if the server list is not loaded. If it is, finish is +// called with a nil immediately. +func (r *ServerRow) load(finish func(error)) { + if r.children.Rows != nil { + finish(nil) + return + } + + list := r.serverList + children := r.children + children.setLoading() + + if !r.IsHollow() { + r.SetSensitive(false) + } go func() { - var err = list.Servers(r.children) + var err = list.Servers(children) if err != nil { log.Error(errors.Wrap(err, "Failed to get servers")) } @@ -245,6 +260,8 @@ func (r *ServerRow) SetHollowServerList(list cchat.Lister, ctrl Controller) { // Use the childrenX method instead of SetX. We can wrap nil // errors. r.childrenSetErr(errors.Wrap(err, "Failed to get servers")) + + finish(err) }) }() } @@ -344,6 +361,8 @@ func (r *ServerRow) SetFailed(err error, retry func()) { r.SetTooltipText(err.Error()) r.Button.SetFailed(err, retry) r.Button.Label.SetMarkup(rich.MakeRed(r.Button.GetLabel())) + r.ActionsMenu.Reset() + r.ActionsMenu.AddAction("Retry", retry) } // SetDone is shared between the parent struct and the children list. This is @@ -356,13 +375,13 @@ func (r *ServerRow) SetDone() { r.SetTooltipText("") } -func (r *ServerRow) SetNormalExtraMenu(items []menu.Item) { - AssertUnhollow(r) +// func (r *ServerRow) SetNormalExtraMenu(items []menu.Item) { +// AssertUnhollow(r) - r.Button.SetNormalExtraMenu(items) - r.SetSensitive(true) - r.SetTooltipText("") -} +// r.Button.SetNormalExtraMenu(items) +// r.SetSensitive(true) +// r.SetTooltipText("") +// } // SetSelected is used for highlighting the current message server. func (r *ServerRow) SetSelected(selected bool) { @@ -400,10 +419,15 @@ func (r *ServerRow) SetRevealChild(reveal bool) { return } - // Load the list of servers if we're still in loading mode. Before, we have - // to call Servers on this. Now, we already know that there are hollow - // servers in the children container. - r.children.LoadAll() + // Ensure that we have successfully loaded the server. + r.load(func(err error) { + if err == nil { + // Load the list of servers if we're still in loading mode. Before, + // we have to call Servers on this. Now, we already know that there + // are hollow servers in the children container. + r.children.LoadAll() + } + }) } // GetRevealChild returns whether or not the server list is expanded, or always diff --git a/internal/ui/service/session/session.go b/internal/ui/service/session/session.go index c11456e..dddeea6 100644 --- a/internal/ui/service/session/session.go +++ b/internal/ui/service/session/session.go @@ -152,6 +152,7 @@ func newRow(parent traverse.Breadcrumber, name text.Rich, ctrl Servicer) *Row { rowIconCSS(row.icon.Icon) row.ListBoxRow, _ = gtk.ListBoxRowNew() + row.ListBoxRow.Show() rowCSS(row.ListBoxRow) // TODO: commander button @@ -166,7 +167,7 @@ func newRow(parent traverse.Breadcrumber, name text.Rich, ctrl Servicer) *Row { // Bind right clicks and show a popover menu on such event. row.icon.Connect("button-press-event", func(_ gtk.IWidget, ev *gdk.Event) { if gts.EventIsRightClick(ev) { - row.ActionsMenu.Popover(row).Popup() + row.ActionsMenu.Popup(row) } }) @@ -236,9 +237,6 @@ func (r *Row) Breadcrumb() string { // method will reconnect. If the row is already loaded, then SessionSelected // will be called. func (r *Row) Activate() { - // Display the empty server list first, then try and reconnect. - r.svcctrl.SessionSelected(r) - // If session is nil, then we've probably failed to load it. The row is // deactivated while loading, so this wouldn't have happened. if r.Session == nil { @@ -248,6 +246,9 @@ func (r *Row) Activate() { // method. r.Servers.Children.LoadAll() } + + // Display the empty server list first, then try and reconnect. + r.svcctrl.SessionSelected(r) } // SetLoading sets the session button to have a spinner circle. DO NOT CONFUSE