diff --git a/data/gresource.xml b/data/gresource.xml
index be8c1ded9..8e04581a5 100644
--- a/data/gresource.xml
+++ b/data/gresource.xml
@@ -56,6 +56,9 @@
icons/scalable/actions/tuba-markdown-symbolic.svg
icons/scalable/actions/tuba-rich-text-symbolic.svg
icons/scalable/actions/tuba-earth-symbolic.svg
+ icons/scalable/actions/tuba-bear-symbolic.svg
+ icons/scalable/actions/tuba-image-round-symbolic.svg
+ icons/scalable/actions/tuba-sentiment-satisfied-symbolic.svg
icons/scalable/actions/tuba-verified-checkmark-symbolic.svg
icons/scalable/actions/tuba-funnel-symbolic.svg
icons/scalable/actions/tuba-error-symbolic.svg
@@ -88,6 +91,7 @@
ui/dialogs/list_edit.ui
ui/dialogs/new_account.ui
ui/dialogs/compose.ui
+ ui/dialogs/new_composer.ui
ui/dialogs/main.ui
ui/dialogs/preferences.ui
ui/dialogs/profile_edit.ui
diff --git a/data/gtk/dropdown/icon.ui b/data/gtk/dropdown/icon.ui
index a7f616c57..41a6ece58 100644
--- a/data/gtk/dropdown/icon.ui
+++ b/data/gtk/dropdown/icon.ui
@@ -1,13 +1,29 @@
-
-
-
diff --git a/data/icons/scalable/actions/tuba-bear-symbolic.svg b/data/icons/scalable/actions/tuba-bear-symbolic.svg
new file mode 100644
index 000000000..253250365
--- /dev/null
+++ b/data/icons/scalable/actions/tuba-bear-symbolic.svg
@@ -0,0 +1,2 @@
+
+
diff --git a/data/icons/scalable/actions/tuba-image-round-symbolic.svg b/data/icons/scalable/actions/tuba-image-round-symbolic.svg
new file mode 100644
index 000000000..bc45f2ef6
--- /dev/null
+++ b/data/icons/scalable/actions/tuba-image-round-symbolic.svg
@@ -0,0 +1,2 @@
+
+
diff --git a/data/icons/scalable/actions/tuba-sentiment-satisfied-symbolic.svg b/data/icons/scalable/actions/tuba-sentiment-satisfied-symbolic.svg
new file mode 100644
index 000000000..6bf2ccf52
--- /dev/null
+++ b/data/icons/scalable/actions/tuba-sentiment-satisfied-symbolic.svg
@@ -0,0 +1,2 @@
+
+
diff --git a/data/style.css b/data/style.css
index d4761799d..4e71ef8d4 100644
--- a/data/style.css
+++ b/data/style.css
@@ -658,6 +658,18 @@ GtkSourceAssistant row:last-child {
font-size: small;
}
+.accented-color {
+ color: @accent_color;
+}
+
+.font-large {
+ font-size: large;
+}
+
+.dropdown-border-radius > button {
+ border-radius: 9999px;
+}
+
.filter {
margin: -2px;
border-radius: 0;
diff --git a/data/ui/dialogs/new_composer.ui b/data/ui/dialogs/new_composer.ui
new file mode 100644
index 000000000..c7e7cb602
--- /dev/null
+++ b/data/ui/dialogs/new_composer.ui
@@ -0,0 +1,163 @@
+
+
+
+
+
+ 500
+ 400
+ 360
+ 200
+
+
+
+
+
+
+
+ 1
+ 1
+ 400
+
+
+ start
+ 100
+
+
+ vertical
+ 1
+ start
+ 30
+
+
+ New Post
+ 1
+ word-char
+ center
+
+
+
+
+
+ 1
+ vertical
+
+
+
+
+
+
+
+
+
+
+ 20
+ 32
+ 32
+ 20
+ 16
+
+
+ horizontal
+ 6
+
+
+
+
+
+
+
+
+ tuba-image-round-symbolic
+
+
+
+
+
+ format-justify-left-symbolic
+
+
+
+
+
+ tuba-warning-symbolic
+
+
+
+
+ 0
+ 0
+ 2
+
+
+
+
+
+ horizontal
+ 12
+
+ 0
+ 1
+
+
+
+
+
+ end
+ center
+ end
+ 12
+
+
+ 1
+ 1
+
+
+
+
+
+ Post
+ 1
+ end
+ center
+
+
+ 2
+ 0
+ 2
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Application.vala b/src/Application.vala
index 32288c8e2..14da46f1c 100644
--- a/src/Application.vala
+++ b/src/Application.vala
@@ -356,7 +356,7 @@ namespace Tuba {
void compose_activated () {
if (accounts.active.instance_info == null) return;
- new Dialogs.Compose ();
+ new Dialogs.NewCompose ();
}
void back_activated () {
diff --git a/src/Dialogs/Composer/NewDialog.vala b/src/Dialogs/Composer/NewDialog.vala
new file mode 100644
index 000000000..b55dca85b
--- /dev/null
+++ b/src/Dialogs/Composer/NewDialog.vala
@@ -0,0 +1,218 @@
+[GtkTemplate (ui = "/dev/geopjr/Tuba/ui/dialogs/new_composer.ui")]
+public class Tuba.Dialogs.NewCompose : Adw.Dialog {
+ [GtkChild] private unowned Gtk.Label counter_label;
+ [GtkChild] private unowned Gtk.Button post_btn;
+ [GtkChild] private unowned Gtk.Box btns_box;
+ [GtkChild] private unowned Gtk.Box dropdowns_box;
+ [GtkChild] private unowned Gtk.Grid grid;
+
+ [GtkChild] private unowned Gtk.Box status_box;
+ [GtkChild] private unowned Gtk.Box main_box;
+ [GtkChild] private unowned Gtk.Label status_title;
+
+ [GtkChild] private unowned Gtk.MenuButton native_emojis_button;
+ [GtkChild] private unowned Gtk.MenuButton custom_emojis_button;
+
+ private bool _is_narrow = false;
+ public bool is_narrow {
+ get {
+ return _is_narrow;
+ }
+ set {
+ Gtk.GridLayout layout_manager = (Gtk.GridLayout) grid.get_layout_manager ();
+ Gtk.GridLayoutChild counter_layout_child = (Gtk.GridLayoutChild) layout_manager.get_layout_child (counter_label);
+ Gtk.GridLayoutChild post_layout_child = (Gtk.GridLayoutChild) layout_manager.get_layout_child (post_btn);
+ Gtk.GridLayoutChild btns_layout_child = (Gtk.GridLayoutChild) layout_manager.get_layout_child (btns_box);
+
+ if (value) {
+ post_layout_child.column = 1;
+ post_layout_child.row = 1;
+ post_layout_child.row_span = 1;
+
+ counter_layout_child.row = 0;
+ counter_layout_child.column = 1;
+
+ btns_layout_child.column_span = 1;
+
+ counter_label.margin_end = 10;
+ counter_label.margin_start = 0;
+ grid.row_spacing = 12;
+ grid.margin_start = 16;
+ grid.margin_end = 16;
+ } else {
+ post_layout_child.column = 2;
+ post_layout_child.row = 0;
+ post_layout_child.row_span = 2;
+
+ counter_layout_child.row = 1;
+ counter_layout_child.column = 1;
+
+ btns_layout_child.column_span = 2;
+
+ counter_label.margin_end = 0;
+ counter_label.margin_start = 12;
+ grid.row_spacing = 16;
+ grid.margin_start = 32;
+ grid.margin_end = 32;
+ }
+
+ _is_narrow = value;
+ }
+ }
+ protected int64 char_limit { get; set; default = 500; }
+
+ private int64 _remaining_chars = 500;
+ protected int64 remaining_chars {
+ get {
+ return _remaining_chars;
+ }
+ set {
+ _remaining_chars = value;
+ counter_label.label = counter_label.tooltip_text = @"$value / $char_limit";
+
+ if (value < 0) {
+ counter_label.add_css_class ("error");
+ counter_label.remove_css_class ("accented-color");
+ } else {
+ counter_label.remove_css_class ("error");
+ counter_label.add_css_class ("accented-color");
+ }
+ }
+ }
+
+ private void install_emoji_pickers () {
+ var emoji_picker = new Gtk.EmojiChooser ();
+ native_emojis_button.popover = emoji_picker;
+ emoji_picker.emoji_picked.connect (editor.insert_string_at_cursor);
+
+ if (accounts.active.instance_emojis?.size > 0) {
+ var custom_emoji_picker = new Widgets.CustomEmojiChooser ();
+ custom_emojis_button.popover = custom_emoji_picker;
+ custom_emoji_picker.emoji_picked.connect (editor.insert_string_at_cursor);
+ }
+ }
+
+ private Componenets.Editor editor;
+ private void install_editor () {
+ editor = new Dialogs.Componenets.Editor ();
+ main_box.append (editor);
+
+ editor.notify["char-count"].connect (update_remaining_chars);
+ this.focus_widget = editor;
+ }
+
+ private void update_remaining_chars () {
+ int64 res = char_limit;
+ res -= editor.char_count;
+ remaining_chars = res;
+ }
+
+ protected Gtk.DropDown visibility_button;
+ protected Gtk.DropDown language_button;
+
+ private void append_dropdown (Gtk.DropDown dropdown) {
+ var togglebtn = dropdown.get_first_child ();
+ if (togglebtn != null) {
+ togglebtn.add_css_class ("flat");
+ }
+
+ dropdowns_box.append (dropdown);
+ }
+
+ protected void install_visibility (string default_visibility = settings.default_post_visibility) {
+ visibility_button = new Gtk.DropDown (accounts.active.visibility_list, null) {
+ expression = new Gtk.PropertyExpression (typeof (InstanceAccount.Visibility), null, "name"),
+ factory = new Gtk.BuilderListItemFactory.from_resource (null, @"$(Build.RESOURCES)gtk/dropdown/icon.ui"),
+ list_factory = new Gtk.BuilderListItemFactory.from_resource (null, @"$(Build.RESOURCES)gtk/dropdown/full.ui"),
+ tooltip_text = _("Post Privacy"),
+ valign = Gtk.Align.CENTER
+ };
+ visibility_button.add_css_class ("dropdown-border-radius");
+
+ var safe_visibility = accounts.active.visibility.has_key (default_visibility) ? default_visibility : "public";
+ uint default_visibility_index;
+ if (
+ accounts.active.visibility_list.find (
+ accounts.active.visibility[safe_visibility],
+ out default_visibility_index
+ )
+ ) {
+ visibility_button.selected = default_visibility_index;
+ }
+
+ append_dropdown (visibility_button);
+ }
+
+ private void install_languages (string? locale_iso = null) {
+ language_button = new Gtk.DropDown (app.app_locales.list_store, null) {
+ expression = new Gtk.PropertyExpression (typeof (Tuba.Locales.Locale), null, "name"),
+ factory = new Gtk.BuilderListItemFactory.from_resource (null, @"$(Build.RESOURCES)gtk/dropdown/language_title.ui"),
+ list_factory = new Gtk.BuilderListItemFactory.from_resource (null, @"$(Build.RESOURCES)gtk/dropdown/language.ui"),
+ tooltip_text = _("Post Language"),
+ enable_search = true,
+ valign = Gtk.Align.CENTER
+ };
+ language_button.add_css_class ("dropdown-border-radius");
+
+ if (locale_iso != null) {
+ uint default_lang_index;
+ if (
+ app.app_locales.list_store.find_with_equal_func (
+ new Tuba.Locales.Locale (locale_iso, null, null),
+ Tuba.Locales.Locale.compare,
+ out default_lang_index
+ )
+ ) {
+ language_button.selected = default_lang_index;
+ }
+ }
+
+ append_dropdown (language_button);
+ }
+
+ construct {
+ var condition = new Adw.BreakpointCondition.length (
+ Adw.BreakpointConditionLengthType.MAX_WIDTH,
+ 400, Adw.LengthUnit.SP
+ );
+ var breakpoint = new Adw.Breakpoint (condition);
+ breakpoint.add_setter (this, "is-narrow", true);
+ add_breakpoint (breakpoint);
+
+ var char_limit_api = accounts.active.instance_info.compat_status_max_characters;
+ if (char_limit_api > 0)
+ char_limit = char_limit_api;
+
+ install_editor ();
+ install_emoji_pickers ();
+ install_visibility ();
+ install_languages ();
+
+ update_remaining_chars ();
+ present (app.main_window);
+ }
+
+ public NewCompose (API.Status template = new API.Status.empty ()) {
+ Object ();
+ }
+
+ public NewCompose.reply (API.Status to) {
+ Object ();
+
+ try {
+ Widgets.Status widget_status = (Widgets.Status?) to.to_widget ();
+ widget_status.add_css_class ("card");
+ widget_status.actions.visible = false;
+ widget_status.menu_button.visible = false;
+ widget_status.activatable = false;
+ widget_status.can_target = false;
+ widget_status.can_focus = false;
+
+ status_box.insert_child_after (widget_status, status_title);
+ } catch (Error e) {
+ warning (@"Couldn't create status widget: $(e.message)");
+ }
+
+ status_title.label = _("Reply to %s").printf (to.account.handle);
+ }
+}
diff --git a/src/Dialogs/Composer/NewDialogEditor.vala b/src/Dialogs/Composer/NewDialogEditor.vala
new file mode 100644
index 000000000..1e6d9d603
--- /dev/null
+++ b/src/Dialogs/Composer/NewDialogEditor.vala
@@ -0,0 +1,103 @@
+public class Tuba.Dialogs.Componenets.Editor : Adw.Bin {
+ public int64 char_count { get; private set; default = 0; }
+ public string content {
+ owned get {
+ return editor.buffer.text;
+ }
+ set {
+ editor.buffer.text = value;
+ }
+ }
+
+ public void insert_string_at_cursor (string text) {
+ editor.buffer.insert_at_cursor (text, text.data.length);
+ }
+
+ protected Gtk.Overlay overlay;
+ protected Gtk.Label placeholder;
+ protected GtkSource.View editor;
+
+ private void count_chars () {
+ int64 res = 0;
+
+ // if (cw_button.active)
+ // res += (int64) cw_entry.buffer.length;
+ res += editor.buffer.get_char_count ();
+
+ char_count = res;
+ }
+
+ private void on_content_changed () {
+ editor.show_completion ();
+ count_chars ();
+ placeholder.visible = char_count == 0;
+ }
+
+ construct {
+ install_editor ();
+ install_overlay ();
+
+ child = overlay;
+ }
+
+ private void install_editor () {
+ editor = new GtkSource.View () {
+ vexpand = true,
+ hexpand = true,
+ top_margin = 6,
+ right_margin = 6,
+ bottom_margin = 6,
+ left_margin = 6,
+ pixels_below_lines = 6,
+ accepts_tab = false,
+ wrap_mode = Gtk.WrapMode.WORD_CHAR,
+ tab_width = 1,
+ // TODO: remove when other componenets are enabled
+ height_request = 100
+ };
+ editor.remove_css_class ("view");
+ editor.add_css_class ("font-large");
+
+ #if LIBSPELLING
+ var adapter = new Spelling.TextBufferAdapter ((GtkSource.Buffer) editor.buffer, Spelling.Checker.get_default ());
+
+ editor.extra_menu = adapter.get_menu_model ();
+ editor.insert_action_group ("spelling", adapter);
+ adapter.enabled = true;
+ #endif
+
+ editor.completion.add_provider (new Tuba.HandleProvider ());
+ editor.completion.add_provider (new Tuba.HashtagProvider ());
+ editor.completion.add_provider (new Tuba.EmojiProvider ());
+ editor.completion.select_on_show = true;
+ editor.completion.show_icons = true;
+ editor.completion.page_size = 3;
+ update_editor_style_scheme ();
+
+ editor.buffer.changed.connect (on_content_changed);
+ }
+
+ protected void update_editor_style_scheme () {
+ var manager = GtkSource.StyleSchemeManager.get_default ();
+ var scheme = manager.get_scheme ("adwaita");
+ var buffer = editor.buffer as GtkSource.Buffer;
+ buffer.style_scheme = scheme;
+ }
+
+ private void install_overlay () {
+ overlay = new Gtk.Overlay ();
+ placeholder = new Gtk.Label (_("What's on your mind?")) {
+ valign = Gtk.Align.START,
+ halign = Gtk.Align.START,
+ justify = Gtk.Justification.FILL,
+ margin_top = 6,
+ margin_start = 6,
+ wrap = true,
+ sensitive = false,
+ css_classes = {"font-large"}
+ };
+
+ overlay.add_overlay (placeholder);
+ overlay.child = editor;
+ }
+}
diff --git a/src/Dialogs/Composer/meson.build b/src/Dialogs/Composer/meson.build
index bab710a6f..dc8e9b65d 100644
--- a/src/Dialogs/Composer/meson.build
+++ b/src/Dialogs/Composer/meson.build
@@ -3,6 +3,8 @@ sources += files(
'AttachmentsPageAttachment.vala',
'Dialog.vala',
'EditorPage.vala',
+ 'NewDialog.vala',
+ 'NewDialogEditor.vala',
'Page.vala',
'PollPage.vala',
)
diff --git a/src/Widgets/Status.vala b/src/Widgets/Status.vala
index f09f3f441..e1ea5fd5d 100644
--- a/src/Widgets/Status.vala
+++ b/src/Widgets/Status.vala
@@ -651,7 +651,8 @@
}
private void on_reply_button_clicked () {
- new Dialogs.Compose.reply (status.formal, on_reply);
+ // new Dialogs.Compose.reply (status.formal, on_reply);
+ new Dialogs.NewCompose.reply (status.formal);
}
[GtkCallback] public void toggle_spoiler () {