Skip to content
This repository has been archived by the owner on May 22, 2023. It is now read-only.

Commit

Permalink
Merge branch 'master' of https://github.com/derricw/siggo
Browse files Browse the repository at this point in the history
  • Loading branch information
Derric Williams committed Feb 12, 2021
2 parents 6c347f4 + cafac3b commit 5177f94
Show file tree
Hide file tree
Showing 6 changed files with 94 additions and 78 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ A terminal ui for signal-cli, written in Go.
* configurable contact [colors](config/README.md#configure-contact-colors)
* can use [fzf](https://github.com/junegunn/fzf) to fuzzy-find files to attach
* support for groups! (but not creating new groups)
* quickly filter messages by providing a regex pattern

### Dependencies

Expand Down Expand Up @@ -61,6 +62,7 @@ If you are updating from a previous version, I recommend deleting your conversat
* `K` - Previous Contact
* `a` - Attach file (sent with next message)
* `A` - Use fzf to attach a file
* `/` - Filter conversation by providing a pattern
* `i` - Insert Mode
* `CTRL+L` - Clear input field (also clears staged attachments)
* `I` - Compose (opens $EDITOR and lets you make a fancy message)
Expand Down
17 changes: 17 additions & 0 deletions model/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"fmt"
"os"
"path/filepath"
"regexp"
"sort"
"time"

Expand Down Expand Up @@ -252,6 +253,22 @@ func (c *Conversation) String() string {
return out
}

// Filter redners the conversation, but filters out any messages that don't have a regex match
// TODO: eliminate code duplication with String()
func (c *Conversation) Filter(pattern string) string {
if pattern == "" {
return c.String()
}
out := ""
for _, k := range c.MessageOrder {
s := c.Messages[k].String()
if found, err := regexp.MatchString(pattern, s); found == true || err != nil {
out += s
}
}
return out
}

// AddMessage appends a message to the conversation
func (c *Conversation) AddMessage(message *Message) {
c.addMessage(message)
Expand Down
2 changes: 1 addition & 1 deletion widgets/attach.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ func NewAttachInput(parent *ChatWindow) *CommandInput {

// FZFFile opens up FZF and fuzzy-searches for a file
func FZFFile() (string, error) {
cmd := exec.Command("fzf")
cmd := exec.Command("fzf", "--prompt=attach: ", "--margin=10%,10%,10%,10%", "--border")
cmd.Stdin = os.Stdin
cmd.Stderr = os.Stderr
buf := bytes.NewBuffer([]byte{})
Expand Down
100 changes: 25 additions & 75 deletions widgets/chatwindow.go
Original file line number Diff line number Diff line change
Expand Up @@ -188,28 +188,22 @@ func (c *ChatWindow) FocusMe() {
c.app.SetFocus(c)
}

// ShowContactSearch opens a contact search panel
func (c *ChatWindow) ShowContactSearch() {
log.Debug("SHOWING CONTACT SEARCH")
p := NewContactSearch(c)
c.searchPanel = p
c.SetRows(0, 3, p.maxHeight)
// ShowAttachInput opens a commandPanel to choose a file to attach
func (c *ChatWindow) ShowAttachInput() {
c.HideCommandInput() // only one at a time
log.Debug("SHOWING ATTACH INPUT")
p := NewAttachInput(c)
c.commandPanel = p
c.SetRows(0, 3, 1)
c.AddItem(p, 2, 0, 1, 2, 0, 0, false)
c.app.SetFocus(p)
}

// HideSearch hides any current search panel
func (c *ChatWindow) HideSearch() {
log.Debug("HIDING SEARCH")
c.RemoveItem(c.searchPanel)
c.SetRows(0, 3)
c.FocusMe()
}

// ShowAttachInput opens a commandPanel to choose a file to attach
func (c *ChatWindow) ShowAttachInput() {
log.Debug("SHOWING CONTACT SEARCH")
p := NewAttachInput(c)
// ShowFilterInput opens a commandPanel to filter the conversation
func (c *ChatWindow) ShowFilterInput() {
c.HideCommandInput() // only one at a time
log.Debug("SHOWING FILTER INPUT")
p := NewFilterInput(c)
c.commandPanel = p
c.SetRows(0, 3, 1)
c.AddItem(p, 2, 0, 1, 2, 0, 0, false)
Expand All @@ -220,7 +214,12 @@ func (c *ChatWindow) ShowAttachInput() {
func (c *ChatWindow) HideCommandInput() {
log.Debug("HIDING COMMAND INPUT")
c.RemoveItem(c.commandPanel)
// TODO: this should happen automatically when i clear a FilterInput
// maybe command panel should be an interface with a "Close" method
// that does stuff like this
c.conversationPanel.Filter("")
c.SetRows(0, 3)
c.update()
c.FocusMe()
}

Expand All @@ -232,7 +231,7 @@ func (c *ChatWindow) ShowStatusBar() {

// HideStatusBar stops showing the status bar
func (c *ChatWindow) HideStatusBar() {
c.RemoveItem(c.statusBar) // do we actually need to do this?
c.RemoveItem(c.statusBar)
c.SetRows(0, 3)
}

Expand Down Expand Up @@ -441,59 +440,6 @@ func (c *ChatWindow) update() {
}
}

type SearchPanel struct {
*tview.Grid
list *tview.TextView
input *SearchInput
parent *ChatWindow
maxHeight int
}

func (p *SearchPanel) Close() {
p.parent.HideSearch()
}

func NewContactSearch(parent *ChatWindow) *SearchPanel {
maxHeight := 10
p := &SearchPanel{
Grid: tview.NewGrid().SetRows(maxHeight-3, 1),
list: tview.NewTextView(),
parent: parent,
maxHeight: maxHeight,
}
//contactList := parent.siggo.Contacts().SortedByName()
p.input = NewSearchInput(p)
p.AddItem(p.list, 0, 0, 1, 1, 0, 0, false)
p.AddItem(p.input, 1, 0, 1, 1, 0, 0, true)
p.SetBorder(true)
p.SetTitle("search contacts...")
return p
}

type SearchInput struct {
*tview.InputField
parent *SearchPanel
}

func NewSearchInput(parent *SearchPanel) *SearchInput {
si := &SearchInput{
InputField: tview.NewInputField(),
parent: parent,
}
si.SetLabel("> ")
si.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
// Setup keys
log.Debugf("Key Event <SEARCH>: %v mods: %v rune: %v", event.Key(), event.Modifiers(), event.Rune())
switch event.Key() {
case tcell.KeyESC:
si.parent.Close()
return nil
}
return event
})
return si
}

type StatusBar struct {
*tview.TextView
parent *ChatWindow
Expand Down Expand Up @@ -558,6 +504,9 @@ func NewChatWindow(siggo *model.Siggo, app *tview.Application) *ChatWindow {
case 97: // a
w.ShowAttachInput()
return nil
case 47: // /
w.ShowFilterInput()
return nil
case 65: // a
w.FancyAttach()
return nil
Expand Down Expand Up @@ -589,10 +538,11 @@ func NewChatWindow(siggo *model.Siggo, app *tview.Application) *ChatWindow {
case tcell.KeyESC:
w.NormalMode()
w.HideStatusBar()
w.HideCommandInput()
return nil
case tcell.KeyCtrlT:
w.ShowContactSearch()
return nil
//case tcell.KeyCtrlT:
//w.ShowContactSearch()
//return nil
case tcell.KeyCtrlN:
w.NextUnreadMessage()
return nil
Expand Down
13 changes: 11 additions & 2 deletions widgets/conversation.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,23 @@ package widgets
import (
"fmt"

"github.com/derricw/siggo/model"
"github.com/rivo/tview"
log "github.com/sirupsen/logrus"

"github.com/derricw/siggo/model"
)

type ConversationPanel struct {
*tview.TextView
hideTitle bool
hidePhoneNumber bool
// only show messages matching a filter
filter string
}

func (p *ConversationPanel) Update(conv *model.Conversation) {
p.Clear()
p.SetText(conv.String())
p.SetText(conv.Filter(p.filter))
if !p.hideTitle {
if !p.hidePhoneNumber {
p.SetTitle(fmt.Sprintf("%s <%s>", conv.Contact.String(), conv.Contact.Number))
Expand All @@ -30,6 +34,11 @@ func (p *ConversationPanel) Clear() {
p.SetText("")
}

func (p *ConversationPanel) Filter(s string) {
log.Debugf("filtering converstaion: %s", s)
p.filter = s
}

func NewConversationPanel(siggo *model.Siggo) *ConversationPanel {
c := &ConversationPanel{
TextView: tview.NewTextView(),
Expand Down
38 changes: 38 additions & 0 deletions widgets/filter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package widgets

import (
"github.com/gdamore/tcell"
"github.com/rivo/tview"
log "github.com/sirupsen/logrus"
)

// NewFilterInput is a command input that lets you filter the current conversation
func NewFilterInput(parent *ChatWindow) *CommandInput {
ci := &CommandInput{
InputField: tview.NewInputField(),
parent: parent,
}
ci.SetLabel("/")
//ci.SetText("")
ci.SetFieldBackgroundColor(tview.Styles.PrimitiveBackgroundColor)
ci.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
// Setup keys
log.Debugf("Key Event <FILTER>: %v mods: %v rune: %v", event.Key(), event.Modifiers(), event.Rune())
switch event.Key() {
case tcell.KeyESC:
ci.parent.conversationPanel.Filter("")
ci.parent.HideCommandInput()
return nil
case tcell.KeyEnter:
s := ci.GetText()
if s != "" {
ci.parent.conversationPanel.Filter(s)
}
ci.parent.NormalMode()
ci.parent.update()
return nil
}
return event
})
return ci
}

0 comments on commit 5177f94

Please sign in to comment.