Show bubble containing the number of unread messages in the conversation list (#764)
Co-authored-by: codedust <codedust@users.noreply.github.com> Co-authored-by: fiaxh <git@lightrise.org>
This commit is contained in:
parent
23c0216853
commit
86420fdef1
|
@ -32,11 +32,19 @@ public class ChatInteraction : StreamInteractionModule, Object {
|
||||||
stream_interactor.get_module(ContentItemStore.IDENTITY).new_item.connect(new_item);
|
stream_interactor.get_module(ContentItemStore.IDENTITY).new_item.connect(new_item);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool has_unread(Conversation conversation) {
|
public int get_num_unread(Conversation conversation) {
|
||||||
ContentItem? last_content_item = stream_interactor.get_module(ContentItemStore.IDENTITY).get_latest(conversation);
|
ContentItem? read_up_to_item = stream_interactor.get_module(ContentItemStore.IDENTITY).get_item_by_id(conversation, conversation.read_up_to_item);
|
||||||
if (last_content_item == null) return false;
|
if (read_up_to_item == null) return 0;
|
||||||
|
|
||||||
return last_content_item.id != conversation.read_up_to_item;
|
Database db = Dino.Application.get_default().db;
|
||||||
|
string local_time = read_up_to_item.sort_time.to_unix().to_string();
|
||||||
|
string time = read_up_to_item.display_time.to_unix().to_string();
|
||||||
|
string id = read_up_to_item.id.to_string();
|
||||||
|
return (int)db.content_item.select()
|
||||||
|
.where(@"local_time > ? OR (local_time = ? AND time > ?) OR (local_time = ? AND time = ? AND id > ?)", { local_time, local_time, time, local_time, time, id })
|
||||||
|
.with(db.content_item.conversation_id, "=", conversation.id)
|
||||||
|
.with(db.content_item.hide, "=", false)
|
||||||
|
.count();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool is_active_focus(Conversation? conversation = null) {
|
public bool is_active_focus(Conversation? conversation = null) {
|
||||||
|
|
|
@ -46,7 +46,7 @@
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkRevealer" id="time_revealer">
|
<object class="GtkRevealer" id="time_revealer">
|
||||||
<property name="transition-type">slide-right</property>
|
<property name="transition-type">slide-right</property>
|
||||||
<property name="transition-duration">100</property>
|
<property name="transition-duration">50</property>
|
||||||
<property name="reveal-child">True</property>
|
<property name="reveal-child">True</property>
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<child>
|
<child>
|
||||||
|
@ -71,6 +71,7 @@
|
||||||
<object class="GtkLabel" id="nick_label">
|
<object class="GtkLabel" id="nick_label">
|
||||||
<property name="max_width_chars">15</property>
|
<property name="max_width_chars">15</property>
|
||||||
<property name="ellipsize">end</property>
|
<property name="ellipsize">end</property>
|
||||||
|
<property name="valign">end</property>
|
||||||
<property name="xalign">0</property>
|
<property name="xalign">0</property>
|
||||||
<style>
|
<style>
|
||||||
<class name="dim-label"/>
|
<class name="dim-label"/>
|
||||||
|
@ -86,12 +87,36 @@
|
||||||
<property name="max_width_chars">1</property>
|
<property name="max_width_chars">1</property>
|
||||||
<property name="ellipsize">end</property>
|
<property name="ellipsize">end</property>
|
||||||
<property name="expand">True</property>
|
<property name="expand">True</property>
|
||||||
|
<property name="valign">end</property>
|
||||||
<property name="xalign">0</property>
|
<property name="xalign">0</property>
|
||||||
<attributes>
|
<attributes>
|
||||||
<attribute name="scale" value="0.8"/>
|
<attribute name="scale" value="0.8"/>
|
||||||
</attributes>
|
</attributes>
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkRevealer" id="unread_count_revealer">
|
||||||
|
<property name="transition-type">slide-right</property>
|
||||||
|
<property name="transition-duration">50</property>
|
||||||
|
<property name="reveal-child">True</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel" id="unread_count_label">
|
||||||
|
<property name="vexpand">False</property>
|
||||||
|
<property name="visible">False</property>
|
||||||
|
<property name="margin-start">15</property>
|
||||||
|
<property name="xalign">0.5</property>
|
||||||
|
<attributes>
|
||||||
|
<attribute name="scale" value="0.6"/>
|
||||||
|
<attribute name="weight" value="PANGO_WEIGHT_BOLD"/>
|
||||||
|
</attributes>
|
||||||
|
<style>
|
||||||
|
<class name="unread-count"/>
|
||||||
|
</style>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
</object>
|
</object>
|
||||||
|
@ -116,6 +141,7 @@
|
||||||
<object class="GtkButton" id="x_button">
|
<object class="GtkButton" id="x_button">
|
||||||
<property name="vexpand">False</property>
|
<property name="vexpand">False</property>
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
|
<property name="margin-start">5</property>
|
||||||
<style>
|
<style>
|
||||||
<class name="conversation_list_row_xbutton"/>
|
<class name="conversation_list_row_xbutton"/>
|
||||||
<class name="circular"/>
|
<class name="circular"/>
|
||||||
|
|
|
@ -42,6 +42,14 @@ window.dino-main .dino-conversation .message-box:hover {
|
||||||
background: alpha(@theme_fg_color, 0.04);
|
background: alpha(@theme_fg_color, 0.04);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
window.dino-main .unread-count {
|
||||||
|
background-color: alpha(@theme_fg_color, 0.8);
|
||||||
|
color: @theme_base_color;
|
||||||
|
font-family: monospace;
|
||||||
|
border-radius: 999em;
|
||||||
|
padding: .2em .41em;
|
||||||
|
}
|
||||||
|
|
||||||
window.dino-main .dino-sidebar > frame {
|
window.dino-main .dino-sidebar > frame {
|
||||||
background: @insensitive_bg_color;
|
background: @insensitive_bg_color;
|
||||||
border-left: 1px solid @borders;
|
border-left: 1px solid @borders;
|
||||||
|
|
|
@ -17,9 +17,11 @@ public class ConversationSelectorRow : ListBoxRow {
|
||||||
[GtkChild] protected Label time_label;
|
[GtkChild] protected Label time_label;
|
||||||
[GtkChild] protected Label nick_label;
|
[GtkChild] protected Label nick_label;
|
||||||
[GtkChild] protected Label message_label;
|
[GtkChild] protected Label message_label;
|
||||||
|
[GtkChild] protected Label unread_count_label;
|
||||||
[GtkChild] protected Button x_button;
|
[GtkChild] protected Button x_button;
|
||||||
[GtkChild] protected Revealer time_revealer;
|
[GtkChild] protected Revealer time_revealer;
|
||||||
[GtkChild] protected Revealer xbutton_revealer;
|
[GtkChild] protected Revealer xbutton_revealer;
|
||||||
|
[GtkChild] protected Revealer unread_count_revealer;
|
||||||
[GtkChild] public Revealer main_revealer;
|
[GtkChild] public Revealer main_revealer;
|
||||||
|
|
||||||
public Conversation conversation { get; private set; }
|
public Conversation conversation { get; private set; }
|
||||||
|
@ -27,7 +29,7 @@ public class ConversationSelectorRow : ListBoxRow {
|
||||||
protected const int AVATAR_SIZE = 40;
|
protected const int AVATAR_SIZE = 40;
|
||||||
|
|
||||||
protected ContentItem? last_content_item;
|
protected ContentItem? last_content_item;
|
||||||
protected bool read = true;
|
protected int num_unread = 0;
|
||||||
|
|
||||||
|
|
||||||
protected StreamInteractor stream_interactor;
|
protected StreamInteractor stream_interactor;
|
||||||
|
@ -202,21 +204,27 @@ public class ConversationSelectorRow : ListBoxRow {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void update_read() {
|
protected void update_read() {
|
||||||
bool current_read_status = !stream_interactor.get_module(ChatInteraction.IDENTITY).has_unread(conversation);
|
int current_num_unread = stream_interactor.get_module(ChatInteraction.IDENTITY).get_num_unread(conversation);
|
||||||
if (read == current_read_status) return;
|
if (num_unread == current_num_unread) return;
|
||||||
read = current_read_status;
|
num_unread = current_num_unread;
|
||||||
|
|
||||||
|
if (num_unread == 0) {
|
||||||
|
unread_count_label.visible = false;
|
||||||
|
|
||||||
if (read) {
|
|
||||||
name_label.attributes.filter((attr) => attr.equal(attr_weight_new(Weight.BOLD)));
|
name_label.attributes.filter((attr) => attr.equal(attr_weight_new(Weight.BOLD)));
|
||||||
time_label.attributes.filter((attr) => attr.equal(attr_weight_new(Weight.BOLD)));
|
time_label.attributes.filter((attr) => attr.equal(attr_weight_new(Weight.BOLD)));
|
||||||
nick_label.attributes.filter((attr) => attr.equal(attr_weight_new(Weight.BOLD)));
|
nick_label.attributes.filter((attr) => attr.equal(attr_weight_new(Weight.BOLD)));
|
||||||
message_label.attributes.filter((attr) => attr.equal(attr_weight_new(Weight.BOLD)));
|
message_label.attributes.filter((attr) => attr.equal(attr_weight_new(Weight.BOLD)));
|
||||||
} else {
|
} else {
|
||||||
|
unread_count_label.label = num_unread.to_string();
|
||||||
|
unread_count_label.visible = true;
|
||||||
|
|
||||||
name_label.attributes.insert(attr_weight_new(Weight.BOLD));
|
name_label.attributes.insert(attr_weight_new(Weight.BOLD));
|
||||||
time_label.attributes.insert(attr_weight_new(Weight.BOLD));
|
time_label.attributes.insert(attr_weight_new(Weight.BOLD));
|
||||||
nick_label.attributes.insert(attr_weight_new(Weight.BOLD));
|
nick_label.attributes.insert(attr_weight_new(Weight.BOLD));
|
||||||
message_label.attributes.insert(attr_weight_new(Weight.BOLD));
|
message_label.attributes.insert(attr_weight_new(Weight.BOLD));
|
||||||
}
|
}
|
||||||
|
|
||||||
name_label.label = name_label.label; // TODO initializes redrawing, which would otherwise not happen. nicer?
|
name_label.label = name_label.label; // TODO initializes redrawing, which would otherwise not happen. nicer?
|
||||||
time_label.label = time_label.label;
|
time_label.label = time_label.label;
|
||||||
nick_label.label = nick_label.label;
|
nick_label.label = nick_label.label;
|
||||||
|
@ -227,9 +235,11 @@ public class ConversationSelectorRow : ListBoxRow {
|
||||||
StateFlags curr_flags = get_state_flags();
|
StateFlags curr_flags = get_state_flags();
|
||||||
if ((curr_flags & StateFlags.PRELIGHT) != 0) {
|
if ((curr_flags & StateFlags.PRELIGHT) != 0) {
|
||||||
time_revealer.set_reveal_child(false);
|
time_revealer.set_reveal_child(false);
|
||||||
|
unread_count_revealer.set_reveal_child(false);
|
||||||
xbutton_revealer.set_reveal_child(true);
|
xbutton_revealer.set_reveal_child(true);
|
||||||
} else {
|
} else {
|
||||||
time_revealer.set_reveal_child(true);
|
time_revealer.set_reveal_child(true);
|
||||||
|
unread_count_revealer.set_reveal_child(true);
|
||||||
xbutton_revealer.set_reveal_child(false);
|
xbutton_revealer.set_reveal_child(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue