Forráskód Böngészése

feat(ui): add root-level help footer and dedupe keymap bindings

ayn2op 1 hónapja
szülő
commit
07c09508e8

+ 2 - 2
internal/ui/chat/keybinds.go

@@ -52,7 +52,7 @@ func (v *View) baseShortHelp() []keybind.Keybind {
 	if !v.messageInput.GetDisabled() {
 		short = append(short, cfg.FocusMessageInput.Keybind)
 	}
-	short = append(short, cfg.ToggleGuildsTree.Keybind, cfg.ToggleChannelsPicker.Keybind, cfg.ToggleHelp.Keybind)
+	short = append(short, cfg.ToggleGuildsTree.Keybind, cfg.ToggleChannelsPicker.Keybind)
 	return short
 }
 
@@ -66,6 +66,6 @@ func (v *View) baseFullHelp() [][]keybind.Keybind {
 		focus,
 		{cfg.FocusPrevious.Keybind, cfg.FocusNext.Keybind},
 		{cfg.ToggleGuildsTree.Keybind, cfg.ToggleChannelsPicker.Keybind},
-		{cfg.ToggleHelp.Keybind, cfg.Suspend.Keybind, cfg.Logout.Keybind, cfg.Quit.Keybind},
+		{cfg.Logout.Keybind},
 	}
 }

+ 1 - 32
internal/ui/chat/view.go

@@ -9,7 +9,6 @@ import (
 	"github.com/ayn2op/discordo/internal/config"
 	"github.com/ayn2op/discordo/internal/ui"
 	"github.com/ayn2op/tview"
-	"github.com/ayn2op/tview/help"
 	"github.com/ayn2op/tview/keybind"
 	"github.com/ayn2op/tview/layers"
 	"github.com/diamondburned/arikawa/v3/discord"
@@ -39,7 +38,6 @@ type View struct {
 	messagesList   *messagesList
 	messageInput   *messageInput
 	channelsPicker *channelsPicker
-	help           *help.Help
 
 	selectedChannel   *discord.Channel
 	selectedChannelMu sync.RWMutex
@@ -74,20 +72,6 @@ func NewView(app *tview.Application, cfg *config.Config, token string) *View {
 	v.channelsPicker = newChannelsPicker(cfg, v)
 	v.channelsPicker.SetCancelFunc(v.closePicker)
 
-	v.help = help.New()
-
-	styles := help.DefaultStyles()
-	styles.ShortKeyStyle = cfg.Theme.Help.ShortKeyStyle.Style
-	styles.ShortDescStyle = cfg.Theme.Help.ShortDescStyle.Style
-	styles.FullKeyStyle = cfg.Theme.Help.FullKeyStyle.Style
-	styles.FullDescStyle = cfg.Theme.Help.FullDescStyle.Style
-	v.help.SetStyles(styles)
-
-	v.help.SetKeyMap(v)
-	v.help.SetCompactModifiers(cfg.Help.CompactModifiers)
-	v.help.SetShortSeparator(cfg.Help.Separator)
-	v.help.SetBorderPadding(0, 0, cfg.Help.Padding[0], cfg.Help.Padding[1])
-
 	v.SetBackgroundLayerStyle(v.cfg.Theme.Dialog.BackgroundStyle.Style)
 	v.buildLayout()
 	return v
@@ -122,10 +106,7 @@ func (v *View) buildLayout() {
 
 	v.rootFlex.
 		SetDirection(tview.FlexRow).
-		AddItem(v.mainFlex, 0, 1, true).
-		AddItem(v.help, 1, 0, false)
-
-	v.updateHelpHeight()
+		AddItem(v.mainFlex, 0, 1, true)
 	v.AddLayer(v.rootFlex, layers.WithName(flexLayerName), layers.WithResize(true), layers.WithVisible(true))
 	v.AddLayer(v.messageInput.mentionsList, layers.WithName(mentionsListLayerName), layers.WithResize(false), layers.WithVisible(false))
 }
@@ -238,10 +219,6 @@ func (v *View) HandleEvent(event tcell.Event) tview.Command {
 	case *tview.KeyEvent:
 		redraw := tview.RedrawCommand{}
 		switch {
-		case keybind.Matches(event, v.cfg.Keybinds.ToggleHelp.Keybind):
-			v.help.SetShowAll(!v.help.ShowAll())
-			v.updateHelpHeight()
-			return redraw
 		case keybind.Matches(event, v.cfg.Keybinds.FocusGuildsTree.Keybind):
 			v.messageInput.removeMentionsList()
 			v.focusGuildsTree()
@@ -321,14 +298,6 @@ func (v *View) consumeLayerCommands(command tview.Command) tview.Command {
 	return tview.BatchCommand(remaining)
 }
 
-func (v *View) updateHelpHeight() {
-	height := 1
-	if v.help.ShowAll() {
-		height = max(len(v.help.FullHelpLines(v.FullHelp(), 0)), 1)
-	}
-	v.rootFlex.ResizeItem(v.help, height, 0)
-}
-
 func (v *View) showConfirmModal(prompt string, buttons []string, onDone func(label string)) {
 	previousFocus := v.app.GetFocus()
 

+ 41 - 0
internal/ui/root/keybinds.go

@@ -0,0 +1,41 @@
+package root
+
+import (
+	"github.com/ayn2op/tview/help"
+	"github.com/ayn2op/tview/keybind"
+)
+
+var _ help.KeyMap = (*View)(nil)
+
+func (v *View) ShortHelp() []keybind.Keybind {
+	global := []keybind.Keybind{
+		v.cfg.Keybinds.ToggleHelp.Keybind,
+		v.cfg.Keybinds.Suspend.Keybind,
+		v.cfg.Keybinds.Quit.Keybind,
+	}
+	if active := v.activeKeyMap(); active != nil {
+		short := active.ShortHelp()
+		return append(short, global...)
+	}
+	return global
+}
+
+func (v *View) FullHelp() [][]keybind.Keybind {
+	global := []keybind.Keybind{
+		v.cfg.Keybinds.ToggleHelp.Keybind,
+		v.cfg.Keybinds.Suspend.Keybind,
+		v.cfg.Keybinds.Quit.Keybind,
+	}
+	if active := v.activeKeyMap(); active != nil {
+		full := active.FullHelp()
+		return append(full, global)
+	}
+	return [][]keybind.Keybind{global}
+}
+
+func (v *View) activeKeyMap() help.KeyMap {
+	if keyMap, ok := v.inner.(help.KeyMap); ok {
+		return keyMap
+	}
+	return nil
+}

+ 57 - 15
internal/ui/root/view.go

@@ -6,6 +6,7 @@ import (
 	"github.com/ayn2op/discordo/internal/ui/chat"
 	"github.com/ayn2op/discordo/internal/ui/login"
 	"github.com/ayn2op/tview"
+	"github.com/ayn2op/tview/help"
 	"github.com/ayn2op/tview/keybind"
 	"github.com/gdamore/tcell/v3"
 )
@@ -13,34 +14,68 @@ import (
 const tokenEnvVarKey = "DISCORDO_TOKEN"
 
 type View struct {
-	app   *tview.Application
-	inner tview.Primitive
-	cfg   *config.Config
+	app      *tview.Application
+	rootFlex *tview.Flex // inner + help
+	inner    tview.Primitive
+	help     *help.Help
+
+	cfg *config.Config
 }
 
 func NewView(cfg *config.Config, app *tview.Application) *View {
-	return &View{
-		app: app,
+	v := &View{
+		app:      app,
+		rootFlex: tview.NewFlex(),
+		help:     help.New(),
+
 		cfg: cfg,
 	}
+
+	v.rootFlex.SetDirection(tview.FlexRow)
+
+	styles := help.DefaultStyles()
+	styles.ShortKeyStyle = cfg.Theme.Help.ShortKeyStyle.Style
+	styles.ShortDescStyle = cfg.Theme.Help.ShortDescStyle.Style
+	styles.FullKeyStyle = cfg.Theme.Help.FullKeyStyle.Style
+	styles.FullDescStyle = cfg.Theme.Help.FullDescStyle.Style
+	v.help.SetStyles(styles)
+
+	v.help.SetKeyMap(v)
+	v.help.SetCompactModifiers(cfg.Help.CompactModifiers)
+	v.help.SetShortSeparator(cfg.Help.Separator)
+	v.help.SetBorderPadding(0, 0, cfg.Help.Padding[0], cfg.Help.Padding[1])
+	v.buildLayout()
+	return v
 }
 
 func (v *View) showLoginView() tview.Command {
 	v.inner = login.NewForm(v.app, v.cfg)
+	v.buildLayout()
 	return v.inner.HandleEvent(tview.NewInitEvent())
 }
 
 func (v *View) showChatView(token string) tview.Command {
 	v.inner = chat.NewView(v.app, v.cfg, token)
+	v.buildLayout()
 	return v.inner.HandleEvent(tview.NewInitEvent())
 }
 
+func (v *View) buildLayout() {
+	v.rootFlex.Clear()
+
+	content := v.inner
+	if content == nil {
+		content = tview.NewBox()
+	}
+	v.rootFlex.AddItem(content, 0, 1, true)
+	v.rootFlex.AddItem(v.help, 1, 0, false)
+	v.updateHelpHeight()
+}
+
 var _ tview.Primitive = (*View)(nil)
 
 func (v *View) Draw(screen tcell.Screen) {
-	if v.inner != nil {
-		v.inner.Draw(screen)
-	}
+	v.rootFlex.Draw(screen)
 }
 
 func (v *View) HandleEvent(event tcell.Event) tview.Command {
@@ -68,6 +103,10 @@ func (v *View) HandleEvent(event tcell.Event) tview.Command {
 
 	case *tview.KeyEvent:
 		switch {
+		case keybind.Matches(event, v.cfg.Keybinds.ToggleHelp.Keybind):
+			v.help.SetShowAll(!v.help.ShowAll())
+			v.updateHelpHeight()
+			return tview.RedrawCommand{}
 		case keybind.Matches(event, v.cfg.Keybinds.Suspend.Keybind):
 			v.suspend()
 			return nil
@@ -86,17 +125,20 @@ func (v *View) HandleEvent(event tcell.Event) tview.Command {
 	return nil
 }
 
-func (v *View) GetRect() (int, int, int, int) {
-	if v.inner != nil {
-		return v.inner.GetRect()
+func (v *View) updateHelpHeight() {
+	height := 1
+	if v.help.ShowAll() {
+		height = max(len(v.help.FullHelpLines(v.FullHelp(), 0)), 1)
 	}
-	return 0, 0, 0, 0
+	v.rootFlex.ResizeItem(v.help, height, 0)
+}
+
+func (v *View) GetRect() (int, int, int, int) {
+	return v.rootFlex.GetRect()
 }
 
 func (v *View) SetRect(x int, y int, width int, height int) {
-	if v.inner != nil {
-		v.inner.SetRect(x, y, width, height)
-	}
+	v.rootFlex.SetRect(x, y, width, height)
 }
 
 func (v *View) Focus(delegate func(p tview.Primitive)) {