diff --git a/po/POTFILES.in b/po/POTFILES.in index 08af6977ac43e868fb8a27dc41941f46ed269c95..746b003ad6c184536acf18d3cec1461001654cec 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -9,6 +9,7 @@ src/chatty-chat-list.c src/chatty-chat-view.c src/chatty-chat.c src/chatty-chat.h +src/chatty-contact-list.c src/chatty-contact-provider.c src/chatty-contact-provider.h src/chatty-history.c diff --git a/src/chatty-application.c b/src/chatty-application.c index 4e97115bd29f2a806aafb6f4fac0772ffd9c627a..ef3ea0f3d94b8834519d6cb1afe0145a38b361d8 100644 --- a/src/chatty-application.c +++ b/src/chatty-application.c @@ -111,7 +111,7 @@ application_open_uri (ChattyApplication *self) CHATTY_INFO (self->uri, "Opening uri:"); if (self->main_window && self->uri) - chatty_window_set_uri (CHATTY_WINDOW (self->main_window), self->uri); + chatty_window_set_uri (CHATTY_WINDOW (self->main_window), self->uri, NULL); g_clear_pointer (&self->uri, g_free); diff --git a/src/chatty-contact-list.c b/src/chatty-contact-list.c new file mode 100644 index 0000000000000000000000000000000000000000..a8681435d27d42fe942e6bc5ea0eaaac5dbe325d --- /dev/null +++ b/src/chatty-contact-list.c @@ -0,0 +1,509 @@ +/* + * Copyright (C) 2022 Purism SPC + * + * Authors: + * Mohammed Sadiq + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +#define G_LOG_DOMAIN "chatty-contact-list" + +#include "config.h" + +#include +#include "contrib/gtk.h" + +#include "chatty-chat.h" +#include "chatty-purple.h" +#include "chatty-list-row.h" +#include "chatty-manager.h" +#include "chatty-contact-list.h" + +#define ITEMS_COUNT 50 + +struct _ChattyContactList +{ + GtkBox parent_instance; + + GtkWidget *scrolled_window; + GtkWidget *main_stack; + GtkWidget *empty_view; + GtkWidget *contact_list_view; + + GtkWidget *selected_contact_list; + GtkWidget *new_contact_list; + GtkWidget *new_contact_row; + GtkWidget *contact_list; + + ChattyItem *dummy_contact; + GListStore *selection_store; + GtkSliceListModel *slice_model; + GtkFilter *filter; + char *search_str; + + ChattyManager *manager; + + ChattyProtocol active_protocols; + ChattyProtocol filter_protocols; + gboolean can_multi_select; +}; + +G_DEFINE_TYPE (ChattyContactList, chatty_contact_list, GTK_TYPE_BOX) + +enum { + DELETE_ROW, + SELECTION_CHANGED, + N_SIGNALS +}; + +static guint signals[N_SIGNALS]; + +static GtkWidget * +new_chat_contact_row_new (ChattyItem *item, + ChattyContactList *self) +{ + GtkWidget *row; + + row = chatty_list_contact_row_new (item); + chatty_list_row_set_selectable (CHATTY_LIST_ROW (row), self->can_multi_select); + + return row; +} + +static GtkWidget * +new_selected_contact_row_new (ChattyItem *item, + ChattyContactList *self) +{ + GtkWidget *row; + + row = new_chat_contact_row_new (item, self); + chatty_list_row_select (CHATTY_LIST_ROW (row), TRUE); + + if (!gtk_widget_is_visible (self->contact_list)) + chatty_list_row_show_delete_button (CHATTY_LIST_ROW (row)); + + return row; +} + +static gboolean +new_chat_dialog_contact_is_selected (ChattyContact *contact) +{ + g_return_val_if_fail (CHATTY_IS_CONTACT (contact), FALSE); + + return !!g_object_get_data (G_OBJECT (contact), "selected"); +} + +static void +update_new_contact_row (ChattyContactList *self) +{ + const char *dummy_value; + guint end_len, n_items; + gboolean valid = FALSE; + + chatty_contact_set_value (CHATTY_CONTACT (self->dummy_contact), self->search_str); + chatty_list_row_set_item (CHATTY_LIST_ROW (self->new_contact_row), self->dummy_contact); + + if (!self->search_str || !*self->search_str || + !(self->active_protocols & CHATTY_PROTOCOL_MMS_SMS)) { + gtk_widget_hide (self->new_contact_row); + return; + } + + end_len = strspn (self->search_str, "0123456789"); + valid = end_len == strlen (self->search_str); + valid = valid || !!chatty_utils_username_is_valid (self->search_str, CHATTY_PROTOCOL_MMS_SMS); + gtk_widget_set_visible (self->new_contact_row, valid); + + if (!self->can_multi_select) + return; + + dummy_value = chatty_item_get_username (self->dummy_contact); + n_items = g_list_model_get_n_items (G_LIST_MODEL (self->selection_store)); + + /* If new custom contact row match any of the selected contact, hide it */ + for (guint i = 0; i < n_items; i++) { + g_autoptr(ChattyItem) item = NULL; + const char *value; + + item = g_list_model_get_item (G_LIST_MODEL (self->selection_store), i); + value = chatty_item_get_username (item); + + if (g_strcmp0 (value, dummy_value) == 0) { + gtk_widget_hide (self->new_contact_row); + break; + } + } +} + +static gboolean +contact_list_filter_item_cb (ChattyItem *item, + ChattyContactList *self) +{ + ChattyAccount *account; + ChattyProtocol protocols; + + g_return_val_if_fail (CHATTY_IS_CONTACT_LIST (self), FALSE); + + if (self->can_multi_select) { + account = chatty_manager_get_mm_account (self->manager); + + if (chatty_account_get_status (account) == CHATTY_CONNECTED) { + /* Show only non-selected items, selected items are shown elsewhere */ + if (CHATTY_IS_CONTACT (item) && + !new_chat_dialog_contact_is_selected (CHATTY_CONTACT (item)) && + chatty_item_matches (item, self->search_str, CHATTY_PROTOCOL_MMS_SMS, TRUE)) + return TRUE; + } + + return FALSE; + } + +#ifdef PURPLE_ENABLED + if (CHATTY_IS_PP_BUDDY (item)) { + account = chatty_pp_buddy_get_account (CHATTY_PP_BUDDY (item)); + + if (chatty_account_get_status (account) != CHATTY_CONNECTED) + return FALSE; + } +#endif + + if (CHATTY_IS_CHAT (item)) { +#ifdef PURPLE_ENABLED + /* Hide chat if it's buddy chat as the buddy is shown separately */ + if (CHATTY_IS_PP_CHAT (item) && + chatty_pp_chat_get_purple_buddy (CHATTY_PP_CHAT (item))) + return FALSE; +#endif + + account = chatty_chat_get_account (CHATTY_CHAT (item)); + + if (!account || chatty_account_get_status (account) != CHATTY_CONNECTED) + return FALSE; + } + + protocols = self->active_protocols & self->filter_protocols; + + return chatty_item_matches (item, self->search_str, protocols, TRUE); +} + +static void +contact_list_edge_reached_cb (ChattyContactList *self, + GtkPositionType position) +{ + g_assert (CHATTY_IS_CONTACT_LIST (self)); + + if (position != GTK_POS_BOTTOM || + gtk_stack_get_visible_child (GTK_STACK (self->main_stack)) != self->contact_list_view) + return; + + gtk_slice_list_model_set_size (self->slice_model, + gtk_slice_list_model_get_size (self->slice_model) + ITEMS_COUNT); +} + +static void +selected_contact_row_activated_cb (ChattyContactList *self, + ChattyListRow *row, + GtkListBox *list) +{ + ChattyItem *item; + + item = chatty_list_row_get_item (row); + g_object_set_data (G_OBJECT (item), "selected", GINT_TO_POINTER (FALSE)); + + if (chatty_contact_is_dummy (CHATTY_CONTACT (item))) { + /* If the deselected item value matches the search string, show new contact row */ + if (self->search_str && + g_strcmp0 (chatty_item_get_username (item), self->search_str) == 0) + gtk_widget_show (self->new_contact_row); + } else { + guint position; + + /* Emit items-changed so that it will be re-filtered and thus shown as it's no longer selected */ + if (chatty_utils_get_item_position (chatty_manager_get_contact_list (self->manager), item, &position)) + g_list_model_items_changed (chatty_manager_get_contact_list (self->manager), position, 1, 1); + } + + chatty_utils_remove_list_item (self->selection_store, item); + g_signal_emit (self, signals[SELECTION_CHANGED], 0); +} + +static void +contact_list_row_activated_cb (ChattyContactList *self, + ChattyListRow *row, + GtkListBox *list) +{ + ChattyItem *item; + + g_assert (CHATTY_IS_CONTACT_LIST (self)); + g_assert (CHATTY_IS_LIST_ROW (row)); + g_assert (GTK_IS_LIST_BOX (list)); + g_assert (self->selection_store); + + item = chatty_list_row_get_item (row); + if (CHATTY_IS_CONTACT (item) && chatty_contact_is_dummy (CHATTY_CONTACT (item))) { + g_autoptr(ChattyContact) contact = NULL; + + contact = chatty_contact_dummy_new (_("Unknown Contact"), + chatty_item_get_username (item)); + g_list_store_append (self->selection_store, contact); + } else { + g_object_set_data (G_OBJECT (item), "selected", GINT_TO_POINTER (TRUE)); + g_list_store_append (self->selection_store, item); + } + + if (self->can_multi_select) + gtk_widget_hide (GTK_WIDGET (row)); + + g_signal_emit (self, signals[SELECTION_CHANGED], 0); +} + +static void +contact_list_changed_cb (ChattyContactList *self) +{ + HdyStatusPage *page; + gboolean empty; + + g_assert (CHATTY_IS_CONTACT_LIST (self)); + + empty = !gtk_widget_get_visible (self->new_contact_row); + empty = empty && g_list_model_get_n_items (G_LIST_MODEL (self->slice_model)) == 0; + if (self->selection_store) + empty = empty && g_list_model_get_n_items (G_LIST_MODEL (self->selection_store)) == 0; + + if (empty) + gtk_stack_set_visible_child (GTK_STACK (self->main_stack), self->empty_view); + else + gtk_stack_set_visible_child (GTK_STACK (self->main_stack), self->contact_list_view); + + page = HDY_STATUS_PAGE (self->empty_view); + if (self->search_str && *self->search_str) { + hdy_status_page_set_icon_name (page, "system-search-symbolic"); + hdy_status_page_set_title (page, _("No Search Results")); + hdy_status_page_set_description (page, _("Try different search, or type a valid " + "number to create new chat")); + } else { + hdy_status_page_set_icon_name (page, "sm.puri.Chatty-symbolic"); + hdy_status_page_set_title (page, _("No Contacts")); + hdy_status_page_set_description (page, NULL); + } +} + +static void +contact_list_active_protocols_changed_cb (ChattyContactList *self) +{ + ChattyAccount *mm_account; + ChattyProtocol protocol; + gboolean valid; + + g_assert (CHATTY_IS_CONTACT_LIST (self)); + + self->active_protocols = chatty_manager_get_active_protocols (self->manager); + gtk_filter_changed (self->filter, GTK_FILTER_CHANGE_DIFFERENT); + + protocol = CHATTY_PROTOCOL_MMS_SMS; + valid = protocol == chatty_utils_username_is_valid (self->search_str, protocol); + mm_account = chatty_manager_get_mm_account (self->manager); + valid = valid && chatty_account_get_status (mm_account) == CHATTY_CONNECTED; + gtk_widget_set_visible (self->new_contact_row, valid); + contact_list_changed_cb (self); +} + +static void +contact_list_delete_item (ChattyContactList *self, + ChattyListRow *row) +{ + g_assert (CHATTY_IS_CONTACT_LIST (self)); + g_assert (CHATTY_IS_LIST_ROW (row)); + + selected_contact_row_activated_cb (self, row, GTK_LIST_BOX (self->selected_contact_list)); +} + +static void +chatty_contact_list_finalize (GObject *object) +{ + ChattyContactList *self = (ChattyContactList *)object; + + g_clear_object (&self->dummy_contact); + g_clear_object (&self->slice_model); + g_clear_object (&self->selection_store); + g_clear_object (&self->filter); + g_clear_object (&self->manager); + g_free (self->search_str); + + G_OBJECT_CLASS (chatty_contact_list_parent_class)->finalize (object); +} + +static void +chatty_contact_list_class_init (ChattyContactListClass *klass) +{ + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = chatty_contact_list_finalize; + + signals [DELETE_ROW] = + g_signal_new ("delete-row", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, NULL, NULL, NULL, + G_TYPE_NONE, 1, CHATTY_TYPE_LIST_ROW); + + signals [SELECTION_CHANGED] = + g_signal_new ("selection-changed", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, NULL, NULL, NULL, + G_TYPE_NONE, 0); + + gtk_widget_class_set_template_from_resource (widget_class, + "/sm/puri/Chatty/" + "ui/chatty-contact-list.ui"); + + gtk_widget_class_bind_template_child (widget_class, ChattyContactList, scrolled_window); + gtk_widget_class_bind_template_child (widget_class, ChattyContactList, main_stack); + gtk_widget_class_bind_template_child (widget_class, ChattyContactList, empty_view); + gtk_widget_class_bind_template_child (widget_class, ChattyContactList, contact_list_view); + + gtk_widget_class_bind_template_child (widget_class, ChattyContactList, selected_contact_list); + gtk_widget_class_bind_template_child (widget_class, ChattyContactList, new_contact_list); + gtk_widget_class_bind_template_child (widget_class, ChattyContactList, new_contact_row); + gtk_widget_class_bind_template_child (widget_class, ChattyContactList, contact_list); + + gtk_widget_class_bind_template_callback (widget_class, contact_list_edge_reached_cb); + gtk_widget_class_bind_template_callback (widget_class, selected_contact_row_activated_cb); + gtk_widget_class_bind_template_callback (widget_class, contact_list_row_activated_cb); + gtk_widget_class_bind_template_callback (widget_class, contact_list_changed_cb); +} + +static void +chatty_contact_list_init (ChattyContactList *self) +{ + g_autoptr(GtkFilterListModel) filter_model = NULL; + g_autoptr(GtkSortListModel) sort_model = NULL; + g_autoptr(GtkSorter) sorter = NULL; + + gtk_widget_init_template (GTK_WIDGET (self)); + + self->manager = g_object_ref (chatty_manager_get_default ()); + self->filter_protocols = CHATTY_PROTOCOL_ANY; + + self->dummy_contact = CHATTY_ITEM (chatty_contact_dummy_new (_("Send To"), NULL)); + chatty_list_row_set_item (CHATTY_LIST_ROW (self->new_contact_row), self->dummy_contact); + + sorter = gtk_custom_sorter_new ((GCompareDataFunc)chatty_item_compare, NULL, NULL); + sort_model = gtk_sort_list_model_new (chatty_manager_get_contact_list (self->manager), sorter); + + self->filter = gtk_custom_filter_new ((GtkCustomFilterFunc)contact_list_filter_item_cb, self, NULL); + filter_model = gtk_filter_list_model_new (G_LIST_MODEL (sort_model), self->filter); + + self->slice_model = gtk_slice_list_model_new (G_LIST_MODEL (filter_model), 0, ITEMS_COUNT); + g_signal_connect_object (self->slice_model, "items-changed", + G_CALLBACK (contact_list_changed_cb), self, + G_CONNECT_SWAPPED); + gtk_list_box_bind_model (GTK_LIST_BOX (self->contact_list), + G_LIST_MODEL (self->slice_model), + (GtkListBoxCreateWidgetFunc)new_chat_contact_row_new, + g_object_ref (self), g_object_unref); + g_signal_connect_object (self->manager, "notify::active-protocols", + G_CALLBACK (contact_list_active_protocols_changed_cb), self, G_CONNECT_SWAPPED); + g_signal_connect_object (self, "delete-row", + G_CALLBACK (contact_list_delete_item), + self, G_CONNECT_AFTER); + contact_list_active_protocols_changed_cb (self); + contact_list_changed_cb (self); +} + +GtkWidget * +chatty_contact_list_new (void) +{ + return g_object_new (CHATTY_TYPE_CONTACT_LIST, NULL); +} + +void +chatty_contact_list_set_selection_store (ChattyContactList *self, + GListStore *list_store) +{ + g_return_if_fail (CHATTY_IS_CONTACT_LIST (self)); + g_return_if_fail (G_IS_LIST_STORE (list_store)); + g_return_if_fail (g_list_model_get_item_type (G_LIST_MODEL (list_store)) == CHATTY_TYPE_ITEM); + + g_set_object (&self->selection_store, list_store); + + gtk_list_box_bind_model (GTK_LIST_BOX (self->selected_contact_list), + (gpointer) list_store, + (GtkListBoxCreateWidgetFunc)new_selected_contact_row_new, + g_object_ref (self), g_object_unref); + g_signal_connect_object (list_store, "items-changed", + G_CALLBACK (contact_list_changed_cb), self, + G_CONNECT_SWAPPED); +} + +void +chatty_contact_list_show_selected_only (ChattyContactList *self) +{ + g_return_if_fail (CHATTY_IS_CONTACT_LIST (self)); + + gtk_stack_set_visible_child (GTK_STACK (self->main_stack), self->contact_list_view); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (self->scrolled_window), + GTK_POLICY_NEVER, GTK_POLICY_NEVER); + gtk_widget_hide (self->new_contact_row); + gtk_widget_hide (self->contact_list); +} + +static void +contact_list_update_selectable (GtkWidget *widget, + gpointer callback_data) +{ + ChattyContactList *self = callback_data; + + g_assert (CHATTY_IS_CONTACT_LIST (self)); + + chatty_list_row_set_selectable ((ChattyListRow *)widget, self->can_multi_select); +} + +void +chatty_contact_list_can_multi_select (ChattyContactList *self, + gboolean can_multi_select) +{ + GListModel *model; + guint n_items; + + g_return_if_fail (CHATTY_IS_CONTACT_LIST (self)); + g_return_if_fail (self->selection_store); + + self->can_multi_select = !!can_multi_select; + + gtk_widget_set_visible (self->selected_contact_list, can_multi_select); + chatty_list_row_set_selectable (CHATTY_LIST_ROW (self->new_contact_row), can_multi_select); + gtk_container_foreach (GTK_CONTAINER (self->contact_list), + (GtkCallback)contact_list_update_selectable, self); + + model = G_LIST_MODEL (self->selection_store); + n_items = g_list_model_get_n_items (model); + + for (guint i = 0; i < n_items; i++) { + g_autoptr(GObject) item = NULL; + + item = g_list_model_get_item (model, i); + g_object_set_data (item, "selected", GINT_TO_POINTER (FALSE)); + } + + g_list_store_remove_all (self->selection_store); +} + +void +chatty_contact_list_set_filter (ChattyContactList *self, + ChattyProtocol protocol, + const char *needle) +{ + g_return_if_fail (CHATTY_IS_CONTACT_LIST (self)); + + self->filter_protocols = protocol; + g_free (self->search_str); + self->search_str = g_utf8_casefold (needle, -1); + + update_new_contact_row (self); + gtk_slice_list_model_set_size (self->slice_model, ITEMS_COUNT); + gtk_filter_changed (self->filter, GTK_FILTER_CHANGE_DIFFERENT); +} diff --git a/src/chatty-contact-list.h b/src/chatty-contact-list.h new file mode 100644 index 0000000000000000000000000000000000000000..0b25a2e6c501f0afac25eaebf5f98dd2bdb9fd9a --- /dev/null +++ b/src/chatty-contact-list.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2022 Purism SPC + * + * Authors: + * Mohammed Sadiq + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +#pragma once + +#include + +#include "chatty-enums.h" + +G_BEGIN_DECLS + +#define CHATTY_TYPE_CONTACT_LIST (chatty_contact_list_get_type ()) + +G_DECLARE_FINAL_TYPE (ChattyContactList, chatty_contact_list, CHATTY, CONTACT_LIST, GtkBox) + +GtkWidget *chatty_contact_list_new (void); +void chatty_contact_list_set_selection_store (ChattyContactList *self, + GListStore *list_store); +void chatty_contact_list_show_selected_only (ChattyContactList *self); +void chatty_contact_list_can_multi_select (ChattyContactList *self, + gboolean can_multi_select); +void chatty_contact_list_set_filter (ChattyContactList *self, + ChattyProtocol protocol, + const char *needle); + +G_END_DECLS diff --git a/src/chatty-list-row.c b/src/chatty-list-row.c index e610e1e64b4440c91754d156ecea23d64be67f62..2a7fb0e49998d34f011b9fc9df11bd85096efdd6 100644 --- a/src/chatty-list-row.c +++ b/src/chatty-list-row.c @@ -18,6 +18,7 @@ #include "chatty-purple.h" #include "chatty-contact.h" +#include "chatty-contact-list.h" #include "chatty-chat.h" #include "chatty-avatar.h" #include "chatty-list-row.h" @@ -39,6 +40,7 @@ struct _ChattyListRow GtkWidget *last_modified; GtkWidget *unread_message_count; GtkWidget *checkbox; + GtkWidget *close_button; GtkWidget *add_contact_button; GtkWidget *call_button; @@ -382,6 +384,24 @@ write_eds_contact_cb (GObject *object, } } +static void +chatty_list_row_delete_clicked_cb (ChattyListRow *self) +{ + GtkWidget *scrolled, *list; + + g_assert (CHATTY_IS_LIST_ROW (self)); + + /* We can't directly use CHATTY_TYPE_CONTACT_LIST as it's not linked with the shared library */ + scrolled = gtk_widget_get_ancestor (GTK_WIDGET (self), GTK_TYPE_SCROLLED_WINDOW); + + if (!scrolled) + return; + + list = gtk_widget_get_parent (scrolled); + if (list) + g_signal_emit_by_name (list, "delete-row", self); +} + static void chatty_list_row_add_contact_clicked_cb (ChattyListRow *self) { @@ -434,6 +454,7 @@ chatty_list_row_class_init (ChattyListRowClass *klass) "ui/chatty-list-row.ui"); gtk_widget_class_bind_template_child (widget_class, ChattyListRow, avatar); gtk_widget_class_bind_template_child (widget_class, ChattyListRow, checkbox); + gtk_widget_class_bind_template_child (widget_class, ChattyListRow, close_button); gtk_widget_class_bind_template_child (widget_class, ChattyListRow, title); gtk_widget_class_bind_template_child (widget_class, ChattyListRow, subtitle); gtk_widget_class_bind_template_child (widget_class, ChattyListRow, last_modified); @@ -441,6 +462,7 @@ chatty_list_row_class_init (ChattyListRowClass *klass) gtk_widget_class_bind_template_child (widget_class, ChattyListRow, add_contact_button); gtk_widget_class_bind_template_child (widget_class, ChattyListRow, call_button); + gtk_widget_class_bind_template_callback (widget_class, chatty_list_row_delete_clicked_cb); gtk_widget_class_bind_template_callback (widget_class, chatty_list_row_add_contact_clicked_cb); gtk_widget_class_bind_template_callback (widget_class, chatty_list_row_call_button_clicked_cb); } @@ -560,3 +582,12 @@ chatty_list_row_set_call (ChattyListRow *self, gboolean enable) } else gtk_widget_hide (self->call_button); } + +void +chatty_list_row_show_delete_button (ChattyListRow *self) +{ + g_return_if_fail (CHATTY_IS_LIST_ROW (self)); + + gtk_widget_show (self->close_button); + gtk_widget_hide (self->checkbox); +} diff --git a/src/chatty-list-row.h b/src/chatty-list-row.h index b4f40d2c4c6273b491695290bd012ad9698bc145..b826549ed8813d7660dd72e43181439001de2df7 100644 --- a/src/chatty-list-row.h +++ b/src/chatty-list-row.h @@ -32,5 +32,6 @@ void chatty_list_row_set_contact (ChattyListRow *self, gboolean enable); void chatty_list_row_set_call (ChattyListRow *self, gboolean enable); +void chatty_list_row_show_delete_button (ChattyListRow *self); G_END_DECLS diff --git a/src/chatty-manager.c b/src/chatty-manager.c index ae7572a8bd40399c1da91189cc273e5df677557b..3868ecb064df89cea54be15d00af314e95618ebc 100644 --- a/src/chatty-manager.c +++ b/src/chatty-manager.c @@ -701,7 +701,8 @@ chatty_manager_find_chat_with_name (ChattyManager *self, gboolean chatty_manager_set_uri (ChattyManager *self, - const char *uri) + const char *uri, + const char *name) { g_autoptr(ChattySmsUri) sms_uri = NULL; ChattyAccount *account; @@ -731,6 +732,7 @@ chatty_manager_set_uri (ChattyManager *self, } chat = chatty_mm_account_start_chat_with_uri (CHATTY_MM_ACCOUNT (account), sms_uri); + chatty_item_set_name (CHATTY_ITEM (chat), name); g_signal_emit (self, signals[OPEN_CHAT], 0, chat); diff --git a/src/chatty-manager.h b/src/chatty-manager.h index 3f8b777b349eeaa364cdf4da1ed413cc203eac1c..47e690ae941df948209a30705b25c18e04b7e8fd 100644 --- a/src/chatty-manager.h +++ b/src/chatty-manager.h @@ -61,7 +61,8 @@ ChattyChat *chatty_manager_find_chat_with_name (ChattyManager *self, const char *chat_id); ChattyAccount *chatty_manager_get_mm_account (ChattyManager *self); gboolean chatty_manager_set_uri (ChattyManager *self, - const char *uri); + const char *uri, + const char *name); ChattyHistory *chatty_manager_get_history (ChattyManager *self); G_END_DECLS diff --git a/src/chatty-window.c b/src/chatty-window.c index 7a72eea73722583750b5fb3cc6dfa9ee4b7bd10c..06986d5b424495970d7a8d9dbc4ad600ccecdef5 100644 --- a/src/chatty-window.c +++ b/src/chatty-window.c @@ -140,7 +140,7 @@ chatty_window_open_item (ChattyWindow *self, const char *number; number = chatty_item_get_username (item); - chatty_window_set_uri (self, number); + chatty_window_set_uri (self, number, NULL); return; } @@ -268,77 +268,28 @@ notify_fold_cb (ChattyWindow *self) } static void -window_new_message_clicked_cb (ChattyWindow *self) +window_show_new_chat_dialog (ChattyWindow *self, + gboolean can_multi_select) { ChattyNewChatDialog *dialog; - ChattyItem *item; - const char *phone_number = NULL; - gint response; g_assert (CHATTY_IS_WINDOW (self)); dialog = CHATTY_NEW_CHAT_DIALOG (self->new_chat_dialog); - chatty_new_chat_dialog_set_multi_selection (dialog, FALSE); - - response = gtk_dialog_run (GTK_DIALOG (self->new_chat_dialog)); - gtk_widget_hide (self->new_chat_dialog); - - if (response != GTK_RESPONSE_OK) - return; - - item = chatty_new_chat_dialog_get_selected_item (dialog); - - if (CHATTY_IS_CONTACT (item) && - chatty_contact_is_dummy (CHATTY_CONTACT (item))) - phone_number = chatty_item_get_username (item); + chatty_new_chat_dialog_set_multi_selection (dialog, can_multi_select); + gtk_window_present (GTK_WINDOW (self->new_chat_dialog)); +} - if (phone_number) - chatty_window_set_uri (self, phone_number); - else if (item) - chatty_window_open_item (self, item); - else - g_return_if_reached (); +static void +window_new_message_clicked_cb (ChattyWindow *self) +{ + window_show_new_chat_dialog (self, FALSE); } static void window_new_sms_mms_message_clicked_cb (ChattyWindow *self) { - g_autoptr(GString) sendlist = g_string_new (NULL); - ChattyNewChatDialog *dialog; - GPtrArray *items; - gint response; - - g_assert (CHATTY_IS_WINDOW (self)); - - dialog = CHATTY_NEW_CHAT_DIALOG (self->new_chat_dialog); - chatty_new_chat_dialog_set_multi_selection (dialog, TRUE); - - response = gtk_dialog_run (GTK_DIALOG (self->new_chat_dialog)); - gtk_widget_hide (self->new_chat_dialog); - - if (response != GTK_RESPONSE_OK) - return; - - items = chatty_new_chat_dialog_get_selected_items (dialog); - - for (guint i = 0; i < items->len; i++) { - const char *phone_number; - ChattyItem *item; - - item = items->pdata[i]; - - if (CHATTY_IS_CONTACT (item)) { - phone_number = chatty_item_get_username (item); - sendlist = g_string_append (sendlist, phone_number); - g_string_append (sendlist, ","); - } - } - - /* Remove the trailing "," */ - if (sendlist->len >= 1) - g_string_truncate (sendlist, sendlist->len - 1); - - chatty_window_set_uri (self, sendlist->str); + window_show_new_chat_dialog (self, TRUE); } static void @@ -615,6 +566,54 @@ protocol_list_header_func (GtkListBoxRow *row, } } +static void +new_chat_selection_changed_cb (ChattyWindow *self, + ChattyNewChatDialog *dialog) +{ + g_autoptr(GString) users = g_string_new (NULL); + GListModel *model; + guint n_items; + const char *name; + + g_assert (CHATTY_IS_WINDOW (self)); + g_assert (CHATTY_IS_NEW_CHAT_DIALOG (dialog)); + + model = chatty_new_chat_dialog_get_selected_items (dialog); + n_items = g_list_model_get_n_items (model); + + if (n_items == 0) + return; + + for (guint i = 0; i < n_items; i++) { + g_autoptr(ChattyItem) item = NULL; + const char *phone_number; + + item = g_list_model_get_item (model, i); + + if (CHATTY_IS_CONTACT (item)) { + phone_number = chatty_item_get_username (item); + g_string_append (users, phone_number); + g_string_append (users, ","); + } + } + + /* Remove the trailing "," */ + if (users->len >= 1) + g_string_truncate (users, users->len - 1); + + if (n_items == 1) { + g_autoptr(ChattyItem) item = NULL; + + item = g_list_model_get_item (model, 0); + + if (!CHATTY_IS_CONTACT (item) || + !chatty_contact_is_dummy (CHATTY_CONTACT (item))) + chatty_window_open_item (self, item); + } + + name = chatty_new_chat_dialog_get_chat_title (dialog); + chatty_window_set_uri (self, users->str, name); +} static void chatty_window_unmap (GtkWidget *widget) @@ -671,6 +670,10 @@ chatty_window_constructed (GObject *object) gtk_window_maximize (window); self->new_chat_dialog = chatty_new_chat_dialog_new (GTK_WINDOW (self)); + g_signal_connect_object (self->new_chat_dialog, "selection-changed", + G_CALLBACK (new_chat_selection_changed_cb), + self, + G_CONNECT_SWAPPED); self->chat_info_dialog = chatty_info_dialog_new (GTK_WINDOW (self)); G_OBJECT_CLASS (chatty_window_parent_class)->constructed (object); @@ -829,9 +832,10 @@ chatty_window_new (GtkApplication *application) void chatty_window_set_uri (ChattyWindow *self, - const char *uri) + const char *uri, + const char *name) { - if (!chatty_manager_set_uri (self->manager, uri)) + if (!chatty_manager_set_uri (self->manager, uri, name)) return; gtk_widget_hide (self->new_chat_dialog); diff --git a/src/chatty-window.h b/src/chatty-window.h index 7420292b6ece3063eda0d71d3ac7c98a5b4be7a7..25122d72387cb0856fe8d3d80c92e99a95f50026 100644 --- a/src/chatty-window.h +++ b/src/chatty-window.h @@ -20,7 +20,8 @@ G_DECLARE_FINAL_TYPE (ChattyWindow, chatty_window, CHATTY, WINDOW, HdyApplicatio GtkWidget *chatty_window_new (GtkApplication *application); void chatty_window_set_uri (ChattyWindow *self, - const char *uri); + const char *uri, + const char *name); ChattyChat *chatty_window_get_active_chat (ChattyWindow *self); void chatty_window_open_chat (ChattyWindow *self, ChattyChat *chat); diff --git a/src/chatty.gresource.xml b/src/chatty.gresource.xml index 1bf8b36b1cb82858d045dd26e708dc9ef1dccada..b9f8a8db2cb9a35ecac1de54bc269ef83b652c21 100644 --- a/src/chatty.gresource.xml +++ b/src/chatty.gresource.xml @@ -8,6 +8,7 @@ ui/chatty-list-row.ui ui/chatty-chat-list.ui ui/chatty-chat-view.ui + ui/chatty-contact-list.ui ui/chatty-contact-row.ui ui/chatty-file-item.ui ui/chatty-image-item.ui diff --git a/src/css/style.css b/src/css/style.css index 7668747f1f505a8d96c1f4e4d174b1bbf63ef0ff..e7e5a537a1b1552605931c8688afe31da108b3a8 100644 --- a/src/css/style.css +++ b/src/css/style.css @@ -147,3 +147,8 @@ button.delete-button { min-height: 27px; min-width: 27px; } + +.no-margin, +.no-margin > scrolledwindow > viewport > clamp { + margin: 0; +} diff --git a/src/dialogs/chatty-new-chat-dialog.c b/src/dialogs/chatty-new-chat-dialog.c index c0dd950e096e35719b53c3fc4dd8a1ff85c9b322..8516162c2d641b7cc7b932f2849daad36a019bf6 100644 --- a/src/dialogs/chatty-new-chat-dialog.c +++ b/src/dialogs/chatty-new-chat-dialog.c @@ -20,10 +20,10 @@ #include "chatty-manager.h" #include "chatty-chat.h" #include "chatty-purple.h" -#include "chatty-contact.h" +#include "chatty-contact-list.h" +#include "chatty-list-row.h" #include "chatty-mm-account.h" #include "chatty-ma-account.h" -#include "chatty-list-row.h" #include "chatty-log.h" #include "chatty-utils.h" #include "chatty-new-chat-dialog.h" @@ -36,155 +36,71 @@ static void chatty_new_chat_name_check (ChattyNewChatDialog *self, GtkWidget *button); -#define ITEMS_COUNT 50 - struct _ChattyNewChatDialog { - GtkDialog parent_instance; + HdyWindow parent_instance; + + GtkWidget *header_bar; + GtkWidget *edit_contact_button; + GtkWidget *back_button; + GtkWidget *cancel_button; + GtkWidget *apply_button; + GtkWidget *progress_spinner; + + GtkWidget *group_title_entry; + GtkWidget *self_contact_row; + GtkWidget *selected_contact_list; + GtkWidget *add_more_row; - GtkWidget *chats_listbox; - GtkWidget *contacts_listbox; - GtkWidget *new_contact_row; + GtkWidget *contact_list; GtkWidget *contacts_search_entry; GtkWidget *contact_edit_grid; GtkWidget *new_chat_stack; GtkWidget *accounts_list; GtkWidget *contact_name_entry; GtkWidget *contact_alias_entry; - GtkWidget *back_button; - GtkWidget *add_contact_button; - GtkWidget *edit_contact_button; - GtkWidget *start_button; - GtkWidget *cancel_button; GtkWidget *add_in_contacts_button; - GtkWidget *dummy_prefix_radio; - GtkWidget *header_view_new_chat; - GtkWidget *contact_list_stack; + GtkWidget *main_stack; + GtkWidget *new_group_chat_view; GtkWidget *contact_list_view; - GtkWidget *empty_search_view; + GtkWidget *add_contact_view; - GtkSliceListModel *slice_model; - GtkFilter *filter; - char *search_str; + GtkWidget *dummy_prefix_radio; + ChattyItem *self_contact; ChattyAccount *selected_account; ChattyManager *manager; - ChattyProtocol active_protocols; - - GPtrArray *selected_items; - ChattyItem *selected_item; + GListStore *selection_list; - ChattyContact *dummy_contact; GCancellable *cancellable; gboolean multi_selection; }; -G_DEFINE_TYPE (ChattyNewChatDialog, chatty_new_chat_dialog, GTK_TYPE_DIALOG) - +G_DEFINE_TYPE (ChattyNewChatDialog, chatty_new_chat_dialog, HDY_TYPE_WINDOW) -static GtkWidget * -new_chat_contact_row_new (ChattyItem *item, - ChattyNewChatDialog *self) -{ - GtkWidget *row; - - row = chatty_list_contact_row_new (item); - chatty_list_row_set_selectable (CHATTY_LIST_ROW (row), self->multi_selection); +enum { + SELECTION_CHANGED, + N_SIGNALS +}; - return row; -} +static guint signals[N_SIGNALS]; static void -dialog_active_protocols_changed_cb (ChattyNewChatDialog *self) +start_button_clicked_cb (ChattyNewChatDialog *self) { - ChattyAccount *mm_account; - ChattyProtocol protocol; - gboolean valid; + GListModel *model; g_assert (CHATTY_IS_NEW_CHAT_DIALOG (self)); - self->active_protocols = chatty_manager_get_active_protocols (self->manager); - gtk_filter_changed (self->filter, GTK_FILTER_CHANGE_DIFFERENT); - - protocol = CHATTY_PROTOCOL_MMS_SMS; - valid = protocol == chatty_utils_username_is_valid (self->search_str, protocol); - mm_account = chatty_manager_get_mm_account (self->manager); - valid = valid && chatty_account_get_status (mm_account) == CHATTY_CONNECTED; - gtk_widget_set_visible (self->new_contact_row, valid); - - if (valid || g_list_model_get_n_items (G_LIST_MODEL (self->slice_model)) > 0) - gtk_stack_set_visible_child (GTK_STACK (self->contact_list_stack), self->contact_list_view); - else - gtk_stack_set_visible_child (GTK_STACK (self->contact_list_stack), self->empty_search_view); -} - -static gboolean -new_chat_dialog_contact_is_selected (ChattyContact *contact) -{ - g_return_val_if_fail (CHATTY_IS_CONTACT (contact), FALSE); - - return !!g_object_get_data (G_OBJECT (contact), "selected"); -} - -static gboolean -dialog_filter_item_cb (ChattyItem *item, - ChattyNewChatDialog *self) -{ - g_return_val_if_fail (CHATTY_IS_NEW_CHAT_DIALOG (self), FALSE); - - if (self->multi_selection) { - ChattyAccount *mm_account; - - mm_account = chatty_manager_get_mm_account (self->manager); - if (chatty_account_get_status (mm_account) == CHATTY_CONNECTED) { - if (chatty_item_matches (item, self->search_str, CHATTY_PROTOCOL_MMS_SMS, TRUE) && - !new_chat_dialog_contact_is_selected (CHATTY_CONTACT (item))) - return TRUE; - else - return FALSE; - } else - return FALSE; - } - -#ifdef PURPLE_ENABLED - if (CHATTY_IS_PP_BUDDY (item)) { - ChattyAccount *account; - - account = chatty_pp_buddy_get_account (CHATTY_PP_BUDDY (item)); - - if (chatty_account_get_status (account) != CHATTY_CONNECTED) - return FALSE; - } -#endif - - if (CHATTY_IS_CHAT (item)) { - ChattyAccount *account; - -#ifdef PURPLE_ENABLED - /* Hide chat if it's buddy chat as the buddy is shown separately */ - if (CHATTY_IS_PP_CHAT (item) && - chatty_pp_chat_get_purple_buddy (CHATTY_PP_CHAT (item))) - return FALSE; -#endif - - account = chatty_chat_get_account (CHATTY_CHAT (item)); - - if (!account || chatty_account_get_status (account) != CHATTY_CONNECTED) - return FALSE; - } - - return chatty_item_matches (item, self->search_str, self->active_protocols, TRUE); -} + model = G_LIST_MODEL (self->selection_list); -static void -start_button_clicked_cb (ChattyNewChatDialog *self) -{ - g_assert (CHATTY_IS_NEW_CHAT_DIALOG (self)); + if (g_list_model_get_n_items (model) < 1) + return; - gtk_dialog_response (GTK_DIALOG (self), GTK_RESPONSE_OK); + g_signal_emit (self, signals[SELECTION_CHANGED], 0); } static void @@ -192,18 +108,7 @@ cancel_button_clicked_cb (ChattyNewChatDialog *self) { g_assert (CHATTY_IS_NEW_CHAT_DIALOG (self)); - gtk_dialog_response (GTK_DIALOG (self), GTK_RESPONSE_CANCEL); -} - -static void -chatty_new_chat_dialog_update_selectable (GtkWidget *widget, - gpointer callback_data) -{ - ChattyNewChatDialog *self = callback_data; - - g_assert (CHATTY_IS_NEW_CHAT_DIALOG (self)); - - chatty_list_row_set_selectable ((ChattyListRow *)widget, self->multi_selection); + gtk_widget_hide (GTK_WIDGET (self)); } void @@ -213,68 +118,83 @@ chatty_new_chat_dialog_set_multi_selection (ChattyNewChatDialog *self, g_assert (CHATTY_IS_NEW_CHAT_DIALOG (self)); self->multi_selection = enable; - gtk_header_bar_set_show_close_button (GTK_HEADER_BAR (self->header_view_new_chat), !enable); - - chatty_list_row_set_selectable (CHATTY_LIST_ROW (self->new_contact_row), enable); - gtk_container_foreach (GTK_CONTAINER (self->chats_listbox), - (GtkCallback)chatty_new_chat_dialog_update_selectable, self); + hdy_header_bar_set_show_close_button (HDY_HEADER_BAR (self->header_bar), !enable); + chatty_contact_list_can_multi_select (CHATTY_CONTACT_LIST (self->contact_list), enable); + gtk_widget_set_sensitive (self->apply_button, FALSE); if (enable) { - gtk_widget_show (self->start_button); - gtk_widget_show (self->contacts_listbox); - gtk_widget_show (self->cancel_button); - gtk_widget_hide (self->edit_contact_button); - gtk_widget_set_sensitive (self->start_button, FALSE); - } else { - gtk_widget_show (self->edit_contact_button); - gtk_widget_hide (self->contacts_listbox); - gtk_widget_hide (self->start_button); - gtk_widget_hide (self->cancel_button); + gtk_widget_set_sensitive (self->apply_button, FALSE); + gtk_stack_set_visible_child (GTK_STACK (self->main_stack), self->new_group_chat_view); } } static void -new_chat_list_changed_cb (ChattyNewChatDialog *self) +back_button_clicked_cb (ChattyNewChatDialog *self) { - guint n_items; - g_assert (CHATTY_IS_NEW_CHAT_DIALOG (self)); - n_items = g_list_model_get_n_items (G_LIST_MODEL (self->slice_model)); - - if (n_items > 0 || gtk_widget_get_visible (self->new_contact_row)) - gtk_stack_set_visible_child (GTK_STACK (self->contact_list_stack), self->contact_list_view); + if (self->multi_selection) + gtk_stack_set_visible_child (GTK_STACK (self->main_stack), self->new_group_chat_view); else - gtk_stack_set_visible_child (GTK_STACK (self->contact_list_stack), self->empty_search_view); + gtk_stack_set_visible_child (GTK_STACK (self->main_stack), self->contact_list_view); } + static void -chatty_new_chat_dialog_update_new_contact_row (ChattyNewChatDialog *self) +edit_contact_button_clicked_cb (ChattyNewChatDialog *self) { g_assert (CHATTY_IS_NEW_CHAT_DIALOG (self)); - self->dummy_contact = g_object_new (CHATTY_TYPE_CONTACT, NULL); - chatty_contact_set_name (self->dummy_contact, _("Send To")); - g_object_set_data (G_OBJECT (self->dummy_contact), "dummy", GINT_TO_POINTER (TRUE)); + chatty_new_chat_dialog_update (self); + + gtk_stack_set_visible_child (GTK_STACK (self->main_stack), self->add_contact_view); } static void -back_button_clicked_cb (ChattyNewChatDialog *self) +new_chat_dialog_page_changed_cb (ChattyNewChatDialog *self) { + GtkWidget *visible_child; + g_assert (CHATTY_IS_NEW_CHAT_DIALOG (self)); - gtk_stack_set_visible_child_name (GTK_STACK (self->new_chat_stack), "view-new-chat"); -} + gtk_widget_hide (self->back_button); + gtk_widget_hide (self->cancel_button); + gtk_widget_hide (self->apply_button); + gtk_widget_hide (self->edit_contact_button); + gtk_widget_show (self->apply_button); + hdy_header_bar_set_show_close_button (HDY_HEADER_BAR (self->header_bar), FALSE); + visible_child = gtk_stack_get_visible_child (GTK_STACK (self->main_stack)); + + if (visible_child == self->contact_list_view) { + if (self->multi_selection) { + gtk_button_set_label (GTK_BUTTON (self->apply_button), _("Add")); + gtk_widget_show (self->back_button); + } else { + gtk_widget_hide (self->apply_button); + hdy_header_bar_set_show_close_button (HDY_HEADER_BAR (self->header_bar), TRUE); + gtk_widget_show (self->edit_contact_button); + } + } else if (visible_child == self->new_group_chat_view) { + gboolean can_create; + + gtk_button_set_label (GTK_BUTTON (self->apply_button), _("Create")); + gtk_widget_show (self->cancel_button); + + can_create = g_list_model_get_n_items (G_LIST_MODEL (self->selection_list)) > 0; + gtk_widget_set_sensitive (self->apply_button, can_create); + } else { + gtk_button_set_label (GTK_BUTTON (self->apply_button), _("Add Contact")); + gtk_widget_show (self->back_button); + } +} static void -edit_contact_button_clicked_cb (ChattyNewChatDialog *self) +add_more_contact_row_activated_cb (ChattyNewChatDialog *self) { g_assert (CHATTY_IS_NEW_CHAT_DIALOG (self)); - chatty_new_chat_dialog_update (self); - - gtk_stack_set_visible_child_name (GTK_STACK (self->new_chat_stack), "view-new-contact"); + gtk_stack_set_visible_child (GTK_STACK (self->main_stack), self->contact_list_view); } static void @@ -292,7 +212,7 @@ open_contacts_finish_cb (GObject *object, chatty_eds_open_contacts_app_finish (chatty_eds, result, &error); gtk_widget_set_sensitive (self->add_in_contacts_button, TRUE); - gtk_stack_set_visible_child_name (GTK_STACK (self->new_chat_stack), "view-new-chat"); + gtk_stack_set_visible_child (GTK_STACK (self->main_stack), self->contact_list_view); if (!error) return; @@ -321,299 +241,50 @@ add_in_contacts_button_clicked_cb (ChattyNewChatDialog *self) open_contacts_finish_cb, self); } - - static void -contact_stroll_edge_reached_cb (ChattyNewChatDialog *self, - GtkPositionType position) +contact_list_selection_changed_cb (ChattyNewChatDialog *self) { - const char *name; + GListModel *model; + guint n_items; g_assert (CHATTY_IS_NEW_CHAT_DIALOG (self)); - if (position != GTK_POS_BOTTOM) - return; - - name = gtk_stack_get_visible_child_name (GTK_STACK (self->new_chat_stack)); - - if (!g_str_equal (name, "view-new-chat")) - return; + model = G_LIST_MODEL (self->selection_list); + n_items = g_list_model_get_n_items (model); - gtk_slice_list_model_set_size (self->slice_model, - gtk_slice_list_model_get_size (self->slice_model) + ITEMS_COUNT); + if (self->multi_selection) { + gtk_widget_set_sensitive (self->apply_button, n_items > 0); + } else if (n_items > 0) { + g_signal_emit (self, signals[SELECTION_CHANGED], 0); + } } static void contact_search_entry_activated_cb (ChattyNewChatDialog *self) { - GtkListBox *box; - GtkWidget *row; - g_assert (CHATTY_IS_NEW_CHAT_DIALOG (self)); - box = GTK_LIST_BOX (self->chats_listbox); - - if (gtk_widget_is_visible (self->new_contact_row)) - row = self->new_contact_row; + if (self->multi_selection) + start_button_clicked_cb (self); else - row = (GtkWidget *)gtk_list_box_get_row_at_index (box, 0); - - if (row) { - self->selected_item = chatty_list_row_get_item (CHATTY_LIST_ROW (row)); - - gtk_dialog_response (GTK_DIALOG (self), GTK_RESPONSE_OK); - } + contact_list_selection_changed_cb (self); } static void contact_search_entry_changed_cb (ChattyNewChatDialog *self, GtkEntry *entry) { - ChattyAccount *account; - g_autofree char *old_needle = NULL; const char *str; - GtkFilterChange change; - ChattyProtocol protocol; - gboolean valid; - guint len; g_assert (CHATTY_IS_NEW_CHAT_DIALOG (self)); g_assert (GTK_IS_ENTRY (entry)); str = gtk_entry_get_text (entry); - if (!str) - str = ""; - - old_needle = self->search_str; - self->search_str = g_utf8_casefold (str, -1); - len = strlen (self->search_str); - - if (!old_needle) - old_needle = g_strdup (""); - - if (g_str_has_prefix (self->search_str, old_needle)) - change = GTK_FILTER_CHANGE_MORE_STRICT; - else if (g_str_has_prefix (old_needle, self->search_str)) - change = GTK_FILTER_CHANGE_LESS_STRICT; - else - change = GTK_FILTER_CHANGE_DIFFERENT; - - gtk_slice_list_model_set_size (self->slice_model, ITEMS_COUNT); - gtk_filter_changed (self->filter, change); - - chatty_contact_set_value (self->dummy_contact, self->search_str); - chatty_list_row_set_item (CHATTY_LIST_ROW (self->new_contact_row), - CHATTY_ITEM (self->dummy_contact)); - - protocol = CHATTY_PROTOCOL_MMS_SMS; - valid = protocol == chatty_utils_username_is_valid (self->search_str, protocol); - /* It is confusing for the dummy contact to disappear if the length is less than 3 */ - if (!valid && len < 3 && len > 0) { - guint end_len; - end_len = strspn (self->search_str, "0123456789"); - - if (end_len == len) - valid = TRUE; - } - account = chatty_manager_get_mm_account (self->manager); - valid = valid && chatty_account_get_status (account) == CHATTY_CONNECTED; - gtk_widget_set_visible (self->new_contact_row, valid); - - if (valid || g_list_model_get_n_items (G_LIST_MODEL (self->slice_model)) > 0) { - gtk_stack_set_visible_child (GTK_STACK (self->contact_list_stack), self->contact_list_view); - if (self->multi_selection) { - ChattyItem *selected_item; - const char *phone_number; - gboolean has_match = FALSE; - - selected_item = chatty_list_row_get_item (CHATTY_LIST_ROW (self->new_contact_row)); - phone_number = chatty_item_get_username (selected_item); - - /* Check if search string matches an item in the selected list */ - for (guint i = 0; i < self->selected_items->len; i++) { - const char *item_number = NULL; - ChattyItem *item; - - item = self->selected_items->pdata[i]; - if (item) - item_number = chatty_item_get_username (item); - - if (g_strcmp0 (item_number, phone_number) == 0) { - has_match = TRUE; - break; - } - } - - chatty_list_row_select (CHATTY_LIST_ROW (self->new_contact_row), has_match); - - gtk_container_foreach (GTK_CONTAINER (self->chats_listbox), - (GtkCallback)chatty_new_chat_dialog_update_selectable, - self); - } - } else - gtk_stack_set_visible_child (GTK_STACK (self->contact_list_stack), self->empty_search_view); -} - -static void -selected_contact_row_activated_cb (ChattyNewChatDialog *self, - ChattyListRow *row) -{ - const char *phone_number = NULL; - ChattyItem *selected_item; - - g_assert (CHATTY_IS_NEW_CHAT_DIALOG (self)); - g_assert (CHATTY_IS_LIST_ROW (row)); - - selected_item = chatty_list_row_get_item (row); - phone_number = chatty_item_get_username (selected_item); - - for (guint i = 0; i < self->selected_items->len; i++) { - const char *item_number = NULL; - ChattyItem *item; - - item = self->selected_items->pdata[i]; - if (item) - item_number = chatty_item_get_username (item); - - if (g_strcmp0 (item_number, phone_number) == 0) { - CHATTY_DEBUG (phone_number, "Removing item from list:"); - g_ptr_array_remove_index (self->selected_items, i); - - if (!self->selected_items->len) - gtk_widget_set_sensitive (self->start_button, FALSE); - - break; - } - } - if (chatty_contact_is_dummy (CHATTY_CONTACT (selected_item))) { - ChattyItem *dummy_item; - const char *dummy_number; - - dummy_item = chatty_list_row_get_item (CHATTY_LIST_ROW (self->new_contact_row)); - dummy_number = chatty_item_get_username (dummy_item); - if (g_strcmp0 (dummy_number, phone_number) == 0) - chatty_list_row_select (CHATTY_LIST_ROW (self->new_contact_row), FALSE); - - } else { - g_autofree char *contacts_search_entry = NULL; - - contacts_search_entry = g_strdup(gtk_entry_get_text (GTK_ENTRY (self->contacts_search_entry))); - g_object_set_data (G_OBJECT (selected_item), "selected", GINT_TO_POINTER (FALSE)); - if (!*contacts_search_entry) - gtk_entry_set_text (GTK_ENTRY (self->contacts_search_entry), "reset"); - else - gtk_entry_set_text (GTK_ENTRY (self->contacts_search_entry), ""); - - contact_search_entry_changed_cb (self, GTK_ENTRY (self->contacts_search_entry)); - gtk_entry_set_text (GTK_ENTRY (self->contacts_search_entry), contacts_search_entry); - } - gtk_widget_destroy (GTK_WIDGET (row)); -} - -static void -contact_row_activated_cb (ChattyNewChatDialog *self, - ChattyListRow *row) -{ - g_assert (CHATTY_IS_NEW_CHAT_DIALOG (self)); - g_assert (CHATTY_IS_LIST_ROW (row)); - - if (self->multi_selection) { - GtkListBoxRow *chats_listbox_row; - GtkWidget *new_row = NULL; - ChattyItem *selected_item; - const char *phone_number; - - selected_item = chatty_list_row_get_item (row); - phone_number = chatty_item_get_username (selected_item); - /* If there is a dummy contact, make sure it is not already selected */ - if (chatty_contact_is_dummy (CHATTY_CONTACT (selected_item))) { - guint i = 0; - - chatty_list_row_select (CHATTY_LIST_ROW (self->new_contact_row), TRUE); - chats_listbox_row = gtk_list_box_get_row_at_index (GTK_LIST_BOX (self->contacts_listbox), 0); - while (chats_listbox_row != NULL) { - ChattyItem *item = chatty_list_row_get_item (CHATTY_LIST_ROW (chats_listbox_row)); - const char *item_number = chatty_item_get_username (item); - if (g_strcmp0 (item_number, phone_number) == 0) { - selected_contact_row_activated_cb (self, (CHATTY_LIST_ROW (chats_listbox_row))); - return; - } - i++; - chats_listbox_row = gtk_list_box_get_row_at_index (GTK_LIST_BOX (self->contacts_listbox), i); - } - } - - CHATTY_DEBUG_MSG ("Adding %s to list", phone_number); - if (chatty_contact_is_dummy (CHATTY_CONTACT (selected_item))) { - ChattyContact *dummy_contact = NULL; - - dummy_contact = g_object_new (CHATTY_TYPE_CONTACT, NULL); - chatty_contact_set_name (dummy_contact, _("Unknown Contact")); - chatty_contact_set_value (dummy_contact, - gtk_entry_get_text (GTK_ENTRY (self->contacts_search_entry))); - g_object_set_data (G_OBJECT (dummy_contact), "dummy", GINT_TO_POINTER (TRUE)); - new_row = chatty_list_row_new (CHATTY_ITEM (dummy_contact)); - g_ptr_array_add (self->selected_items, dummy_contact); - } else { - ChattyItem *dummy_item; - const char *dummy_number; - - dummy_item = chatty_list_row_get_item (CHATTY_LIST_ROW (self->new_contact_row)); - dummy_number = chatty_item_get_username (dummy_item); - new_row = chatty_list_row_new (chatty_list_row_get_item (row)); - g_ptr_array_add (self->selected_items, g_object_ref (selected_item)); - - g_object_set_data (G_OBJECT (selected_item), "selected", GINT_TO_POINTER (TRUE)); - gtk_widget_hide (GTK_WIDGET (row)); - if (g_strcmp0 (dummy_number, phone_number) == 0) { - chatty_list_row_select (CHATTY_LIST_ROW (self->new_contact_row), TRUE); - } - } - - chatty_list_row_set_selectable (CHATTY_LIST_ROW (new_row), TRUE); - chatty_list_row_select (CHATTY_LIST_ROW (new_row), TRUE); - gtk_list_box_prepend (GTK_LIST_BOX (self->contacts_listbox), - GTK_WIDGET (new_row)); - gtk_widget_set_sensitive (self->start_button, TRUE); - } else { - self->selected_item = chatty_list_row_get_item (row); - - gtk_dialog_response (GTK_DIALOG (self), GTK_RESPONSE_OK); - } + chatty_contact_list_set_filter (CHATTY_CONTACT_LIST (self->contact_list), + CHATTY_PROTOCOL_ANY, str ?: ""); } -static void -add_contact_button_clicked_cb (ChattyNewChatDialog *self) -{ -#ifdef PURPLE_ENABLED - GPtrArray *buddies; - const char *who, *alias; - - g_assert (CHATTY_IS_NEW_CHAT_DIALOG (self)); - - if (!gtk_widget_get_sensitive (self->add_contact_button)) - return; - - buddies = g_ptr_array_new_full (1, g_free); - - who = gtk_entry_get_text (GTK_ENTRY (self->contact_name_entry)); - alias = gtk_entry_get_text (GTK_ENTRY (self->contact_alias_entry)); - chatty_pp_account_add_buddy (CHATTY_PP_ACCOUNT (self->selected_account), who, alias); - - g_ptr_array_add (buddies, g_strdup (who)); - chatty_account_start_direct_chat_async (self->selected_account, buddies, NULL, NULL); -#endif - - gtk_widget_hide (GTK_WIDGET (self)); - - gtk_entry_set_text (GTK_ENTRY (self->contact_name_entry), ""); - gtk_entry_set_text (GTK_ENTRY (self->contact_alias_entry), ""); - - gtk_stack_set_visible_child_name (GTK_STACK (self->new_chat_stack), "view-new-chat"); -} - - static void contact_name_text_changed_cb (ChattyNewChatDialog *self) { @@ -621,7 +292,7 @@ contact_name_text_changed_cb (ChattyNewChatDialog *self) chatty_new_chat_name_check (self, GTK_ENTRY (self->contact_name_entry), - self->add_contact_button); + self->apply_button); } @@ -647,6 +318,50 @@ account_list_row_activated_cb (ChattyNewChatDialog *self, chatty_new_chat_set_edit_mode (self, TRUE); } +static void +new_chat_dialog_apply_button_clicked_cb (ChattyNewChatDialog *self) +{ + g_assert (CHATTY_IS_NEW_CHAT_DIALOG (self)); + + if (gtk_stack_get_visible_child (GTK_STACK (self->main_stack)) == self->add_contact_view) { +#ifdef PURPLE_ENABLED + GPtrArray *buddies; + const char *who, *alias; + + g_assert (CHATTY_IS_NEW_CHAT_DIALOG (self)); + + if (!gtk_widget_get_sensitive (self->apply_button)) + return; + + buddies = g_ptr_array_new_full (1, g_free); + + who = gtk_entry_get_text (GTK_ENTRY (self->contact_name_entry)); + alias = gtk_entry_get_text (GTK_ENTRY (self->contact_alias_entry)); + chatty_pp_account_add_buddy (CHATTY_PP_ACCOUNT (self->selected_account), who, alias); + + g_ptr_array_add (buddies, g_strdup (who)); + chatty_account_start_direct_chat_async (self->selected_account, buddies, NULL, NULL); +#endif + + gtk_widget_hide (GTK_WIDGET (self)); + } else if (gtk_stack_get_visible_child (GTK_STACK (self->main_stack)) == self->contact_list_view) { + GListModel *model; + + g_assert (CHATTY_IS_NEW_CHAT_DIALOG (self)); + + model = G_LIST_MODEL (self->selection_list); + + if (g_list_model_get_n_items (model) == 0) + return; + + if (self->multi_selection) + gtk_stack_set_visible_child (GTK_STACK (self->main_stack), self->new_group_chat_view); + else + g_signal_emit (self, signals[SELECTION_CHANGED], 0); + } else { + g_signal_emit (self, signals[SELECTION_CHANGED], 0); + } +} static void chatty_new_chat_name_check (ChattyNewChatDialog *self, @@ -680,11 +395,11 @@ chatty_new_chat_set_edit_mode (ChattyNewChatDialog *self, if (edit) { gtk_widget_show (GTK_WIDGET (self->contact_edit_grid)); - gtk_widget_show (GTK_WIDGET (self->add_contact_button)); + gtk_widget_show (GTK_WIDGET (self->apply_button)); gtk_widget_hide (GTK_WIDGET (self->add_in_contacts_button)); } else { gtk_widget_hide (GTK_WIDGET (self->contact_edit_grid)); - gtk_widget_hide (GTK_WIDGET (self->add_contact_button)); + gtk_widget_hide (GTK_WIDGET (self->apply_button)); gtk_widget_show (GTK_WIDGET (self->add_in_contacts_button)); } } @@ -806,43 +521,33 @@ chatty_new_chat_dialog_update (ChattyNewChatDialog *self) } static void -chatty_new_chat_unset_items (gpointer data, - gpointer user_data) +new_chat_dialog_selected_contacts_changed_cb (ChattyNewChatDialog *self) { - g_object_set_data (data, "selected", GINT_TO_POINTER (FALSE)); + guint n_items; + + g_assert (CHATTY_IS_NEW_CHAT_DIALOG (self)); + + n_items = g_list_model_get_n_items (G_LIST_MODEL (self->selection_list)); + gtk_widget_set_visible (GTK_WIDGET (self->selected_contact_list), n_items > 0); + gtk_widget_set_sensitive (GTK_WIDGET (self->apply_button), n_items > 0); } static void chatty_new_chat_dialog_show (GtkWidget *widget) { ChattyNewChatDialog *self = (ChattyNewChatDialog *)widget; - const char *contacts_search_entry; g_return_if_fail (CHATTY_IS_NEW_CHAT_DIALOG (self)); - g_ptr_array_foreach (self->selected_items, - chatty_new_chat_unset_items, NULL); - g_ptr_array_set_size (self->selected_items, 0); - self->selected_items->pdata[0] = NULL; - - /* Re-filter so that selection changes are reverted */ - gtk_filter_changed (self->filter, GTK_FILTER_CHANGE_DIFFERENT); - chatty_list_row_select (CHATTY_LIST_ROW (self->new_contact_row), FALSE); - - gtk_widget_set_sensitive (self->start_button, FALSE); - - gtk_container_foreach (GTK_CONTAINER (self->contacts_listbox), - (GtkCallback)gtk_widget_destroy, NULL); - /* Reset selection list */ - self->selected_item = NULL; + g_list_store_remove_all (self->selection_list); - contacts_search_entry = gtk_entry_get_text (GTK_ENTRY (self->contacts_search_entry)); - if (!*contacts_search_entry) { - gtk_entry_set_text (GTK_ENTRY (self->contacts_search_entry), "reset"); - contact_search_entry_changed_cb (self, GTK_ENTRY (self->contacts_search_entry)); - } + gtk_widget_set_sensitive (self->apply_button, FALSE); gtk_entry_set_text (GTK_ENTRY (self->contacts_search_entry), ""); + gtk_stack_set_visible_child (GTK_STACK (self->main_stack), self->contact_list_view); + new_chat_dialog_page_changed_cb (self); + chatty_new_chat_dialog_set_multi_selection (self, self->multi_selection); + new_chat_dialog_selected_contacts_changed_cb (self); GTK_WIDGET_CLASS (chatty_new_chat_dialog_parent_class)->show (widget); } @@ -855,15 +560,8 @@ chatty_new_chat_dialog_dispose (GObject *object) if (self->cancellable) g_cancellable_cancel (self->cancellable); - if (self->selected_items) - g_ptr_array_foreach (self->selected_items, - chatty_new_chat_unset_items, NULL); - - g_clear_pointer (&self->selected_items, g_ptr_array_unref); g_clear_object (&self->cancellable); g_clear_object (&self->manager); - g_clear_object (&self->slice_model); - g_clear_object (&self->filter); G_OBJECT_CLASS (chatty_new_chat_dialog_parent_class)->dispose (object); } @@ -878,83 +576,82 @@ chatty_new_chat_dialog_class_init (ChattyNewChatDialogClass *klass) widget_class->show = chatty_new_chat_dialog_show; + signals [SELECTION_CHANGED] = + g_signal_new ("selection-changed", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, NULL, NULL, NULL, + G_TYPE_NONE, 0); + gtk_widget_class_set_template_from_resource (widget_class, "/sm/puri/Chatty/" "ui/chatty-dialog-new-chat.ui"); - gtk_widget_class_bind_template_child (widget_class, ChattyNewChatDialog, new_chat_stack); - gtk_widget_class_bind_template_child (widget_class, ChattyNewChatDialog, header_view_new_chat); + gtk_widget_class_bind_template_child (widget_class, ChattyNewChatDialog, header_bar); + gtk_widget_class_bind_template_child (widget_class, ChattyNewChatDialog, edit_contact_button); + gtk_widget_class_bind_template_child (widget_class, ChattyNewChatDialog, back_button); + gtk_widget_class_bind_template_child (widget_class, ChattyNewChatDialog, cancel_button); + gtk_widget_class_bind_template_child (widget_class, ChattyNewChatDialog, apply_button); + gtk_widget_class_bind_template_child (widget_class, ChattyNewChatDialog, progress_spinner); + + gtk_widget_class_bind_template_child (widget_class, ChattyNewChatDialog, group_title_entry); + gtk_widget_class_bind_template_child (widget_class, ChattyNewChatDialog, self_contact_row); + gtk_widget_class_bind_template_child (widget_class, ChattyNewChatDialog, selected_contact_list); + gtk_widget_class_bind_template_child (widget_class, ChattyNewChatDialog, add_more_row); + gtk_widget_class_bind_template_child (widget_class, ChattyNewChatDialog, contacts_search_entry); - gtk_widget_class_bind_template_child (widget_class, ChattyNewChatDialog, new_contact_row); - gtk_widget_class_bind_template_child (widget_class, ChattyNewChatDialog, contacts_listbox); - gtk_widget_class_bind_template_child (widget_class, ChattyNewChatDialog, chats_listbox); + gtk_widget_class_bind_template_child (widget_class, ChattyNewChatDialog, contact_list); gtk_widget_class_bind_template_child (widget_class, ChattyNewChatDialog, contact_edit_grid); gtk_widget_class_bind_template_child (widget_class, ChattyNewChatDialog, contact_name_entry); gtk_widget_class_bind_template_child (widget_class, ChattyNewChatDialog, contact_alias_entry); gtk_widget_class_bind_template_child (widget_class, ChattyNewChatDialog, accounts_list); - gtk_widget_class_bind_template_child (widget_class, ChattyNewChatDialog, back_button); - gtk_widget_class_bind_template_child (widget_class, ChattyNewChatDialog, edit_contact_button); - gtk_widget_class_bind_template_child (widget_class, ChattyNewChatDialog, add_contact_button); gtk_widget_class_bind_template_child (widget_class, ChattyNewChatDialog, add_in_contacts_button); - gtk_widget_class_bind_template_child (widget_class, ChattyNewChatDialog, start_button); - gtk_widget_class_bind_template_child (widget_class, ChattyNewChatDialog, cancel_button); - gtk_widget_class_bind_template_child (widget_class, ChattyNewChatDialog, contact_list_stack); + gtk_widget_class_bind_template_child (widget_class, ChattyNewChatDialog, main_stack); + gtk_widget_class_bind_template_child (widget_class, ChattyNewChatDialog, new_group_chat_view); gtk_widget_class_bind_template_child (widget_class, ChattyNewChatDialog, contact_list_view); - gtk_widget_class_bind_template_child (widget_class, ChattyNewChatDialog, empty_search_view); + gtk_widget_class_bind_template_child (widget_class, ChattyNewChatDialog, add_contact_view); - gtk_widget_class_bind_template_callback (widget_class, back_button_clicked_cb); gtk_widget_class_bind_template_callback (widget_class, edit_contact_button_clicked_cb); - gtk_widget_class_bind_template_callback (widget_class, contact_stroll_edge_reached_cb); + gtk_widget_class_bind_template_callback (widget_class, back_button_clicked_cb); + gtk_widget_class_bind_template_callback (widget_class, cancel_button_clicked_cb); + gtk_widget_class_bind_template_callback (widget_class, new_chat_dialog_apply_button_clicked_cb); + + gtk_widget_class_bind_template_callback (widget_class, new_chat_dialog_page_changed_cb); + gtk_widget_class_bind_template_callback (widget_class, add_more_contact_row_activated_cb); gtk_widget_class_bind_template_callback (widget_class, contact_search_entry_activated_cb); gtk_widget_class_bind_template_callback (widget_class, contact_search_entry_changed_cb); - gtk_widget_class_bind_template_callback (widget_class, selected_contact_row_activated_cb); - gtk_widget_class_bind_template_callback (widget_class, contact_row_activated_cb); - gtk_widget_class_bind_template_callback (widget_class, add_contact_button_clicked_cb); + gtk_widget_class_bind_template_callback (widget_class, contact_list_selection_changed_cb); gtk_widget_class_bind_template_callback (widget_class, add_in_contacts_button_clicked_cb); gtk_widget_class_bind_template_callback (widget_class, contact_name_text_changed_cb); gtk_widget_class_bind_template_callback (widget_class, account_list_row_activated_cb); - gtk_widget_class_bind_template_callback (widget_class, start_button_clicked_cb); - gtk_widget_class_bind_template_callback (widget_class, cancel_button_clicked_cb); } static void chatty_new_chat_dialog_init (ChattyNewChatDialog *self) { - g_autoptr(GtkFilterListModel) filter_model = NULL; - g_autoptr(GtkSortListModel) sort_model = NULL; - g_autoptr(GtkSorter) sorter = NULL; - gtk_widget_init_template (GTK_WIDGET (self)); self->cancellable = g_cancellable_new (); + self->self_contact = CHATTY_ITEM (chatty_contact_dummy_new (_("You"), "MMS")); + chatty_list_row_set_item (CHATTY_LIST_ROW (self->self_contact_row), self->self_contact); + + self->selection_list = g_list_store_new (CHATTY_TYPE_ITEM); + g_signal_connect_object (self->selection_list, "items-changed", + G_CALLBACK (new_chat_dialog_selected_contacts_changed_cb), + self, G_CONNECT_SWAPPED); + chatty_contact_list_set_selection_store (CHATTY_CONTACT_LIST (self->contact_list), + self->selection_list); + chatty_contact_list_show_selected_only (CHATTY_CONTACT_LIST (self->selected_contact_list)); + chatty_contact_list_set_selection_store (CHATTY_CONTACT_LIST (self->selected_contact_list), + self->selection_list); + chatty_contact_list_can_multi_select (CHATTY_CONTACT_LIST (self->selected_contact_list), TRUE); + self->multi_selection = FALSE; - self->selected_items = g_ptr_array_new_full (1, g_object_unref); self->dummy_prefix_radio = gtk_radio_button_new_from_widget (GTK_RADIO_BUTTON (NULL)); self->manager = g_object_ref (chatty_manager_get_default ()); - - sorter = gtk_custom_sorter_new ((GCompareDataFunc)chatty_item_compare, NULL, NULL); - sort_model = gtk_sort_list_model_new (chatty_manager_get_contact_list (self->manager), sorter); - - self->filter = gtk_custom_filter_new ((GtkCustomFilterFunc)dialog_filter_item_cb, self, NULL); - filter_model = gtk_filter_list_model_new (G_LIST_MODEL (sort_model), self->filter); - - self->slice_model = gtk_slice_list_model_new (G_LIST_MODEL (filter_model), 0, ITEMS_COUNT); - g_signal_connect_object (self->slice_model, "items-changed", - G_CALLBACK (new_chat_list_changed_cb), self, - G_CONNECT_SWAPPED); - gtk_list_box_bind_model (GTK_LIST_BOX (self->chats_listbox), - G_LIST_MODEL (self->slice_model), - (GtkListBoxCreateWidgetFunc)new_chat_contact_row_new, - g_object_ref (self), g_object_unref); - - g_signal_connect_object (self->manager, "notify::active-protocols", - G_CALLBACK (dialog_active_protocols_changed_cb), self, G_CONNECT_SWAPPED); - dialog_active_protocols_changed_cb (self); - - chatty_new_chat_dialog_update_new_contact_row (self); } @@ -965,23 +662,28 @@ chatty_new_chat_dialog_new (GtkWindow *parent_window) return g_object_new (CHATTY_TYPE_NEW_CHAT_DIALOG, "transient-for", parent_window, - "use-header-bar", 1, NULL); } - -ChattyItem * -chatty_new_chat_dialog_get_selected_item (ChattyNewChatDialog *self) +GListModel * +chatty_new_chat_dialog_get_selected_items (ChattyNewChatDialog *self) { g_return_val_if_fail (CHATTY_IS_NEW_CHAT_DIALOG (self), NULL); - return self->selected_item; + return G_LIST_MODEL (self->selection_list); } -GPtrArray * -chatty_new_chat_dialog_get_selected_items (ChattyNewChatDialog *self) +const char * +chatty_new_chat_dialog_get_chat_title (ChattyNewChatDialog *self) { + const char *group_title; + g_return_val_if_fail (CHATTY_IS_NEW_CHAT_DIALOG (self), NULL); - return self->selected_items; + group_title = gtk_entry_get_text (GTK_ENTRY (self->group_title_entry)); + + if (group_title && *group_title) + return group_title; + + return NULL; } diff --git a/src/dialogs/chatty-new-chat-dialog.h b/src/dialogs/chatty-new-chat-dialog.h index 3499a55eec85c750010185ba737707ed772309a4..5fe5cedf39db559c9ae65adf3b42b7aee8472f64 100644 --- a/src/dialogs/chatty-new-chat-dialog.h +++ b/src/dialogs/chatty-new-chat-dialog.h @@ -19,9 +19,9 @@ G_DECLARE_FINAL_TYPE (ChattyNewChatDialog, chatty_new_chat_dialog, CHATTY, NEW_C GtkWidget *chatty_new_chat_dialog_new (GtkWindow *parent_window); void chatty_new_chat_set_edit_mode (ChattyNewChatDialog *self, gboolean edit); -ChattyItem *chatty_new_chat_dialog_get_selected_item (ChattyNewChatDialog *self); +GListModel *chatty_new_chat_dialog_get_selected_items (ChattyNewChatDialog *self); void chatty_new_chat_dialog_set_multi_selection (ChattyNewChatDialog *self, gboolean enable); -GPtrArray *chatty_new_chat_dialog_get_selected_items (ChattyNewChatDialog *self); +const char *chatty_new_chat_dialog_get_chat_title (ChattyNewChatDialog *self); G_END_DECLS diff --git a/src/meson.build b/src/meson.build index 4a91ccea90dd2279108258f278121305986320eb..05e8c9f9afadac21516b5a37340c2ab581496554 100644 --- a/src/meson.build +++ b/src/meson.build @@ -69,7 +69,7 @@ ui_files = files ( # but works fine locally # 'ui/chatty-info-dialog.ui', # 'ui/chatty-dialog-join-muc.ui', - 'ui/chatty-dialog-new-chat.ui', + # 'ui/chatty-dialog-new-chat.ui', 'ui/chatty-fp-row.ui', 'ui/chatty-list-row.ui', 'ui/chatty-message-row.ui', @@ -88,6 +88,7 @@ chatty_sources += [ 'chatty-manager.c', 'chatty-application.c', 'chatty-chat-list.c', + 'chatty-contact-list.c', 'chatty-window.c', 'dialogs/chatty-info-dialog.c', 'dialogs/chatty-settings-dialog.c', diff --git a/src/ui/chatty-contact-list.ui b/src/ui/chatty-contact-list.ui new file mode 100644 index 0000000000000000000000000000000000000000..dcb0d727d6313bb89ea60081f3dcef922e1f5594 --- /dev/null +++ b/src/ui/chatty-contact-list.ui @@ -0,0 +1,80 @@ + + + + diff --git a/src/ui/chatty-dialog-new-chat.ui b/src/ui/chatty-dialog-new-chat.ui index e59970a523ffa35efc1ab56e9ea8bc0986216a59..04893bb452d67cd003062d44ddec60e88f65ccd6 100644 --- a/src/ui/chatty-dialog-new-chat.ui +++ b/src/ui/chatty-dialog-new-chat.ui @@ -1,166 +1,206 @@ -