Conversation details dialog
This commit is contained in:
parent
387433ebb9
commit
5ba95ef6b7
|
@ -1,5 +1,7 @@
|
||||||
using Gtk;
|
using Gtk;
|
||||||
|
|
||||||
|
using Dino.Entities;
|
||||||
|
|
||||||
namespace Dino.Plugins {
|
namespace Dino.Plugins {
|
||||||
|
|
||||||
public enum Priority {
|
public enum Priority {
|
||||||
|
@ -20,7 +22,7 @@ public interface EncryptionListEntry : Object {
|
||||||
public abstract Entities.Encryption encryption { get; }
|
public abstract Entities.Encryption encryption { get; }
|
||||||
public abstract string name { get; }
|
public abstract string name { get; }
|
||||||
|
|
||||||
public abstract bool can_encrypt(Entities.Conversation conversation);
|
public abstract bool can_encrypt(Conversation conversation);
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract class AccountSettingsEntry : Object {
|
public abstract class AccountSettingsEntry : Object {
|
||||||
|
@ -33,11 +35,22 @@ public abstract class AccountSettingsEntry : Object {
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface AccountSettingsWidget : Gtk.Widget {
|
public interface AccountSettingsWidget : Gtk.Widget {
|
||||||
public abstract void set_account(Entities.Account account);
|
public abstract void set_account(Account account);
|
||||||
|
|
||||||
public abstract signal void activated();
|
public abstract signal void activated();
|
||||||
|
|
||||||
public abstract void deactivate();
|
public abstract void deactivate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public abstract class ContactDetailsProvider : Object {
|
||||||
|
public abstract string id { get; }
|
||||||
|
|
||||||
|
public abstract void populate(Conversation conversation, ContactDetails contact_details);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ContactDetails : Object {
|
||||||
|
public signal void save();
|
||||||
|
public signal void add(string category, string label, string desc, Widget widget);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -5,6 +5,7 @@ namespace Dino.Plugins {
|
||||||
public class Registry {
|
public class Registry {
|
||||||
internal ArrayList<EncryptionListEntry> encryption_list_entries = new ArrayList<EncryptionListEntry>();
|
internal ArrayList<EncryptionListEntry> encryption_list_entries = new ArrayList<EncryptionListEntry>();
|
||||||
internal ArrayList<AccountSettingsEntry> account_settings_entries = new ArrayList<AccountSettingsEntry>();
|
internal ArrayList<AccountSettingsEntry> account_settings_entries = new ArrayList<AccountSettingsEntry>();
|
||||||
|
internal ArrayList<ContactDetailsProvider> contact_details_entries = new ArrayList<ContactDetailsProvider>();
|
||||||
|
|
||||||
public bool register_encryption_list_entry(EncryptionListEntry entry) {
|
public bool register_encryption_list_entry(EncryptionListEntry entry) {
|
||||||
lock(encryption_list_entries) {
|
lock(encryption_list_entries) {
|
||||||
|
@ -28,6 +29,16 @@ public class Registry {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool register_contact_details_entry(ContactDetailsProvider entry) {
|
||||||
|
lock(contact_details_entries) {
|
||||||
|
foreach(ContactDetailsProvider e in contact_details_entries) {
|
||||||
|
if (e.id == entry.id) return false;
|
||||||
|
}
|
||||||
|
contact_details_entries.add(entry);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -45,6 +45,16 @@ public class MucManager : StreamInteractionModule, Object {
|
||||||
if (conversation != null) stream_interactor.get_module(ConversationManager.IDENTITY).close_conversation(conversation);
|
if (conversation != null) stream_interactor.get_module(ConversationManager.IDENTITY).close_conversation(conversation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[CCode (has_target = false)] public delegate void OnResult(Jid jid, Xep.DataForms.DataForm data_form, Object? store);
|
||||||
|
public void get_config_form(Account account, Jid jid, OnResult on_result, Object? store) {
|
||||||
|
Core.XmppStream stream = stream_interactor.get_stream(account);
|
||||||
|
if (stream == null) return;
|
||||||
|
stream.get_module(Xep.Muc.Module.IDENTITY).get_config_form(stream, jid.to_string(), (stream, jid, data_form, store) => {
|
||||||
|
Tuple<OnResult, Object?> tuple = store as Tuple<OnResult, Object?>;
|
||||||
|
tuple.a(new Jid(jid), data_form, tuple.b);
|
||||||
|
}, Tuple.create(on_result, store));
|
||||||
|
}
|
||||||
|
|
||||||
public void change_subject(Account account, Jid jid, string subject) {
|
public void change_subject(Account account, Jid jid, string subject) {
|
||||||
Core.XmppStream stream = stream_interactor.get_stream(account);
|
Core.XmppStream stream = stream_interactor.get_stream(account);
|
||||||
if (stream != null) stream.get_module(Xep.Muc.Module.IDENTITY).change_subject(stream, jid.bare_jid.to_string(), subject);
|
if (stream != null) stream.get_module(Xep.Muc.Module.IDENTITY).change_subject(stream, jid.bare_jid.to_string(), subject);
|
||||||
|
|
|
@ -27,6 +27,7 @@ set(RESOURCE_LIST
|
||||||
add_conversation/list_row.ui
|
add_conversation/list_row.ui
|
||||||
add_conversation/select_jid_fragment.ui
|
add_conversation/select_jid_fragment.ui
|
||||||
chat_input.ui
|
chat_input.ui
|
||||||
|
contact_details_dialog.ui
|
||||||
conversation_list_titlebar.ui
|
conversation_list_titlebar.ui
|
||||||
conversation_selector/view.ui
|
conversation_selector/view.ui
|
||||||
conversation_selector/chat_row_tooltip.ui
|
conversation_selector/chat_row_tooltip.ui
|
||||||
|
@ -84,6 +85,9 @@ SOURCES
|
||||||
src/ui/chat_input/occupants_tab_completer.vala
|
src/ui/chat_input/occupants_tab_completer.vala
|
||||||
src/ui/chat_input/smiley_converter.vala
|
src/ui/chat_input/smiley_converter.vala
|
||||||
src/ui/chat_input/view.vala
|
src/ui/chat_input/view.vala
|
||||||
|
src/ui/contact_details/settings_provider.vala
|
||||||
|
src/ui/contact_details/dialog.vala
|
||||||
|
src/ui/contact_details/muc_config_form_provider.vala
|
||||||
src/ui/conversation_list_titlebar.vala
|
src/ui/conversation_list_titlebar.vala
|
||||||
src/ui/conversation_selector/chat_row.vala
|
src/ui/conversation_selector/chat_row.vala
|
||||||
src/ui/conversation_selector/conversation_row.vala
|
src/ui/conversation_selector/conversation_row.vala
|
||||||
|
@ -108,7 +112,8 @@ SOURCES
|
||||||
src/ui/occupant_menu/view.vala
|
src/ui/occupant_menu/view.vala
|
||||||
src/ui/settings_dialog.vala
|
src/ui/settings_dialog.vala
|
||||||
src/ui/unified_window.vala
|
src/ui/unified_window.vala
|
||||||
src/ui/util.vala
|
src/ui/util/helper.vala
|
||||||
|
src/ui/util/label_hybrid.vala
|
||||||
CUSTOM_VAPIS
|
CUSTOM_VAPIS
|
||||||
${CMAKE_BINARY_DIR}/exports/xmpp-vala.vapi
|
${CMAKE_BINARY_DIR}/exports/xmpp-vala.vapi
|
||||||
${CMAKE_BINARY_DIR}/exports/qlite.vapi
|
${CMAKE_BINARY_DIR}/exports/qlite.vapi
|
||||||
|
|
109
main/data/contact_details_dialog.ui
Normal file
109
main/data/contact_details_dialog.ui
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<interface>
|
||||||
|
<template class="DinoUiContactDetailsDialog">
|
||||||
|
<property name="modal">True</property>
|
||||||
|
<child type="titlebar">
|
||||||
|
<object class="GtkHeaderBar">
|
||||||
|
<property name="title">Conversation Details</property>
|
||||||
|
<property name="show_close_button">True</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child internal-child="vbox">
|
||||||
|
<object class="GtkBox">
|
||||||
|
<property name="expand">True</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkScrolledWindow">
|
||||||
|
<property name="propagate_natural_height">True</property>
|
||||||
|
<property name="max_content_height">500</property>
|
||||||
|
<property name="hscrollbar_policy">never</property>
|
||||||
|
<property name="expand">True</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkBox">
|
||||||
|
<property name="orientation">vertical</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkGrid">
|
||||||
|
<property name="margin-top">20</property>
|
||||||
|
<property name="margin-bottom">12</property>
|
||||||
|
<property name="margin-right">100</property>
|
||||||
|
<property name="margin-left">100</property>
|
||||||
|
<property name="column-spacing">15</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkImage" id="avatar">
|
||||||
|
<property name="height_request">50</property>
|
||||||
|
<property name="width_request">50</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left_attach">0</property>
|
||||||
|
<property name="top_attach">0</property>
|
||||||
|
<property name="width">1</property>
|
||||||
|
<property name="height">2</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel" id="name_label">
|
||||||
|
<property name="xalign">0</property>
|
||||||
|
<property name="expand">True</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<attributes>
|
||||||
|
<attribute name="weight" value="PANGO_WEIGHT_BOLD"/>
|
||||||
|
</attributes>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left_attach">1</property>
|
||||||
|
<property name="top_attach">0</property>
|
||||||
|
<property name="width">1</property>
|
||||||
|
<property name="height">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel" id="jid_label">
|
||||||
|
<property name="xalign">0</property>
|
||||||
|
<property name="expand">True</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left_attach">1</property>
|
||||||
|
<property name="top_attach">1</property>
|
||||||
|
<property name="width">1</property>
|
||||||
|
<property name="height">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel" id="account_label">
|
||||||
|
<property name="xalign">1</property>
|
||||||
|
<property name="yalign">1</property>
|
||||||
|
<property name="margin">5</property>
|
||||||
|
<property name="expand">True</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left_attach">2</property>
|
||||||
|
<property name="top_attach">1</property>
|
||||||
|
<property name="width">1</property>
|
||||||
|
<property name="height">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkBox" id="main_box">
|
||||||
|
<property name="orientation">vertical</property>
|
||||||
|
<property name="margin-right">100</property>
|
||||||
|
<property name="margin-left">100</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</template>
|
||||||
|
</interface>
|
|
@ -2,6 +2,7 @@
|
||||||
<menu id="menu_conversation">
|
<menu id="menu_conversation">
|
||||||
<section>
|
<section>
|
||||||
<item>
|
<item>
|
||||||
|
<attribute name="action">app.contact_details</attribute>
|
||||||
<attribute name="label" translatable="yes">Contact Details</attribute>
|
<attribute name="label" translatable="yes">Contact Details</attribute>
|
||||||
</item>
|
</item>
|
||||||
</section>
|
</section>
|
||||||
|
|
|
@ -53,7 +53,7 @@ public class Dialog : Gtk.Dialog {
|
||||||
select_jid_fragment.add_jid.connect((row) => {
|
select_jid_fragment.add_jid.connect((row) => {
|
||||||
AddContactDialog add_contact_dialog = new AddContactDialog(stream_interactor);
|
AddContactDialog add_contact_dialog = new AddContactDialog(stream_interactor);
|
||||||
add_contact_dialog.set_transient_for(this);
|
add_contact_dialog.set_transient_for(this);
|
||||||
add_contact_dialog.show();
|
add_contact_dialog.present();
|
||||||
});
|
});
|
||||||
select_jid_fragment.edit_jid.connect(() => {
|
select_jid_fragment.edit_jid.connect(() => {
|
||||||
|
|
||||||
|
|
|
@ -92,13 +92,13 @@ public class Dialog : Gtk.Dialog {
|
||||||
select_fragment.add_jid.connect((row) => {
|
select_fragment.add_jid.connect((row) => {
|
||||||
AddGroupchatDialog dialog = new AddGroupchatDialog(stream_interactor);
|
AddGroupchatDialog dialog = new AddGroupchatDialog(stream_interactor);
|
||||||
dialog.set_transient_for(this);
|
dialog.set_transient_for(this);
|
||||||
dialog.show();
|
dialog.present();
|
||||||
});
|
});
|
||||||
select_fragment.edit_jid.connect((row) => {
|
select_fragment.edit_jid.connect((row) => {
|
||||||
ConferenceListRow conference_row = row as ConferenceListRow;
|
ConferenceListRow conference_row = row as ConferenceListRow;
|
||||||
AddGroupchatDialog dialog = new AddGroupchatDialog.for_conference(stream_interactor, conference_row.account, conference_row.bookmark);
|
AddGroupchatDialog dialog = new AddGroupchatDialog.for_conference(stream_interactor, conference_row.account, conference_row.bookmark);
|
||||||
dialog.set_transient_for(this);
|
dialog.set_transient_for(this);
|
||||||
dialog.show();
|
dialog.present();
|
||||||
});
|
});
|
||||||
select_fragment.remove_jid.connect((row) => {
|
select_fragment.remove_jid.connect((row) => {
|
||||||
ConferenceListRow conference_row = row as ConferenceListRow;
|
ConferenceListRow conference_row = row as ConferenceListRow;
|
||||||
|
|
|
@ -19,7 +19,7 @@ public class Dino.Ui.Application : Dino.Application {
|
||||||
notifications = new Notifications(stream_interaction, window);
|
notifications = new Notifications(stream_interaction, window);
|
||||||
notifications.start();
|
notifications.start();
|
||||||
notifications.conversation_selected.connect(window.on_conversation_selected);
|
notifications.conversation_selected.connect(window.on_conversation_selected);
|
||||||
window.show();
|
window.present();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,13 +28,13 @@ public class Dino.Ui.Application : Dino.Application {
|
||||||
dialog.set_transient_for(window);
|
dialog.set_transient_for(window);
|
||||||
dialog.account_enabled.connect(add_connection);
|
dialog.account_enabled.connect(add_connection);
|
||||||
dialog.account_disabled.connect(remove_connection);
|
dialog.account_disabled.connect(remove_connection);
|
||||||
dialog.show();
|
dialog.present();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void show_settings_window() {
|
private void show_settings_window() {
|
||||||
SettingsDialog dialog = new SettingsDialog();
|
SettingsDialog dialog = new SettingsDialog();
|
||||||
dialog.set_transient_for(window);
|
dialog.set_transient_for(window);
|
||||||
dialog.show();
|
dialog.present();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void create_set_app_menu() {
|
private void create_set_app_menu() {
|
||||||
|
|
120
main/src/ui/contact_details/dialog.vala
Normal file
120
main/src/ui/contact_details/dialog.vala
Normal file
|
@ -0,0 +1,120 @@
|
||||||
|
using Gee;
|
||||||
|
using Gtk;
|
||||||
|
using Markup;
|
||||||
|
|
||||||
|
using Dino.Entities;
|
||||||
|
|
||||||
|
namespace Dino.Ui.ContactDetails {
|
||||||
|
|
||||||
|
[GtkTemplate (ui = "/org/dino-im/contact_details_dialog.ui")]
|
||||||
|
public class Dialog : Gtk.Dialog {
|
||||||
|
|
||||||
|
[GtkChild] public Image avatar;
|
||||||
|
[GtkChild] public Label name_label;
|
||||||
|
[GtkChild] public Label jid_label;
|
||||||
|
[GtkChild] public Label account_label;
|
||||||
|
[GtkChild] public Box main_box;
|
||||||
|
|
||||||
|
private StreamInteractor stream_interactor;
|
||||||
|
private Conversation conversation;
|
||||||
|
|
||||||
|
private Plugins.ContactDetails contact_details = new Plugins.ContactDetails();
|
||||||
|
private HashMap<string, ListBox> categories = new HashMap<string, ListBox>();
|
||||||
|
private Util.LabelHybridGroup hybrid_group = new Util.LabelHybridGroup();
|
||||||
|
|
||||||
|
public Dialog(StreamInteractor stream_interactor, Conversation conversation) {
|
||||||
|
Object(use_header_bar : 1);
|
||||||
|
this.stream_interactor = stream_interactor;
|
||||||
|
this.conversation = conversation;
|
||||||
|
|
||||||
|
title = conversation.type_ == Conversation.Type.GROUPCHAT ? _("Conference Details") : _("Contact Details");
|
||||||
|
(get_header_bar() as HeaderBar).set_subtitle(Util.get_conversation_display_name(stream_interactor, conversation));
|
||||||
|
|
||||||
|
name_label.label = Util.get_conversation_display_name(stream_interactor, conversation);
|
||||||
|
jid_label.label = conversation.counterpart.to_string();
|
||||||
|
account_label.label = "via " + conversation.account.bare_jid.to_string();
|
||||||
|
Util.image_set_from_scaled_pixbuf(avatar, (new AvatarGenerator(50, 50, avatar.scale_factor)).draw_conversation(stream_interactor, conversation));
|
||||||
|
|
||||||
|
contact_details.add.connect(add_entry);
|
||||||
|
|
||||||
|
Application app = GLib.Application.get_default() as Application;
|
||||||
|
app.plugin_registry.register_contact_details_entry(new SettingsProvider(stream_interactor));
|
||||||
|
app.plugin_registry.register_contact_details_entry(new MucConfigFormProvider(stream_interactor));
|
||||||
|
|
||||||
|
foreach (Plugins.ContactDetailsProvider provider in app.plugin_registry.contact_details_entries) {
|
||||||
|
provider.populate(conversation, contact_details);
|
||||||
|
}
|
||||||
|
|
||||||
|
destroy.connect(() => {
|
||||||
|
contact_details.save();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void add_entry(string category, string label, string? description, Widget w) {
|
||||||
|
add_category(category);
|
||||||
|
|
||||||
|
ListBoxRow list_row = new ListBoxRow() { activatable=false, visible=true };
|
||||||
|
Box row = new Box(Orientation.HORIZONTAL, 20) { margin_left=15, margin_right=15, margin_top=3, margin_bottom=3, visible=true };
|
||||||
|
list_row.add(row);
|
||||||
|
Label label_label = new Label(label) { xalign=0, yalign=0.5f, hexpand=true, visible=true };
|
||||||
|
if (description != null && description != "") {
|
||||||
|
Box box = new Box(Orientation.VERTICAL, 0) { visible=true };
|
||||||
|
box.add(label_label);
|
||||||
|
Label desc_label = new Label("") { xalign=0, yalign=0.5f, hexpand=true, visible=true };
|
||||||
|
desc_label.set_markup("<span size='small'>%s</span>".printf(Markup.escape_text(description)));
|
||||||
|
desc_label.get_style_context().add_class("dim-label");
|
||||||
|
box.add(desc_label);
|
||||||
|
row.add(box);
|
||||||
|
} else {
|
||||||
|
row.add(label_label);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget widget = w;
|
||||||
|
if (widget.get_type().is_a(typeof(Entry))) {
|
||||||
|
Util.EntryLabelHybrid hybrid = new Util.EntryLabelHybrid(widget as Entry) { xalign=1, visible=true };
|
||||||
|
hybrid_group.add(hybrid);
|
||||||
|
widget = hybrid;
|
||||||
|
} else if (widget.get_type().is_a(typeof(ComboBoxText))) {
|
||||||
|
Util.ComboBoxTextLabelHybrid hybrid = new Util.ComboBoxTextLabelHybrid(widget as ComboBoxText) { xalign=1, visible=true };
|
||||||
|
hybrid_group.add(hybrid);
|
||||||
|
widget = hybrid;
|
||||||
|
}
|
||||||
|
widget.margin_bottom = 5;
|
||||||
|
widget.margin_top = 5;
|
||||||
|
|
||||||
|
|
||||||
|
row.add(widget);
|
||||||
|
categories[category].add(list_row);
|
||||||
|
|
||||||
|
Idle.add(() => {
|
||||||
|
int pref_height, pref_width;
|
||||||
|
get_content_area().get_preferred_height(null, out pref_height);
|
||||||
|
get_preferred_width(out pref_width, null);
|
||||||
|
resize(pref_width, int.min(500, pref_height));
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void add_category(string category) {
|
||||||
|
if (!categories.has_key(category)) {
|
||||||
|
ListBox list_box = new ListBox() { selection_mode=SelectionMode.NONE, visible=true };
|
||||||
|
categories[category] = list_box;
|
||||||
|
list_box.set_header_func((row, before_row) => {
|
||||||
|
if (row.get_header() == null && before_row != null) {
|
||||||
|
row.set_header(new Separator(Orientation.HORIZONTAL));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Box box = new Box(Orientation.VERTICAL, 5) { margin_top=12, margin_bottom=12, visible=true };
|
||||||
|
Label category_label = new Label("") { xalign=0, visible=true };
|
||||||
|
category_label.set_markup(@"<b>$(Markup.escape_text(category))</b>");
|
||||||
|
box.add(category_label);
|
||||||
|
Frame frame = new Frame(null) { visible=true };
|
||||||
|
frame.add(list_box);
|
||||||
|
box.add(frame);
|
||||||
|
main_box.add(box);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
131
main/src/ui/contact_details/muc_config_form_provider.vala
Normal file
131
main/src/ui/contact_details/muc_config_form_provider.vala
Normal file
|
@ -0,0 +1,131 @@
|
||||||
|
using Gee;
|
||||||
|
using Gtk;
|
||||||
|
|
||||||
|
using Dino.Entities;
|
||||||
|
using Xmpp.Xep;
|
||||||
|
|
||||||
|
namespace Dino.Ui.ContactDetails {
|
||||||
|
|
||||||
|
public class MucConfigFormProvider : Plugins.ContactDetailsProvider {
|
||||||
|
public override string id { get { return "muc_config_form"; } }
|
||||||
|
private StreamInteractor stream_interactor;
|
||||||
|
|
||||||
|
public MucConfigFormProvider(StreamInteractor stream_interactor) {
|
||||||
|
this.stream_interactor = stream_interactor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void populate(Conversation conversation, Plugins.ContactDetails contact_details) {
|
||||||
|
if (conversation.type_ == Conversation.Type.GROUPCHAT) {
|
||||||
|
Xmpp.Core.XmppStream? stream = stream_interactor.get_stream(conversation.account);
|
||||||
|
if (stream == null) return;
|
||||||
|
stream_interactor.get_module(MucManager.IDENTITY).get_config_form(conversation.account, conversation.counterpart, (jid, data_form, store) => {
|
||||||
|
Plugins.ContactDetails contact_details_ = store as Plugins.ContactDetails;
|
||||||
|
contact_details_.save.connect(() => {
|
||||||
|
data_form.submit();
|
||||||
|
});
|
||||||
|
Idle.add(() => {
|
||||||
|
for (int i = 0; i < data_form.fields.size; i++) {
|
||||||
|
DataForms.DataForm.Field field = data_form.fields[i];
|
||||||
|
add_field(field, contact_details_);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}, contact_details);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void add_field(DataForms.DataForm.Field field, Plugins.ContactDetails contact_details) {
|
||||||
|
string label = field.label ?? "";
|
||||||
|
string? desc = null;
|
||||||
|
switch (field.var) {
|
||||||
|
case "muc#roomconfig_roomname":
|
||||||
|
label = _("Name");
|
||||||
|
desc = _("Name of the room");
|
||||||
|
break;
|
||||||
|
case "muc#roomconfig_roomdesc":
|
||||||
|
label = _("Description");
|
||||||
|
desc = _("Description of the room");
|
||||||
|
break;
|
||||||
|
case "muc#roomconfig_persistentroom":
|
||||||
|
label = _("Persistent");
|
||||||
|
break;
|
||||||
|
case "muc#roomconfig_publicroom":
|
||||||
|
label = _("Publicly searchable");
|
||||||
|
break;
|
||||||
|
case "muc#roomconfig_changesubject":
|
||||||
|
label = _("Occupants may change subject");
|
||||||
|
break;
|
||||||
|
case "muc#roomconfig_whois":
|
||||||
|
label = _("Discover real jids");
|
||||||
|
desc = "Who may discover real jids";
|
||||||
|
break;
|
||||||
|
case "muc#roomconfig_roomsecret":
|
||||||
|
label = _("Password");
|
||||||
|
desc = _("Passwort required to enter the room. Leave empty for none.");
|
||||||
|
break;
|
||||||
|
case "muc#roomconfig_moderatedroom":
|
||||||
|
label = _("Moderated");
|
||||||
|
break;
|
||||||
|
case "muc#roomconfig_membersonly":
|
||||||
|
label = _("Members only");
|
||||||
|
desc = _("Only members may enter the room");
|
||||||
|
break;
|
||||||
|
case "muc#roomconfig_historylength":
|
||||||
|
label = _("Message History");
|
||||||
|
desc = _("Maximum number of history messages returned by the room");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget? widget = get_widget(field);
|
||||||
|
if (widget != null) contact_details.add(_("Room Configuration"), label, desc, widget);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Widget? get_widget(DataForms.DataForm.Field field) {
|
||||||
|
switch (field.type_) {
|
||||||
|
case DataForms.DataForm.Type.BOOLEAN:
|
||||||
|
DataForms.DataForm.BooleanField boolean_field = field as DataForms.DataForm.BooleanField;
|
||||||
|
Switch sw = new Switch() { active=boolean_field.value, valign=Align.CENTER, visible=true };
|
||||||
|
sw.state_set.connect((state) => {
|
||||||
|
boolean_field.value = state;
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
return sw;
|
||||||
|
case DataForms.DataForm.Type.JID_MULTI:
|
||||||
|
return null;
|
||||||
|
case DataForms.DataForm.Type.LIST_SINGLE:
|
||||||
|
DataForms.DataForm.ListSingleField list_single_field = field as DataForms.DataForm.ListSingleField;
|
||||||
|
ComboBoxText combobox = new ComboBoxText() { valign=Align.CENTER, visible=true };
|
||||||
|
for (int i = 0; i < list_single_field.options.size; i++) {
|
||||||
|
DataForms.DataForm.Option option = list_single_field.options[i];
|
||||||
|
combobox.append(option.value, option.label);
|
||||||
|
if (option.value == list_single_field.value) combobox.active = i;
|
||||||
|
}
|
||||||
|
combobox.changed.connect(() => {
|
||||||
|
list_single_field.value = combobox.get_active_id();
|
||||||
|
});
|
||||||
|
return combobox;
|
||||||
|
case DataForms.DataForm.Type.LIST_MULTI:
|
||||||
|
return null;
|
||||||
|
case DataForms.DataForm.Type.TEXT_PRIVATE:
|
||||||
|
DataForms.DataForm.TextPrivateField text_private_field = field as DataForms.DataForm.TextPrivateField;
|
||||||
|
Entry entry = new Entry() { text=text_private_field.value ?? "", valign=Align.CENTER, visible=true, visibility=false };
|
||||||
|
entry.key_release_event.connect(() => {
|
||||||
|
text_private_field.value = entry.text;
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
return entry;
|
||||||
|
case DataForms.DataForm.Type.TEXT_SINGLE:
|
||||||
|
DataForms.DataForm.TextSingleField text_single_field = field as DataForms.DataForm.TextSingleField;
|
||||||
|
Entry entry = new Entry() { text=text_single_field.value ?? "", valign=Align.CENTER, visible=true };
|
||||||
|
entry.key_release_event.connect(() => {
|
||||||
|
text_single_field.value = entry.text;
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
return entry;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
102
main/src/ui/contact_details/settings_provider.vala
Normal file
102
main/src/ui/contact_details/settings_provider.vala
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
using Gtk;
|
||||||
|
|
||||||
|
using Dino.Entities;
|
||||||
|
|
||||||
|
namespace Dino.Ui.ContactDetails {
|
||||||
|
|
||||||
|
public class SettingsProvider : Plugins.ContactDetailsProvider {
|
||||||
|
public override string id { get { return "chat_settings"; } }
|
||||||
|
|
||||||
|
private StreamInteractor stream_interactor;
|
||||||
|
|
||||||
|
public SettingsProvider(StreamInteractor stream_interactor) {
|
||||||
|
this.stream_interactor = stream_interactor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void populate(Conversation conversation, Plugins.ContactDetails contact_details) {
|
||||||
|
if (conversation.type_ == Conversation.Type.CHAT) {
|
||||||
|
ComboBoxText[] comboboxes = new ComboBoxText[2];
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
comboboxes[i] = new ComboBoxText() { visible=true };
|
||||||
|
comboboxes[i].append("default", _("Default"));
|
||||||
|
comboboxes[i].append("on", _("On"));
|
||||||
|
comboboxes[i].append("off", _("Off"));
|
||||||
|
}
|
||||||
|
|
||||||
|
contact_details.add(_("Settings"), _("Send typing notifications"), "", comboboxes[0]);
|
||||||
|
comboboxes[0].active_id = get_setting_id(conversation.get_send_typing_setting());
|
||||||
|
comboboxes[0].changed.connect(() => { print("changed!\n"); conversation.send_typing = get_setting(comboboxes[0].active_id); } );
|
||||||
|
|
||||||
|
contact_details.add(_("Settings"), _("Send message marker"), "", comboboxes[1]);
|
||||||
|
comboboxes[1].active_id = get_setting_id(conversation.get_send_marker_setting());
|
||||||
|
comboboxes[1].changed.connect(() => { conversation.send_marker = get_setting(comboboxes[1].active_id); } );
|
||||||
|
|
||||||
|
contact_details.add(_("Settings"), _("Notifications"), "", comboboxes[2]);
|
||||||
|
comboboxes[2].active_id = get_notify_setting_id(conversation.get_notification_setting(stream_interactor));
|
||||||
|
comboboxes[2].changed.connect(() => { conversation.notify_setting = get_notify_setting(comboboxes[2].active_id); } );
|
||||||
|
} else if (conversation.type_ == Conversation.Type.GROUPCHAT) {
|
||||||
|
ComboBoxText combobox = new ComboBoxText() { visible=true };
|
||||||
|
combobox.append("default", _("Default"));
|
||||||
|
combobox.append("hightlight", _("Only when mentioned"));
|
||||||
|
combobox.append("on", _("On"));
|
||||||
|
combobox.append("off", _("Off"));
|
||||||
|
contact_details.add(_("Local Settings"), _("Notifications"), "", combobox);
|
||||||
|
combobox.active_id = get_notify_setting_id(conversation.get_notification_setting(stream_interactor));
|
||||||
|
combobox.changed.connect(() => { conversation.notify_setting = get_notify_setting(combobox.active_id); } );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Conversation.Setting get_setting(string id) {
|
||||||
|
switch (id) {
|
||||||
|
case "default":
|
||||||
|
return Conversation.Setting.DEFAULT;
|
||||||
|
case "on":
|
||||||
|
return Conversation.Setting.ON;
|
||||||
|
case "off":
|
||||||
|
return Conversation.Setting.OFF;
|
||||||
|
}
|
||||||
|
assert_not_reached();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Conversation.NotifySetting get_notify_setting(string id) {
|
||||||
|
switch (id) {
|
||||||
|
case "default":
|
||||||
|
return Conversation.NotifySetting.DEFAULT;
|
||||||
|
case "on":
|
||||||
|
return Conversation.NotifySetting.ON;
|
||||||
|
case "off":
|
||||||
|
return Conversation.NotifySetting.OFF;
|
||||||
|
case "highlight":
|
||||||
|
return Conversation.NotifySetting.HIGHLIGHT;
|
||||||
|
}
|
||||||
|
assert_not_reached();
|
||||||
|
}
|
||||||
|
|
||||||
|
public string get_setting_id(Conversation.Setting setting) {
|
||||||
|
switch (setting) {
|
||||||
|
case Conversation.Setting.DEFAULT:
|
||||||
|
return "default";
|
||||||
|
case Conversation.Setting.ON:
|
||||||
|
return "on";
|
||||||
|
case Conversation.Setting.OFF:
|
||||||
|
return "off";
|
||||||
|
}
|
||||||
|
assert_not_reached();
|
||||||
|
}
|
||||||
|
|
||||||
|
public string get_notify_setting_id(Conversation.NotifySetting setting) {
|
||||||
|
switch (setting) {
|
||||||
|
case Conversation.NotifySetting.DEFAULT:
|
||||||
|
return "default";
|
||||||
|
case Conversation.NotifySetting.ON:
|
||||||
|
return "on";
|
||||||
|
case Conversation.NotifySetting.OFF:
|
||||||
|
return "off";
|
||||||
|
case Conversation.NotifySetting.HIGHLIGHT:
|
||||||
|
return "hightlight";
|
||||||
|
}
|
||||||
|
assert_not_reached();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -14,9 +14,9 @@ public class ConversationListTitlebar : Gtk.HeaderBar {
|
||||||
|
|
||||||
private StreamInteractor stream_interactor;
|
private StreamInteractor stream_interactor;
|
||||||
|
|
||||||
public ConversationListTitlebar(Window application, StreamInteractor stream_interactor) {
|
public ConversationListTitlebar(StreamInteractor stream_interactor, Window window) {
|
||||||
this.stream_interactor = stream_interactor;
|
this.stream_interactor = stream_interactor;
|
||||||
create_add_menu(application);
|
create_add_menu(window);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void create_add_menu(Window window) {
|
private void create_add_menu(Window window) {
|
||||||
|
@ -25,18 +25,18 @@ public class ConversationListTitlebar : Gtk.HeaderBar {
|
||||||
AddConversation.Chat.Dialog add_chat_dialog = new AddConversation.Chat.Dialog(stream_interactor);
|
AddConversation.Chat.Dialog add_chat_dialog = new AddConversation.Chat.Dialog(stream_interactor);
|
||||||
add_chat_dialog.set_transient_for(window);
|
add_chat_dialog.set_transient_for(window);
|
||||||
add_chat_dialog.conversation_opened.connect((conversation) => conversation_opened(conversation));
|
add_chat_dialog.conversation_opened.connect((conversation) => conversation_opened(conversation));
|
||||||
add_chat_dialog.show();
|
add_chat_dialog.present();
|
||||||
});
|
});
|
||||||
window.get_application().add_action(contacts_action);
|
GLib.Application.get_default().add_action(contacts_action);
|
||||||
|
|
||||||
SimpleAction conference_action = new SimpleAction("add_conference", null);
|
SimpleAction conference_action = new SimpleAction("add_conference", null);
|
||||||
conference_action.activate.connect(() => {
|
conference_action.activate.connect(() => {
|
||||||
AddConversation.Conference.Dialog add_conference_dialog = new AddConversation.Conference.Dialog(stream_interactor);
|
AddConversation.Conference.Dialog add_conference_dialog = new AddConversation.Conference.Dialog(stream_interactor);
|
||||||
add_conference_dialog.set_transient_for(window);
|
add_conference_dialog.set_transient_for(window);
|
||||||
add_conference_dialog.conversation_opened.connect((conversation) => conversation_opened(conversation));
|
add_conference_dialog.conversation_opened.connect((conversation) => conversation_opened(conversation));
|
||||||
add_conference_dialog.show();
|
add_conference_dialog.present();
|
||||||
});
|
});
|
||||||
window.get_application().add_action(conference_action);
|
GLib.Application.get_default().add_action(conference_action);
|
||||||
|
|
||||||
Builder builder = new Builder.from_resource("/org/dino-im/menu_add.ui");
|
Builder builder = new Builder.from_resource("/org/dino-im/menu_add.ui");
|
||||||
MenuModel menu = builder.get_object("menu_add") as MenuModel;
|
MenuModel menu = builder.get_object("menu_add") as MenuModel;
|
||||||
|
|
|
@ -91,6 +91,14 @@ public class ConversationTitlebar : Gtk.HeaderBar {
|
||||||
Builder builder = new Builder.from_resource("/org/dino-im/menu_conversation.ui");
|
Builder builder = new Builder.from_resource("/org/dino-im/menu_conversation.ui");
|
||||||
MenuModel menu = builder.get_object("menu_conversation") as MenuModel;
|
MenuModel menu = builder.get_object("menu_conversation") as MenuModel;
|
||||||
menu_button.set_menu_model(menu);
|
menu_button.set_menu_model(menu);
|
||||||
|
|
||||||
|
SimpleAction contact_details_action = new SimpleAction("contact_details", null);
|
||||||
|
contact_details_action.activate.connect(() => {
|
||||||
|
ContactDetails.Dialog contact_details_dialog = new ContactDetails.Dialog(stream_interactor, conversation);
|
||||||
|
contact_details_dialog.set_transient_for((Window) get_toplevel());
|
||||||
|
contact_details_dialog.present();
|
||||||
|
});
|
||||||
|
GLib.Application.get_default().add_action(contact_details_action);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void encryption_changed() {
|
private void encryption_changed() {
|
||||||
|
|
|
@ -120,7 +120,7 @@ public class Dialog : Gtk.Dialog {
|
||||||
account_list.select_row(account_item);
|
account_list.select_row(account_item);
|
||||||
account_list.queue_draw();
|
account_list.queue_draw();
|
||||||
});
|
});
|
||||||
add_account_dialog.show();
|
add_account_dialog.present();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void on_remove_button_clicked() {
|
private void on_remove_button_clicked() {
|
||||||
|
|
|
@ -84,7 +84,7 @@ public class UnifiedWindow : Window {
|
||||||
|
|
||||||
private void setup_headerbar() {
|
private void setup_headerbar() {
|
||||||
conversation_titlebar = new ConversationTitlebar(stream_interactor) { visible=true };
|
conversation_titlebar = new ConversationTitlebar(stream_interactor) { visible=true };
|
||||||
conversation_list_titlebar = new ConversationListTitlebar(this, stream_interactor) { visible=true };
|
conversation_list_titlebar = new ConversationListTitlebar(stream_interactor, this) { visible=true };
|
||||||
headerbar_paned.add1(conversation_list_titlebar);
|
headerbar_paned.add1(conversation_list_titlebar);
|
||||||
headerbar_paned.add2(conversation_titlebar);
|
headerbar_paned.add2(conversation_titlebar);
|
||||||
|
|
||||||
|
|
|
@ -1,124 +0,0 @@
|
||||||
using Gtk;
|
|
||||||
|
|
||||||
using Dino.Entities;
|
|
||||||
using Xmpp;
|
|
||||||
|
|
||||||
namespace Dino.Ui {
|
|
||||||
|
|
||||||
public class Util : Object {
|
|
||||||
|
|
||||||
private const string[] tango_colors_light = {"FCE94F", "FCAF3E", "E9B96E", "8AE234", "729FCF", "AD7FA8", "EF2929"};
|
|
||||||
private const string[] tango_colors_medium = {"EDD400", "F57900", "C17D11", "73D216", "3465A4", "75507B", "CC0000"};
|
|
||||||
private const string[] material_colors_800 = {"D32F2F", "C2185B", "7B1FA2", "512DA8", "303F9F", "1976D2", "0288D1", "0097A7", "00796B", "388E3C", "689F38", "AFB42B", "FFA000", "F57C00", "E64A19", "5D4037"};
|
|
||||||
private const string[] material_colors_500 = {"F44336", "E91E63", "9C27B0", "673AB7", "3f51B5", "2196F3", "03A9f4", "00BCD4", "009688", "4CAF50", "8BC34a", "CDDC39", "FFC107", "FF9800", "FF5722", "795548"};
|
|
||||||
private const string[] material_colors_300 = {"E57373", "F06292", "BA68C8", "9575CD", "7986CB", "64B5F6", "4FC3F7", "4DD0E1", "4DB6AC", "81C784", "AED581", "DCE775", "FFD54F", "FFB74D", "FF8A65", "A1887F"};
|
|
||||||
private const string[] material_colors_200 = {"EF9A9A", "F48FB1", "CE93D8", "B39DDB", "9FA8DA", "90CAF9", "81D4FA", "80DEEA", "80CBC4", "A5D6A7", "C5E1A5", "E6EE9C", "FFE082", "FFCC80", "FFAB91", "BCAAA4"};
|
|
||||||
|
|
||||||
public static string get_avatar_hex_color(string name) {
|
|
||||||
return material_colors_300[name.hash() % material_colors_300.length];
|
|
||||||
// return tango_colors_light[name.hash() % tango_colors_light.length];
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string get_name_hex_color(string name, bool dark_theme = false) {
|
|
||||||
if (dark_theme) {
|
|
||||||
return material_colors_300[name.hash() % material_colors_300.length];
|
|
||||||
} else {
|
|
||||||
return material_colors_500[name.hash() % material_colors_500.length];
|
|
||||||
}
|
|
||||||
// return tango_colors_medium[name.hash() % tango_colors_medium.length];
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string color_for_show(string show) {
|
|
||||||
switch(show) {
|
|
||||||
case "online": return "#9CCC65";
|
|
||||||
case "away": return "#FFCA28";
|
|
||||||
case "chat": return "#66BB6A";
|
|
||||||
case "xa": return "#EF5350";
|
|
||||||
case "dnd": return "#EF5350";
|
|
||||||
default: return "#BDBDBD";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string get_conversation_display_name(StreamInteractor stream_interactor, Conversation conversation) {
|
|
||||||
if (conversation.type_ == Conversation.Type.GROUPCHAT_PM) {
|
|
||||||
return conversation.counterpart.resourcepart + " from " + get_display_name(stream_interactor, conversation.counterpart.bare_jid, conversation.account);
|
|
||||||
}
|
|
||||||
return get_display_name(stream_interactor, conversation.counterpart, conversation.account);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string get_display_name(StreamInteractor stream_interactor, Jid jid, Account account) {
|
|
||||||
if (stream_interactor.get_module(MucManager.IDENTITY).is_groupchat_occupant(jid, account)) {
|
|
||||||
return jid.resourcepart;
|
|
||||||
} else {
|
|
||||||
if (jid.bare_jid.equals(account.bare_jid.bare_jid)) {
|
|
||||||
if (account.alias == null || account.alias == "") {
|
|
||||||
return account.bare_jid.to_string();
|
|
||||||
} else {
|
|
||||||
return account.alias;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Roster.Item roster_item = stream_interactor.get_module(RosterManager.IDENTITY).get_roster_item(account, jid);
|
|
||||||
if (roster_item != null && roster_item.name != null) {
|
|
||||||
return roster_item.name;
|
|
||||||
}
|
|
||||||
return jid.bare_jid.to_string();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string get_message_display_name(StreamInteractor stream_interactor, Entities.Message message, Account account) {
|
|
||||||
Jid? real_jid = stream_interactor.get_module(MucManager.IDENTITY).get_message_real_jid(message);
|
|
||||||
if (real_jid != null) {
|
|
||||||
return get_display_name(stream_interactor, real_jid, account);
|
|
||||||
} else {
|
|
||||||
return get_display_name(stream_interactor, message.from, account);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void image_set_from_scaled_pixbuf(Image image, Gdk.Pixbuf pixbuf, int scale = 0) {
|
|
||||||
if (scale == 0) scale = image.get_scale_factor();
|
|
||||||
image.set_from_surface(Gdk.cairo_surface_create_from_pixbuf(pixbuf, scale, image.get_window()));
|
|
||||||
}
|
|
||||||
|
|
||||||
private const string force_background_css = "%s { background-color: %s; }";
|
|
||||||
private const string force_color_css = "%s { color: %s; }";
|
|
||||||
|
|
||||||
private static void force_css(Gtk.Widget widget, string css) {
|
|
||||||
var p = new Gtk.CssProvider();
|
|
||||||
try {
|
|
||||||
p.load_from_data(css);
|
|
||||||
widget.get_style_context().add_provider(p, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
|
|
||||||
} catch (GLib.Error err) {
|
|
||||||
// handle err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void force_background(Gtk.Widget widget, string color, string selector = "*") {
|
|
||||||
force_css(widget, force_background_css.printf(selector, color));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void force_base_background(Gtk.Widget widget, string selector = "*") {
|
|
||||||
force_background(widget, "@theme_base_color", selector);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void force_color(Gtk.Widget widget, string color, string selector = "*") {
|
|
||||||
force_css(widget, force_color_css.printf(selector, color));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void force_error_color(Gtk.Widget widget, string selector = "*") {
|
|
||||||
force_color(widget, "@error_color", selector);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool is_dark_theme(Gtk.Widget widget) {
|
|
||||||
Gdk.RGBA bg = widget.get_style_context().get_background_color(StateFlags.NORMAL);
|
|
||||||
return (bg.red < 0.5 && bg.green < 0.5 && bg.blue < 0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool is_24h_format() {
|
|
||||||
GLib.Settings settings = new GLib.Settings("org.gnome.desktop.interface");
|
|
||||||
string settings_format = settings.get_string("clock-format");
|
|
||||||
string p_format = (new DateTime.now_local()).format("%p");
|
|
||||||
return settings_format == "24h" || p_format == " ";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
121
main/src/ui/util/helper.vala
Normal file
121
main/src/ui/util/helper.vala
Normal file
|
@ -0,0 +1,121 @@
|
||||||
|
using Gtk;
|
||||||
|
|
||||||
|
using Dino.Entities;
|
||||||
|
using Xmpp;
|
||||||
|
|
||||||
|
namespace Dino.Ui.Util {
|
||||||
|
|
||||||
|
private const string[] tango_colors_light = {"FCE94F", "FCAF3E", "E9B96E", "8AE234", "729FCF", "AD7FA8", "EF2929"};
|
||||||
|
private const string[] tango_colors_medium = {"EDD400", "F57900", "C17D11", "73D216", "3465A4", "75507B", "CC0000"};
|
||||||
|
private const string[] material_colors_800 = {"D32F2F", "C2185B", "7B1FA2", "512DA8", "303F9F", "1976D2", "0288D1", "0097A7", "00796B", "388E3C", "689F38", "AFB42B", "FFA000", "F57C00", "E64A19", "5D4037"};
|
||||||
|
private const string[] material_colors_500 = {"F44336", "E91E63", "9C27B0", "673AB7", "3f51B5", "2196F3", "03A9f4", "00BCD4", "009688", "4CAF50", "8BC34a", "CDDC39", "FFC107", "FF9800", "FF5722", "795548"};
|
||||||
|
private const string[] material_colors_300 = {"E57373", "F06292", "BA68C8", "9575CD", "7986CB", "64B5F6", "4FC3F7", "4DD0E1", "4DB6AC", "81C784", "AED581", "DCE775", "FFD54F", "FFB74D", "FF8A65", "A1887F"};
|
||||||
|
private const string[] material_colors_200 = {"EF9A9A", "F48FB1", "CE93D8", "B39DDB", "9FA8DA", "90CAF9", "81D4FA", "80DEEA", "80CBC4", "A5D6A7", "C5E1A5", "E6EE9C", "FFE082", "FFCC80", "FFAB91", "BCAAA4"};
|
||||||
|
|
||||||
|
public static string get_avatar_hex_color(string name) {
|
||||||
|
return material_colors_300[name.hash() % material_colors_300.length];
|
||||||
|
// return tango_colors_light[name.hash() % tango_colors_light.length];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string get_name_hex_color(string name, bool dark_theme = false) {
|
||||||
|
if (dark_theme) {
|
||||||
|
return material_colors_300[name.hash() % material_colors_300.length];
|
||||||
|
} else {
|
||||||
|
return material_colors_500[name.hash() % material_colors_500.length];
|
||||||
|
}
|
||||||
|
// return tango_colors_medium[name.hash() % tango_colors_medium.length];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string color_for_show(string show) {
|
||||||
|
switch(show) {
|
||||||
|
case "online": return "#9CCC65";
|
||||||
|
case "away": return "#FFCA28";
|
||||||
|
case "chat": return "#66BB6A";
|
||||||
|
case "xa": return "#EF5350";
|
||||||
|
case "dnd": return "#EF5350";
|
||||||
|
default: return "#BDBDBD";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string get_conversation_display_name(StreamInteractor stream_interactor, Conversation conversation) {
|
||||||
|
if (conversation.type_ == Conversation.Type.GROUPCHAT_PM) {
|
||||||
|
return conversation.counterpart.resourcepart + " from " + get_display_name(stream_interactor, conversation.counterpart.bare_jid, conversation.account);
|
||||||
|
}
|
||||||
|
return get_display_name(stream_interactor, conversation.counterpart, conversation.account);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string get_display_name(StreamInteractor stream_interactor, Jid jid, Account account) {
|
||||||
|
if (stream_interactor.get_module(MucManager.IDENTITY).is_groupchat_occupant(jid, account)) {
|
||||||
|
return jid.resourcepart;
|
||||||
|
} else {
|
||||||
|
if (jid.bare_jid.equals(account.bare_jid.bare_jid)) {
|
||||||
|
if (account.alias == null || account.alias == "") {
|
||||||
|
return account.bare_jid.to_string();
|
||||||
|
} else {
|
||||||
|
return account.alias;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Roster.Item roster_item = stream_interactor.get_module(RosterManager.IDENTITY).get_roster_item(account, jid);
|
||||||
|
if (roster_item != null && roster_item.name != null) {
|
||||||
|
return roster_item.name;
|
||||||
|
}
|
||||||
|
return jid.bare_jid.to_string();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string get_message_display_name(StreamInteractor stream_interactor, Entities.Message message, Account account) {
|
||||||
|
Jid? real_jid = stream_interactor.get_module(MucManager.IDENTITY).get_message_real_jid(message);
|
||||||
|
if (real_jid != null) {
|
||||||
|
return get_display_name(stream_interactor, real_jid, account);
|
||||||
|
} else {
|
||||||
|
return get_display_name(stream_interactor, message.from, account);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void image_set_from_scaled_pixbuf(Image image, Gdk.Pixbuf pixbuf, int scale = 0) {
|
||||||
|
if (scale == 0) scale = image.get_scale_factor();
|
||||||
|
image.set_from_surface(Gdk.cairo_surface_create_from_pixbuf(pixbuf, scale, image.get_window()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private const string force_background_css = "%s { background-color: %s; }";
|
||||||
|
private const string force_color_css = "%s { color: %s; }";
|
||||||
|
|
||||||
|
private static void force_css(Gtk.Widget widget, string css) {
|
||||||
|
var p = new Gtk.CssProvider();
|
||||||
|
try {
|
||||||
|
p.load_from_data(css);
|
||||||
|
widget.get_style_context().add_provider(p, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
|
||||||
|
} catch (GLib.Error err) {
|
||||||
|
// handle err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void force_background(Gtk.Widget widget, string color, string selector = "*") {
|
||||||
|
force_css(widget, force_background_css.printf(selector, color));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void force_base_background(Gtk.Widget widget, string selector = "*") {
|
||||||
|
force_background(widget, "@theme_base_color", selector);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void force_color(Gtk.Widget widget, string color, string selector = "*") {
|
||||||
|
force_css(widget, force_color_css.printf(selector, color));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void force_error_color(Gtk.Widget widget, string selector = "*") {
|
||||||
|
force_color(widget, "@error_color", selector);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool is_dark_theme(Gtk.Widget widget) {
|
||||||
|
Gdk.RGBA bg = widget.get_style_context().get_background_color(StateFlags.NORMAL);
|
||||||
|
return (bg.red < 0.5 && bg.green < 0.5 && bg.blue < 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool is_24h_format() {
|
||||||
|
GLib.Settings settings = new GLib.Settings("org.gnome.desktop.interface");
|
||||||
|
string settings_format = settings.get_string("clock-format");
|
||||||
|
string p_format = (new DateTime.now_local()).format("%p");
|
||||||
|
return settings_format == "24h" || p_format == " ";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
129
main/src/ui/util/label_hybrid.vala
Normal file
129
main/src/ui/util/label_hybrid.vala
Normal file
|
@ -0,0 +1,129 @@
|
||||||
|
using Gee;
|
||||||
|
using Gtk;
|
||||||
|
|
||||||
|
namespace Dino.Ui.Util {
|
||||||
|
|
||||||
|
public class LabelHybrid : Stack {
|
||||||
|
|
||||||
|
public Label label = new Label("") { visible=true };
|
||||||
|
protected Button button = new Button() { relief=ReliefStyle.NONE, visible=true };
|
||||||
|
|
||||||
|
public void init(Widget widget) {
|
||||||
|
button.add(label);
|
||||||
|
add_named(button, "label");
|
||||||
|
add_named(widget, "widget");
|
||||||
|
|
||||||
|
button.clicked.connect(() => {
|
||||||
|
show_widget();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void show_widget() {
|
||||||
|
visible_child_name = "widget";
|
||||||
|
}
|
||||||
|
|
||||||
|
public void show_label() {
|
||||||
|
visible_child_name = "label";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class EntryLabelHybrid : LabelHybrid {
|
||||||
|
|
||||||
|
public string text {
|
||||||
|
get { return entry.text; }
|
||||||
|
set {
|
||||||
|
entry.text = value;
|
||||||
|
label.label = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool visibility {
|
||||||
|
get { return entry.visibility; }
|
||||||
|
set { entry.visibility = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public float xalign {
|
||||||
|
get { return label.xalign; }
|
||||||
|
set {
|
||||||
|
label.xalign = value;
|
||||||
|
entry.set_alignment(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Entry entry;
|
||||||
|
|
||||||
|
public EntryLabelHybrid(Entry? e = null) {
|
||||||
|
entry = e ?? new Entry() { visible=true };
|
||||||
|
init(entry);
|
||||||
|
update_label();
|
||||||
|
|
||||||
|
entry.key_release_event.connect((event) => {
|
||||||
|
if (event.keyval == Gdk.Key.Return) {
|
||||||
|
show_label();
|
||||||
|
} else {
|
||||||
|
label.label = entry.text;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void update_label() {
|
||||||
|
text = text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ComboBoxTextLabelHybrid : LabelHybrid {
|
||||||
|
|
||||||
|
public int active {
|
||||||
|
get { return combobox.active; }
|
||||||
|
set { combobox.active = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public float xalign {
|
||||||
|
get { return label.xalign; }
|
||||||
|
set { label.xalign = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private ComboBoxText combobox;
|
||||||
|
|
||||||
|
public ComboBoxTextLabelHybrid(ComboBoxText? cb = null) {
|
||||||
|
combobox = cb ?? new ComboBoxText() { visible=true };
|
||||||
|
init(combobox);
|
||||||
|
update_label();
|
||||||
|
|
||||||
|
combobox.changed.connect(() => {
|
||||||
|
update_label();
|
||||||
|
show_label();
|
||||||
|
});
|
||||||
|
button.clicked.connect(() => {
|
||||||
|
combobox.popup();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void append(string id, string text) { combobox.append(id, text); }
|
||||||
|
public string get_active_text() { return combobox.get_active_text(); }
|
||||||
|
|
||||||
|
private void update_label() {
|
||||||
|
label.label = combobox.get_active_text();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class LabelHybridGroup {
|
||||||
|
|
||||||
|
private Gee.List<LabelHybrid> hybrids = new ArrayList<LabelHybrid>();
|
||||||
|
|
||||||
|
public void add(LabelHybrid hybrid) {
|
||||||
|
hybrids.add(hybrid);
|
||||||
|
|
||||||
|
hybrid.notify["visible-child-name"].connect(() => {
|
||||||
|
if (hybrid.visible_child_name == "label") return;
|
||||||
|
foreach (LabelHybrid h in hybrids) {
|
||||||
|
if (h != hybrid) {
|
||||||
|
h.set_visible_child_name("label");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in a new issue