Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(MediaViewer): ScaleRevealer #602

Merged
merged 13 commits into from
Oct 15, 2023
1 change: 1 addition & 0 deletions data/gresource.xml
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@
<file>gtk/dropdown/expiration.ui</file>

<file>ui/views/base.ui</file>
<file>ui/views/media_viewer.ui</file>
<file>ui/views/profile_header.ui</file>
<file>ui/views/sidebar/view.ui</file>
<file>ui/views/sidebar/account.ui</file>
Expand Down
7 changes: 5 additions & 2 deletions data/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -231,11 +231,14 @@ flowboxchild {
background: alpha(@success_bg_color, 0.1);
}

.media-viewer-headerbar {
background: rgba(0, 0, 0, .7);
.media-viewer {
color: white;
}

.media-viewer .top-bar {
background-image: none;
}

.ttl-status-heading {
font-size: small;
}
Expand Down
40 changes: 13 additions & 27 deletions data/ui/dialogs/main.ui
Original file line number Diff line number Diff line change
Expand Up @@ -10,38 +10,24 @@
</object>
</child>
<child>
<object class="GtkStack" id="main_stack">
<property name="vexpand">1</property>
<property name="hexpand">1</property>
<property name="vhomogeneous">0</property>
<property name="transition_type">crossfade</property>
<property name="interpolate_size">1</property>
<child>
<object class="GtkStackPage">
<property name="name">main</property>
<property name="child">
<object class="AdwOverlaySplitView" id="split_view">
<property name="sidebar">
<object class="TubaViewsSidebar" id="sidebar" />
</property>
<property name="content">
<object class="AdwNavigationView" id="navigation_view">
<signal name="notify::visible-page" handler="on_visible_page_changed" />
</object>
</property>
</object>
</property>
<object class="GtkOverlay">
<child type="overlay">
<object class="TubaViewsMediaViewer" id="media_viewer">
<property name="visible">0</property>
</object>
</child>
<child>
<object class="GtkStackPage">
<property name="name">media_viewer</property>
<property name="child">
<object class="TubaViewsMediaViewer" id="media_viewer">
<property name="child">
<object class="AdwOverlaySplitView" id="split_view">
<property name="sidebar">
<object class="TubaViewsSidebar" id="sidebar" />
</property>
<property name="content">
<object class="AdwNavigationView" id="navigation_view">
<signal name="notify::visible-page" handler="on_visible_page_changed" />
</object>
</property>
</object>
</child>
</property>
</object>
</child>
</template>
Expand Down
183 changes: 183 additions & 0 deletions data/ui/views/media_viewer.ui
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<requires lib="gtk" version="4.0" />
<menu id="menu-model">
<item>
<attribute name="label" translatable="yes">Open in Browser</attribute>
<attribute name="action">mediaviewer.open-in-browser</attribute>
</item>
<item>
<attribute name="label" translatable="yes">Copy URL</attribute>
<attribute name="action">mediaviewer.copy-url</attribute>
</item>
<item>
<attribute name="label" translatable="yes">Save Media</attribute>
<attribute name="action">mediaviewer.save-as</attribute>
</item>
<item>
<attribute name="label" translatable="yes">Copy Media</attribute>
<attribute name="action">mediaviewer.copy-media</attribute>
<attribute name="hidden-when">action-disabled</attribute>
</item>
</menu>
<template class="TubaViewsMediaViewer" parent="GtkWidget">
<property name="focusable">1</property>
<object class="GtkPopoverMenu" id="context_menu">
<property name="menu-model">menu-model</property>
<property name="has-arrow">0</property>
<property name="halign">start</property>
</object>
<child>
<object class="TubaWidgetsScaleRevealer" id="scale_revealer">
<property name="child">
<object class="AdwToolbarView">
<style>
<class name="media-viewer" />
</style>
<child type="top">
<object class="AdwHeaderBar" id="headerbar">
<property name="centering-policy">strict</property>
<property name="title-widget">
<object class="GtkLabel">
<property name="label" translatable="yes">Media Viewer</property>
<style>
<class name="title" />
</style>
</object>
</property>
<child type="start">
<object class="GtkButton">
<property name="icon-name">tuba-left-large-symbolic</property>
<property name="tooltip-text" translatable="yes">Go Back</property>
<signal name="clicked" handler="clear" swapped="no" />
</object>
</child>
<child type="end">
<object class="GtkButton" id="fullscreen_btn">
<property name="icon-name">view-fullscreen-symbolic</property>
<property name="tooltip-text" translatable="yes">Toggle Fullscreen</property>
<signal name="clicked" handler="toggle_fullscreen" swapped="no" />
</object>
</child>
<child type="end">
<object class="GtkMenuButton">
<property name="menu-model">menu-model</property>
<property name="icon-name">view-more-symbolic</property>
<property name="tooltip-text" translatable="yes">Menu</property>
</object>
</child>
</object>
</child>
<property name="content">
<object class="GtkBox">
<property name="orientation">vertical</property>
<property name="hexpand">1</property>
<property name="vexpand">1</property>
<child>
<object class="GtkOverlay">
<property name="hexpand">1</property>
<property name="vexpand">1</property>
<child type="overlay">
<object class="GtkRevealer" id="page_buttons_revealer">
<property name="transition_type">crossfade</property>
<property name="reveal-child">0</property>
<property name="visible">0</property>
<property name="valign">end</property>
<property name="halign">start</property>
<property name="margin_end">18</property>
<property name="margin_bottom">18</property>
<property name="child">
<object class="GtkBox">
<property name="orientation">horizontal</property>
<property name="spacing">12</property>
<child>
<object class="GtkButton" id="prev_btn">
<property name="icon-name">go-previous-symbolic</property>
<property name="tooltip-text" translatable="yes">Previous Attachment</property>
<signal name="clicked" handler="on_previous_clicked" swapped="no" />
<style>
<class name="osd" />
<class name="media-viewer-fab" />
<class name="circular" />
</style>
</object>
</child>
<child>
<object class="GtkButton" id="next_btn">
<property name="icon-name">go-next-symbolic</property>
<property name="tooltip-text" translatable="yes">Next Attachment</property>
<signal name="clicked" handler="on_next_clicked" swapped="no" />
<style>
<class name="osd" />
<class name="media-viewer-fab" />
<class name="circular" />
</style>
</object>
</child>
</object>
</property>
</object>
</child>
<child type="overlay">
<object class="GtkRevealer" id="zoom_buttons_revealer">
<property name="transition_type">crossfade</property>
<property name="reveal-child">0</property>
<property name="visible">0</property>
<property name="valign">end</property>
<property name="halign">end</property>
<property name="margin_end">18</property>
<property name="margin_bottom">18</property>
<property name="child">
<object class="GtkBox">
<property name="orientation">horizontal</property>
<property name="spacing">12</property>
<child>
<object class="GtkButton" id="zoom_out_btn">
<property name="icon-name">zoom-out-symbolic</property>
<property name="tooltip-text" translatable="yes">Zoom Out</property>
<signal name="clicked" handler="on_zoom_out_clicked" swapped="no" />
<style>
<class name="osd" />
<class name="media-viewer-fab" />
<class name="circular" />
</style>
</object>
</child>
<child>
<object class="GtkButton" id="zoom_in_btn">
<property name="icon-name">zoom-in-symbolic</property>
<property name="tooltip-text" translatable="yes">Zoom In</property>
<signal name="clicked" handler="on_zoom_in_clicked" swapped="no" />
<style>
<class name="osd" />
<class name="media-viewer-fab" />
<class name="circular" />
</style>
</object>
</child>
</object>
</property>
</object>
</child>
<property name="child">
<object class="AdwCarousel" id="carousel">
<property name="hexpand">1</property>
<property name="vexpand">1</property>
</object>
</property>
</object>
</child>
<child>
<object class="AdwCarouselIndicatorDots" id="carousel_dots">
<property name="carousel">carousel</property>
<property name="visible">0</property>
</object>
</child>
</object>
</property>
</object>
</property>
</object>
</child>
</template>
</interface>
2 changes: 1 addition & 1 deletion src/API/Status/PreviewCard.vala
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ public class Tuba.API.PreviewCard : Entity, Widgetizable {
Host.open_uri (card_url);
} else {
if (bookwyrm_obj == null) {
app.main_window.show_media_viewer_remote_video (res_url, null, card_url);
app.main_window.show_media_viewer (res_url, Tuba.Attachment.MediaType.VIDEO, null, 0, null, false, null, card_url, true);
} else {
app.main_window.show_book (bookwyrm_obj, card_url);
}
Expand Down
76 changes: 35 additions & 41 deletions src/Dialogs/MainWindow.vala
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ public class Tuba.Dialogs.MainWindow: Adw.ApplicationWindow, Saveable {
[GtkChild] unowned Adw.NavigationView navigation_view;
[GtkChild] public unowned Adw.OverlaySplitView split_view;
[GtkChild] unowned Views.Sidebar sidebar;
[GtkChild] unowned Gtk.Stack main_stack;
// [GtkChild] unowned Gtk.Stack main_stack;
[GtkChild] unowned Views.MediaViewer media_viewer;
[GtkChild] unowned Adw.Breakpoint breakpoint;

Expand All @@ -17,6 +17,18 @@ public class Tuba.Dialogs.MainWindow: Adw.ApplicationWindow, Saveable {
var gtk_settings = Gtk.Settings.get_default ();
breakpoint.add_setter (this, "is-mobile", true);
notify["is-mobile"].connect (update_selected_home_item);
media_viewer.bind_property ("visible", split_view, "can-focus", GLib.BindingFlags.SYNC_CREATE | GLib.BindingFlags.INVERT_BOOLEAN);
media_viewer.notify["visible"].connect (on_media_viewer_toggle);
}

private weak Gtk.Widget? media_viewer_source_widget;
private void on_media_viewer_toggle () {
if (is_media_viewer_visible || media_viewer_source_widget == null) return;

Gtk.Widget focusable_widget = media_viewer_source_widget;
while (focusable_widget != null && !focusable_widget.focusable) focusable_widget = focusable_widget.get_parent ();
if (focusable_widget != null) focusable_widget.grab_focus ();
media_viewer_source_widget = null;
}

public bool is_home {
Expand Down Expand Up @@ -44,53 +56,35 @@ public class Tuba.Dialogs.MainWindow: Adw.ApplicationWindow, Saveable {
#endif
}

public bool is_media_viewer_visible () {
return main_stack.visible_child_name == "media_viewer";
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 show_media_viewer (string url, string? alt_text, bool video, Gdk.Paintable? preview, int? pos) {
if (!is_media_viewer_visible ()) {
main_stack.visible_child_name = "media_viewer";
media_viewer.clear.connect (hide_media_viewer);
}

if (video) {
media_viewer.add_video (url, preview, pos);
} else {
media_viewer.add_image (url, alt_text, preview, pos);
}
}

public void show_media_viewer_single (string? url, Gdk.Paintable? paintable) {
if (paintable == null) return;

if (!is_media_viewer_visible ()) {
main_stack.visible_child_name = "media_viewer";
media_viewer.clear.connect (hide_media_viewer);
}

media_viewer.set_single_paintable (url, paintable);
}

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);
public void show_media_viewer (
string url,
Tuba.Attachment.MediaType media_type,
Gdk.Paintable? preview,
int? pos = null,
Gtk.Widget? source_widget = null,
bool as_is = false,
string? alt_text = null,
string? user_friendly_url = null,
bool stream = false
) {
if (as_is && preview == null) return;

media_viewer.add_media (url, media_type, preview, pos, as_is, alt_text, user_friendly_url, stream);

if (!is_media_viewer_visible) {
media_viewer.reveal (source_widget);
media_viewer_source_widget = source_widget;
}

media_viewer.set_remote_video (url, preview, user_friendly_url);
}

public void hide_media_viewer () {
if (!is_media_viewer_visible ()) return;

main_stack.visible_child_name = "main";
}

public void show_book (API.BookWyrm book, string? fallback = null) {
Expand Down Expand Up @@ -151,7 +145,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;
};
Expand Down
Loading