More keyboard refactor.

This commit is contained in:
Storm Dragon
2026-09-05 12:43:31 -04:00
parent 97fcde7e96
commit 202530743a
7 changed files with 229 additions and 48 deletions
+146 -8
View File
@@ -18,9 +18,10 @@ type adminPrompt struct {
}
type adminItem struct {
label string
children []uiterm.TreeItem
action func()
label string
children []uiterm.TreeItem
action func()
applicationAction bool
}
func (i adminItem) String() string {
@@ -41,6 +42,10 @@ func (b *Barnard) OnAdminMenuPress(ui *uiterm.Ui, key uiterm.Key) {
b.OpenAdminMenu()
}
func (b *Barnard) OnHelpMenuPress(ui *uiterm.Ui, key uiterm.Key) {
b.OpenKeyboardHelp()
}
func (b *Barnard) OnAdminEscape(ui *uiterm.Ui, key uiterm.Key) {
if b.pendingAdminPrompt != nil {
b.pendingAdminPrompt = nil
@@ -64,6 +69,8 @@ func (b *Barnard) OpenAdminMenu() {
b.AddOutputLine("Admin: not connected")
return
}
b.keyboardHelpOpen = false
b.adminReturnView = b.Ui.Active()
b.adminReturnItem = b.UiTree.ActiveItem()
b.adminTargetUser = b.selectedUserValue()
b.adminTargetChan = b.Client.Self.Channel
@@ -103,9 +110,17 @@ func (b *Barnard) OpenAdminMenu() {
}
func (b *Barnard) CloseAdminMenu(ui *uiterm.Ui) {
b.Ui.SetActive(uiViewTree)
b.UiTree.SetActiveItem(b.adminReturnItem, sameUserChannelTreeItem)
b.keyboardHelpOpen = false
returnView := b.adminReturnView
if returnView != uiViewInput && returnView != uiViewTree {
returnView = uiViewTree
}
b.Ui.SetActive(returnView)
if returnView == uiViewTree {
b.UiTree.SetActiveItem(b.adminReturnItem, sameUserChannelTreeItem)
}
b.adminReturnItem = nil
b.adminReturnView = ""
width, height := termboxSize()
b.OnUiResize(ui, width, height)
ui.Refresh()
@@ -123,6 +138,9 @@ func (b *Barnard) AdminItemBuild(item uiterm.TreeItem) []uiterm.TreeItem {
}
return nil
}
if b.keyboardHelpOpen {
return b.keyboardHelpItems()
}
target := "server"
if b.adminTargetUser != nil {
@@ -133,6 +151,10 @@ func (b *Barnard) AdminItemBuild(item uiterm.TreeItem) []uiterm.TreeItem {
items := []uiterm.TreeItem{
adminItem{label: "Action target: " + target},
adminItem{label: "Audio settings", children: b.audioSettingsItems()},
adminItem{label: "Open keyboard help", action: func() {
b.keyboardHelpOpen = true
}, applicationAction: true},
adminItem{label: "Information actions", children: b.informationItems()},
}
if children := b.adminUserItems(); len(children) > 0 {
@@ -153,10 +175,118 @@ func (b *Barnard) AdminItemBuild(item uiterm.TreeItem) []uiterm.TreeItem {
if children := b.adminContextActionItems(); len(children) > 0 {
items = append(items, adminItem{label: "Context actions", children: children})
}
items = append(items, adminItem{label: "Close actions menu", action: b.closeAdminAction})
items = append(items, adminItem{label: "Close actions menu", action: b.closeAdminAction, applicationAction: true})
return items
}
func (b *Barnard) OpenKeyboardHelp() {
b.keyboardHelpOpen = true
b.adminReturnView = b.Ui.Active()
b.adminReturnItem = b.UiTree.ActiveItem()
b.UiAdmin.Rebuild()
b.Ui.SetActive(uiViewAdmin)
width, height := termboxSize()
b.OnUiResize(b.Ui, width, height)
b.AddOutputLine("Help: keyboard shortcuts opened")
b.Ui.Refresh()
}
func (b *Barnard) audioSettingsItems() []uiterm.TreeItem {
agc := enabledLabel(b.UserConfig.GetAGCEnabled())
noiseSuppression := enabledLabel(b.UserConfig.GetNoiseSuppressionEnabled())
micVolume := b.UserConfig.GetMicVolume()
return []uiterm.TreeItem{
adminItem{label: "Automatic gain control: " + agc + "; Enter toggles", applicationAction: true, action: func() {
enabled := b.toggleAGC()
b.AddOutputLine("Settings: automatic gain control " + enabledLabel(enabled))
b.UpdateGeneralStatus("Automatic gain control: "+enabledLabel(enabled), false)
}},
adminItem{label: "Noise suppression: " + noiseSuppression + "; Enter toggles", applicationAction: true, action: func() {
enabled := b.toggleNoiseSuppression()
b.AddOutputLine("Settings: noise suppression " + enabledLabel(enabled))
b.UpdateGeneralStatus("Noise suppression: "+enabledLabel(enabled), false)
}},
adminItem{label: fmt.Sprintf("Microphone level: %.0f percent", micVolume*100)},
adminItem{label: "Increase microphone level by 10 percent", applicationAction: true, action: func() {
volume := b.adjustMicVolume(0.1)
b.AddOutputLine(fmt.Sprintf("Settings: microphone level %.0f percent", volume*100))
b.UpdateGeneralStatus(fmt.Sprintf("Microphone level: %.0f percent", volume*100), false)
}},
adminItem{label: "Decrease microphone level by 10 percent", applicationAction: true, action: func() {
volume := b.adjustMicVolume(-0.1)
b.AddOutputLine(fmt.Sprintf("Settings: microphone level %.0f percent", volume*100))
b.UpdateGeneralStatus(fmt.Sprintf("Microphone level: %.0f percent", volume*100), false)
}},
adminItem{label: "Reset microphone level to 100 percent", applicationAction: true, action: func() {
volume := b.setMicVolume(1)
b.AddOutputLine(fmt.Sprintf("Settings: microphone level %.0f percent", volume*100))
b.UpdateGeneralStatus(fmt.Sprintf("Microphone level: %.0f percent", volume*100), false)
}},
}
}
func enabledLabel(enabled bool) string {
if enabled {
return "on"
}
return "off"
}
func (b *Barnard) keyboardHelpItems() []uiterm.TreeItem {
hotkeys := b.Hotkeys
return []uiterm.TreeItem{
adminItem{label: "Global shortcuts", children: []uiterm.TreeItem{
adminItem{label: hotkeyLabel(hotkeys.HelpMenu) + ": open keyboard help"},
adminItem{label: hotkeyLabel(hotkeys.AdminMenu) + ": open actions and settings"},
adminItem{label: hotkeyLabel(hotkeys.Talk) + ": toggle transmission"},
adminItem{label: hotkeyLabel(hotkeys.SelfMuteToggle) + ": toggle self-mute"},
adminItem{label: hotkeyLabel(hotkeys.NoiseSuppressionToggle) + ": toggle noise suppression"},
adminItem{label: hotkeyLabel(hotkeys.AGCToggle) + ": toggle automatic gain control"},
adminItem{label: hotkeyLabel(hotkeys.RecordToggle) + ": toggle recording"},
adminItem{label: hotkeyLabel(hotkeys.ClearOutput) + ": clear the chat log"},
adminItem{label: hotkeyLabel(hotkeys.ToggleTimestamps) + ": toggle timestamps"},
adminItem{label: hotkeyLabel(hotkeys.SwitchViews) + ": switch between message area and user list"},
adminItem{label: hotkeyLabel(hotkeys.Exit) + ": quit"},
}},
adminItem{label: "Message area", children: []uiterm.TreeItem{
adminItem{label: "Left and Right arrows: move through text"},
adminItem{label: "Up and Down arrows: previous or next submitted message"},
adminItem{label: "Home and End: beginning or end of text"},
}},
adminItem{label: "User and channel list", children: []uiterm.TreeItem{
adminItem{label: hotkeyLabel(hotkeys.MuteToggle) + ": mute or unmute focused item"},
adminItem{label: hotkeyLabel(hotkeys.VolumeDown) + " and " + hotkeyLabel(hotkeys.VolumeUp) + ": decrease or increase volume"},
adminItem{label: hotkeyLabel(hotkeys.VolumeReset) + ": restore default audio settings"},
adminItem{label: "Enter: select user for private message or enter channel"},
}},
adminItem{label: "Chat log", children: []uiterm.TreeItem{
adminItem{label: hotkeyLabel(hotkeys.ScrollUp) + " and " + hotkeyLabel(hotkeys.ScrollDown) + ": scroll"},
adminItem{label: hotkeyLabel(hotkeys.ScrollToTop) + " and " + hotkeyLabel(hotkeys.ScrollToBottom) + ": jump to oldest or newest"},
}},
adminItem{label: "Press Escape to close this menu"},
}
}
func hotkeyLabel(key *uiterm.Key) string {
if key == nil {
return "Unbound"
}
labels := map[uiterm.Key]string{
uiterm.KeyF1: "F1", uiterm.KeyF2: "F2", uiterm.KeyF3: "F3", uiterm.KeyF4: "F4",
uiterm.KeyF5: "F5", uiterm.KeyF6: "F6", uiterm.KeyF7: "F7", uiterm.KeyF8: "F8",
uiterm.KeyF9: "F9", uiterm.KeyF10: "F10", uiterm.KeyF11: "F11", uiterm.KeyF12: "F12",
uiterm.KeyCtrlL: "Control+L", uiterm.KeyCtrlQ: "Control+Q", uiterm.KeyCtrlR: "Control+R", uiterm.KeyCtrlT: "Control+T",
uiterm.KeyAltM: "Alt+M", uiterm.KeyTab: "Tab", uiterm.KeyHome: "Home", uiterm.KeyEnd: "End",
uiterm.KeyPgup: "Page Up", uiterm.KeyPgdn: "Page Down", uiterm.KeyArrowUp: "Up Arrow", uiterm.KeyArrowDown: "Down Arrow",
uiterm.KeyArrowLeft: "Left Arrow", uiterm.KeyArrowRight: "Right Arrow",
uiterm.KeyBackspace: "Backspace", uiterm.KeyBackspace2: "Backspace", uiterm.KeyM: "M",
}
if label, ok := labels[*key]; ok {
return label
}
return strings.ReplaceAll(key.String(), "_", " ")
}
func (b *Barnard) AdminItemKeyPress(ui *uiterm.Ui, tree *uiterm.Tree, item uiterm.TreeItem, key uiterm.Key) {
if isAdminEscapeKey(key) {
b.OnAdminEscape(ui, key)
@@ -169,13 +299,21 @@ func (b *Barnard) AdminItemKeyPress(ui *uiterm.Ui, tree *uiterm.Tree, item uiter
if !ok || admin.action == nil {
return
}
if !b.withValidAdminTargets(admin.action) {
if admin.applicationAction {
admin.action()
} else if !b.withValidAdminTargets(admin.action) {
b.AddOutputLine("Admin: action target is no longer available")
}
b.UiAdmin.Rebuild()
b.UiAdmin.RebuildPreservingActiveItem(sameAdminMenuItem)
b.Ui.Refresh()
}
func sameAdminMenuItem(previous, current uiterm.TreeItem) bool {
previousItem, previousOK := previous.(adminItem)
currentItem, currentOK := current.(adminItem)
return previousOK && currentOK && previousItem.label == currentItem.label
}
func (b *Barnard) AdminItemCharacter(ui *uiterm.Ui, tree *uiterm.Tree, item uiterm.TreeItem, ch rune) {
if isAdminEscapeCharacter(ch) {
b.OnAdminEscape(ui, uiterm.KeyEsc)