Implement scrolling with J/K keys and fix image positioning
Co-authored-by: foglar <82380203+foglar@users.noreply.github.com>
This commit is contained in:
parent
c47fb1a073
commit
b4b65b9b60
@ -28,6 +28,21 @@ func updateChatView(v *gocui.View) {
|
|||||||
clear := cleanimage.NewKittyImageCleaner()
|
clear := cleanimage.NewKittyImageCleaner()
|
||||||
fmt.Print(clear.DeleteByColumn(chatViewColumn, false))
|
fmt.Print(clear.DeleteByColumn(chatViewColumn, false))
|
||||||
|
|
||||||
|
// Reset scroll offset when switching contacts or if out of bounds
|
||||||
|
if chatScrollOffset < 0 {
|
||||||
|
chatScrollOffset = 0
|
||||||
|
}
|
||||||
|
if chatScrollOffset > len(chatData.Messages) {
|
||||||
|
chatScrollOffset = len(chatData.Messages)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set view origin based on scroll offset
|
||||||
|
ox, _ := v.Origin()
|
||||||
|
v.SetOrigin(ox, chatScrollOffset)
|
||||||
|
|
||||||
|
// Get view dimensions to check if images are visible
|
||||||
|
_, viewHeight := v.Size()
|
||||||
|
|
||||||
for i, msg := range chatData.Messages {
|
for i, msg := range chatData.Messages {
|
||||||
decoded, err := base64.StdEncoding.DecodeString(msg.Content)
|
decoded, err := base64.StdEncoding.DecodeString(msg.Content)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -60,13 +75,27 @@ func updateChatView(v *gocui.View) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Calculate row position accounting for scroll offset
|
||||||
|
// Each message takes 3 lines (messageRowIncrement)
|
||||||
|
rowPosition := i*messageRowIncrement + messageRowOffset - chatScrollOffset
|
||||||
|
|
||||||
|
// Only render images that are visible in the view
|
||||||
|
if rowPosition >= 0 && rowPosition < viewHeight {
|
||||||
if !strings.EqualFold(msg.Sender, users[selectedUserIdx]) {
|
if !strings.EqualFold(msg.Sender, users[selectedUserIdx]) {
|
||||||
fmt.Fprintf(v, "%s", "\t\t\t\t\t"+Colors.Text(Colors.Base02)+"You ("+formattedTime+"):"+Colors.Reset+"\n\t\t\t\t\t"+string(decoded)+"\n\n")
|
fmt.Fprintf(v, "%s", "\t\t\t\t\t"+Colors.Text(Colors.Base02)+"You ("+formattedTime+"):"+Colors.Reset+"\n\t\t\t\t\t"+string(decoded)+"\n\n")
|
||||||
render_image.RenderImage(userIconPath, i*messageRowIncrement+messageRowOffset, chatViewColumn, w, h, false)
|
render_image.RenderImage(userIconPath, rowPosition, chatViewColumn, w, h, false)
|
||||||
} else {
|
} else {
|
||||||
fmt.Fprintf(v, "%s", "\t\t\t\t\t"+Colors.Text(Colors.Base05)+msg.Sender+" ("+formattedTime+"):"+Colors.Reset+"\n\t\t\t\t\t"+string(decoded)+"\n\n")
|
fmt.Fprintf(v, "%s", "\t\t\t\t\t"+Colors.Text(Colors.Base05)+msg.Sender+" ("+formattedTime+"):"+Colors.Reset+"\n\t\t\t\t\t"+string(decoded)+"\n\n")
|
||||||
iconPath := fmt.Sprintf(contactIconPathFmt, strings.ToLower(msg.Sender))
|
iconPath := fmt.Sprintf(contactIconPathFmt, strings.ToLower(msg.Sender))
|
||||||
render_image.RenderImage(iconPath, i*messageRowIncrement+messageRowOffset, chatViewColumn, w, h, false)
|
render_image.RenderImage(iconPath, rowPosition, chatViewColumn, w, h, false)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Still print the text even if image is not visible
|
||||||
|
if !strings.EqualFold(msg.Sender, users[selectedUserIdx]) {
|
||||||
|
fmt.Fprintf(v, "%s", "\t\t\t\t\t"+Colors.Text(Colors.Base02)+"You ("+formattedTime+"):"+Colors.Reset+"\n\t\t\t\t\t"+string(decoded)+"\n\n")
|
||||||
|
} else {
|
||||||
|
fmt.Fprintf(v, "%s", "\t\t\t\t\t"+Colors.Text(Colors.Base05)+msg.Sender+" ("+formattedTime+"):"+Colors.Reset+"\n\t\t\t\t\t"+string(decoded)+"\n\n")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -92,6 +121,38 @@ func sendMessage(g *gocui.Gui, v *gocui.View) error {
|
|||||||
log.Printf("Error getting chat view: %v", err)
|
log.Printf("Error getting chat view: %v", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reset scroll to bottom when sending a new message
|
||||||
|
chatScrollOffset = 0
|
||||||
updateChatView(chatView)
|
updateChatView(chatView)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func scrollChatUp(g *gocui.Gui, v *gocui.View) error {
|
||||||
|
chatView, err := g.View("chat")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scroll up by 1 line
|
||||||
|
if chatScrollOffset > 0 {
|
||||||
|
chatScrollOffset--
|
||||||
|
updateChatView(chatView)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func scrollChatDown(g *gocui.Gui, v *gocui.View) error {
|
||||||
|
chatView, err := g.View("chat")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scroll down by 1 line
|
||||||
|
maxScroll := len(chatData.Messages) * messageRowIncrement
|
||||||
|
if chatScrollOffset < maxScroll {
|
||||||
|
chatScrollOffset++
|
||||||
|
updateChatView(chatView)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@ -14,6 +14,18 @@ func keybindings(g *gocui.Gui) error {
|
|||||||
if err := g.SetKeybinding("", gocui.KeyCtrlK, gocui.ModNone, prevContact); err != nil {
|
if err := g.SetKeybinding("", gocui.KeyCtrlK, gocui.ModNone, prevContact); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if err := g.SetKeybinding("", 'j', gocui.ModNone, scrollChatDown); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := g.SetKeybinding("", 'J', gocui.ModNone, scrollChatDown); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := g.SetKeybinding("", 'k', gocui.ModNone, scrollChatUp); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := g.SetKeybinding("", 'K', gocui.ModNone, scrollChatUp); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
if err := g.SetKeybinding("", gocui.KeyTab, gocui.ModNone, toggleProfileView); err != nil {
|
if err := g.SetKeybinding("", gocui.KeyTab, gocui.ModNone, toggleProfileView); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@ -44,7 +44,7 @@ func layoutChat(g *gocui.Gui, maxX, maxY int) error {
|
|||||||
}
|
}
|
||||||
v.Title = " Chat "
|
v.Title = " Chat "
|
||||||
v.Wrap = true
|
v.Wrap = true
|
||||||
v.Autoscroll = true
|
v.Autoscroll = false
|
||||||
updateChatView(v)
|
updateChatView(v)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@ -74,6 +74,9 @@ func nextContact(g *gocui.Gui, v *gocui.View) error {
|
|||||||
selectedUserIdx = 0
|
selectedUserIdx = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reset scroll offset when changing contacts
|
||||||
|
chatScrollOffset = 0
|
||||||
|
|
||||||
if err := updateContactsView(g); err != nil {
|
if err := updateContactsView(g); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -96,6 +99,9 @@ func prevContact(g *gocui.Gui, v *gocui.View) error {
|
|||||||
selectedUserIdx = len(users) - 1
|
selectedUserIdx = len(users) - 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reset scroll offset when changing contacts
|
||||||
|
chatScrollOffset = 0
|
||||||
|
|
||||||
if err := updateContactsView(g); err != nil {
|
if err := updateContactsView(g); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,6 +10,7 @@ var users []string
|
|||||||
var prevWidth, prevHeight int
|
var prevWidth, prevHeight int
|
||||||
var chatData ChatData
|
var chatData ChatData
|
||||||
var selectedUserIdx int = 0
|
var selectedUserIdx int = 0
|
||||||
|
var chatScrollOffset int = 0
|
||||||
|
|
||||||
func Run() {
|
func Run() {
|
||||||
LoadContacts(defaultServerPath)
|
LoadContacts(defaultServerPath)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user