ソースを参照

feat(ui/chat): fetch older messages on select-scrolling (#716)

Ayyan 3 ヶ月 前
コミット
3c3c33e978

+ 1 - 1
internal/config/config.toml

@@ -19,7 +19,7 @@ show_attachment_links = true
 # Note: Use autocomplete_limit = 0 to disable.
 autocomplete_limit = 20
 
-# The number of messages to fetch when a text-based channel is selected from guilds tree. The minimum and maximum value is 0 and 100, respectively.
+# The number of messages to fetch when a text-based channel is selected from guilds tree. The minimum and maximum value is 1 and 100, respectively.
 messages_limit = 50
 
 [timestamps]

+ 4 - 3
internal/ui/chat/guilds_tree.go

@@ -202,9 +202,10 @@ func (gt *guildsTree) onSelected(node *tview.TreeNode) {
 
 		go gt.chatView.state.ReadState.MarkRead(channel.ID, channel.LastMessageID)
 
-		messages, err := gt.chatView.state.Messages(channel.ID, uint(gt.cfg.MessagesLimit))
+		limit := gt.cfg.MessagesLimit
+		messages, err := gt.chatView.state.Messages(channel.ID, uint(limit))
 		if err != nil {
-			slog.Error("failed to get messages", "err", err, "channel_id", channel.ID, "limit", gt.cfg.MessagesLimit)
+			slog.Error("failed to get messages", "err", err, "channel_id", channel.ID, "limit", limit)
 			return
 		}
 
@@ -218,7 +219,7 @@ func (gt *guildsTree) onSelected(node *tview.TreeNode) {
 
 		gt.chatView.messagesList.reset()
 		gt.chatView.messagesList.setTitle(*channel)
-		gt.chatView.messagesList.drawMessages(messages)
+		gt.chatView.messagesList.setMessages(messages)
 		gt.chatView.messagesList.ScrollToEnd()
 
 		hasNoPerm := channel.Type != discord.DirectMessage && channel.Type != discord.GroupDM && !gt.chatView.state.HasPermissions(channel.ID, discord.PermissionSendMessages)

+ 29 - 6
internal/ui/chat/messages_list.go

@@ -82,10 +82,8 @@ func (ml *messagesList) setTitle(channel discord.Channel) {
 	ml.SetTitle(title)
 }
 
-func (ml *messagesList) drawMessages(messages []discord.Message) {
-	ml.messages = slices.Grow(ml.messages[:0], len(messages))
-	ml.messages = ml.messages[:len(messages)]
-	copy(ml.messages, messages)
+func (ml *messagesList) setMessages(messages []discord.Message) {
+	ml.messages = slices.Clone(messages)
 	slices.Reverse(ml.messages)
 }
 
@@ -355,6 +353,33 @@ func (ml *messagesList) _select(name string) {
 			cursor = len(messages) - 1
 		case cursor > 0:
 			cursor--
+		case cursor == 0:
+			selectedChannel := ml.chatView.SelectedChannel()
+			if selectedChannel == nil {
+				return
+			}
+
+			channelID := selectedChannel.ID
+			before := ml.messages[0].ID
+			limit := uint(ml.cfg.MessagesLimit)
+			messages, err := ml.chatView.state.MessagesBefore(channelID, before, limit)
+			if err != nil {
+				slog.Error("failed to fetch older messages", "err", err)
+				return
+			}
+			if len(messages) == 0 {
+				return
+			}
+
+			if guildID := selectedChannel.GuildID; guildID.IsValid() {
+				ml.requestGuildMembers(guildID, messages)
+			}
+
+			older := slices.Clone(messages)
+			slices.Reverse(older)
+
+			ml.messages = slices.Concat(older, ml.messages)
+			cursor = len(messages) - 1
 		}
 	case ml.cfg.Keys.MessagesList.SelectNext:
 		switch {
@@ -379,8 +404,6 @@ func (ml *messagesList) _select(name string) {
 			if refIdx != -1 {
 				cursor = refIdx
 			}
-		} else {
-			return
 		}
 	}