return self->last_mentioned;
}
+const gchar *chime_room_get_last_read(ChimeRoom *self)
+{
+ g_return_val_if_fail(CHIME_IS_ROOM(self), NULL);
+
+ return self->last_read;
+}
+
+const gchar *chime_room_get_last_sent(ChimeRoom *self)
+{
+ g_return_val_if_fail(CHIME_IS_ROOM(self), NULL);
+
+ return self->last_sent;
+}
+
+const gchar *chime_room_get_created_on(ChimeRoom *self)
+{
+ g_return_val_if_fail(CHIME_IS_ROOM(self), NULL);
+
+ return self->created_on;
+}
+
+static gboolean cmp_time(const char *ev, const char *last_read)
+{
+ GTimeVal ev_time, read_time;
+
+ if (!ev || !g_time_val_from_iso8601(ev, &ev_time))
+ return FALSE;
+
+ if (!last_read || !g_time_val_from_iso8601(last_read, &read_time))
+ return TRUE;
+
+ return (ev_time.tv_sec > read_time.tv_sec ||
+ (ev_time.tv_sec == read_time.tv_sec && ev_time.tv_usec > read_time.tv_usec));
+}
+
+gboolean chime_room_has_mention(ChimeRoom *self)
+{
+ g_return_val_if_fail(CHIME_IS_ROOM(self), FALSE);
+
+ return cmp_time(self->last_mentioned, self->last_read);
+}
+
+gboolean chime_room_has_unread(ChimeRoom *self)
+{
+ g_return_val_if_fail(CHIME_IS_ROOM(self), FALSE);
+
+ return cmp_time(self->last_sent, self->last_read);
+}
+
+
static gboolean parse_privacy(JsonNode *node, const gchar *member, gboolean *val)
{
const gchar *str;
chime_call_set_silent(chat->call, FALSE);
}
+static void leave_room_cb(GObject *source, GAsyncResult *result, gpointer _chat)
+{
+ struct chime_chat *chat = _chat;
+ ChimeConnection *cxn = CHIME_CONNECTION(source);
+ GError *error = NULL;
+
+ if (!chime_connection_remove_room_member_finish(cxn, result, &error)) {
+ purple_conversation_write(chat->conv, NULL, error->message,
+ PURPLE_MESSAGE_ERROR, time(NULL));
+ }
+ /* If it succeeds, that's self-evident. */
+}
+
+static void leave_room(PurpleBuddy *buddy, gpointer _chat)
+{
+ struct chime_chat *chat = _chat;
+ ChimeConnection *cxn = PURPLE_CHIME_CXN(chat->conv->account->gc);
+ ChimeRoom *room = CHIME_ROOM(chat->m.obj);
+ ChimeContact *me = chime_connection_contact_by_id(cxn,
+ chime_connection_get_profile_id(cxn));
+
+ chime_connection_remove_room_member_async(cxn, room, me, NULL, leave_room_cb, chat);
+}
+
GList *chime_purple_chat_menu(PurpleChat *pchat)
{
items = g_list_append(items,
purple_menu_action_new(_("Share screen..."),
PURPLE_CALLBACK(select_screen_share), chat, NULL));
+ } else if (CHIME_IS_ROOM(chat->m.obj)) {
+ items = g_list_append(items,
+ purple_menu_action_new(_("Leave room"),
+ PURPLE_CALLBACK(leave_room), chat, NULL));
}
return items;
#include <libsoup/soup.h>
-static void add_room_to_list(ChimeConnection *cxn, ChimeRoom *room, gpointer _roomlist)
+struct room_sort {
+ struct room_sort *next;
+ gboolean unread;
+ gboolean mention;
+ GTimeVal when;
+ ChimeRoom *room;
+};
+
+static gboolean cmp_room(struct room_sort *a, struct room_sort *b)
{
- PurpleRoomlist *roomlist = _roomlist;
-
- PurpleRoomlistRoom *proom = purple_roomlist_room_new(PURPLE_ROOMLIST_ROOMTYPE_ROOM,
- chime_room_get_name(room), NULL);
- purple_roomlist_room_add_field(roomlist, proom, chime_room_get_id(room));
- purple_roomlist_room_add_field(roomlist, proom, GUINT_TO_POINTER(chime_room_get_visibility(room)));
- purple_roomlist_room_add_field(roomlist, proom, GUINT_TO_POINTER(chime_room_get_privacy(room)));
- purple_roomlist_room_add(roomlist, proom);
+ if (a->mention != b->mention)
+ return a->mention;
+ if (a->unread != b->unread)
+ return a->unread;
+ if (a->when.tv_sec > b->when.tv_sec)
+ return TRUE;
+ if (a->when.tv_sec == b->when.tv_sec &&
+ a->when.tv_usec > b->when.tv_sec)
+ return TRUE;
+ return FALSE;
+}
+
+static void sort_room(ChimeConnection *cxn, ChimeRoom *room, gpointer _rs_list)
+{
+ struct room_sort **rs_list = _rs_list;
+ struct room_sort *rs = g_new0(struct room_sort, 1);
+ const char *tm;
+
+ rs->room = room;
+ rs->unread = chime_room_has_unread(room);
+ rs->mention = chime_room_has_mention(room);
+
+ tm = chime_room_get_last_sent(room);
+ if (!tm || !g_time_val_from_iso8601(tm, &rs->when)) {
+ tm = chime_room_get_created_on(room);
+ if (tm)
+ g_time_val_from_iso8601(tm, &rs->when);
+ }
+ while (*rs_list && cmp_room(*rs_list, rs))
+ rs_list = &((*rs_list)->next);
+ rs->next = *rs_list;
+ *rs_list = rs;
}
PurpleRoomlist *chime_purple_roomlist_get_list(PurpleConnection *conn)
{
ChimeConnection *cxn = PURPLE_CHIME_CXN(conn);
PurpleRoomlist *roomlist;
+ struct room_sort *rooms = NULL, *tmp_rs;
GList *fields = NULL;
roomlist = purple_roomlist_new(conn->account);
fields = g_list_append(fields, purple_roomlist_field_new(PURPLE_ROOMLIST_FIELD_STRING, "", "RoomId", TRUE));
- fields = g_list_append(fields, purple_roomlist_field_new(PURPLE_ROOMLIST_FIELD_BOOL, _("Visible"), "Visibility", FALSE));
- fields = g_list_append(fields, purple_roomlist_field_new(PURPLE_ROOMLIST_FIELD_BOOL, _("Private"), "Privacy", FALSE));
+ fields = g_list_append(fields, purple_roomlist_field_new(PURPLE_ROOMLIST_FIELD_STRING, _("Status"), "Status", FALSE));
+ fields = g_list_append(fields, purple_roomlist_field_new(PURPLE_ROOMLIST_FIELD_STRING, _("Last Sent"), "Last Sent", FALSE));
purple_roomlist_set_fields(roomlist, fields);
- chime_connection_foreach_room(cxn, add_room_to_list, roomlist);
+ chime_connection_foreach_room(cxn, sort_room, &rooms);
+
+ while (rooms) {
+ ChimeRoom *room = rooms->room;
+ PurpleRoomlistRoom *proom = purple_roomlist_room_new(PURPLE_ROOMLIST_ROOMTYPE_ROOM,
+ chime_room_get_name(room), NULL);
+ purple_roomlist_room_add_field(roomlist, proom, chime_room_get_id(room));
+ purple_roomlist_room_add_field(roomlist, proom, rooms->mention ? "@" : (rooms->unread ? "•" : ""));
+ purple_roomlist_room_add_field(roomlist, proom, chime_room_get_last_sent(room) ? : chime_room_get_created_on(room));
+ purple_roomlist_room_add(roomlist, proom);
+ tmp_rs = rooms;
+ rooms = rooms->next;
+ g_free(tmp_rs);
+ }
purple_roomlist_set_in_progress(roomlist, FALSE);
return roomlist;