package main import ( "citrons.xyz/talk/client/clipboard" "citrons.xyz/talk/client/window" "citrons.xyz/talk/tui" "citrons.xyz/talk/proto" "zgo.at/termfo/keys" "strings" ) func (a *application) getWin() window.Window { win := a.windowCache.Open(a.currentWindow) if win == nil { return emptyWindow {a.currentWindow} } return win } func (a *application) pushPrompt(p window.Prompt) { a.prompts = append(a.prompts, p) } func (a *application) removePrompt(p window.Prompt) { for i := len(a.prompts) - 1; i >= 0; i-- { if p != a.prompts[i] { continue } if i < len(a.prompts) - 1 { a.prompts = append(a.prompts[:i], a.prompts[i + 1:]...) } else { a.prompts = a.prompts[:i] } break } } func (a *application) getPrompt() window.Prompt { if len(a.prompts) > 0 { return a.prompts[len(a.prompts) - 1] } return a.getWin() } func (a *application) onInput(ev tui.Event) { tui.Selected = "input" win := a.getWin() prompt := a.getPrompt() prompt.Input().Update(ev) wm := ev.Key.WithoutMods() if wm > '0' && wm <= '9' && ev.Key & keys.Alt != 0 { i := wm - '1' if int(i) < len(a.channelList) { a.goTo(a.channelList[i].location) } } buf := win.Buffer() scroll := tui.Size().Height - 5 switch ev.Key { case keys.PageUp: buf.Scroll(scroll) case keys.PageDown: buf.Scroll(-scroll) case keys.Enter: input := prompt.Input() if !input.IsEmpty() { is, text := isCommand(input.Text()) if !is { prompt.Send(text) } else { a.processCommand(text) input.SetText("") } } case 'c' | keys.Ctrl: sel := prompt.Input().Selection() if sel != "" { clipboard.Get().Copy(sel) } case 'v' | keys.Ctrl: if globalApp.activePaste == nil { globalApp.activePaste = clipboard.Get().Paste() } case 'x' | keys.Ctrl: sel := prompt.Input().Selection() if sel != "" { clipboard.Get().Copy(sel) prompt.Input().Write("") } case keys.Up | keys.Alt: index := a.channelList.traverse(-1) a.channelScroll.Set(index - 5) case keys.Down | keys.Alt: index := a.channelList.traverse(1) a.channelScroll.Set(index - 5) case 'p' | keys.Ctrl: a.traverseHistory(-1) case 'n' | keys.Ctrl: a.traverseHistory(1) case '0' | keys.Alt: a.goTo(cmdWindowLocation{}) case 'l' | keys.Ctrl: a.cmdWindow.clearPreview() } } func (a *application) onPaste(text string) { a.getPrompt().Input().Write(text) } func (a *application) logUserUpdate(uid string, update proto.Object) { u := a.cache.Get(uid) if u == nil { return } switch { case update.Fields["status"] != "": lastIndex++ a.cmdWindow.Buffer().Add(userStatusMsg { lastIndex, uid, u.Fields[""], update.Fields["status"], }) case update.Fields[""] != "": lastIndex++ a.cmdWindow.Buffer().Add(nameChangeMsg { lastIndex, uid, u.Fields[""], update.Fields[""], }) } } func (a *application) showNickBox() { tui.Push("username", tui.Box {Width: tui.TextSize, Height: tui.TextSize}) tui.Text("[", nil) name := a.getNick() name = string([]rune(name)[:8]) tui.Text(name, nil) tui.Text("] ", nil) tui.Pop() } func (a *application) showWindow() { tui.Push("window", tui.Box {Width: tui.Fill, Height: tui.Fill}) if a.currentWindow != (cmdWindowLocation{}) { a.cmdWindow.showPreview() } win := a.getWin() prompt := a.getPrompt() win.Buffer().Show("buffer") tui.Push("input border", tui.Box { Width: tui.Fill, Height: 1, Dir: tui.Left, Style: &tui.Style {Bg: tui.White, Fg: tui.Black}, }) if win.Buffer().ScrollPos() > 0 { tui.Push("", tui.Box {Width: tui.TextSize, Height: 1, NoWrap: true}) if win.Buffer().AtTop() { tui.Text("[TOP]", nil) } else { tui.Text("[MORE]", nil) } tui.Pop() } tui.Push("", tui.Box {Width: tui.Fill, Height: 1}) tui.Pop() tui.Push("status", tui.Box {Width: tui.TextSize, Height: 1, NoWrap: true}) prompt.ShowStatusLine() tui.Pop() tui.Pop() tui.Push("replying to", tui.Box {Width: tui.Fill, Height: tui.Children}) if prompt == win { win.ShowComposingReply() } tui.Pop() tui.Push("input container", tui.Box { Width: tui.Fill, Height: tui.Children, Dir: tui.Right, }) a.showNickBox() input := prompt.Input() priv := input.Private if strings.HasPrefix(input.Text(), "/") { input.Private = strings.HasPrefix(input.Text(), "/password ") } input.Show("input") input.Private = priv tui.Pop() tui.Pop() } func (a *application) show() { s := tui.Size() tui.Push("", tui.Box { Width: tui.BoxSize(s.Width), Height: tui.BoxSize(s.Height), Dir: tui.Right, }) a.channelList.show(&a.channelScroll) tui.Push("border", tui.Box {Width: 1, Height: tui.Fill}) tui.Text(strings.Repeat("│", s.Height), nil) tui.Pop() a.showWindow() }