diff --git a/data/gresource.xml b/data/gresource.xml
index 68859ad8e..214c4aad6 100644
--- a/data/gresource.xml
+++ b/data/gresource.xml
@@ -69,6 +69,7 @@
gtk/dropdown/expiration.ui
ui/views/base.ui
+ ui/views/media_viewer.ui
ui/views/profile_header.ui
ui/views/sidebar/view.ui
ui/views/sidebar/account.ui
diff --git a/data/style.css b/data/style.css
index 35326c2fe..32fe8a624 100644
--- a/data/style.css
+++ b/data/style.css
@@ -231,8 +231,8 @@ flowboxchild {
background: alpha(@success_bg_color, 0.1);
}
-.media-viewer-headerbar {
- background: rgba(0, 0, 0, .7);
+.media-viewer {
+ background: black;
color: white;
}
diff --git a/data/ui/views/media_viewer.ui b/data/ui/views/media_viewer.ui
new file mode 100644
index 000000000..2fdd69205
--- /dev/null
+++ b/data/ui/views/media_viewer.ui
@@ -0,0 +1,182 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Dialogs/MainWindow.vala b/src/Dialogs/MainWindow.vala
index a7d6bf7a4..c5439bd54 100644
--- a/src/Dialogs/MainWindow.vala
+++ b/src/Dialogs/MainWindow.vala
@@ -44,21 +44,16 @@ public class Tuba.Dialogs.MainWindow: Adw.ApplicationWindow, Saveable {
#endif
}
- public bool is_media_viewer_visible () {
- return media_viewer.visible;
+ public bool is_media_viewer_visible {
+ get { return media_viewer.visible; }
}
public void scroll_media_viewer (int pos) {
- if (!is_media_viewer_visible ()) return;
+ if (!is_media_viewer_visible) return;
media_viewer.scroll_to (pos);
}
- public void temp_reveal_media_viewer (Gtk.Widget widget) {
- // if (is_media_viewer_visible ())
- media_viewer.reveal (widget);
- }
-
public void show_media_viewer (
string url,
Tuba.Attachment.MediaType media_type,
@@ -73,7 +68,7 @@ public class Tuba.Dialogs.MainWindow: Adw.ApplicationWindow, Saveable {
media_viewer.add_media (url, media_type, preview, pos, as_is, user_friendly_url);
- if (!is_media_viewer_visible ()) {
+ if (!is_media_viewer_visible) {
if (source_widget != null) {
media_viewer.reveal (source_widget);
} else {
@@ -83,12 +78,11 @@ public class Tuba.Dialogs.MainWindow: Adw.ApplicationWindow, Saveable {
}
public void show_media_viewer_remote_video (string url, Gdk.Paintable? preview, string? user_friendly_url = null) {
- if (!is_media_viewer_visible ()) {
- // main_stack.visible_child_name = "media_viewer";
- // media_viewer.clear.connect (hide_media_viewer);
- }
-
media_viewer.set_remote_video (url, preview, user_friendly_url);
+
+ if (!is_media_viewer_visible) {
+ media_viewer.visible = true;
+ }
}
public void show_book (API.BookWyrm book, string? fallback = null) {
@@ -149,7 +143,7 @@ public class Tuba.Dialogs.MainWindow: Adw.ApplicationWindow, Saveable {
}
public bool back () {
- if (is_media_viewer_visible ()) {
+ if (is_media_viewer_visible) {
media_viewer.clear ();
return true;
};
diff --git a/src/Views/MediaViewer.vala b/src/Views/MediaViewer.vala
index 3db4fb168..be6ca597f 100644
--- a/src/Views/MediaViewer.vala
+++ b/src/Views/MediaViewer.vala
@@ -61,7 +61,8 @@ public class Tuba.Attachment {
}
}
-public class Tuba.Views.MediaViewer : Gtk.Box {
+[GtkTemplate (ui = "/dev/geopjr/Tuba/ui/views/media_viewer.ui")]
+public class Tuba.Views.MediaViewer : Adw.Bin {
const double MAX_ZOOM = 20;
static double last_used_volume = 1.0;
@@ -283,44 +284,29 @@ public class Tuba.Views.MediaViewer : Gtk.Box {
};
private Gee.ArrayList- items = new Gee.ArrayList
- ();
- protected Gtk.Button fullscreen_btn;
- protected Adw.HeaderBar headerbar;
- private Adw.Carousel carousel;
- private Adw.CarouselIndicatorDots carousel_dots;
protected SimpleAction copy_media_simple_action;
- private Tuba.Widgets.ScaleRevealer scale_revealer;
- protected Gtk.PopoverMenu context_menu { get; set; }
- construct {
- carousel = new Adw.Carousel () {
- vexpand = true,
- hexpand = true,
- css_classes = {"osd"}
- };
+ [GtkChild] unowned Gtk.PopoverMenu context_menu;
+ [GtkChild] unowned Gtk.Button fullscreen_btn;
+
+ [GtkChild] unowned Gtk.Revealer page_buttons_revealer;
+ [GtkChild] unowned Gtk.Button prev_btn;
+ [GtkChild] unowned Gtk.Button next_btn;
+
+ [GtkChild] unowned Gtk.Revealer zoom_buttons_revealer;
+ [GtkChild] unowned Gtk.Button zoom_out_btn;
+ [GtkChild] unowned Gtk.Button zoom_in_btn;
+
+ [GtkChild] unowned Tuba.Widgets.ScaleRevealer scale_revealer;
+ [GtkChild] unowned Adw.Carousel carousel;
+ [GtkChild] unowned Adw.CarouselIndicatorDots carousel_dots;
+ construct {
// Move between media using the arrow keys
var keypresscontroller = new Gtk.EventControllerKey ();
keypresscontroller.key_pressed.connect (on_keypress);
add_controller (keypresscontroller);
- var overlay = new Gtk.Overlay () {
- vexpand = true,
- hexpand = true
- };
-
- Gtk.Widget zoom_btns;
- Gtk.Widget page_btns;
- generate_media_buttons (out page_btns, out zoom_btns);
-
- scale_revealer = new Tuba.Widgets.ScaleRevealer () {
- child = carousel
- };
- scale_revealer.transition_done.connect (on_scale_revealer_transition_end);
-
- overlay.add_overlay (page_btns);
- overlay.add_overlay (zoom_btns);
- overlay.child = scale_revealer;
-
var drag = new Gtk.GestureDrag ();
drag.drag_begin.connect (on_drag_begin);
drag.drag_update.connect (on_drag_update);
@@ -337,9 +323,6 @@ public class Tuba.Views.MediaViewer : Gtk.Box {
motion.motion.connect (on_motion);
add_controller (motion);
- orientation = Gtk.Orientation.VERTICAL;
- spacing = 0;
-
var actions = new GLib.SimpleActionGroup ();
actions.add_action_entries (ACTION_ENTRIES, this);
@@ -349,55 +332,11 @@ public class Tuba.Views.MediaViewer : Gtk.Box {
this.insert_action_group ("mediaviewer", actions);
- headerbar = new Adw.HeaderBar () {
- title_widget = new Gtk.Label (_("Media Viewer")) {
- css_classes = {"title"}
- },
- css_classes = {"flat", "media-viewer-headerbar"}
- };
- var back_btn = new Gtk.Button.from_icon_name ("tuba-left-large-symbolic") {
- tooltip_text = _("Go Back")
- };
- back_btn.clicked.connect (on_back_clicked);
- headerbar.pack_start (back_btn);
-
- var end_box = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 0);
- fullscreen_btn = new Gtk.Button.from_icon_name ("view-fullscreen-symbolic") {
- tooltip_text = _("Toggle Fullscreen")
- };
- fullscreen_btn.clicked.connect (toggle_fullscreen);
-
- var menu_model = create_actions_menu ();
- var actions_btn = new Gtk.MenuButton () {
- icon_name = "view-more-symbolic",
- menu_model = menu_model
- };
-
- context_menu = new Gtk.PopoverMenu.from_model (menu_model) {
- has_arrow = false,
- halign = Gtk.Align.START
- };
+ carousel.notify["n-pages"].connect (on_carousel_n_pages_changed);
+ carousel.page_changed.connect (on_carousel_page_changed);
+ scale_revealer.transition_done.connect (on_scale_revealer_transition_end);
context_menu.set_parent (this);
- end_box.append (fullscreen_btn);
- end_box.append (actions_btn);
- headerbar.pack_end (end_box);
-
- carousel_dots = new Adw.CarouselIndicatorDots () {
- carousel = carousel,
- css_classes = {"osd"},
- visible = false
- };
-
- carousel.bind_property ("n_pages", carousel_dots, "visible", BindingFlags.SYNC_CREATE, (b, src, ref target) => {
- target.set_boolean (src.get_uint () > 1);
- return true;
- });
-
- append (headerbar);
- append (overlay);
- append (carousel_dots);
-
setup_mouse_previous_click ();
setup_double_click ();
setup_mouse_secondary_click ();
@@ -408,7 +347,11 @@ public class Tuba.Views.MediaViewer : Gtk.Box {
}
private void on_scale_revealer_transition_end () {
- if (!scale_revealer.reveal_child) this.visible = false;
+ if (!scale_revealer.reveal_child) {
+ this.visible = false;
+ scale_revealer.source_widget = null;
+ reset_media_viewer ();
+ }
}
int? old_height;
@@ -486,28 +429,17 @@ public class Tuba.Views.MediaViewer : Gtk.Box {
return true;
}
- protected void on_back_clicked () {
- clear ();
+ [GtkCallback]
+ public void clear () {
+ if (!revealed) reset_media_viewer ();
scale_revealer.reveal_child = false;
}
- protected void toggle_fullscreen () {
+ [GtkCallback]
+ private void toggle_fullscreen () {
this.fullscreen = !this._fullscreen;
}
- protected GLib.Menu create_actions_menu () {
- var menu_model = new GLib.Menu ();
- menu_model.append (_("Open in Browser"), "mediaviewer.open-in-browser");
- menu_model.append (_("Copy URL"), "mediaviewer.copy-url");
- menu_model.append (_("Save Media"), "mediaviewer.save-as");
-
- var copy_media_menu_item = new MenuItem (_("Copy Media"), "mediaviewer.copy-media");
- copy_media_menu_item.set_attribute_value ("hidden-when", "action-disabled");
- menu_model.append_item (copy_media_menu_item);
-
- return menu_model;
- }
-
private void copy_url () {
Item? page = safe_get ((int) carousel.position);
if (page == null) return;
@@ -605,7 +537,7 @@ public class Tuba.Views.MediaViewer : Gtk.Box {
}
private void handle_mouse_previous_click (int n_press, double x, double y) {
- on_back_clicked ();
+ clear ();
}
private void on_double_click (int n_press, double x, double y) {
@@ -617,7 +549,7 @@ public class Tuba.Views.MediaViewer : Gtk.Box {
page.on_double_click ();
}
- public virtual signal void clear () {
+ private void reset_media_viewer () {
this.fullscreen = false;
items.foreach ((item) => {
@@ -744,106 +676,60 @@ public class Tuba.Views.MediaViewer : Gtk.Box {
}, Priority.LOW);
}
- private Gtk.Button zoom_out_btn;
- private Gtk.Button zoom_in_btn;
- private Gtk.Revealer page_buttons_revealer;
- private Gtk.Revealer zoom_buttons_revealer;
- private void generate_media_buttons (out Gtk.Revealer page_btns, out Gtk.Revealer zoom_btns) {
- var t_page_btns = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 12);
- var t_zoom_btns = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 12);
-
- var prev_btn = new Gtk.Button.from_icon_name ("go-previous-symbolic") {
- css_classes = {"circular", "osd", "media-viewer-fab"},
- tooltip_text = _("Previous Attachment")
- };
-
- var next_btn = new Gtk.Button.from_icon_name ("go-next-symbolic") {
- css_classes = {"circular", "osd", "media-viewer-fab"},
- tooltip_text = _("Next Attachment")
- };
-
- prev_btn.clicked.connect (() => scroll_to (((int) carousel.position) - 1, false));
- next_btn.clicked.connect (() => scroll_to (((int) carousel.position) + 1, false));
-
- carousel.notify["n-pages"].connect (() => {
- var has_more_than_1_item = carousel.n_pages > 1;
-
- prev_btn.visible = has_more_than_1_item;
- next_btn.visible = has_more_than_1_item;
- });
-
- t_page_btns.append (prev_btn);
- t_page_btns.append (next_btn);
-
- zoom_out_btn = new Gtk.Button.from_icon_name ("zoom-out-symbolic") {
- css_classes = {"circular", "osd", "media-viewer-fab"},
- tooltip_text = _("Zoom Out")
- };
+ [GtkCallback]
+ private void on_previous_clicked () {
+ scroll_to (((int) carousel.position) - 1, false);
+ }
- zoom_in_btn = new Gtk.Button.from_icon_name ("zoom-in-symbolic") {
- css_classes = {"circular", "osd", "media-viewer-fab"},
- tooltip_text = _("Zoom In")
- };
+ [GtkCallback]
+ private void on_next_clicked () {
+ scroll_to (((int) carousel.position) + 1, false);
+ }
- zoom_out_btn.clicked.connect (() => {
- Item? page = safe_get ((int) carousel.position);
+ [GtkCallback]
+ private void on_zoom_out_clicked () {
+ Item? page = safe_get ((int) carousel.position);
if (page == null) return;
page.zoom_out ();
- });
- zoom_in_btn.clicked.connect (() => {
- Item? page = safe_get ((int) carousel.position);
+ }
+
+ [GtkCallback]
+ private void on_zoom_in_clicked () {
+ Item? page = safe_get ((int) carousel.position);
if (page == null) return;
page.zoom_in ();
- });
-
- carousel.page_changed.connect ((pos) => {
- prev_btn.sensitive = pos > 0;
- next_btn.sensitive = pos < items.size - 1;
-
- Item? page = safe_get ((int) pos);
- // Media buttons overlap the video
- // controller, so position them higher
- if (page != null && page.is_video) {
- page_buttons_revealer.margin_bottom = zoom_buttons_revealer.margin_bottom = 68;
- zoom_buttons_revealer.visible = false;
- play_video ((int) pos);
- copy_media_simple_action.set_enabled (false);
- } else {
- page_buttons_revealer.margin_bottom = zoom_buttons_revealer.margin_bottom = 18;
- zoom_buttons_revealer.visible = true;
- pause_all_videos ();
- copy_media_simple_action.set_enabled (true);
- }
+ }
- on_zoom_change ();
- });
+ private void on_carousel_page_changed (uint pos) {
+ prev_btn.sensitive = pos > 0;
+ next_btn.sensitive = pos < items.size - 1;
+
+ Item? page = safe_get ((int) pos);
+ // Media buttons overlap the video
+ // controller, so position them higher
+ if (page != null && page.is_video) {
+ page_buttons_revealer.margin_bottom = zoom_buttons_revealer.margin_bottom = 68;
+ zoom_buttons_revealer.visible = false;
+ play_video ((int) pos);
+ copy_media_simple_action.set_enabled (false);
+ } else {
+ page_buttons_revealer.margin_bottom = zoom_buttons_revealer.margin_bottom = 18;
+ zoom_buttons_revealer.visible = true;
+ pause_all_videos ();
+ copy_media_simple_action.set_enabled (true);
+ }
- t_zoom_btns.append (zoom_out_btn);
- t_zoom_btns.append (zoom_in_btn);
-
- zoom_buttons_revealer = new Gtk.Revealer () {
- child = t_zoom_btns,
- transition_type = Gtk.RevealerTransitionType.CROSSFADE,
- valign = Gtk.Align.END,
- halign = Gtk.Align.END,
- margin_end = 18,
- margin_bottom = 18,
- visible = false
- };
+ on_zoom_change ();
+ }
- page_buttons_revealer = new Gtk.Revealer () {
- child = t_page_btns,
- transition_type = Gtk.RevealerTransitionType.CROSSFADE,
- valign = Gtk.Align.END,
- halign = Gtk.Align.START,
- margin_start = 18,
- margin_bottom = 18
- };
+ private void on_carousel_n_pages_changed () {
+ bool has_more_than_1_item = carousel.n_pages > 1;
- page_btns = page_buttons_revealer;
- zoom_btns = zoom_buttons_revealer;
+ carousel_dots.visible = has_more_than_1_item;
+ prev_btn.visible = has_more_than_1_item;
+ next_btn.visible = has_more_than_1_item;
}
public void on_zoom_change () {
diff --git a/src/Widgets/Attachment/Item.vala b/src/Widgets/Attachment/Item.vala
index d36f31267..1beb92c2b 100644
--- a/src/Widgets/Attachment/Item.vala
+++ b/src/Widgets/Attachment/Item.vala
@@ -221,7 +221,7 @@ public class Tuba.Widgets.Attachment.Item : Adw.Bin {
gesture_click_controller.set_state (Gtk.EventSequenceState.CLAIMED);
gesture_lp_controller.set_state (Gtk.EventSequenceState.CLAIMED);
- if (app.main_window.is_media_viewer_visible ()) return;
+ if (app.main_window.is_media_viewer_visible) return;
Gdk.Rectangle rectangle = {
(int) x,
(int) y,