Show last message sender in conversation list
This commit is contained in:
parent
dc26841b9e
commit
addd5a013f
|
@ -9,11 +9,10 @@
|
|||
<property name="reveal-child">False</property>
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkGrid">
|
||||
<object class="GtkBox">
|
||||
<property name="orientation">horizontal</property>
|
||||
<property name="margin">7</property>
|
||||
<property name="margin-right">14</property>
|
||||
<property name="column-spacing">10</property>
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkImage" id="image">
|
||||
|
@ -23,114 +22,117 @@
|
|||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkGrid">
|
||||
<object class="GtkBox">
|
||||
<property name="margin-left">10</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="name_label">
|
||||
<property name="max_width_chars">1</property>
|
||||
<property name="ellipsize">end</property>
|
||||
<property name="expand">True</property>
|
||||
<property name="margin-right">7</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="visible">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">0</property>
|
||||
<property name="width">1</property>
|
||||
<property name="height">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkRevealer" id="time_revealer">
|
||||
<property name="transition-type">slide-right</property>
|
||||
<property name="transition-duration">100</property>
|
||||
<property name="reveal-child">True</property>
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="time_label">
|
||||
<property name="hexpand">False</property>
|
||||
<property name="xalign">1</property>
|
||||
<attributes>
|
||||
<attribute name="scale" value="0.7"/>
|
||||
</attributes>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">0</property>
|
||||
<property name="width">1</property>
|
||||
<property name="height">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="message_label">
|
||||
<property name="max_width_chars">1</property>
|
||||
<property name="ellipsize">end</property>
|
||||
<property name="expand">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<attributes>
|
||||
<attribute name="scale" value="0.8"/>
|
||||
</attributes>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="width">2</property>
|
||||
<property name="height">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="orientation">horizontal</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="vexpand">True</property>
|
||||
<object class="GtkLabel" id="name_label">
|
||||
<property name="max_width_chars">1</property>
|
||||
<property name="ellipsize">end</property>
|
||||
<property name="expand">True</property>
|
||||
<property name="margin-right">7</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="visible">True</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkRevealer" id="xbutton_revealer">
|
||||
<property name="transition-type">slide-left</property>
|
||||
<object class="GtkRevealer" id="time_revealer">
|
||||
<property name="transition-type">slide-right</property>
|
||||
<property name="transition-duration">100</property>
|
||||
<property name="reveal-child">False</property>
|
||||
<property name="reveal-child">True</property>
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="x_button">
|
||||
<property name="vexpand">False</property>
|
||||
<property name="visible">True</property>
|
||||
<style>
|
||||
<class name="conversation_list_row_xbutton"/>
|
||||
<class name="circular"/>
|
||||
<class name="flat"/>
|
||||
</style>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="icon-name">window-close-symbolic</property>
|
||||
<property name="icon-size">1</property>
|
||||
<property name="visible">True</property>
|
||||
</object>
|
||||
</child>
|
||||
<object class="GtkLabel" id="time_label">
|
||||
<property name="hexpand">False</property>
|
||||
<property name="xalign">1</property>
|
||||
<attributes>
|
||||
<attribute name="scale" value="0.7"/>
|
||||
</attributes>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="orientation">horizontal</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="vexpand">True</property>
|
||||
<property name="visible">True</property>
|
||||
<object class="GtkLabel" id="nick_label">
|
||||
<property name="max_width_chars">15</property>
|
||||
<property name="ellipsize">end</property>
|
||||
<property name="xalign">0</property>
|
||||
<style>
|
||||
<class name="dim-label"/>
|
||||
</style>
|
||||
<attributes>
|
||||
<!--<attribute name="weight" value="bold"/>-->
|
||||
<attribute name="scale" value="0.8"/>
|
||||
</attributes>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="message_label">
|
||||
<property name="max_width_chars">1</property>
|
||||
<property name="ellipsize">end</property>
|
||||
<property name="expand">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<attributes>
|
||||
<attribute name="scale" value="0.8"/>
|
||||
</attributes>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">2</property>
|
||||
<property name="top_attach">0</property>
|
||||
<property name="width">1</property>
|
||||
<property name="height">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="vexpand">True</property>
|
||||
<property name="visible">True</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkRevealer" id="xbutton_revealer">
|
||||
<property name="transition-type">slide-left</property>
|
||||
<property name="transition-duration">100</property>
|
||||
<property name="reveal-child">False</property>
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="x_button">
|
||||
<property name="vexpand">False</property>
|
||||
<property name="visible">True</property>
|
||||
<style>
|
||||
<class name="conversation_list_row_xbutton"/>
|
||||
<class name="circular"/>
|
||||
<class name="flat"/>
|
||||
</style>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="icon-name">window-close-symbolic</property>
|
||||
<property name="icon-size">1</property>
|
||||
<property name="visible">True</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="vexpand">True</property>
|
||||
<property name="visible">True</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
|
|
|
@ -2,7 +2,6 @@ using Gdk;
|
|||
using Gee;
|
||||
using Gtk;
|
||||
|
||||
using Xmpp;
|
||||
using Dino.Entities;
|
||||
|
||||
namespace Dino.Ui.ConversationSelector {
|
||||
|
@ -16,36 +15,24 @@ public class ChatRow : ConversationRow {
|
|||
tooltip.set_custom(generate_tooltip());
|
||||
return true;
|
||||
});
|
||||
update_avatar();
|
||||
stream_interactor.get_module(RosterManager.IDENTITY).updated_roster_item.connect((account, jid, roster_item) => {
|
||||
if (conversation.account.equals(account) && conversation.counterpart.equals(jid)) {
|
||||
update_name_label();
|
||||
update_avatar();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public override void on_show_received(Show show) {
|
||||
update_avatar();
|
||||
}
|
||||
|
||||
public override void network_connection(bool connected) {
|
||||
if (!connected) {
|
||||
set_avatar((new AvatarGenerator(AVATAR_SIZE, AVATAR_SIZE, image.scale_factor)).set_greyscale(true).draw_conversation(stream_interactor, conversation), image.scale_factor);
|
||||
protected override void update_message_label() {
|
||||
base.update_message_label();
|
||||
if (last_message != null && last_message.direction == Message.DIRECTION_SENT) {
|
||||
nick_label.visible = true;
|
||||
nick_label.label = _("Me") + ": ";
|
||||
} else {
|
||||
update_avatar();
|
||||
nick_label.label = "";
|
||||
}
|
||||
}
|
||||
|
||||
public void on_updated_roster_item(Roster.Item roster_item) {
|
||||
if (roster_item.name != null) {
|
||||
display_name = roster_item.name;
|
||||
update_name();
|
||||
}
|
||||
update_avatar();
|
||||
}
|
||||
|
||||
public void update_avatar() {
|
||||
ArrayList<Jid> full_jids = stream_interactor.get_module(PresenceManager.IDENTITY).get_full_jids(conversation.counterpart, conversation.account);
|
||||
set_avatar((new AvatarGenerator(AVATAR_SIZE, AVATAR_SIZE, image.scale_factor))
|
||||
.set_greyscale(full_jids == null)
|
||||
.draw_conversation(stream_interactor, conversation), image.scale_factor);
|
||||
}
|
||||
|
||||
private Widget generate_tooltip() {
|
||||
Builder builder = new Builder.from_resource("/im/dino/conversation_selector/chat_row_tooltip.ui");
|
||||
Box main_box = builder.get_object("main_box") as Box;
|
||||
|
|
|
@ -3,7 +3,6 @@ using Gdk;
|
|||
using Gtk;
|
||||
using Pango;
|
||||
|
||||
using Xmpp;
|
||||
using Dino.Entities;
|
||||
|
||||
namespace Dino.Ui.ConversationSelector {
|
||||
|
@ -14,21 +13,20 @@ public abstract class ConversationRow : ListBoxRow {
|
|||
public signal void closed();
|
||||
|
||||
[GtkChild] protected Image image;
|
||||
[GtkChild] private Label name_label;
|
||||
[GtkChild] private Label time_label;
|
||||
[GtkChild] private Label message_label;
|
||||
[GtkChild] protected Label name_label;
|
||||
[GtkChild] protected Label time_label;
|
||||
[GtkChild] protected Label nick_label;
|
||||
[GtkChild] protected Label message_label;
|
||||
[GtkChild] protected Button x_button;
|
||||
[GtkChild] private Revealer time_revealer;
|
||||
[GtkChild] private Revealer xbutton_revealer;
|
||||
[GtkChild] protected Revealer time_revealer;
|
||||
[GtkChild] protected Revealer xbutton_revealer;
|
||||
[GtkChild] public Revealer main_revealer;
|
||||
|
||||
public Conversation conversation { get; private set; }
|
||||
|
||||
protected const int AVATAR_SIZE = 40;
|
||||
|
||||
protected string display_name;
|
||||
protected string message;
|
||||
protected DateTime time;
|
||||
protected Message? last_message;
|
||||
protected bool read = true;
|
||||
|
||||
|
||||
|
@ -42,27 +40,23 @@ public abstract class ConversationRow : ListBoxRow {
|
|||
this.conversation = conversation;
|
||||
this.stream_interactor = stream_interactor;
|
||||
|
||||
x_button.clicked.connect(on_x_button_clicked);
|
||||
x_button.clicked.connect(close_conversation);
|
||||
stream_interactor.connection_manager.connection_state_changed.connect(update_avatar);
|
||||
|
||||
update_name(Util.get_conversation_display_name(stream_interactor, conversation));
|
||||
update_name_label();
|
||||
update_avatar();
|
||||
message_received();
|
||||
|
||||
}
|
||||
|
||||
public void update() {
|
||||
update_time();
|
||||
update_time_label();
|
||||
}
|
||||
|
||||
public void message_received(Entities.Message? m = null) {
|
||||
Entities.Message? message = stream_interactor.get_module(MessageStorage.IDENTITY).get_last_message(conversation);
|
||||
if (message != null) {
|
||||
update_message(message.body.replace("\n", " "));
|
||||
update_time(message.time);
|
||||
}
|
||||
}
|
||||
|
||||
public void set_avatar(Pixbuf pixbuf, int scale_factor = 1) {
|
||||
Util.image_set_from_scaled_pixbuf(image, pixbuf, scale_factor);
|
||||
image.queue_draw();
|
||||
last_message = stream_interactor.get_module(MessageStorage.IDENTITY).get_last_message(conversation) ?? m;
|
||||
update_message_label();
|
||||
update_time_label();
|
||||
}
|
||||
|
||||
public void mark_read() {
|
||||
|
@ -73,33 +67,39 @@ public abstract class ConversationRow : ListBoxRow {
|
|||
update_read(false);
|
||||
}
|
||||
|
||||
public abstract void on_show_received(Show presence);
|
||||
public abstract void network_connection(bool connected);
|
||||
|
||||
protected void update_name(string? new_name = null) {
|
||||
if (new_name != null) {
|
||||
display_name = new_name;
|
||||
}
|
||||
name_label.label = display_name;
|
||||
public virtual void on_show_received(Show presence) {
|
||||
update_avatar();
|
||||
}
|
||||
|
||||
protected void update_time(DateTime? new_time = null) {
|
||||
time_label.visible = true;
|
||||
if (new_time != null) {
|
||||
time = new_time;
|
||||
}
|
||||
if (time != null) {
|
||||
time_label.label = get_relative_time(time.to_local());
|
||||
public void update_avatar() {
|
||||
bool self_online = stream_interactor.connection_manager.get_state(conversation.account) == ConnectionManager.ConnectionState.CONNECTED;
|
||||
bool counterpart_online = stream_interactor.get_module(PresenceManager.IDENTITY).get_full_jids(conversation.counterpart, conversation.account) != null;
|
||||
bool greyscale = !self_online || !counterpart_online;
|
||||
|
||||
Idle.add(() => {
|
||||
Pixbuf pixbuf = ((new AvatarGenerator(AVATAR_SIZE, AVATAR_SIZE, image.scale_factor))
|
||||
.set_greyscale(greyscale)
|
||||
.draw_conversation(stream_interactor, conversation));
|
||||
Util.image_set_from_scaled_pixbuf(image, pixbuf, image.get_scale_factor());
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
protected void update_name_label(string? new_name = null) {
|
||||
name_label.label = Util.get_conversation_display_name(stream_interactor, conversation);
|
||||
}
|
||||
|
||||
protected void update_time_label(DateTime? new_time = null) {
|
||||
if (last_message != null) {
|
||||
time_label.visible = true;
|
||||
time_label.label = get_relative_time(last_message.time.to_local());
|
||||
}
|
||||
}
|
||||
|
||||
protected void update_message(string? new_message = null) {
|
||||
if (new_message != null) {
|
||||
message = new_message;
|
||||
}
|
||||
if (message != null) {
|
||||
protected virtual void update_message_label() {
|
||||
if (last_message != null) {
|
||||
message_label.visible = true;
|
||||
message_label.label = message;
|
||||
message_label.label = last_message.body.replace("\n", " ");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -108,14 +108,17 @@ public abstract class ConversationRow : ListBoxRow {
|
|||
if (read) {
|
||||
name_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)));
|
||||
message_label.attributes.filter((attr) => attr.equal(attr_weight_new(Weight.BOLD)));
|
||||
} else {
|
||||
name_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));
|
||||
message_label.attributes.insert(attr_weight_new(Weight.BOLD));
|
||||
}
|
||||
name_label.label = name_label.label; // TODO initializes redrawing, which would otherwise not happen. nicer?
|
||||
time_label.label = time_label.label;
|
||||
nick_label.label = nick_label.label;
|
||||
message_label.label = message_label.label;
|
||||
}
|
||||
|
||||
|
@ -142,7 +145,7 @@ public abstract class ConversationRow : ListBoxRow {
|
|||
return box;
|
||||
}
|
||||
|
||||
private void on_x_button_clicked() {
|
||||
private void close_conversation() {
|
||||
main_revealer.set_transition_type(RevealerTransitionType.SLIDE_UP);
|
||||
main_revealer.set_reveal_child(false);
|
||||
closed();
|
||||
|
@ -177,8 +180,8 @@ public abstract class ConversationRow : ListBoxRow {
|
|||
return _("Yesterday");
|
||||
} else if (timespan > 9 * TimeSpan.MINUTE) {
|
||||
return datetime.format(Util.is_24h_format() ?
|
||||
/* xgettext:no-c-format */ /* Time in 24h format (w/o seconds) */ _("%H\u2236%M") :
|
||||
/* xgettext:no-c-format */ /* Time in 12h format (w/o seconds) */ _("%l\u2236%M %p"));
|
||||
/* xgettext:no-c-format */ /* Time in 24h format (w/o seconds) */ _("%H∶%M") :
|
||||
/* xgettext:no-c-format */ /* Time in 12h format (w/o seconds) */ _("%l∶%M %p"));
|
||||
} else if (timespan > 1 * TimeSpan.MINUTE) {
|
||||
ulong mins = (ulong) (timespan.abs() / TimeSpan.MINUTE);
|
||||
return n("%i min ago", "%i mins ago", mins).printf(mins);
|
||||
|
|
|
@ -2,7 +2,6 @@ using Gdk;
|
|||
using Gee;
|
||||
using Gtk;
|
||||
|
||||
using Xmpp;
|
||||
using Dino.Entities;
|
||||
|
||||
namespace Dino.Ui.ConversationSelector {
|
||||
|
@ -19,25 +18,16 @@ public class GroupchatPmRow : ConversationRow {
|
|||
update_avatar();
|
||||
}
|
||||
|
||||
public override void on_show_received(Show show) {
|
||||
update_avatar();
|
||||
}
|
||||
|
||||
public override void network_connection(bool connected) {
|
||||
if (!connected) {
|
||||
set_avatar((new AvatarGenerator(AVATAR_SIZE, AVATAR_SIZE, image.scale_factor)).set_greyscale(true).draw_conversation(stream_interactor, conversation), image.scale_factor);
|
||||
protected override void update_message_label() {
|
||||
base.update_message_label();
|
||||
if (last_message != null && last_message.direction == Message.DIRECTION_SENT) {
|
||||
nick_label.visible = true;
|
||||
nick_label.label = _("Me") + ": ";
|
||||
} else {
|
||||
update_avatar();
|
||||
nick_label.label = "";
|
||||
}
|
||||
}
|
||||
|
||||
public void update_avatar() {
|
||||
ArrayList<Jid> full_jids = stream_interactor.get_module(PresenceManager.IDENTITY).get_full_jids(conversation.counterpart, conversation.account);
|
||||
set_avatar((new AvatarGenerator(AVATAR_SIZE, AVATAR_SIZE, image.scale_factor))
|
||||
.set_greyscale(full_jids == null)
|
||||
.draw_conversation(stream_interactor, conversation), image.scale_factor);
|
||||
}
|
||||
|
||||
private Widget generate_tooltip() {
|
||||
Builder builder = new Builder.from_resource("/im/dino/conversation_selector/chat_row_tooltip.ui");
|
||||
Box main_box = builder.get_object("main_box") as Box;
|
||||
|
|
|
@ -10,36 +10,18 @@ public class GroupchatRow : ConversationRow {
|
|||
set_tooltip_text(conversation.counterpart.bare_jid.to_string());
|
||||
update_avatar();
|
||||
|
||||
x_button.clicked.connect(on_x_button_clicked);
|
||||
stream_interactor.get_module(MucManager.IDENTITY).left.connect(() => {
|
||||
Idle.add(() => {
|
||||
update_avatar();
|
||||
return false;
|
||||
});
|
||||
closed.connect(() => {
|
||||
stream_interactor.get_module(MucManager.IDENTITY).part(conversation.account, conversation.counterpart);
|
||||
});
|
||||
stream_interactor.get_module(MucManager.IDENTITY).left.connect(update_avatar);
|
||||
}
|
||||
|
||||
|
||||
public override void on_show_received(Show show) {
|
||||
set_avatar((new AvatarGenerator(AVATAR_SIZE, AVATAR_SIZE, image.scale_factor))
|
||||
.draw_conversation(stream_interactor, conversation), image.scale_factor);
|
||||
}
|
||||
|
||||
public override void network_connection(bool connected) {
|
||||
update_avatar();
|
||||
}
|
||||
|
||||
private void on_x_button_clicked() {
|
||||
stream_interactor.get_module(MucManager.IDENTITY).part(conversation.account, conversation.counterpart);
|
||||
}
|
||||
|
||||
private void update_avatar() {
|
||||
ConnectionManager.ConnectionState connection_state = stream_interactor.connection_manager.get_state(conversation.account);
|
||||
bool is_joined = stream_interactor.get_module(MucManager.IDENTITY).is_joined(conversation.counterpart, conversation.account);
|
||||
|
||||
set_avatar((new AvatarGenerator(AVATAR_SIZE, AVATAR_SIZE, image.scale_factor))
|
||||
.set_greyscale(connection_state != ConnectionManager.ConnectionState.CONNECTED || !is_joined)
|
||||
.draw_conversation(stream_interactor, conversation), image.scale_factor);
|
||||
protected override void update_message_label() {
|
||||
base.update_message_label();
|
||||
if (last_message != null) {
|
||||
nick_label.visible = true;
|
||||
nick_label.label = Util.get_message_display_name(stream_interactor, last_message, conversation.account) + ": ";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -48,16 +48,6 @@ public class List : ListBox {
|
|||
return false;
|
||||
});
|
||||
});
|
||||
stream_interactor.get_module(RosterManager.IDENTITY).updated_roster_item.connect((account, jid, roster_item) => {
|
||||
Idle.add(() => {
|
||||
Conversation? conversation = stream_interactor.get_module(ConversationManager.IDENTITY).get_conversation(jid, account);
|
||||
if (conversation != null && rows.has_key(conversation)) {
|
||||
ChatRow row = rows[conversation] as ChatRow;
|
||||
if (row != null) row.on_updated_roster_item(roster_item);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
});
|
||||
stream_interactor.get_module(AvatarManager.IDENTITY).received_avatar.connect((avatar, jid, account) => {
|
||||
Idle.add(() => {
|
||||
Conversation? conversation = stream_interactor.get_module(ConversationManager.IDENTITY).get_conversation(jid, account);
|
||||
|
@ -68,14 +58,6 @@ public class List : ListBox {
|
|||
return false;
|
||||
});
|
||||
});
|
||||
stream_interactor.connection_manager.connection_state_changed.connect((account, state) => {
|
||||
Idle.add(() => {
|
||||
foreach (ConversationRow row in rows.values) {
|
||||
if (row.conversation.account.equals(account)) row.network_connection(state == ConnectionManager.ConnectionState.CONNECTED);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
});
|
||||
Timeout.add_seconds(60, () => {
|
||||
foreach (ConversationRow row in rows.values) row.update();
|
||||
return true;
|
||||
|
|
Loading…
Reference in a new issue