Unverified Commit b0801ac6 authored by Aline Gondim Santos's avatar Aline Gondim Santos Committed by Amin Bandali
Browse files

plugins: add ChatHandler API

Change-Id: I829a984f9cec1dfd6be0b62e0bd733cbe1231477
GitLab: jami-plugins#4
parent 317b43d4
......@@ -43,6 +43,7 @@
#include <api/lrc.h>
#include <api/newcallmodel.h>
#include <api/avmodel.h>
#include <api/pluginmodel.h>
// Client
#include "marshals.h"
......@@ -53,26 +54,9 @@
/* size of avatar */
static constexpr int AVATAR_WIDTH = 150; /* px */
static constexpr int AVATAR_HEIGHT = 150; /* px */
#define PLUGIN_ICON_SIZE 25
enum class RecordAction {
RECORD,
STOP,
SEND
};
struct CppImpl {
struct Interaction {
std::string conv;
uint64_t id;
lrc::api::interaction::Info info;
};
std::vector<Interaction> interactionsBuffer_;
lrc::api::AVModel* avModel_;
RecordAction current_action_ {RecordAction::RECORD};
// store current recording location
std::string saveFileName_;
};
class CppImpl;
struct _ChatView
{
......@@ -100,6 +84,7 @@ struct _ChatViewPrivate
QMetaObject::Connection composing_changed_connection;
QMetaObject::Connection interaction_removed;
QMetaObject::Connection update_interaction_connection;
QMetaObject::Connection update_plugin_status;
QMetaObject::Connection update_add_to_conversations;
QMetaObject::Connection local_renderer_connection;
......@@ -117,6 +102,9 @@ struct _ChatViewPrivate
bool video_started_by_settings;
GtkWidget* video_widget;
GtkWidget* record_popover;
GtkWidget* plugin_handlers_popover;
GtkWidget* plugin_box;
GtkWidget* list_chat_handlers_available;
GtkWidget* button_retry;
GtkWidget* button_main_action;
GtkWidget* label_time;
......@@ -130,6 +118,117 @@ G_DEFINE_TYPE_WITH_PRIVATE(ChatView, chat_view, GTK_TYPE_BOX);
#define CHAT_VIEW_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), CHAT_VIEW_TYPE, ChatViewPrivate))
enum class RecordAction {
RECORD,
STOP,
SEND
};
class CppImpl {
public:
explicit CppImpl(ChatView& widget);
struct Interaction {
std::string conv;
uint64_t id;
lrc::api::interaction::Info info;
};
std::vector<Interaction> interactionsBuffer_;
lrc::api::AVModel* avModel_;
lrc::api::PluginModel* pluginModel_;
RecordAction current_action_ {RecordAction::RECORD};
// store current recording location
std::string saveFileName_;
ChatView* self = nullptr;
ChatViewPrivate* widgets = nullptr;
void updatePluginList();
void add_chat_handler(lrc::api::plugin::PluginHandlerDetails);
};
CppImpl::CppImpl(ChatView& widget)
: self{&widget}
, widgets{CHAT_VIEW_GET_PRIVATE(&widget)}
{}
static void
activate_chat_handler(GtkToggleButton* switchBtn, GParamSpec*, ChatView* view);
void
CppImpl::add_chat_handler(lrc::api::plugin::PluginHandlerDetails chatHandlerDetails)
{
QString bestName = _("Unnamed handler");
auto* chatHandlerImage = gtk_image_new_from_icon_name("application-x-addon-symbolic", GTK_ICON_SIZE_LARGE_TOOLBAR);
auto accountId = widgets->conversation_->accountId;
auto peerId = widgets->conversation_->participants.front();
auto chatHandlerStatus = pluginModel_->getChatHandlerStatus(accountId, peerId);
bool isActive = false;
if (!chatHandlerDetails.name.isEmpty()) {
bestName = chatHandlerDetails.name;
if (!chatHandlerStatus.isEmpty()) {
for (const auto& toggledChatHandler : chatHandlerStatus)
if (toggledChatHandler == chatHandlerDetails.id) {
isActive = true;
break;
}
}
}
std::string chatHandlerID = chatHandlerDetails.id.toStdString();
if (!chatHandlerDetails.iconPath.isEmpty()) {
GdkPixbuf* chatHandlerIcon = gdk_pixbuf_new_from_file_at_size((chatHandlerDetails.iconPath).toStdString().c_str(), PLUGIN_ICON_SIZE, PLUGIN_ICON_SIZE, NULL);
chatHandlerImage = gtk_image_new_from_pixbuf(chatHandlerIcon);
}
gchar* text = nullptr;
text = g_markup_printf_escaped(
"<span font=\"10\">%s</span>",
qUtf8Printable(bestName)
);
auto* box_item = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 12);
GtkStyleContext* context_box;
context_box = gtk_widget_get_style_context(GTK_WIDGET(box_item));
gtk_style_context_add_class(context_box, "boxitem");
gtk_widget_set_name(box_item, chatHandlerID.c_str());
auto* activate_chathandler_button = gtk_check_button_new();
gtk_widget_set_can_focus(activate_chathandler_button, false);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(activate_chathandler_button), isActive);
g_signal_connect(activate_chathandler_button, "notify::active", G_CALLBACK(activate_chat_handler), self);
auto* info = gtk_label_new(nullptr);
gtk_label_set_markup(GTK_LABEL(info), text);
g_object_set(G_OBJECT(info), "ellipsize", PANGO_ELLIPSIZE_END, NULL);
g_object_set_data(G_OBJECT(info), "chatHandlerID", (void*)g_strdup(qUtf8Printable(chatHandlerDetails.id)));
gtk_container_add(GTK_CONTAINER(box_item), GTK_WIDGET(chatHandlerImage));
gtk_container_add(GTK_CONTAINER(box_item), GTK_WIDGET(info));
gtk_container_add(GTK_CONTAINER(box_item), GTK_WIDGET(activate_chathandler_button));
gtk_list_box_insert(GTK_LIST_BOX(widgets->list_chat_handlers_available), GTK_WIDGET(box_item), -1);
g_free(text);
}
void
CppImpl::updatePluginList()
{
auto row = 0;
while (GtkWidget* children = GTK_WIDGET(gtk_list_box_get_row_at_index(GTK_LIST_BOX(widgets->list_chat_handlers_available), row))) {
gtk_container_remove(GTK_CONTAINER(widgets->list_chat_handlers_available), children);
}
auto chatHandlers = pluginModel_->getChatHandlers();
for(const auto& chatHandler : chatHandlers)
{
lrc::api::plugin::PluginHandlerDetails chatHandlerDetails = pluginModel_->getChatHandlerDetails(chatHandler);
add_chat_handler(chatHandlerDetails);
}
}
enum {
NEW_MESSAGES_DISPLAYED,
HIDE_VIEW_CLICKED,
......@@ -158,6 +257,7 @@ chat_view_dispose(GObject *object)
QObject::disconnect(priv->new_interaction_connection);
QObject::disconnect(priv->composing_changed_connection);
QObject::disconnect(priv->update_interaction_connection);
QObject::disconnect(priv->update_plugin_status);
QObject::disconnect(priv->interaction_removed);
QObject::disconnect(priv->update_add_to_conversations);
QObject::disconnect(priv->local_renderer_connection);
......@@ -460,6 +560,88 @@ chat_view_show_recorder(ChatView *self, int pt_x, int pt_y, bool is_video_record
gtk_widget_hide(priv->button_retry);
}
static GtkToggleButton*
get_chathandler_btn(GtkListBoxRow* row)
{
auto* row_children = gtk_container_get_children(GTK_CONTAINER(row));
auto* box_infos = g_list_first(row_children)->data;
auto* children = gtk_container_get_children(GTK_CONTAINER(box_infos));
auto* button = g_list_last(children);
return GTK_TOGGLE_BUTTON(button->data);
}
static GtkLabel*
get_chathandler_label(GtkListBoxRow* row)
{
auto* row_children = gtk_container_get_children(GTK_CONTAINER(row));
auto* box_infos = g_list_first(row_children)->data;
auto* children = gtk_container_get_children(GTK_CONTAINER(box_infos));
auto* button = g_list_last(children);
return GTK_LABEL(g_list_previous(button)->data);
}
static void
activate_chat_handler(GtkToggleButton* switchBtn, GParamSpec*, ChatView* view)
{
g_return_if_fail(IS_CHAT_VIEW(view));
auto* priv = CHAT_VIEW_GET_PRIVATE(view);
auto rowIdx = 0;
while (auto* children = gtk_list_box_get_row_at_index(GTK_LIST_BOX(priv->list_chat_handlers_available), rowIdx)) {
auto* label = get_chathandler_label(GTK_LIST_BOX_ROW(children));
auto* btn = get_chathandler_btn(GTK_LIST_BOX_ROW(children));
if (switchBtn == btn) {
auto toggled = gtk_toggle_button_get_active(btn);
QString chatHandlerID = QString::fromStdString((gchar*)g_object_get_data(G_OBJECT(label), "chatHandlerID"));
auto accountId = priv->conversation_->accountId;
auto peerId = priv->conversation_->participants.front();
priv->cpp->pluginModel_->toggleChatHandler(chatHandlerID, accountId, peerId, toggled);
}
++rowIdx;
}
}
static void
chat_handler_list(ChatView *self)
{
g_return_if_fail(IS_CHAT_VIEW(self));
auto* priv = CHAT_VIEW_GET_PRIVATE(self);
auto row = 0;
while (GtkWidget* children = GTK_WIDGET(gtk_list_box_get_row_at_index(GTK_LIST_BOX(priv->list_chat_handlers_available), row))) {
auto* chatHandlerName = get_chathandler_label(GTK_LIST_BOX_ROW(children));
std::string chatHandlerNameStr = gtk_label_get_text(GTK_LABEL(chatHandlerName));
gtk_widget_show_all(children);
++row;
}
}
void
chat_view_show_handlers_list(ChatView *self, int pt_x, int pt_y)
{
g_return_if_fail(IS_CHAT_VIEW(self));
auto* priv = CHAT_VIEW_GET_PRIVATE(self);
gtk_popover_set_relative_to(GTK_POPOVER(priv->plugin_handlers_popover), GTK_WIDGET(priv->box_webkit_chat_container));
GdkRectangle rect;
rect.width = 1;
rect.height = 1;
rect.x = pt_x;
rect.y = pt_y;
gtk_popover_set_pointing_to(GTK_POPOVER(priv->plugin_handlers_popover), &rect);
#if GTK_CHECK_VERSION(3,22,0)
gtk_popover_popdown(GTK_POPOVER(priv->plugin_handlers_popover));
#endif
gtk_widget_show_all(priv->plugin_handlers_popover);
chat_handler_list(self);
gtk_list_box_set_selection_mode(GTK_LIST_BOX(priv->list_chat_handlers_available), GTK_SELECTION_NONE);
}
static gboolean
on_timer_duration_timeout(ChatView* view)
{
......@@ -662,6 +844,18 @@ webkit_chat_container_script_dialog(GtkWidget* webview, gchar *interaction, Chat
if (g_settings_get_boolean(priv->settings, "enable-typing-indication")) {
(*priv->accountInfo_)->conversationModel->setIsComposing(priv->conversation_->uid, composing);
}
} else if (order.find("LIST_PLUGIN_HANDLERS:") == 0) {
auto pos_str {order.substr(std::string("LIST_PLUGIN_HANDLERS:").size())};
auto sep_idx = pos_str.find("x");
if (sep_idx == std::string::npos)
return;
try {
int pt_x = stoi(pos_str.substr(0, sep_idx));
int pt_y = stoi(pos_str.substr(sep_idx + 1));
chat_view_show_handlers_list(self, pt_x, pt_y);
} catch (...) {
// ignore
}
}
}
......@@ -683,6 +877,8 @@ chat_view_class_init(ChatViewClass *klass)
"/net/jami/JamiGnome/chatview.ui");
gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), ChatView, box_webkit_chat_container);
gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), ChatView, plugin_handlers_popover);
gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), ChatView, list_chat_handlers_available);
chat_view_signals[NEW_MESSAGES_DISPLAYED] = g_signal_new (
"new-interactions-displayed",
......@@ -969,6 +1165,7 @@ update_chatview_frame(ChatView* self)
}
} catch (const std::out_of_range&) {}
chat_view_set_record_visible(self, lrc::api::Lrc::activeCalls().size() == 0);
chat_view_set_plugin_visible(self, lrc::api::PluginModel().getPluginsEnabled() && lrc::api::PluginModel().getChatHandlers().size() > 0);
}
static void
......@@ -1154,7 +1351,7 @@ build_chat_view(ChatView* self)
}
});
priv->cpp = new CppImpl();
priv->cpp = new CppImpl(*self);
if (webkit_chat_container_is_ready(WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container)))
webkit_chat_container_ready(self);
......@@ -1164,7 +1361,8 @@ GtkWidget *
chat_view_new (WebKitChatContainer* webkit_chat_container,
AccountInfoPointer const & accountInfo,
lrc::api::conversation::Info& conversation,
lrc::api::AVModel& avModel)
lrc::api::AVModel& avModel,
lrc::api::PluginModel& pluginModel)
{
ChatView *self = CHAT_VIEW(g_object_new(CHAT_VIEW_TYPE, NULL));
......@@ -1175,7 +1373,18 @@ chat_view_new (WebKitChatContainer* webkit_chat_container,
build_chat_view(self);
priv->cpp->avModel_ = &avModel;
priv->cpp->pluginModel_ = &pluginModel;
priv->readyToRecord_ = true;
priv->update_plugin_status = QObject::connect(
&*priv->cpp->pluginModel_, &lrc::api::PluginModel::chatHandlerStatusUpdated,
[self, priv](bool isVisible) {
if (!priv) return;
chat_view_set_plugin_visible(self, isVisible);
priv->cpp->updatePluginList();
});
priv->cpp->updatePluginList();
return (GtkWidget *)self;
}
......@@ -1206,3 +1415,10 @@ chat_view_set_record_visible(ChatView *self, gboolean visible)
auto priv = CHAT_VIEW_GET_PRIVATE(self);
webkit_chat_set_record_visible(WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container), visible);
}
void
chat_view_set_plugin_visible(ChatView *self, gboolean visible)
{
auto priv = CHAT_VIEW_GET_PRIVATE(self);
webkit_chat_set_plugin_visible(WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container), visible);
}
......@@ -35,6 +35,7 @@ namespace lrc
namespace api
{
class AVModel;
class PluginModel;
namespace conversation
{
struct Info;
......@@ -57,10 +58,12 @@ GType chat_view_get_type (void) G_GNUC_CONST;
GtkWidget *chat_view_new (WebKitChatContainer* view,
AccountInfoPointer const & accountInfo,
lrc::api::conversation::Info& conversation,
lrc::api::AVModel& avModel);
lrc::api::AVModel& avModel,
lrc::api::PluginModel& pluginModel);
lrc::api::conversation::Info& chat_view_get_conversation(ChatView*);
void chat_view_update_temporary(ChatView*);
void chat_view_set_header_visible(ChatView*, gboolean);
void chat_view_set_record_visible(ChatView*, gboolean);
void chat_view_set_plugin_visible(ChatView*, gboolean);
G_END_DECLS
......@@ -245,7 +245,7 @@ public:
void add_title(const QString& title);
void add_present_contact(const QString& uri, const QString& custom_data, RowType custom_type, const QString& accountId);
void add_conference(const VectorString& uris, const QString& custom_data, const QString& accountId);
void add_media_handler(lrc::api::plugin::MediaHandlerDetails mediaHandlerDetails);
void add_media_handler(lrc::api::plugin::PluginHandlerDetails mediaHandlerDetails);
void insertControls();
void checkControlsFading();
......@@ -761,16 +761,10 @@ activate_media_handler(GtkToggleButton* switchBtn, GParamSpec*, CurrentCallView*
callToToggle = priv->cpp->conversation->confId;
priv->cpp->lrc_.getPluginModel().toggleCallMediaHandler(mediaHandlerID, callToToggle, toggled);
auto mediaHandlerStatus = priv->cpp->lrc_.getPluginModel().getCallMediaHandlerStatus(callToToggle)[callToToggle];
auto mediaHandlerStatus = priv->cpp->lrc_.getPluginModel().getCallMediaHandlerStatus(callToToggle);
}
++rowIdx;
}
#if GTK_CHECK_VERSION(3,22,0)
gtk_popover_popdown(GTK_POPOVER(priv->activate_plugin_popover));
#else
gtk_widget_hide(GTK_WIDGET(priv->activate_plugin_popover));
#endif
}
static void
......@@ -1065,12 +1059,12 @@ CppImpl::setup(WebKitChatContainer* chat_widget,
}
void
CppImpl::add_media_handler(lrc::api::plugin::MediaHandlerDetails mediaHandlerDetails)
CppImpl::add_media_handler(lrc::api::plugin::PluginHandlerDetails mediaHandlerDetails)
{
QString bestName = _("No name!");
auto* mediaHandlerImage = gtk_image_new_from_icon_name("application-x-addon-symbolic", GTK_ICON_SIZE_LARGE_TOOLBAR);
auto mediaHandlerStatus = lrc_.getPluginModel().getCallMediaHandlerStatus(conversation->callId)[conversation->callId];
auto mediaHandlerStatus = lrc_.getPluginModel().getCallMediaHandlerStatus(conversation->callId);
bool isActive = false;
if (!mediaHandlerDetails.name.isEmpty()) {
bestName = mediaHandlerDetails.name;
......@@ -1127,15 +1121,12 @@ CppImpl::updatePluginList()
gtk_container_remove(GTK_CONTAINER(widgets->list_media_handlers_available), children);
}
auto callMediaHandlers = lrc_.getPluginModel().listCallMediaHandlers();
auto callMediaHandlers = lrc_.getPluginModel().getCallMediaHandlers();
if (lrc_.getPluginModel().listCallMediaHandlers().size() > 0)
for(const auto& callMediaHandler : callMediaHandlers)
{
for(const auto& callMediaHandler : callMediaHandlers)
{
lrc::api::plugin::MediaHandlerDetails mediaHandlerDetails = lrc_.getPluginModel().getCallMediaHandlerDetails(callMediaHandler);
add_media_handler(mediaHandlerDetails);
}
lrc::api::plugin::PluginHandlerDetails mediaHandlerDetails = lrc_.getPluginModel().getCallMediaHandlerDetails(callMediaHandler);
add_media_handler(mediaHandlerDetails);
}
}
......@@ -1570,11 +1561,12 @@ CppImpl::setCallInfo()
// init chat view
widgets->chat_view = chat_view_new(WEBKIT_CHAT_CONTAINER(widgets->webkit_chat_container),
*accountInfo, *conversation, *avModel_);
*accountInfo, *conversation, *avModel_, lrc_.getPluginModel());
gtk_container_add(GTK_CONTAINER(widgets->frame_chat), widgets->chat_view);
chat_view_set_header_visible(CHAT_VIEW(widgets->chat_view), FALSE);
chat_view_set_record_visible(CHAT_VIEW(widgets->chat_view), FALSE);
chat_view_set_plugin_visible(CHAT_VIEW(widgets->chat_view), FALSE);
}
void
......@@ -1966,7 +1958,7 @@ void
CppImpl::update_view()
{
// only shows the plugin button if plugins are enabled AND there is any plugin loaded
if (lrc_.getPluginModel().getPluginsEnabled() && lrc_.getPluginModel().listLoadedPlugins().size() > 0)
if (lrc_.getPluginModel().getPluginsEnabled() && lrc_.getPluginModel().getCallMediaHandlers().size() > 0)
{
gtk_widget_show_all(widgets->togglebutton_activate_plugin);
}
......
......@@ -87,6 +87,7 @@ struct _IncomingCallViewPrivate
GSettings *settings;
lrc::api::AVModel* avModel_;
lrc::api::PluginModel* pluginModel_;
};
G_DEFINE_TYPE_WITH_PRIVATE(IncomingCallView, incoming_call_view, GTK_TYPE_BOX);
......@@ -320,16 +321,19 @@ set_call_info(IncomingCallView *view) {
auto chat_view = chat_view_new(WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container),
*priv->accountInfo_,
*priv->conversation_,
*priv->avModel_);
*priv->avModel_,
*priv->pluginModel_);
gtk_widget_show(chat_view);
chat_view_set_header_visible(CHAT_VIEW(chat_view), FALSE);
chat_view_set_record_visible(CHAT_VIEW(chat_view), FALSE);
chat_view_set_plugin_visible(CHAT_VIEW(chat_view), FALSE);
gtk_container_add(GTK_CONTAINER(priv->frame_chat), chat_view);
}
GtkWidget *
incoming_call_view_new(WebKitChatContainer* view,
lrc::api::AVModel& avModel,
lrc::api::PluginModel& pluginModel,
AccountInfoPointer const & accountInfo,
lrc::api::conversation::Info& conversation)
{
......@@ -340,6 +344,7 @@ incoming_call_view_new(WebKitChatContainer* view,
priv->conversation_ = &conversation;
priv->accountInfo_ = &accountInfo;
priv->avModel_ = &avModel;
priv->pluginModel_ = &pluginModel;
priv->messaging_widget = messaging_widget_new(avModel, conversation, accountInfo);
gtk_box_pack_start(GTK_BOX(priv->box_messaging_widget), priv->messaging_widget, TRUE, TRUE, 0);
......
......@@ -34,6 +34,7 @@ namespace lrc
namespace api
{
class AVModel;
class PluginModel;
namespace conversation
{
struct Info;
......@@ -56,6 +57,7 @@ typedef struct _IncomingCallViewClass IncomingCallViewClass;
GType incoming_call_view_get_type (void) G_GNUC_CONST;
GtkWidget *incoming_call_view_new (WebKitChatContainer* view,
lrc::api::AVModel& avModel,
lrc::api::PluginModel& pluginModel,
AccountInfoPointer const & accountInfo,
lrc::api::conversation::Info& conversation);
void incoming_call_view_let_a_message(IncomingCallView* view, const lrc::api::conversation::Info& conv);
......
......@@ -1619,7 +1619,7 @@ CppImpl::displayIncomingView(lrc::api::conversation::Info& conversation, bool re
chatViewConversation_ = conversation;
GtkWidget* incoming_call_view =
incoming_call_view_new(webkitChatContainer(redraw_webview),
lrc_->getAVModel(), accountInfo_,
lrc_->getAVModel(), lrc_->getPluginModel(), accountInfo_,
*chatViewConversation_);
g_signal_connect(incoming_call_view, "call-hungup",
G_CALLBACK(on_incoming_call_view_decline_call), self);
......@@ -1653,7 +1653,7 @@ GtkWidget*
CppImpl::displayChatView(lrc::api::conversation::Info& conversation, bool redraw_webview)
{
chatViewConversation_ = conversation;
auto* new_view = chat_view_new(webkitChatContainer(redraw_webview), accountInfo_, *chatViewConversation_, lrc_->getAVModel());
auto* new_view = chat_view_new(webkitChatContainer(redraw_webview), accountInfo_, *chatViewConversation_, lrc_->getAVModel(), lrc_->getPluginModel());
g_signal_connect_swapped(new_view, "hide-view-clicked", G_CALLBACK(on_hide_view_clicked), self);
g_signal_connect(new_view, "add-conversation-clicked", G_CALLBACK(on_add_conversation_clicked), self);
g_signal_connect(new_view, "place-audio-call-clicked", G_CALLBACK(on_place_audio_call_clicked), self);
......
......@@ -300,7 +300,7 @@ refreshPluginsList(PluginSettingsView *self)
// Build devices list
while (GtkWidget* children = GTK_WIDGET(gtk_list_box_get_row_at_index(GTK_LIST_BOX(priv->list_installed_plugins), 0)))
gtk_container_remove(GTK_CONTAINER(priv->list_installed_plugins), children);
auto plugins = priv->cpp->pluginModel_->listAvailablePlugins();
auto plugins = priv->cpp->pluginModel_->getInstalledPlugins();
for (const auto& plugin : plugins)
add_plugin(self, plugin);
gtk_widget_set_halign(GTK_WIDGET(priv->list_installed_plugins), GTK_ALIGN_FILL);
......
......@@ -764,6 +764,14 @@ webkit_chat_set_record_visible(WebKitChatContainer *view, bool isVisible)
g_free(function_call);
}
void
webkit_chat_set_plugin_visible(WebKitChatContainer *view, bool isVisible)
{
gchar* function_call = g_strdup_printf("displayPluginControl(%s)", isVisible ? "true" : "false");
webkit_chat_container_execute_js(view, function_call);
g_free(function_call);
}
void
webkit_chat_set_dark_mode(WebKitChatContainer *view, bool darkMode, const std::string& background)
{
......
......@@ -56,6 +56,7 @@ void webkit_chat_container_set_display_links (WebKitChatContainer *view
void webkit_chat_container_set_invitation (WebKitChatContainer *view, bool show, const std::string& contactUri, const std::string& contactId);
void webkit_chat_set_header_visible (WebKitChatContainer *view, bool isVisible);
void webkit_chat_set_record_visible (WebKitChatContainer *view, bool isVisible);
void webkit_chat_set_plugin_visible (WebKitChatContainer *view, bool isVisible);
void webkit_chat_set_dark_mode (WebKitChatContainer *view, bool darkMode, const std::string& background);
void webkit_chat_set_is_composing (WebKitChatContainer *view, const std::string& contactUri, bool isComposing);
void webkit_chat_update_chatview_frame (WebKitChatContainer *view, bool accountEnabled, bool isBanned, bool isInvited, const gchar* alias, const gchar* bestId);
......
......@@ -23,8 +23,42 @@
</packing>
</child>
<!-- end of chat text view -->
</template>
<object class="GtkPopover" id="plugin_handlers_popover">
<property name="can_focus">False</property>
<property name="height_request">200</property>
<property name="width_request">300</property>
<child>
<object class="GtkBox" id="plugin_box">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<property name="spacing">10</property>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="halign">center</property>
<property name="label" translatable="yes">Choose plugin</property>
</object>
</child>
<child>
<object class="GtkScrolledWindow">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="shadow_type">in</property>
<property name="min_content_height">200</property>
<property name="halign">fill</property>
<child>
<object class="GtkListBox" id="list_chat_handlers_available">
<property name="visible">True</property>
<property name="can_focus">True</property>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
<object class="GtkImage" id="image_back_arrow">
<property name="visible">True</property>
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment