diff --git a/libdino/src/entity/encryption.vala b/libdino/src/entity/encryption.vala index 6868def4..6584befd 100644 --- a/libdino/src/entity/encryption.vala +++ b/libdino/src/entity/encryption.vala @@ -34,4 +34,61 @@ namespace Dino.Entities { } } + public enum InterfaceScale { + NONE, + SMALL, + MEDIUM, + LARGE, + EXTRA_LARGE; + + public bool is_some() { + return this != NONE; + } + + public static InterfaceScale parse(string str) { + switch (str) { + case "DINO_ENTITIES_INTERFACE_SCALE_SMALL": + return SMALL; + case "DINO_ENTITIES_INTERFACE_SCALE_MEDIUM": + return MEDIUM; + case "DINO_ENTITIES_INTERFACE_SCALE_LARGE": + return LARGE; + case "DINO_ENTITIES_INTERFACE_SCALE_EXTRA_LARGE": + return EXTRA_LARGE; + default: + return NONE; + } + } + + public static double to_double(InterfaceScale val) { + switch (val) { + case InterfaceScale.SMALL: + return 0.6; + case InterfaceScale.MEDIUM: + return 0.8; + case InterfaceScale.LARGE: + return 1; + case InterfaceScale.EXTRA_LARGE: + return 1.5; + default: + return 0.8; + } + } + + public static double to_css_pt(InterfaceScale val) { + switch (val) { + case InterfaceScale.SMALL: + return 8; + case InterfaceScale.MEDIUM: + return 10; + case InterfaceScale.LARGE: + return 12; + case InterfaceScale.EXTRA_LARGE: + return 16; + default: + return 10; + } + } + } + } \ No newline at end of file diff --git a/libdino/src/entity/settings.vala b/libdino/src/entity/settings.vala index 9b1efa3a..cd68df9d 100644 --- a/libdino/src/entity/settings.vala +++ b/libdino/src/entity/settings.vala @@ -13,11 +13,14 @@ public class Settings : Object { convert_utf8_smileys_ = col_to_bool_or_default("convert_utf8_smileys", true); check_spelling = col_to_bool_or_default("check_spelling", true); default_encryption = col_to_encryption_or_default("default_encryption", Encryption.UNKNOWN); + interface_scale = col_to_interface_scale_or_default("interface_scale", InterfaceScale.MEDIUM); send_button = col_to_bool_or_default("send_button", false); enter_newline = col_to_bool_or_default("enter_newline", false); dark_theme = col_to_bool_or_default("dark_theme", false); } + public signal void update_interface_scale(); + private bool col_to_bool_or_default(string key, bool def) { string? val = db.settings.select({db.settings.value}).with(db.settings.key, "=", key)[db.settings.value]; return val != null ? bool.parse(val) : def; @@ -29,6 +32,12 @@ public class Settings : Object { return val != null ? Encryption.parse(val) : def; } + private InterfaceScale col_to_interface_scale_or_default(string key, InterfaceScale def) { + var sval = db.settings.value; + string? val = db.settings.select({sval}).with(db.settings.key, "=", key)[sval]; + return val != null ? InterfaceScale.parse(val) : def; + } + private bool send_typing_; public bool send_typing { get { return send_typing_; } @@ -103,6 +112,20 @@ public class Settings : Object { } } + private InterfaceScale interface_scale_; + public InterfaceScale interface_scale { + get { return interface_scale_; } + set { + string valstr = value.to_string(); + db.settings.upsert() + .value(db.settings.key, "interface_scale", true) + .value(db.settings.value, valstr) + .perform(); + interface_scale_ = value; + update_interface_scale(); + } + } + public signal void send_button_update(bool visible); private bool send_button_; diff --git a/main/data/conversation_item_widget.ui b/main/data/conversation_item_widget.ui index 3216232d..7fc0134c 100644 --- a/main/data/conversation_item_widget.ui +++ b/main/data/conversation_item_widget.ui @@ -6,7 +6,7 @@ 2 - 35 + 35 35 start 2 @@ -23,6 +23,7 @@ 0 baseline + @@ -36,7 +37,7 @@ 0 baseline - + - + @@ -76,7 +76,7 @@ end 0 - + @@ -91,7 +91,7 @@ False 0.5 - + diff --git a/main/data/quote.ui b/main/data/quote.ui index 277fc374..704a2f76 100644 --- a/main/data/quote.ui +++ b/main/data/quote.ui @@ -56,6 +56,9 @@ end start 0 + + + 0 1 diff --git a/main/data/settings_dialog.ui b/main/data/settings_dialog.ui index 5fafe36d..e2f04b37 100644 --- a/main/data/settings_dialog.ui +++ b/main/data/settings_dialog.ui @@ -157,6 +157,59 @@ + + + + + Interface scale + + + + + Small + True + True + False + False + scale_small + + + + + Medium + True + True + False + False + scale_small + + + + + Large + True + True + False + False + scale_small + + + + + Extra Large + True + True + False + False + scale_small + + + + + + + + diff --git a/main/src/ui/conversation_content_view/conversation_item_skeleton.vala b/main/src/ui/conversation_content_view/conversation_item_skeleton.vala index 5d86f6c7..dc1e501b 100644 --- a/main/src/ui/conversation_content_view/conversation_item_skeleton.vala +++ b/main/src/ui/conversation_content_view/conversation_item_skeleton.vala @@ -61,6 +61,12 @@ public class ConversationItemSkeleton : Plugins.ConversationItemWidgetInterface, set_widget(widget, Plugins.WidgetType.GTK4, 2); } + Dino.Entities.Settings settings = Dino.Application.get_default().settings; + settings.update_interface_scale.connect(() => { + update_name_label(); + update_time(); + }); + if (item.requires_header) { // TODO: For MUC messags, use real jid from message if known avatar_picture.model = new ViewModel.CompatAvatarPictureModel(stream_interactor).add_participant(conversation, item.jid); @@ -174,7 +180,12 @@ public class ConversationItemSkeleton : Plugins.ConversationItemWidgetInterface, } private void update_time() { + Dino.Entities.Settings settings = Dino.Application.get_default().settings; + Pango.AttrList attr_list = new Pango.AttrList(); + attr_list.insert(Pango.attr_scale_new(InterfaceScale.to_double(settings.interface_scale))); + time_label.label = get_relative_time(item.time.to_local()).to_string(); + time_label.set_attributes(attr_list); time_update_timeout = Timeout.add_seconds((int) get_next_time_change(item.time), () => { if (this.main_grid.parent == null) return false; @@ -184,7 +195,11 @@ public class ConversationItemSkeleton : Plugins.ConversationItemWidgetInterface, } private void update_name_label() { + Dino.Entities.Settings settings = Dino.Application.get_default().settings; + Pango.AttrList attr_list = new Pango.AttrList(); + attr_list.insert(Pango.attr_scale_new(InterfaceScale.to_double(settings.interface_scale))); name_label.label = Util.get_participant_display_name(stream_interactor, conversation, item.jid, true); + name_label.set_attributes(attr_list); } private void update_received_mark() { diff --git a/main/src/ui/conversation_content_view/message_widget.vala b/main/src/ui/conversation_content_view/message_widget.vala index 5a18b51c..84529170 100644 --- a/main/src/ui/conversation_content_view/message_widget.vala +++ b/main/src/ui/conversation_content_view/message_widget.vala @@ -281,7 +281,10 @@ public class MessageItemEditMode : Box { [GtkChild] public unowned Frame frame; construct { + Dino.Entities.Settings settings = Dino.Application.get_default().settings; + Util.force_css(frame, "* { border-radius: 3px; padding: 0px 7px; }"); + Util.force_css(frame, " .dino-chatinput { font-size: %spt; }".printf(InterfaceScale.to_css_pt(settings.interface_scale).to_string())); EmojiChooser chooser = new EmojiChooser(); chooser.emoji_picked.connect((emoji) => { @@ -295,6 +298,14 @@ public class MessageItemEditMode : Box { send_button.clicked.connect(() => send()); chat_text_view.cancel_input.connect(() => cancelled()); chat_text_view.send_text.connect(() => send()); + + // Dino.Entities.Settings settings = Dino.Application.get_default().settings; + // settings.update_interface_scale.connect(() => { + // Pango.AttrList attr_list = new Pango.AttrList(); + // attr_list.insert(Pango.attr_scale_new(InterfaceScale.to_double(settings.interface_scale))); + // chat_text_view.text_view.override_font(Pango.font_description_from_string('DejaVu Sans Mono 12')); + // }); + } private void on_text_view_changed() { diff --git a/main/src/ui/conversation_content_view/quote_widget.vala b/main/src/ui/conversation_content_view/quote_widget.vala index 23b62e6a..96697413 100644 --- a/main/src/ui/conversation_content_view/quote_widget.vala +++ b/main/src/ui/conversation_content_view/quote_widget.vala @@ -67,6 +67,15 @@ namespace Dino.Ui.Quote { Label message = (Label) builder.get_object("message"); Button abort_button = (Button) builder.get_object("abort-button"); + Dino.Entities.Settings settings = Dino.Application.get_default().settings; + settings.update_interface_scale.connect(() => { + Pango.AttrList attr_list = new Pango.AttrList(); + attr_list.insert(Pango.attr_scale_new(InterfaceScale.to_double(settings.interface_scale))); + message.set_attributes(attr_list); + time.set_attributes(attr_list); + author.set_attributes(attr_list); + }); + avatar.model = new ViewModel.CompatAvatarPictureModel(model.stream_interactor).add_participant(model.conversation, model.author_jid); model.bind_property("display-name", author, "label", BindingFlags.SYNC_CREATE); model.bind_property("display-time", time, "label", BindingFlags.SYNC_CREATE); diff --git a/main/src/ui/conversation_selector/conversation_selector_row.vala b/main/src/ui/conversation_selector/conversation_selector_row.vala index c180b6b3..249a5d04 100644 --- a/main/src/ui/conversation_selector/conversation_selector_row.vala +++ b/main/src/ui/conversation_selector/conversation_selector_row.vala @@ -39,6 +39,11 @@ public class ConversationSelectorRow : ListBoxRow { this.conversation = conversation; this.stream_interactor = stream_interactor; + Dino.Entities.Settings settings = Dino.Application.get_default().settings; + settings.update_interface_scale.connect(() => { + content_item_received(); + }); + switch (conversation.type_) { case Conversation.Type.CHAT: stream_interactor.get_module(RosterManager.IDENTITY).updated_roster_item.connect((account, jid, roster_item) => { @@ -103,6 +108,13 @@ public class ConversationSelectorRow : ListBoxRow { content_item_received(); } + private AttrList get_scale_attr() { + Dino.Entities.Settings settings = Dino.Application.get_default().settings; + Pango.AttrList attr_list = new Pango.AttrList(); + attr_list.insert(Pango.attr_scale_new(InterfaceScale.to_double(settings.interface_scale))); + return attr_list; + } + public void update() { update_time_label(); } @@ -129,6 +141,10 @@ public class ConversationSelectorRow : ListBoxRow { protected void update_name_label() { name_label.label = Util.get_conversation_display_name(stream_interactor, conversation); + Dino.Entities.Settings settings = Dino.Application.get_default().settings; + Pango.AttrList attr_list = new Pango.AttrList(); + attr_list.insert(Pango.attr_scale_new(InterfaceScale.to_double(settings.interface_scale))); + name_label.set_attributes(attr_list); } private void update_pinned_icon() { @@ -139,6 +155,10 @@ public class ConversationSelectorRow : ListBoxRow { if (last_content_item != null) { time_label.visible = true; time_label.label = get_relative_time(last_content_item.time.to_local()); + Dino.Entities.Settings settings = Dino.Application.get_default().settings; + Pango.AttrList attr_list = new Pango.AttrList(); + attr_list.insert(Pango.attr_scale_new(InterfaceScale.to_double(settings.interface_scale))); + time_label.set_attributes(attr_list); } } @@ -207,8 +227,13 @@ public class ConversationSelectorRow : ListBoxRow { message_label.label = call.direction == Call.DIRECTION_OUTGOING ? _("Outgoing call") : _("Incoming call"); break; } + Dino.Entities.Settings settings = Dino.Application.get_default().settings; + Pango.AttrList attr_list = new Pango.AttrList(); + attr_list.insert(Pango.attr_scale_new(InterfaceScale.to_double(settings.interface_scale))); nick_label.visible = true; + nick_label.set_attributes(attr_list); message_label.visible = true; + message_label.set_attributes(attr_list); } } @@ -247,6 +272,7 @@ public class ConversationSelectorRow : ListBoxRow { } else { unread_count_label.label = num_unread.to_string(); unread_count_label.visible = true; + unread_count_label.set_attributes(get_scale_attr()); if (conversation.get_notification_setting(stream_interactor) == Conversation.NotifySetting.ON) { unread_count_label.add_css_class("unread-count-notify"); diff --git a/main/src/ui/settings_dialog.vala b/main/src/ui/settings_dialog.vala index 8c20a84b..a81b1369 100644 --- a/main/src/ui/settings_dialog.vala +++ b/main/src/ui/settings_dialog.vala @@ -16,6 +16,10 @@ class SettingsDialog : Adw.PreferencesWindow { [GtkChild] private unowned Switch send_button_switch; [GtkChild] private unowned Switch enter_newline_switch; [GtkChild] private unowned Switch dark_theme; + [GtkChild] private unowned CheckButton scale_small; + [GtkChild] private unowned CheckButton scale_medium; + [GtkChild] private unowned CheckButton scale_large; + [GtkChild] private unowned CheckButton scale_xlarge; Dino.Entities.Settings settings = Dino.Application.get_default().settings; @@ -30,6 +34,11 @@ class SettingsDialog : Adw.PreferencesWindow { encryption_radio_omemo.active = settings.default_encryption == Encryption.OMEMO; encryption_radio_openpgp.active = settings.default_encryption == Encryption.PGP; + scale_small.active = settings.interface_scale == InterfaceScale.SMALL; + scale_medium.active = settings.interface_scale == InterfaceScale.MEDIUM; + scale_large.active = settings.interface_scale == InterfaceScale.LARGE; + scale_xlarge.active = settings.interface_scale == InterfaceScale.EXTRA_LARGE; + send_button_switch.active = settings.send_button; enter_newline_switch.active = settings.enter_newline; enter_newline_switch.sensitive = settings.send_button; @@ -59,6 +68,30 @@ class SettingsDialog : Adw.PreferencesWindow { } }); + scale_small.notify["active"].connect(() => { + if (scale_small.active) { + settings.interface_scale = InterfaceScale.SMALL; + } + }); + + scale_medium.notify["active"].connect(() => { + if (scale_medium.active) { + settings.interface_scale = InterfaceScale.MEDIUM; + } + }); + + scale_large.notify["active"].connect(() => { + if (scale_large.active) { + settings.interface_scale = InterfaceScale.LARGE; + } + }); + + scale_xlarge.notify["active"].connect(() => { + if (scale_xlarge.active) { + settings.interface_scale = InterfaceScale.EXTRA_LARGE; + } + }); + send_button_switch.notify["active"].connect(() => { settings.send_button = send_button_switch.active; }); enter_newline_switch.notify["active"].connect(() => { settings.enter_newline = enter_newline_switch.active; }); settings.send_button_update.connect((visible) => {