Refactor attachment grid
* Introduce Slotted attachment grid * Use Stack in attachment Slot * Display attachment type * Fit pictures into the Slot center
This commit is contained in:
parent
3d0bd9e48e
commit
a542be90c1
17
data/app.css
17
data/app.css
|
@ -3,9 +3,24 @@
|
|||
}
|
||||
|
||||
.attachment {
|
||||
border-radius: 4px;
|
||||
border-radius: 6px;
|
||||
background: rgba (150, 150, 150, 0.2);
|
||||
padding:0px;
|
||||
margin:0px;
|
||||
}
|
||||
.attachment .pic {
|
||||
border-radius: 6px;
|
||||
}
|
||||
.attachment .chip {
|
||||
padding: 6px;
|
||||
border-radius:6px;
|
||||
}
|
||||
/*.attachment box button:nth-child(1) {*/
|
||||
/* border-radius:0 0 0 8px;*/
|
||||
/*}*/
|
||||
/*.attachment box button:nth-child(2) {*/
|
||||
/* border-radius:0 8px 0 0;*/
|
||||
/*}*/
|
||||
|
||||
.header-title-button {
|
||||
margin: 0px;
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
<file preprocess="xml-stripblanks">ui/widgets/accounts_button_item.ui</file>
|
||||
<file preprocess="xml-stripblanks">ui/widgets/profile_field_row.ui</file>
|
||||
<file preprocess="xml-stripblanks">ui/widgets/timeline_filter.ui</file>
|
||||
<file preprocess="xml-stripblanks">ui/widgets/attachment_slot.ui</file>
|
||||
<file preprocess="xml-stripblanks">ui/dialogs/compose.ui</file>
|
||||
<file preprocess="xml-stripblanks">ui/dialogs/main.ui</file>
|
||||
<file preprocess="xml-stripblanks">ui/dialogs/preferences.ui</file>
|
||||
|
|
|
@ -0,0 +1,172 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated with glade 3.36.0 -->
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.22"/>
|
||||
<template class="TootleWidgetsAttachmentSlot" parent="GtkFlowBoxChild">
|
||||
<property name="height_request">180</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="hexpand">True</property>
|
||||
<child>
|
||||
<object class="GtkEventBox" id="event_box">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkGrid" id="overlay">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="vexpand">True</property>
|
||||
<child>
|
||||
<object class="GtkImage" id="play_icon">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="margin_start">16</property>
|
||||
<property name="margin_end">16</property>
|
||||
<property name="margin_top">16</property>
|
||||
<property name="margin_bottom">16</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="vexpand">True</property>
|
||||
<property name="pixel_size">48</property>
|
||||
<property name="icon_name">media-playback-start-symbolic</property>
|
||||
<property name="icon_size">0</property>
|
||||
<style>
|
||||
<class name="chip"/>
|
||||
<class name="osd"/>
|
||||
</style>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="edit_bar">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">end</property>
|
||||
<property name="valign">start</property>
|
||||
<property name="margin_start">6</property>
|
||||
<property name="margin_end">6</property>
|
||||
<property name="margin_top">6</property>
|
||||
<property name="margin_bottom">6</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="vexpand">True</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="edit_btn">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="tooltip_text" translatable="yes">Describe for the visually impaired</property>
|
||||
<property name="halign">end</property>
|
||||
<property name="valign">start</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="icon_name">document-edit-symbolic</property>
|
||||
</object>
|
||||
</child>
|
||||
<style>
|
||||
<class name="osd"/>
|
||||
</style>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="remove_btn">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="tooltip_text" translatable="yes">Remove</property>
|
||||
<property name="halign">end</property>
|
||||
<property name="valign">start</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="icon_name">user-trash-symbolic</property>
|
||||
</object>
|
||||
</child>
|
||||
<style>
|
||||
<class name="osd"/>
|
||||
</style>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<style>
|
||||
<class name="linked"/>
|
||||
</style>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="chip">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="valign">start</property>
|
||||
<property name="margin_start">6</property>
|
||||
<property name="margin_end">6</property>
|
||||
<property name="margin_top">6</property>
|
||||
<property name="margin_bottom">6</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="vexpand">True</property>
|
||||
<style>
|
||||
<class name="osd"/>
|
||||
<class name="chip"/>
|
||||
</style>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkStack" id="stack">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="transition_type">crossfade</property>
|
||||
<property name="interpolate_size">True</property>
|
||||
<child>
|
||||
<object class="GtkSpinner" id="loading">
|
||||
<property name="width_request">32</property>
|
||||
<property name="height_request">32</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="opacity">0.5019607843137255</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="vexpand">True</property>
|
||||
<property name="active">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="name">loading</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<style>
|
||||
<class name="attachment"/>
|
||||
</style>
|
||||
</template>
|
||||
</interface>
|
|
@ -79,7 +79,8 @@ executable(
|
|||
'src/Widgets/Notification.vala',
|
||||
'src/Widgets/VisibilityPopover.vala',
|
||||
'src/Widgets/Attachment/Box.vala',
|
||||
'src/Widgets/Attachment/Item.vala',
|
||||
'src/Widgets/Attachment/Slot.vala',
|
||||
'src/Widgets/Attachment/Picture.vala',
|
||||
'src/Dialogs/ISavedWindow.vala',
|
||||
'src/Dialogs/MainWindow.vala',
|
||||
'src/Dialogs/Compose.vala',
|
||||
|
|
|
@ -5,7 +5,7 @@ public class Tootle.API.Attachment : Entity {
|
|||
public string url { get; set; }
|
||||
public string? description { get; set; }
|
||||
public string? _preview_url { get; set; }
|
||||
public string preview_url {
|
||||
public string? preview_url {
|
||||
set { this._preview_url = value; }
|
||||
get { return (this._preview_url == null || this._preview_url == "") ? url : _preview_url; }
|
||||
}
|
||||
|
|
|
@ -76,6 +76,11 @@ public class Tootle.Desktop {
|
|||
return theme.has_icon (fallback) ? fallback : fallback2;
|
||||
}
|
||||
|
||||
public static Gdk.Pixbuf icon_to_pixbuf (string name) {
|
||||
var theme = Gtk.IconTheme.get_default ();
|
||||
return theme.load_icon (name, 32, Gtk.IconLookupFlags.GENERIC_FALLBACK);
|
||||
}
|
||||
|
||||
public static void set_hotkey_tooltip (Gtk.Widget widget, string? description, string[] accelerators) {
|
||||
widget.tooltip_markup = Granite.markup_accel_tooltip (accelerators, description);
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ public class Tootle.Dialogs.Compose : Window {
|
|||
public string label { get; construct set; }
|
||||
public int char_limit {
|
||||
get {
|
||||
return 250;
|
||||
return 500;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -62,6 +62,7 @@ public class Tootle.Dialogs.Compose : Window {
|
|||
}
|
||||
content.buffer.text = Html.remove_tags (status.content);
|
||||
|
||||
validate ();
|
||||
show ();
|
||||
}
|
||||
|
||||
|
|
|
@ -43,10 +43,12 @@ public class Tootle.Dialogs.MainWindow: Gtk.Window, ISavedWindow {
|
|||
timeline_switcher.valign = Align.FILL;
|
||||
timeline_stack.notify["visible-child"].connect (on_timeline_changed);
|
||||
|
||||
add_timeline_view (new Views.Home (), app.ACCEL_TIMELINE_0, 0);
|
||||
add_timeline_view (new Views.Notifications (), app.ACCEL_TIMELINE_1, 1);
|
||||
add_timeline_view (new Views.Local (), app.ACCEL_TIMELINE_2, 2);
|
||||
add_timeline_view (new Views.Federated (), app.ACCEL_TIMELINE_3, 3);
|
||||
add_timeline_view (new Views.Bookmarks (), app.ACCEL_TIMELINE_0, 0);
|
||||
add_timeline_view (new Views.Home (), app.ACCEL_TIMELINE_1, 1);
|
||||
// add_timeline_view (new Views.Home (), app.ACCEL_TIMELINE_0, 0);
|
||||
// add_timeline_view (new Views.Notifications (), app.ACCEL_TIMELINE_1, 1);
|
||||
// add_timeline_view (new Views.Local (), app.ACCEL_TIMELINE_2, 2);
|
||||
// add_timeline_view (new Views.Federated (), app.ACCEL_TIMELINE_3, 3);
|
||||
|
||||
settings.bind_property ("dark-theme", Gtk.Settings.get_default (), "gtk-application-prefer-dark-theme", BindingFlags.SYNC_CREATE);
|
||||
settings.notify["post-text-size"].connect (() => on_zoom_level_changed ());
|
||||
|
|
|
@ -13,24 +13,4 @@ public class Tootle.Drawing {
|
|||
ctx.close_path ();
|
||||
}
|
||||
|
||||
public static void center (Cairo.Context ctx, int w, int h, int tw, int th) {
|
||||
var cx = w/2 - tw/2;
|
||||
var cy = h/2 - th/2;
|
||||
ctx.translate (cx, cy);
|
||||
}
|
||||
|
||||
public static Pixbuf make_thumbnail (Pixbuf pb, int view_w, int view_h) {
|
||||
if (view_w >= pb.width && view_h >= pb.height)
|
||||
return pb;
|
||||
|
||||
double ratio_x = (double) view_w / (double) pb.width;
|
||||
double ratio_y = (double) view_h / (double) pb.height;
|
||||
double ratio = ratio_x < ratio_y ? ratio_x : ratio_y;
|
||||
|
||||
return pb.scale_simple (
|
||||
(int) (pb.width * ratio),
|
||||
(int) (pb.height * ratio),
|
||||
InterpType.BILINEAR);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -81,10 +81,22 @@ public class Tootle.Cache : GLib.Object {
|
|||
id = msg.finished.connect (() => {
|
||||
Pixbuf? pixbuf = null;
|
||||
|
||||
var data = msg.response_body.flatten ().data;
|
||||
var stream = new MemoryInputStream.from_data (data);
|
||||
pixbuf = new Pixbuf.from_stream (stream);
|
||||
stream.close ();
|
||||
try {
|
||||
var code = message.status_code;
|
||||
if (code != Soup.Status.OK) {
|
||||
var msg = network.describe_error (code);
|
||||
throw new Oopsie.INSTANCE (@"Server returned $msg");
|
||||
}
|
||||
|
||||
var data = message.response_body.flatten ().data;
|
||||
var stream = new MemoryInputStream.from_data (data);
|
||||
pixbuf = new Pixbuf.from_stream (stream);
|
||||
stream.close ();
|
||||
}
|
||||
catch (Error e) {
|
||||
warning (@"\"$url\" -> Pixbuf: FAIL ($(e.message))");
|
||||
pixbuf = Desktop.icon_to_pixbuf ("image-x-generic-symbolic");
|
||||
}
|
||||
|
||||
// message (@"[*] $key");
|
||||
items[key] = new Item (pixbuf, 1);
|
||||
|
|
|
@ -68,7 +68,7 @@ public class Tootle.Network : GLib.Object {
|
|||
});
|
||||
}
|
||||
|
||||
public string describe_error (int32 code) {
|
||||
public string describe_error (uint code) {
|
||||
var reason = Soup.Status.get_phrase (code);
|
||||
return @"$code: $reason";
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ public class Tootle.Widgets.Attachment.Box : FlowBox {
|
|||
construct {
|
||||
hexpand = true;
|
||||
can_focus = false;
|
||||
column_spacing = row_spacing = 8;
|
||||
selection_mode = SelectionMode.NONE;
|
||||
}
|
||||
|
||||
|
@ -16,6 +17,7 @@ public class Tootle.Widgets.Attachment.Box : FlowBox {
|
|||
Object (editing: editing);
|
||||
}
|
||||
|
||||
//TODO: Upload attachments in Compose dialog
|
||||
public void select () {
|
||||
var filter = new Gtk.FileFilter ();
|
||||
filter.add_mime_type ("image/jpeg");
|
||||
|
@ -49,20 +51,27 @@ public class Tootle.Widgets.Attachment.Box : FlowBox {
|
|||
public bool populate (ArrayList<API.Attachment>? list) {
|
||||
if (list == null)
|
||||
return false;
|
||||
|
||||
var max = 6;
|
||||
if (list.size % 2 == 0)
|
||||
max = 2;
|
||||
|
||||
//max_children_per_line = (int)Math.fmin (list.size, 5);
|
||||
|
||||
var max = 2;
|
||||
var min = 1;
|
||||
if (list.size == 1)
|
||||
max = 1;
|
||||
else if (list.size % 2 == 0)
|
||||
max = min = 2;
|
||||
else if (list.size % 3 == 0)
|
||||
max = min = 3;
|
||||
|
||||
max_children_per_line = max;
|
||||
min_children_per_line = min;
|
||||
list.@foreach (obj => pack (obj));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool pack (API.Attachment obj) {
|
||||
var w = new Widgets.Attachment.Item (obj);
|
||||
var w = new Widgets.Attachment.Slot (obj);
|
||||
insert (w, -1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,105 +0,0 @@
|
|||
using Gtk;
|
||||
using Gdk;
|
||||
|
||||
public class Tootle.Widgets.Attachment.Item : EventBox {
|
||||
|
||||
public API.Attachment attachment { get; construct set; }
|
||||
|
||||
private Cache.Reference? cached;
|
||||
|
||||
public Item (API.Attachment obj) {
|
||||
Object (attachment: obj);
|
||||
}
|
||||
~Item () {
|
||||
cache.unload (cached);
|
||||
}
|
||||
|
||||
construct {
|
||||
get_style_context ().add_class ("attachment");
|
||||
width_request = height_request = 128;
|
||||
hexpand = true;
|
||||
tooltip_text = attachment.description ?? _("No description is available");
|
||||
|
||||
button_press_event.connect (on_clicked);
|
||||
|
||||
show ();
|
||||
on_request ();
|
||||
}
|
||||
|
||||
protected void on_request () {
|
||||
cached = null;
|
||||
on_redraw ();
|
||||
cache.load (attachment.preview_url, on_cache_result);
|
||||
}
|
||||
|
||||
protected void on_redraw () {
|
||||
var w = get_allocated_width ();
|
||||
var h = get_allocated_height ();
|
||||
queue_draw_area (0, 0, w, h);
|
||||
}
|
||||
|
||||
protected void on_cache_result (Cache.Reference? result) {
|
||||
cached = result;
|
||||
on_redraw ();
|
||||
}
|
||||
|
||||
protected void download () {
|
||||
Desktop.download (attachment.url, path => {
|
||||
app.toast (_("Attachment downloaded"));
|
||||
});
|
||||
}
|
||||
protected void open () {
|
||||
Desktop.download (attachment.url, path => {
|
||||
Desktop.open_uri (path);
|
||||
});
|
||||
}
|
||||
|
||||
public override bool draw (Cairo.Context ctx) {
|
||||
base.draw (ctx);
|
||||
var w = get_allocated_width ();
|
||||
var h = get_allocated_height ();
|
||||
var style = get_style_context ();
|
||||
var border_radius = style.get_property (Gtk.STYLE_PROPERTY_BORDER_RADIUS, style.get_state ()).get_int ();
|
||||
|
||||
if (cached != null) {
|
||||
if (cached.loading) {
|
||||
Drawing.center (ctx, w, h, 32, 32);
|
||||
get_style_context ().render_activity (ctx, 0, 0, 32, 32);
|
||||
}
|
||||
else {
|
||||
var thumb = Drawing.make_thumbnail (cached.data, w, h);
|
||||
Drawing.draw_rounded_rect (ctx, 0, 0, w, h, border_radius);
|
||||
Drawing.center (ctx, w, h, thumb.width, thumb.height);
|
||||
Gdk.cairo_set_source_pixbuf (ctx, thumb, 0, 0);
|
||||
ctx.fill ();
|
||||
}
|
||||
}
|
||||
|
||||
return Gdk.EVENT_STOP;
|
||||
}
|
||||
|
||||
protected virtual bool on_clicked (EventButton ev) {
|
||||
if (ev.button == 1) {
|
||||
open ();
|
||||
return true;
|
||||
}
|
||||
else if (ev.button == 3) {
|
||||
var menu = new Gtk.Menu ();
|
||||
|
||||
var item_open = new Gtk.MenuItem.with_label (_("Open"));
|
||||
item_open.activate.connect (open);
|
||||
menu.add (item_open);
|
||||
|
||||
var item_download = new Gtk.MenuItem.with_label (_("Download"));
|
||||
item_download.activate.connect (download);
|
||||
menu.add (item_download);
|
||||
|
||||
menu.show_all ();
|
||||
menu.attach_widget = this;
|
||||
menu.popup_at_pointer ();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
using Gtk;
|
||||
using Gdk;
|
||||
|
||||
public class Tootle.Widgets.Attachment.Picture : DrawingArea {
|
||||
|
||||
public string url { get; set; }
|
||||
|
||||
Cache.Reference? cached;
|
||||
|
||||
construct {
|
||||
hexpand = vexpand = true;
|
||||
get_style_context ().add_class ("pic");
|
||||
}
|
||||
|
||||
public class Picture (string url) {
|
||||
Object (url: url);
|
||||
}
|
||||
~Picture () {
|
||||
cache.unload (cached);
|
||||
}
|
||||
|
||||
public void on_request () {
|
||||
cached = null;
|
||||
on_redraw ();
|
||||
cache.load (url, on_cache_update);
|
||||
}
|
||||
|
||||
void on_cache_update (Cache.Reference? result) {
|
||||
cached = result;
|
||||
if (cached != null)
|
||||
visible = !cached.loading;
|
||||
on_redraw ();
|
||||
}
|
||||
|
||||
void on_redraw () {
|
||||
var w = get_allocated_width ();
|
||||
var h = get_allocated_height ();
|
||||
queue_draw_area (0, 0, w, h);
|
||||
}
|
||||
|
||||
float get_ratio (int w, int h) {
|
||||
var ow = cached.data.get_width ();
|
||||
var oh = cached.data.get_height ();
|
||||
var xscale = (float) w / ow;
|
||||
var yscale = (float) h / oh;
|
||||
|
||||
if (xscale > yscale)
|
||||
return xscale;
|
||||
else
|
||||
return yscale;
|
||||
}
|
||||
|
||||
public override bool draw (Cairo.Context ctx) {
|
||||
var w = get_allocated_width ();
|
||||
var h = get_allocated_height ();
|
||||
var style = get_style_context ();
|
||||
var border_radius = style.get_property (Gtk.STYLE_PROPERTY_BORDER_RADIUS, style.get_state ()).get_int ();
|
||||
|
||||
if (cached != null) {
|
||||
if (!cached.loading) {
|
||||
Cairo.Surface surface = Gdk.cairo_surface_create_from_pixbuf (cached.data, 1, null);
|
||||
|
||||
ctx.save ();
|
||||
Drawing.draw_rounded_rect (ctx, 0, 0, w, h, border_radius);
|
||||
|
||||
//Proportionally scale to fit into the allocated container
|
||||
var ratio = get_ratio (w, h);
|
||||
ctx.scale (ratio, ratio);
|
||||
|
||||
//Center the result
|
||||
var oh = cached.data.get_height ();
|
||||
var result_h = oh*ratio;
|
||||
var offset_y = (h - result_h) / 2;
|
||||
|
||||
var ow = cached.data.get_width ();
|
||||
var result_w = ow*ratio;
|
||||
var offset_x = (w - result_w) / 2;
|
||||
|
||||
ctx.translate (offset_x, offset_y);
|
||||
|
||||
//Draw it
|
||||
ctx.set_source_surface (surface, 0, 0);
|
||||
ctx.fill ();
|
||||
ctx.restore ();
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
using Gtk;
|
||||
using Gdk;
|
||||
|
||||
[GtkTemplate (ui = "/com/github/bleakgrey/tootle/ui/widgets/attachment_slot.ui")]
|
||||
public class Tootle.Widgets.Attachment.Slot : FlowBoxChild {
|
||||
|
||||
[GtkChild]
|
||||
EventBox event_box;
|
||||
[GtkChild]
|
||||
Label chip;
|
||||
[GtkChild]
|
||||
Image play_icon;
|
||||
[GtkChild]
|
||||
Stack stack;
|
||||
|
||||
public API.Attachment attachment { get; construct set; }
|
||||
|
||||
public Slot (API.Attachment obj) {
|
||||
Object (attachment: obj);
|
||||
|
||||
if (attachment.preview_url != null) {
|
||||
var img = new Widgets.Attachment.Picture (attachment.preview_url);
|
||||
img.notify["visible"].connect (() => {
|
||||
stack.visible_child_name = img.visible ? "content" : "loading";
|
||||
});
|
||||
stack.add_named (img, "content");
|
||||
img.on_request ();
|
||||
}
|
||||
|
||||
if (attachment.kind != "image") {
|
||||
chip.label = attachment.kind;
|
||||
chip.show ();
|
||||
}
|
||||
|
||||
switch (attachment.kind) {
|
||||
case "audio":
|
||||
case "video":
|
||||
case "gifv":
|
||||
play_icon.show ();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
construct {
|
||||
event_box.tooltip_text = attachment.description;
|
||||
event_box.button_release_event.connect (on_clicked);
|
||||
}
|
||||
|
||||
void download () {
|
||||
Desktop.download (attachment.url, path => {
|
||||
app.toast (_("Attachment downloaded"));
|
||||
});
|
||||
}
|
||||
void open () {
|
||||
Desktop.download (attachment.url, path => {
|
||||
Desktop.open_uri (path);
|
||||
});
|
||||
}
|
||||
|
||||
protected virtual bool on_clicked (EventButton ev) {
|
||||
if (ev.button != 1)
|
||||
return false;
|
||||
|
||||
open ();
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -42,7 +42,6 @@ public class Tootle.Widgets.Avatar : EventBox {
|
|||
|
||||
public int get_scaled_size () {
|
||||
return size; //return size * get_scale_factor ();
|
||||
}
|
||||
|
||||
private void on_redraw () {
|
||||
set_size_request (get_scaled_size (), get_scaled_size ());
|
||||
|
@ -62,7 +61,7 @@ public class Tootle.Widgets.Avatar : EventBox {
|
|||
}
|
||||
else {
|
||||
pixbuf = IconTheme.get_default ()
|
||||
.load_icon_for_scale ("avatar-default", size, get_scale_factor (), IconLookupFlags.GENERIC_FALLBACK);
|
||||
.load_icon_for_scale ("avatar-default", get_scaled_size (), get_scale_factor (), IconLookupFlags.GENERIC_FALLBACK);
|
||||
}
|
||||
Gdk.cairo_set_source_pixbuf (ctx, pixbuf, 0, 0);
|
||||
ctx.fill ();
|
||||
|
|
Loading…
Reference in New Issue