Organize room list by last received message (ref #11)
This commit is contained in:
parent
16406d6c91
commit
1e8705319a
@ -49,7 +49,6 @@ type GomuksUI interface {
|
|||||||
|
|
||||||
type MainView interface {
|
type MainView interface {
|
||||||
GetRoom(roomID string) RoomView
|
GetRoom(roomID string) RoomView
|
||||||
HasRoom(roomID string) bool
|
|
||||||
AddRoom(roomID string)
|
AddRoom(roomID string)
|
||||||
RemoveRoom(roomID string)
|
RemoveRoom(roomID string)
|
||||||
SetRooms(roomIDs []string)
|
SetRooms(roomIDs []string)
|
||||||
|
@ -17,7 +17,9 @@
|
|||||||
package open
|
package open
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
)
|
)
|
||||||
|
|
||||||
const FileProtocolHandler = "url.dll,FileProtocolHandler"
|
const FileProtocolHandler = "url.dll,FileProtocolHandler"
|
||||||
|
114
ui/room-list.go
114
ui/room-list.go
@ -29,7 +29,6 @@ import (
|
|||||||
type RoomList struct {
|
type RoomList struct {
|
||||||
*tview.Box
|
*tview.Box
|
||||||
|
|
||||||
indices map[*rooms.Room]int
|
|
||||||
items []*rooms.Room
|
items []*rooms.Room
|
||||||
selected *rooms.Room
|
selected *rooms.Room
|
||||||
|
|
||||||
@ -43,9 +42,8 @@ type RoomList struct {
|
|||||||
|
|
||||||
func NewRoomList() *RoomList {
|
func NewRoomList() *RoomList {
|
||||||
return &RoomList{
|
return &RoomList{
|
||||||
Box: tview.NewBox(),
|
Box: tview.NewBox(),
|
||||||
indices: make(map[*rooms.Room]int),
|
items: []*rooms.Room{},
|
||||||
items: []*rooms.Room{},
|
|
||||||
|
|
||||||
mainTextColor: tcell.ColorWhite,
|
mainTextColor: tcell.ColorWhite,
|
||||||
selectedTextColor: tcell.ColorWhite,
|
selectedTextColor: tcell.ColorWhite,
|
||||||
@ -53,28 +51,49 @@ func NewRoomList() *RoomList {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (list *RoomList) Add(room *rooms.Room) {
|
func (list *RoomList) Contains(roomID string) bool {
|
||||||
list.indices[room] = len(list.items)
|
for _, room := range list.items {
|
||||||
list.items = append(list.items, room)
|
if room.ID == roomID {
|
||||||
if list.selected == nil {
|
return true
|
||||||
list.selected = room
|
}
|
||||||
}
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (list *RoomList) Add(room *rooms.Room) {
|
||||||
|
list.items = append(list.items, room)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (list *RoomList) Remove(room *rooms.Room) {
|
func (list *RoomList) Remove(room *rooms.Room) {
|
||||||
index, ok := list.indices[room]
|
index := list.Index(room)
|
||||||
if !ok {
|
if index != -1 {
|
||||||
return
|
list.items = append(list.items[0:index], list.items[index+1:]...)
|
||||||
}
|
if room == list.selected {
|
||||||
delete(list.indices, room)
|
if index > 0 {
|
||||||
list.items = append(list.items[0:index], list.items[index+1:]...)
|
list.selected = list.items[index-1]
|
||||||
if len(list.items) == 0 {
|
} else if len(list.items) > 0 {
|
||||||
list.selected = nil
|
list.selected = list.items[0]
|
||||||
|
} else {
|
||||||
|
list.selected = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (list *RoomList) Bump(room *rooms.Room) {
|
||||||
|
found := false
|
||||||
|
for i := 0; i < len(list.items)-1; i++ {
|
||||||
|
if list.items[i] == room {
|
||||||
|
found = true
|
||||||
|
}
|
||||||
|
if found {
|
||||||
|
list.items[i] = list.items[i+1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
list.items[len(list.items)-1] = room
|
||||||
|
}
|
||||||
|
|
||||||
func (list *RoomList) Clear() {
|
func (list *RoomList) Clear() {
|
||||||
list.indices = make(map[*rooms.Room]int)
|
|
||||||
list.items = []*rooms.Room{}
|
list.items = []*rooms.Room{}
|
||||||
list.selected = nil
|
list.selected = nil
|
||||||
}
|
}
|
||||||
@ -83,11 +102,55 @@ func (list *RoomList) SetSelected(room *rooms.Room) {
|
|||||||
list.selected = room
|
list.selected = room
|
||||||
}
|
}
|
||||||
|
|
||||||
func (list *RoomList) Get(n int) *rooms.Room {
|
func (list *RoomList) HasSelected() bool {
|
||||||
if n < 0 || n >= len(list.items) {
|
return list.selected != nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (list *RoomList) Selected() *rooms.Room {
|
||||||
|
return list.selected
|
||||||
|
}
|
||||||
|
|
||||||
|
func (list *RoomList) Previous() *rooms.Room {
|
||||||
|
if len(list.items) == 0 {
|
||||||
return nil
|
return nil
|
||||||
|
} else if list.selected == nil {
|
||||||
|
return list.items[0]
|
||||||
}
|
}
|
||||||
return list.items[n]
|
|
||||||
|
index := list.Index(list.selected)
|
||||||
|
if index == len(list.items)-1 {
|
||||||
|
return list.items[0]
|
||||||
|
}
|
||||||
|
return list.items[index+1]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (list *RoomList) Next() *rooms.Room {
|
||||||
|
if len(list.items) == 0 {
|
||||||
|
return nil
|
||||||
|
} else if list.selected == nil {
|
||||||
|
return list.items[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
index := list.Index(list.selected)
|
||||||
|
if index == 0 {
|
||||||
|
return list.items[len(list.items)-1]
|
||||||
|
}
|
||||||
|
return list.items[index-1]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (list *RoomList) Index(room *rooms.Room) int {
|
||||||
|
roomIndex := -1
|
||||||
|
for index, entry := range list.items {
|
||||||
|
if entry == room {
|
||||||
|
roomIndex = index
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return roomIndex
|
||||||
|
}
|
||||||
|
|
||||||
|
func (list *RoomList) Get(n int) *rooms.Room {
|
||||||
|
return list.items[len(list.items)-1-(n%len(list.items))]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw draws this primitive onto the screen.
|
// Draw draws this primitive onto the screen.
|
||||||
@ -98,13 +161,16 @@ func (list *RoomList) Draw(screen tcell.Screen) {
|
|||||||
bottomLimit := y + height
|
bottomLimit := y + height
|
||||||
|
|
||||||
var offset int
|
var offset int
|
||||||
currentItemIndex, hasSelected := list.indices[list.selected]
|
currentItemIndex := list.Index(list.selected)
|
||||||
if hasSelected && currentItemIndex >= height {
|
if currentItemIndex >= height {
|
||||||
offset = currentItemIndex + 1 - height
|
offset = currentItemIndex + 1 - height
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw the list items.
|
// Draw the list items.
|
||||||
for index, item := range list.items {
|
for i := len(list.items) - 1; i >= 0; i-- {
|
||||||
|
item := list.items[i]
|
||||||
|
index := len(list.items) - 1 - i
|
||||||
|
|
||||||
if index < offset {
|
if index < offset {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
120
ui/view-main.go
120
ui/view-main.go
@ -18,7 +18,6 @@ package ui
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
"unicode"
|
"unicode"
|
||||||
@ -39,11 +38,9 @@ import (
|
|||||||
type MainView struct {
|
type MainView struct {
|
||||||
*tview.Flex
|
*tview.Flex
|
||||||
|
|
||||||
roomList *RoomList
|
roomList *RoomList
|
||||||
roomView *tview.Pages
|
roomView *tview.Pages
|
||||||
rooms map[string]*RoomView
|
rooms map[string]*RoomView
|
||||||
currentRoomIndex int
|
|
||||||
roomIDs []string
|
|
||||||
|
|
||||||
lastFocusTime time.Time
|
lastFocusTime time.Time
|
||||||
|
|
||||||
@ -166,9 +163,9 @@ func (view *MainView) KeyEventHandler(roomView *RoomView, key *tcell.EventKey) *
|
|||||||
if key.Modifiers() == tcell.ModCtrl || key.Modifiers() == tcell.ModAlt {
|
if key.Modifiers() == tcell.ModCtrl || key.Modifiers() == tcell.ModAlt {
|
||||||
switch k {
|
switch k {
|
||||||
case tcell.KeyDown:
|
case tcell.KeyDown:
|
||||||
view.SwitchRoom(view.currentRoomIndex + 1)
|
view.SwitchRoom(view.roomList.Next())
|
||||||
case tcell.KeyUp:
|
case tcell.KeyUp:
|
||||||
view.SwitchRoom(view.currentRoomIndex - 1)
|
view.SwitchRoom(view.roomList.Previous())
|
||||||
default:
|
default:
|
||||||
return key
|
return key
|
||||||
}
|
}
|
||||||
@ -241,9 +238,7 @@ func (view *MainView) MouseEventHandler(roomView *RoomView, event *tcell.EventMo
|
|||||||
} else if isInArea(x, y, view.roomList) && event.Buttons() == tcell.Button1 {
|
} else if isInArea(x, y, view.roomList) && event.Buttons() == tcell.Button1 {
|
||||||
_, rly, _, _ := msgView.GetRect()
|
_, rly, _, _ := msgView.GetRect()
|
||||||
n := y - rly + 1
|
n := y - rly + 1
|
||||||
if n >= 0 && n < len(view.roomIDs) {
|
view.SwitchRoom(view.roomList.Get(n))
|
||||||
view.SwitchRoom(n)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
debug.Print("Unhandled mouse event:", event.Buttons(), event.Modifiers(), x, y)
|
debug.Print("Unhandled mouse event:", event.Buttons(), event.Modifiers(), x, y)
|
||||||
}
|
}
|
||||||
@ -253,35 +248,24 @@ func (view *MainView) MouseEventHandler(roomView *RoomView, event *tcell.EventMo
|
|||||||
return event
|
return event
|
||||||
}
|
}
|
||||||
|
|
||||||
func (view *MainView) CurrentRoomID() string {
|
func (view *MainView) SwitchRoom(room *rooms.Room) {
|
||||||
if len(view.roomIDs) == 0 {
|
view.roomView.SwitchToPage(room.ID)
|
||||||
return ""
|
roomView := view.rooms[room.ID]
|
||||||
}
|
|
||||||
return view.roomIDs[view.currentRoomIndex]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (view *MainView) SwitchRoom(roomIndex int) {
|
|
||||||
if roomIndex < 0 {
|
|
||||||
roomIndex = len(view.roomIDs) - 1
|
|
||||||
}
|
|
||||||
if len(view.roomIDs) == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
view.currentRoomIndex = roomIndex % len(view.roomIDs)
|
|
||||||
view.roomView.SwitchToPage(view.CurrentRoomID())
|
|
||||||
roomView := view.rooms[view.CurrentRoomID()]
|
|
||||||
if roomView.MessageView().ScrollOffset == 0 {
|
if roomView.MessageView().ScrollOffset == 0 {
|
||||||
roomView.Room.MarkRead()
|
roomView.Room.MarkRead()
|
||||||
}
|
}
|
||||||
view.roomList.SetSelected(roomView.Room)
|
view.roomList.SetSelected(room)
|
||||||
view.parent.app.SetFocus(view)
|
view.parent.app.SetFocus(view)
|
||||||
view.parent.Render()
|
view.parent.Render()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (view *MainView) Focus(delegate func(p tview.Primitive)) {
|
func (view *MainView) Focus(delegate func(p tview.Primitive)) {
|
||||||
roomView, ok := view.rooms[view.CurrentRoomID()]
|
room := view.roomList.Selected()
|
||||||
if ok {
|
if room != nil {
|
||||||
delegate(roomView)
|
roomView, ok := view.rooms[room.ID]
|
||||||
|
if ok {
|
||||||
|
delegate(roomView)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -294,78 +278,67 @@ func (view *MainView) SaveAllHistory() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (view *MainView) addRoom(index int, room string) {
|
func (view *MainView) addRoomPage(room *rooms.Room) {
|
||||||
roomStore := view.matrix.GetRoom(room)
|
|
||||||
|
|
||||||
view.roomList.Add(roomStore)
|
if !view.roomView.HasPage(room.ID) {
|
||||||
if !view.roomView.HasPage(room) {
|
roomView := NewRoomView(view, room).
|
||||||
roomView := NewRoomView(view, roomStore).
|
|
||||||
SetInputSubmitFunc(view.InputSubmit).
|
SetInputSubmitFunc(view.InputSubmit).
|
||||||
SetInputChangedFunc(view.InputChanged).
|
SetInputChangedFunc(view.InputChanged).
|
||||||
SetInputCapture(view.KeyEventHandler).
|
SetInputCapture(view.KeyEventHandler).
|
||||||
SetMouseCapture(view.MouseEventHandler)
|
SetMouseCapture(view.MouseEventHandler)
|
||||||
view.rooms[room] = roomView
|
view.rooms[room.ID] = roomView
|
||||||
view.roomView.AddPage(room, roomView, true, false)
|
view.roomView.AddPage(room.ID, roomView, true, false)
|
||||||
roomView.UpdateUserList()
|
roomView.UpdateUserList()
|
||||||
|
|
||||||
count, err := roomView.LoadHistory(view.matrix, view.config.HistoryDir)
|
count, err := roomView.LoadHistory(view.matrix, view.config.HistoryDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
debug.Printf("Failed to load history of %s: %v", roomView.Room.GetTitle(), err)
|
debug.Printf("Failed to load history of %s: %v", roomView.Room.GetTitle(), err)
|
||||||
} else if count <= 0 {
|
} else if count <= 0 {
|
||||||
go view.LoadHistory(room, true)
|
go view.LoadHistory(room.ID, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (view *MainView) GetRoom(id string) ifc.RoomView {
|
func (view *MainView) GetRoom(roomID string) ifc.RoomView {
|
||||||
return view.rooms[id]
|
return view.rooms[roomID]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (view *MainView) HasRoom(room string) bool {
|
func (view *MainView) AddRoom(roomID string) {
|
||||||
for _, existingRoom := range view.roomIDs {
|
if view.roomList.Contains(roomID) {
|
||||||
if existingRoom == room {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (view *MainView) AddRoom(room string) {
|
|
||||||
if view.HasRoom(room) {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
view.roomIDs = append(view.roomIDs, room)
|
room := view.matrix.GetRoom(roomID)
|
||||||
view.addRoom(len(view.roomIDs)-1, room)
|
view.roomList.Add(room)
|
||||||
|
view.addRoomPage(room)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (view *MainView) RemoveRoom(room string) {
|
func (view *MainView) RemoveRoom(roomID string) {
|
||||||
roomView := view.GetRoom(room)
|
roomView := view.GetRoom(roomID)
|
||||||
if roomView == nil {
|
if roomView == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
removeIndex := 0
|
|
||||||
if view.CurrentRoomID() == room {
|
|
||||||
removeIndex = view.currentRoomIndex
|
|
||||||
view.SwitchRoom(view.currentRoomIndex - 1)
|
|
||||||
} else {
|
|
||||||
removeIndex = sort.StringSlice(view.roomIDs).Search(room)
|
|
||||||
}
|
|
||||||
view.roomList.Remove(roomView.MxRoom())
|
view.roomList.Remove(roomView.MxRoom())
|
||||||
view.roomIDs = append(view.roomIDs[:removeIndex], view.roomIDs[removeIndex+1:]...)
|
view.SwitchRoom(view.roomList.Selected())
|
||||||
view.roomView.RemovePage(room)
|
|
||||||
delete(view.rooms, room)
|
view.roomView.RemovePage(roomID)
|
||||||
|
delete(view.rooms, roomID)
|
||||||
|
|
||||||
view.parent.Render()
|
view.parent.Render()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (view *MainView) SetRooms(rooms []string) {
|
func (view *MainView) SetRooms(roomIDs []string) {
|
||||||
view.roomIDs = rooms
|
|
||||||
view.roomList.Clear()
|
view.roomList.Clear()
|
||||||
view.roomView.Clear()
|
view.roomView.Clear()
|
||||||
view.rooms = make(map[string]*RoomView)
|
view.rooms = make(map[string]*RoomView)
|
||||||
for index, room := range rooms {
|
for index, roomID := range roomIDs {
|
||||||
view.addRoom(index, room)
|
room := view.matrix.GetRoom(roomID)
|
||||||
|
view.roomList.Add(room)
|
||||||
|
view.addRoomPage(room)
|
||||||
|
if index == len(roomIDs)-1 {
|
||||||
|
view.SwitchRoom(room)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
view.SwitchRoom(0)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (view *MainView) SetTyping(room string, users []string) {
|
func (view *MainView) SetTyping(room string, users []string) {
|
||||||
@ -385,7 +358,7 @@ func sendNotification(room *rooms.Room, sender, text string, critical, sound boo
|
|||||||
|
|
||||||
func (view *MainView) NotifyMessage(room *rooms.Room, message ifc.Message, should pushrules.PushActionArrayShould) {
|
func (view *MainView) NotifyMessage(room *rooms.Room, message ifc.Message, should pushrules.PushActionArrayShould) {
|
||||||
// Whether or not the room where the message came is the currently shown room.
|
// Whether or not the room where the message came is the currently shown room.
|
||||||
isCurrent := room.ID == view.CurrentRoomID()
|
isCurrent := room == view.roomList.Selected()
|
||||||
// Whether or not the terminal window is focused.
|
// Whether or not the terminal window is focused.
|
||||||
isFocused := view.lastFocusTime.Add(30 * time.Second).Before(time.Now())
|
isFocused := view.lastFocusTime.Add(30 * time.Second).Before(time.Now())
|
||||||
|
|
||||||
@ -408,6 +381,7 @@ func (view *MainView) NotifyMessage(room *rooms.Room, message ifc.Message, shoul
|
|||||||
}
|
}
|
||||||
|
|
||||||
message.SetIsHighlight(should.Highlight)
|
message.SetIsHighlight(should.Highlight)
|
||||||
|
view.roomList.Bump(room)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (view *MainView) LoadHistory(room string, initial bool) {
|
func (view *MainView) LoadHistory(room string, initial bool) {
|
||||||
|
Loading…
Reference in New Issue
Block a user