this repo has no description
3
fork

Configure Feed

Select the types of activity you want to include in your feed.

ui: add highlight to unread messages

All unread messages are highlighted with a gray background. This is
currently the same color used on mouse hover, simply because it was easy
to copy.

A channel is marked read when:

* You switch channel (either via mouse or keyboard); or
* you send a message.

This means that new messages _from others in the channel_ will remain
unread until you either:

* send a message; or
* change the current channel.

Future improvements:

* Add a keybinding to mark the channel read (easy-ish)
* Mark a message as read as soon as it's received if the terminal window
(and thus comlink itself) is focused (harder).
* Mark a channel read on window focus (easy-ish).
- This might actually not be nice? I wouldn't want a channel to be
marked read as soon as I focus the window in case there's a long
scrollback I want to catch up on.

authored by

Kristófer R and committed by
Tim Culverhouse
2f6bb886 1025b1e9

+45 -3
+45 -3
src/app.zig
··· 760 760 channel.has_unread = true; 761 761 } 762 762 } 763 + 764 + // If we get a message from the current user mark the channel as 765 + // read, since they must have just sent the message. 766 + const sender: []const u8 = blk: { 767 + const src = msg2.source() orelse break :blk ""; 768 + const l = std.mem.indexOfScalar(u8, src, '!') orelse 769 + std.mem.indexOfScalar(u8, src, '@') orelse 770 + src.len; 771 + break :blk src[0..l]; 772 + }; 773 + if (std.mem.eql(u8, sender, client.config.nick)) { 774 + self.markSelectedChannelRead(); 775 + } 763 776 }, 764 777 } 765 778 }, ··· 773 786 } 774 787 } 775 788 pub fn nextChannel(self: *App) void { 789 + // When leaving a channel we mark it as read, so we make sure that's done 790 + // before we change to the new channel. 791 + self.markSelectedChannelRead(); 792 + 776 793 const state = self.state.buffers; 777 794 if (state.selected_idx >= state.count - 1) 778 795 self.state.buffers.selected_idx = 0 ··· 781 798 } 782 799 783 800 pub fn prevChannel(self: *App) void { 801 + // When leaving a channel we mark it as read, so we make sure that's done 802 + // before we change to the new channel. 803 + self.markSelectedChannelRead(); 804 + 784 805 switch (self.state.buffers.selected_idx) { 785 806 0 => self.state.buffers.selected_idx = self.state.buffers.count - 1, 786 807 else => self.state.buffers.selected_idx -|= 1, ··· 1000 1021 .client => {}, // nothing to do 1001 1022 1002 1023 .channel => |channel| { 1003 - // Mark the channel as read 1004 - try channel.markRead(); 1005 - 1006 1024 // Request WHO if we don't already have it 1007 1025 if (!channel.who_requested) try channel.client.whox(channel); 1008 1026 ··· 1353 1371 item.style.fg = .{ .index = 3 }; 1354 1372 } 1355 1373 } 1374 + 1375 + // Color the background of unread messages gray. 1376 + if (message.localTime(&self.tz)) |instant| { 1377 + if (instant.unixTimestamp() > channel.last_read) { 1378 + for (segments.items) |*item| { 1379 + item.style.bg = .{ .index = 8 }; 1380 + } 1381 + } 1382 + } 1383 + 1356 1384 _ = try content_win.print( 1357 1385 segments.items, 1358 1386 .{ ··· 1531 1559 }); 1532 1560 if (channel_win.hasMouse(self.state.mouse)) |mouse| { 1533 1561 if (mouse.type == .press and mouse.button == .left) { 1562 + // When leaving a channel we mark it as read, so we make sure that's done 1563 + // before we change to the new channel. 1564 + self.markSelectedChannelRead(); 1534 1565 self.state.buffers.selected_idx = row; 1535 1566 } 1536 1567 } ··· 1863 1894 .text = content[start..], 1864 1895 .style = style, 1865 1896 }); 1897 + } 1898 + } 1899 + 1900 + fn markSelectedChannelRead(self: *App) void { 1901 + const buffer = self.selectedBuffer() orelse return; 1902 + 1903 + switch (buffer) { 1904 + .channel => |channel| { 1905 + channel.markRead() catch return; 1906 + }, 1907 + else => {}, 1866 1908 } 1867 1909 } 1868 1910 };