Commit 18040cf2 authored by Evangelos Ribeiro Tzaras's avatar Evangelos Ribeiro Tzaras
Browse files

Update upstream source from tag 'upstream/0.3.4'

Update to upstream version '0.3.4'
with Debian dir 3497f89bb67cac631aa26a3d71edf8f8163d4d4b
parents 88358de0 aa364f28
project(
'chatty', 'c', 'cpp',
version: '0.3.3',
version: '0.3.4',
meson_version: '>= 0.46.0',
)
......
......@@ -36,6 +36,8 @@ src/chatty-utils.h
src/chatty-window.c
src/chatty-window.h
src/dialogs/chatty-info-dialog.c
src/dialogs/chatty-ma-chat-info.c
src/dialogs/chatty-ma-chat-info.h
src/dialogs/chatty-info-dialog.h
src/dialogs/chatty-pp-chat-info.c
src/dialogs/chatty-pp-chat-info.h
......@@ -60,6 +62,7 @@ src/ui/chatty-contact-row.ui
src/ui/chatty-dialog-join-muc.ui
src/ui/chatty-dialog-new-chat.ui
src/ui/chatty-info-dialog.ui
src/ui/chatty-ma-chat-info.ui
src/ui/chatty-pp-chat-info.ui
src/ui/chatty-fp-row.ui
src/ui/chatty-list-row.ui
......
#!/bin/sh
#!/bin/bash
set -e
ABS_BUILDDIR='@ABS_BUILDDIR@'
......@@ -6,4 +6,5 @@ ABS_SRCDIR='@ABS_SRCDIR@'
export GSETTINGS_SCHEMA_DIR="${ABS_BUILDDIR}/data"
set -x
exec "${ABS_BUILDDIR}/src/chatty" "$@"
export MALLOC_PERTURB_="$(($RANDOM % 255 + 1))"
MALLOC_CHECK_=2 exec "${ABS_BUILDDIR}/src/chatty" "$@"
......@@ -2342,6 +2342,67 @@ history_update_chat (ChattyHistory *self,
g_task_return_boolean (task, TRUE);
}
static void
history_update_user (ChattyHistory *self,
GTask *task)
{
ChattyAccount *account;
const char *user_name, *name;
ChattyFileInfo *file_info;
sqlite3_stmt *stmt;
ChattyProtocol protocol;
int id, file_id = 0;
g_assert (CHATTY_IS_HISTORY (self));
g_assert (G_IS_TASK (task));
g_assert (g_thread_self () == self->worker_thread);
if (!self->db) {
g_task_return_new_error (task,
G_IO_ERROR, G_IO_ERROR_FAILED,
"Database not opened");
return;
}
account = g_object_get_data (G_OBJECT (task), "account");
g_assert (CHATTY_IS_ACCOUNT (account));
user_name = chatty_account_get_username (account);
protocol = chatty_item_get_protocols (CHATTY_ITEM (account));
name = chatty_item_get_name (CHATTY_ITEM (account));
if (!user_name || !*user_name) {
g_task_return_new_error (task,
G_IO_ERROR, G_IO_ERROR_FAILED,
"Username is empty");
return;
}
id = insert_or_ignore_user (self, protocol, user_name, name, task);
if (!id)
return;
file_info = chatty_item_get_avatar_file (CHATTY_ITEM (account));
file_id = add_file_info (self, file_info);
if (!file_id) {
g_task_return_boolean (task, TRUE);
return;
}
sqlite3_prepare_v2 (self->db,
"UPDATE users SET avatar_id=?1 "
"WHERE users.id=?2",
-1, &stmt, NULL);
history_bind_int (stmt, 1, file_id, "binding when setting avatar");
history_bind_int (stmt, 2, id, "binding when settings avatar");
sqlite3_step (stmt);
sqlite3_finalize (stmt);
g_task_return_boolean (task, TRUE);
}
static void
history_delete_chat (ChattyHistory *self,
GTask *task)
......@@ -2403,6 +2464,63 @@ history_delete_chat (ChattyHistory *self,
status, sqlite3_errmsg (self->db));
}
static void
history_load_account (ChattyHistory *self,
GTask *task)
{
ChattyAccount *account;
sqlite3_stmt *stmt;
const char *user_name;
int status;
g_assert (CHATTY_IS_HISTORY (self));
g_assert (G_IS_TASK (task));
g_assert (g_thread_self () == self->worker_thread);
if (!self->db) {
g_task_return_new_error (task,
G_IO_ERROR, G_IO_ERROR_FAILED,
"Database not opened");
return;
}
account = g_object_get_data (G_OBJECT (task), "account");
g_assert (CHATTY_IS_ACCOUNT (account));
user_name = chatty_account_get_username (account);
if (!user_name || !*user_name) {
g_task_return_new_error (task,
G_IO_ERROR, G_IO_ERROR_FAILED,
"Error: username name is empty");
return;
}
sqlite3_prepare_v2 (self->db, "SELECT users.alias,files.url,files.path FROM users "
"LEFT JOIN files ON files.id=users.avatar_id "
"WHERE users.username=? LIMIT 1;", -1, &stmt, NULL);
history_bind_text (stmt, 1, user_name, "binding when getting user details");
if (sqlite3_step (stmt) == SQLITE_ROW) {
const char *name, *avatar_url, *avatar_path;
GObject *object;
name = (char *)sqlite3_column_text (stmt, 0);
avatar_url = (char *)sqlite3_column_text (stmt, 1);
avatar_path = (char *)sqlite3_column_text (stmt, 2);
object = G_OBJECT (task);
g_object_set_data_full (object, "name", g_strdup (name), g_free);
g_object_set_data_full (object, "avatar-url", g_strdup (avatar_url), g_free);
g_object_set_data_full (object, "avatar-path", g_strdup (avatar_path), g_free);
}
status = sqlite3_finalize (stmt);
warn_if_sql_error (status, "finalizing when getting user details");
g_task_return_boolean (task, TRUE);
}
static void
history_get_chat_timestamp (ChattyHistory *self,
GTask *task)
......@@ -2959,6 +3077,38 @@ chatty_history_update_chat (ChattyHistory *self,
return status;
}
gboolean
chatty_history_update_user (ChattyHistory *self,
ChattyAccount *account)
{
g_autoptr(GTask) task = NULL;
g_autoptr(GError) error = NULL;
gboolean status;
g_return_val_if_fail (CHATTY_IS_HISTORY (self), FALSE);
g_return_val_if_fail (CHATTY_IS_ACCOUNT (account), FALSE);
task = g_task_new (NULL, NULL, NULL, NULL);
g_object_ref (task);
g_task_set_source_tag (task, chatty_history_update_user);
g_task_set_task_data (task, history_update_user, NULL);
g_object_ref (account);
g_object_set_data_full (G_OBJECT (task), "account", account, g_object_unref);
g_async_queue_push (self->queue, task);
/* Wait until the task is completed */
while (!g_task_get_completed (task))
g_main_context_iteration (NULL, TRUE);
status = g_task_propagate_boolean (task, &error);
if (error)
g_warning ("Error updating user: %s", error->message);
return status;
}
/**
* chatty_history_delete_chat_async:
* @self: a #ChattyHistory
......@@ -3012,6 +3162,39 @@ chatty_history_delete_chat_finish (ChattyHistory *self,
return g_task_propagate_boolean (G_TASK (result), error);
}
void
chatty_history_load_account_async (ChattyHistory *self,
ChattyAccount *account,
GAsyncReadyCallback callback,
gpointer user_data)
{
GTask *task;
g_return_if_fail (CHATTY_IS_HISTORY (self));
g_return_if_fail (CHATTY_IS_ACCOUNT (account));
g_return_if_fail (callback);
task = g_task_new (self, NULL, callback, user_data);
g_task_set_source_tag (task, chatty_history_load_account_async);
g_task_set_task_data (task, history_load_account, NULL);
g_object_ref (account);
g_object_set_data_full (G_OBJECT (task), "account", account, g_object_unref);
g_async_queue_push (self->queue, task);
}
gboolean
chatty_history_load_account_finish (ChattyHistory *self,
GAsyncResult *result,
GError **error)
{
g_return_val_if_fail (CHATTY_IS_HISTORY (self), FALSE);
g_return_val_if_fail (G_IS_TASK (result), FALSE);
g_return_val_if_fail (!error || !*error, FALSE);
return g_task_propagate_boolean (G_TASK (result), error);
}
static void
finish_cb (GObject *object,
GAsyncResult *result,
......
......@@ -64,6 +64,8 @@ GPtrArray *chatty_history_get_chats_finish (ChattyHistory *self,
GError **error);
gboolean chatty_history_update_chat (ChattyHistory *self,
ChattyChat *chat);
gboolean chatty_history_update_user (ChattyHistory *self,
ChattyAccount *account);
void chatty_history_delete_chat_async (ChattyHistory *self,
ChattyChat *chat,
GAsyncReadyCallback callback,
......@@ -71,6 +73,13 @@ void chatty_history_delete_chat_async (ChattyHistory *self,
gboolean chatty_history_delete_chat_finish (ChattyHistory *self,
GAsyncResult *result,
GError **error);
void chatty_history_load_account_async (ChattyHistory *self,
ChattyAccount *account,
GAsyncReadyCallback callback,
gpointer user_data);
gboolean chatty_history_load_account_finish (ChattyHistory *self,
GAsyncResult *result,
GError **error);
/* old APIs */
void chatty_history_open (ChattyHistory *self,
......
/* -*- mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*- */
/* chatty-chat.c
/* chatty-pp-chat.c
*
* Copyright 2020 Purism SPC
*
......@@ -9,7 +9,7 @@
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#define G_LOG_DOMAIN "chatty-chat"
#define G_LOG_DOMAIN "chatty-pp-chat"
#include <purple.h>
......@@ -37,10 +37,10 @@ enum {
};
/**
* SECTION: chatty-chat
* SECTION: chatty-pp-chat
* @title: ChattyChat
* @short_description: An abstraction over #PurpleConversation
* @include: "chatty-chat.h"
* @include: "chatty-pp-chat.h"
*
* libpurple doesn’t have a nice OOP interface for managing anything.
* This class hides all the complexities surrounding it.
......@@ -500,6 +500,9 @@ chatty_pp_chat_get_username (ChattyChat *chat)
g_assert (CHATTY_IS_PP_CHAT (self));
if (self->username && *self->username)
return self->username;
if (self->pp_chat)
username = purple_account_get_username (self->pp_chat->account);
......@@ -512,7 +515,7 @@ chatty_pp_chat_get_username (ChattyChat *chat)
if (username && *username && !self->username)
self->username = chatty_utils_jabber_id_strip (username);
if (self->username && *self->username)
if (self->username)
return self->username;
return "";
......@@ -1005,6 +1008,7 @@ chatty_pp_chat_finalize (GObject *object)
g_object_unref (self->sorted_chat_users);
g_free (self->last_message);
g_free (self->chat_name);
g_free (self->username);
G_OBJECT_CLASS (chatty_pp_chat_parent_class)->finalize (object);
}
......
......@@ -26,7 +26,12 @@ static const SecretSchema *
secret_store_get_schema (void)
{
static const SecretSchema password_schema = {
"sm.puri.Chatty", SECRET_SCHEMA_NONE,
/** SECRET_SCHEMA_DONT_MATCH_NAME is used as a workaround for a bug in gnome-keyring
* which prevents cold keyrings from being searched (and hence does not prompt for unlocking)
* see https://gitlab.gnome.org/GNOME/gnome-keyring/-/issues/89 and
* https://gitlab.gnome.org/GNOME/libsecret/-/issues/7 for more information
*/
"sm.puri.Chatty", SECRET_SCHEMA_DONT_MATCH_NAME,
{
{ CHATTY_USERNAME_ATTRIBUTE, SECRET_SCHEMA_ATTRIBUTE_STRING },
{ CHATTY_SERVER_ATTRIBUTE, SECRET_SCHEMA_ATTRIBUTE_STRING },
......@@ -155,7 +160,13 @@ chatty_secret_load_async (GCancellable *cancellable,
schema = secret_store_get_schema ();
task = g_task_new (NULL, cancellable, callback, user_data);
attr = secret_attributes_build (schema, NULL);
/** With using SECRET_SCHEMA_DONT_MATCH_NAME we need some other attribute
* (apart from the schema name itself) to use for the lookup.
* The protocol attribute seems like a reasonable choice.
*/
attr = secret_attributes_build (schema,
CHATTY_PROTOCOL_ATTRIBUTE, PROTOCOL_MATRIX_STR,
NULL);
CHATTY_TRACE_MSG ("loading secret accounts");
secret_service_search (NULL, schema, attr,
......
......@@ -7,6 +7,7 @@
<file preprocess="xml-stripblanks">ui/chatty-contact-row.ui</file>
<file preprocess="xml-stripblanks">ui/chatty-image-item.ui</file>
<file preprocess="xml-stripblanks">ui/chatty-message-row.ui</file>
<file preprocess="xml-stripblanks">ui/chatty-ma-chat-info.ui</file>
<file preprocess="xml-stripblanks">ui/chatty-pp-chat-info.ui</file>
<file preprocess="xml-stripblanks">ui/chatty-info-dialog.ui</file>
<file preprocess="xml-stripblanks">ui/chatty-ma-account-details.ui</file>
......
......@@ -19,8 +19,10 @@
#include "chatty-list-row.h"
#include "chatty-fp-row.h"
#include "chatty-pp-chat.h"
#include "matrix/chatty-ma-chat.h"
#include "chatty-manager.h"
#include "chatty-utils.h"
#include "chatty-ma-chat-info.h"
#include "chatty-pp-chat-info.h"
#include "chatty-info-dialog.h"
......@@ -29,7 +31,8 @@ struct _ChattyInfoDialog
GtkDialog parent_instance;
GtkWidget *main_stack;
GtkWidget *main_page;
GtkWidget *chat_type_stack;
GtkWidget *ma_chat_info;
GtkWidget *pp_chat_info;
GtkWidget *invite_page;
......@@ -64,7 +67,7 @@ info_dialog_cancel_clicked_cb (ChattyInfoDialog *self)
gtk_widget_hide (self->invite_button);
gtk_widget_show (self->new_invite_button);
gtk_stack_set_visible_child (GTK_STACK (self->main_stack),
self->main_page);
self->chat_type_stack);
}
static void
......@@ -138,7 +141,8 @@ chatty_info_dialog_class_init (ChattyInfoDialogClass *klass)
"ui/chatty-info-dialog.ui");
gtk_widget_class_bind_template_child (widget_class, ChattyInfoDialog, main_stack);
gtk_widget_class_bind_template_child (widget_class, ChattyInfoDialog, main_page);
gtk_widget_class_bind_template_child (widget_class, ChattyInfoDialog, chat_type_stack);
gtk_widget_class_bind_template_child (widget_class, ChattyInfoDialog, ma_chat_info);
gtk_widget_class_bind_template_child (widget_class, ChattyInfoDialog, pp_chat_info);
gtk_widget_class_bind_template_child (widget_class, ChattyInfoDialog, invite_page);
......@@ -153,6 +157,7 @@ chatty_info_dialog_class_init (ChattyInfoDialogClass *klass)
gtk_widget_class_bind_template_callback (widget_class, info_dialog_invite_clicked_cb);
gtk_widget_class_bind_template_callback (widget_class, info_dialog_contact_id_changed_cb);
g_type_ensure (CHATTY_TYPE_MA_CHAT_INFO);
g_type_ensure (CHATTY_TYPE_PP_CHAT_INFO);
}
......@@ -186,7 +191,15 @@ chatty_info_dialog_set_chat (ChattyInfoDialog *self,
if (!g_set_object (&self->chat, chat))
return;
chatty_pp_chat_info_set_item (CHATTY_PP_CHAT_INFO (self->pp_chat_info), chat);
if (CHATTY_IS_MA_CHAT (chat)) {
chatty_ma_chat_info_set_item (CHATTY_MA_CHAT_INFO (self->ma_chat_info), chat);
chatty_pp_chat_info_set_item (CHATTY_PP_CHAT_INFO (self->pp_chat_info), NULL);
gtk_stack_set_visible_child (GTK_STACK (self->chat_type_stack), self->ma_chat_info);
} else {
chatty_ma_chat_info_set_item (CHATTY_MA_CHAT_INFO (self->ma_chat_info), NULL);
chatty_pp_chat_info_set_item (CHATTY_PP_CHAT_INFO (self->pp_chat_info), chat);
gtk_stack_set_visible_child (GTK_STACK (self->chat_type_stack), self->pp_chat_info);
}
if (chatty_item_get_protocols (CHATTY_ITEM (chat)) == CHATTY_PROTOCOL_XMPP &&
!chatty_chat_is_im (self->chat))
......
/* -*- mode: c; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* chatty-ma-chat-info.c
*
* Copyright 2021 Purism SPC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Author(s):
* Mohammed Sadiq <sadiq@sadiqpk.org>
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#define G_LOG_DOMAIN "chatty-ma-chat-info"
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <glib/gi18n.h>
#include "chatty-avatar.h"
#include "chatty-list-row.h"
#include "chatty-fp-row.h"
#include "matrix/chatty-ma-chat.h"
#include "chatty-ma-chat-info.h"
#include "chatty-log.h"
struct _ChattyMaChatInfo
{
HdyPreferencesPage parent_instance;
ChattyChat *chat;
GtkWidget *avatar_button;
GtkWidget *avatar;
GtkWidget *name_label;
GtkWidget *matrix_id_label;
GtkWidget *avatar_chooser_dialog;
};
G_DEFINE_TYPE (ChattyMaChatInfo, chatty_ma_chat_info, HDY_TYPE_PREFERENCES_PAGE)
static void
chatty_ma_chat_info_finalize (GObject *object)
{
ChattyMaChatInfo *self = (ChattyMaChatInfo *)object;
g_clear_object (&self->chat);
G_OBJECT_CLASS (chatty_ma_chat_info_parent_class)->finalize (object);
}
static void
chatty_ma_chat_info_class_init (ChattyMaChatInfoClass *klass)
{
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = chatty_ma_chat_info_finalize;
gtk_widget_class_set_template_from_resource (widget_class,
"/sm/puri/Chatty/"
"ui/chatty-ma-chat-info.ui");
gtk_widget_class_bind_template_child (widget_class, ChattyMaChatInfo, avatar_button);
gtk_widget_class_bind_template_child (widget_class, ChattyMaChatInfo, avatar);
gtk_widget_class_bind_template_child (widget_class, ChattyMaChatInfo, name_label);
gtk_widget_class_bind_template_child (widget_class, ChattyMaChatInfo, matrix_id_label);
gtk_widget_class_bind_template_child (widget_class, ChattyMaChatInfo, avatar_chooser_dialog);
}
static void
chatty_ma_chat_info_init (ChattyMaChatInfo *self)
{
GtkWidget *clamp, *window;
gtk_widget_init_template (GTK_WIDGET (self));
clamp = gtk_widget_get_ancestor (self->avatar, HDY_TYPE_CLAMP);
if (clamp) {
hdy_clamp_set_maximum_size (HDY_CLAMP (clamp), 360);
hdy_clamp_set_tightening_threshold (HDY_CLAMP (clamp), 320);
}
window = gtk_widget_get_ancestor (self->avatar, GTK_TYPE_DIALOG);
if (window)
gtk_window_set_transient_for (GTK_WINDOW (self->avatar_chooser_dialog),
GTK_WINDOW (window));
}
GtkWidget *
chatty_ma_chat_info_new (void)
{
return g_object_new (CHATTY_TYPE_MA_CHAT_INFO, NULL);
}
ChattyChat *
chatty_ma_chat_info_get_item (ChattyMaChatInfo *self)
{
g_return_val_if_fail (CHATTY_IS_MA_CHAT_INFO (self), NULL);
return self->chat;
}
void
chatty_ma_chat_info_set_item (ChattyMaChatInfo *self,
ChattyChat *chat)
{
g_return_if_fail (CHATTY_IS_MA_CHAT_INFO (self));
g_return_if_fail (!chat || CHATTY_IS_CHAT (chat));
if (!g_set_object (&self->chat, chat) || !chat)
return;
gtk_label_set_text (GTK_LABEL (self->matrix_id_label),
chatty_chat_get_chat_name (self->chat));
gtk_label_set_text (GTK_LABEL (self->name_label),
chatty_item_get_name (CHATTY_ITEM (self->chat)));
}
/* -*- mode: c; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* chatty-ma-chat-info.h
*
* Copyright 2021 Purism SPC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Author(s):
* Mohammed Sadiq <sadiq@sadiqpk.org>
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#pragma once
#include <gtk/gtk.h>
#include "chatty-chat.h"
G_BEGIN_DECLS
#define CHATTY_TYPE_MA_CHAT_INFO (chatty_ma_chat_info_get_type ())
G_DECLARE_FINAL_TYPE (ChattyMaChatInfo, chatty_ma_chat_info, CHATTY, MA_CHAT_INFO, HdyPreferencesPage)
GtkWidget *chatty_ma_chat_info_new (void);
ChattyChat *chatty_ma_chat_info_get_item (ChattyMaChatInfo *self);
void chatty_ma_chat_info_set_item (ChattyMaChatInfo *self,
ChattyChat *chat);
G_END_DECLS
......@@ -415,6 +415,11 @@ chatty_pp_chat_info_set_item (ChattyPpChatInfo *self,
g_return_if_fail (CHATTY_IS_PP_CHAT_INFO (self));
g_return_if_fail (!chat || CHATTY_IS_CHAT (chat));
if (self->chat)
g_signal_handlers_disconnect_by_func (self->chat,
pp_chat_info_encrypt_changed_cb,
self);
if (!g_set_object (&self->chat, chat))
return;
......@@ -425,10 +430,5 @@ chatty_pp_chat_info_set_item (ChattyPpChatInfo *self,