mirror of
https://gitlab.gnome.org/World/tootle
synced 2025-02-16 19:40:41 +01:00
Use Hdy.Avatar (#253)
This commit is contained in:
parent
2b4fd15a25
commit
695e71ef4c
14
data/app.css
14
data/app.css
@ -1,7 +1,3 @@
|
||||
.avatar {
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.header .chip {
|
||||
padding: 4px 12px;
|
||||
border-radius: 4px;
|
||||
@ -29,13 +25,17 @@
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.padded.app-view {
|
||||
.padded.ttl-view {
|
||||
margin: 32px 0 32px 0;
|
||||
}
|
||||
.app-view:not(.padded) .content row {
|
||||
.ttl-view:not(.padded) .content row {
|
||||
border-radius: 0px;
|
||||
}
|
||||
|
||||
.app-action-bar .circular {
|
||||
.ttl-action-bar .circular {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.ttl-avatar-button {
|
||||
padding: 0;
|
||||
}
|
||||
|
@ -399,7 +399,7 @@
|
||||
</packing>
|
||||
</child>
|
||||
<style>
|
||||
<class name="app-view"/>
|
||||
<class name="ttl-view"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
|
@ -201,7 +201,7 @@
|
||||
</packing>
|
||||
</child>
|
||||
<style>
|
||||
<class name="app-view"/>
|
||||
<class name="ttl-view"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
|
@ -167,7 +167,7 @@
|
||||
</object>
|
||||
</child>
|
||||
<style>
|
||||
<class name="app-action-bar"/>
|
||||
<class name="ttl-action-bar"/>
|
||||
</style>
|
||||
</object>
|
||||
<packing>
|
||||
@ -295,7 +295,7 @@
|
||||
</object>
|
||||
</child>
|
||||
<style>
|
||||
<class name="app-view"/>
|
||||
<class name="ttl-view"/>
|
||||
</style>
|
||||
</object>
|
||||
<template class="TootleWidgetsAccountsButton" parent="GtkMenuButton">
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated with glade 3.36.0 -->
|
||||
<!-- Generated with glade 3.22.2 -->
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.20"/>
|
||||
<template class="TootleWidgetsAccountsButtonItem" parent="GtkListBoxRow">
|
||||
@ -25,11 +25,27 @@
|
||||
<property name="column_spacing">8</property>
|
||||
<property name="row_homogeneous">True</property>
|
||||
<child>
|
||||
<object class="TootleWidgetsAvatar" id="avatar">
|
||||
<property name="visible">true</property>
|
||||
<property name="size">48</property>
|
||||
<signal name="clicked" handler="open_profile" swapped="no"/>
|
||||
</object>
|
||||
<object class="GtkButton" id="avatar_button">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="valign">start</property>
|
||||
<signal name="clicked" handler="open_profile" swapped="no"/>
|
||||
<child>
|
||||
<object class="TootleWidgetsAvatar" id="avatar">
|
||||
<property name="size">48</property>
|
||||
<property name="valign">start</property>
|
||||
<property name="visible">true</property>
|
||||
</object>
|
||||
</child>
|
||||
<style>
|
||||
<class name="flat"/>
|
||||
<class name="image-button"/>
|
||||
<class name="circular"/>
|
||||
<class name="ttl-avatar-button"/>
|
||||
</style>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">0</property>
|
||||
|
@ -50,19 +50,6 @@
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="TootleWidgetsAvatar" id="avatar">
|
||||
<property name="width_request">48</property>
|
||||
<property name="height_request">48</property>
|
||||
<property name="valign">start</property>
|
||||
<property name="visible">true</property>
|
||||
<signal name="clicked" handler="on_avatar_clicked" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="TootleWidgetsRichLabel" id="header_label">
|
||||
<property name="visible">True</property>
|
||||
@ -89,6 +76,7 @@
|
||||
<property name="hexpand">True</property>
|
||||
<property name="label" translatable="yes">Name</property>
|
||||
<property name="ellipsize">end</property>
|
||||
<property name="single_line_mode">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
@ -103,6 +91,7 @@
|
||||
<property name="label" translatable="no">Handle</property>
|
||||
<property name="opacity">0.5</property>
|
||||
<property name="ellipsize">end</property>
|
||||
<property name="single_line_mode">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
@ -388,6 +377,33 @@
|
||||
<property name="top_attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="avatar_button">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="valign">start</property>
|
||||
<signal name="clicked" handler="on_avatar_clicked" swapped="no"/>
|
||||
<child>
|
||||
<object class="TootleWidgetsAvatar" id="avatar">
|
||||
<property name="size">48</property>
|
||||
<property name="valign">start</property>
|
||||
<property name="visible">true</property>
|
||||
</object>
|
||||
</child>
|
||||
<style>
|
||||
<class name="flat"/>
|
||||
<class name="image-button"/>
|
||||
<class name="circular"/>
|
||||
<class name="ttl-avatar-button"/>
|
||||
</style>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
|
@ -4,7 +4,7 @@ using Gdk;
|
||||
[GtkTemplate (ui = "/com/github/bleakgrey/tootle/ui/dialogs/main.ui")]
|
||||
public class Tootle.Dialogs.MainWindow: Hdy.Window, ISavedWindow {
|
||||
|
||||
public const string ZOOM_CLASS = "app-scalable";
|
||||
public const string ZOOM_CLASS = "ttl-scalable";
|
||||
|
||||
[GtkChild]
|
||||
Hdy.Deck deck;
|
||||
|
@ -33,7 +33,7 @@ public class Tootle.Cache : GLib.Object {
|
||||
}
|
||||
}
|
||||
|
||||
public void unload (Reference? r) {
|
||||
public void unload (ref Reference? r) {
|
||||
if (r == null)
|
||||
return;
|
||||
|
||||
@ -53,11 +53,15 @@ public class Tootle.Cache : GLib.Object {
|
||||
// else {
|
||||
// message (@"[-] $(r.key) - $(item.references)");
|
||||
// }
|
||||
|
||||
r = null;
|
||||
}
|
||||
|
||||
public void load (string? url, owned CachedResultCallback cb) {
|
||||
if (url == null)
|
||||
return;
|
||||
if (url == null) {
|
||||
cb (null);
|
||||
return;
|
||||
}
|
||||
|
||||
var key = url;
|
||||
if (items.contains (key)) {
|
||||
|
@ -35,7 +35,7 @@ public class Tootle.Views.Profile : Views.Timeline {
|
||||
column_view.reorder_child (hdr, 0);
|
||||
|
||||
var avatar = builder.get_object ("avatar") as Widgets.Avatar;
|
||||
avatar.url = profile.avatar;
|
||||
avatar.account = profile;
|
||||
|
||||
var domain = "@" + profile.domain;
|
||||
menu_button.title.label = profile.handle.replace (domain, "");
|
||||
|
@ -16,7 +16,7 @@ public class Tootle.Views.TabbedBase : Views.Base {
|
||||
state = "content";
|
||||
|
||||
states.get_parent ().remove (states);
|
||||
view.get_style_context ().remove_class ("app-view");
|
||||
view.get_style_context ().remove_class ("ttl-view");
|
||||
scrolled.destroy ();
|
||||
pack_start (states);
|
||||
|
||||
|
@ -23,7 +23,7 @@ public class Tootle.Widgets.AccountsButton : Gtk.MenuButton, IAccountListener {
|
||||
public Item (InstanceAccount account, AccountsButton btn) {
|
||||
this.account = account;
|
||||
this.button = btn;
|
||||
avatar.url = account.avatar;
|
||||
avatar.account = account;
|
||||
title.label = account.display_name;
|
||||
handle.label = account.handle;
|
||||
}
|
||||
@ -143,13 +143,13 @@ public class Tootle.Widgets.AccountsButton : Gtk.MenuButton, IAccountListener {
|
||||
|
||||
public virtual void on_account_changed (InstanceAccount? account) {
|
||||
if (account == null) {
|
||||
avatar.url = null;
|
||||
avatar.account = null;
|
||||
item_accounts.text = "<b><span size=\"large\">%s</span></b>\n%s".printf (
|
||||
_("Anonymous"),
|
||||
_("No active account"));
|
||||
}
|
||||
else {
|
||||
avatar.url = account.avatar;
|
||||
avatar.account = account;
|
||||
item_accounts.text = @"<b><span size=\"large\">$(account.display_name)</span></b>\n$(account.handle)";
|
||||
}
|
||||
item_accounts.use_markup = true;
|
||||
|
@ -16,7 +16,7 @@ public class Tootle.Widgets.Attachment.Picture : DrawingArea {
|
||||
Object (url: url);
|
||||
}
|
||||
~Picture () {
|
||||
cache.unload (cached);
|
||||
cache.unload (ref cached);
|
||||
}
|
||||
|
||||
public void on_request () {
|
||||
|
@ -1,85 +1,76 @@
|
||||
using Gtk;
|
||||
using Gdk;
|
||||
|
||||
public class Tootle.Widgets.Avatar : Button {
|
||||
|
||||
public string? url { get; set; }
|
||||
public int size { get; set; default = 48; }
|
||||
public class Tootle.Widgets.Avatar : Bin {
|
||||
|
||||
Cache.Reference? cached;
|
||||
|
||||
construct {
|
||||
get_style_context ().add_class ("avatar");
|
||||
notify["url"].connect (on_url_updated);
|
||||
notify["size"].connect (on_size_changed);
|
||||
// Screen.get_default ().monitors_changed.connect (on_redraw);
|
||||
on_url_updated ();
|
||||
Hdy.Avatar avatar;
|
||||
|
||||
public int size {
|
||||
get {
|
||||
return avatar.size;
|
||||
}
|
||||
set {
|
||||
avatar.size = value;
|
||||
}
|
||||
}
|
||||
|
||||
public Avatar (int size = this.size) {
|
||||
Object (size: size);
|
||||
queue_draw ();
|
||||
public API.Account? account { get; set; }
|
||||
|
||||
construct {
|
||||
avatar = new Hdy.Avatar (48, null, true);
|
||||
add (avatar);
|
||||
show_all ();
|
||||
|
||||
notify["account"].connect (on_invalidated);
|
||||
on_invalidated ();
|
||||
}
|
||||
|
||||
~Avatar () {
|
||||
notify["url"].disconnect (on_url_updated);
|
||||
// Screen.get_default ().monitors_changed.disconnect (on_redraw);
|
||||
cache.unload (cached);
|
||||
notify["account"].disconnect (on_invalidated);
|
||||
cache.unload (ref cached);
|
||||
}
|
||||
|
||||
void on_url_updated () {
|
||||
void on_invalidated () {
|
||||
if (cached != null)
|
||||
cache.unload (cached);
|
||||
cache.unload (ref cached);
|
||||
|
||||
cached = null;
|
||||
queue_draw ();
|
||||
cache.load (url, on_cache_result);
|
||||
|
||||
if (account != null)
|
||||
cache.load (account.avatar, on_cache_result);
|
||||
else
|
||||
on_cache_result (null);
|
||||
}
|
||||
|
||||
void on_cache_result (Cache.Reference? result) {
|
||||
cached = result;
|
||||
queue_draw ();
|
||||
}
|
||||
|
||||
void on_size_changed () {
|
||||
set_size_request (get_scaled_size (), get_scaled_size ());
|
||||
queue_draw ();
|
||||
}
|
||||
|
||||
public int get_scaled_size () {
|
||||
return size; //return size * get_scale_factor ();
|
||||
}
|
||||
|
||||
public override void get_preferred_height (out int min_h, out int nat_h) {
|
||||
min_h = nat_h = get_scaled_size ();
|
||||
}
|
||||
|
||||
public override void get_preferred_width (out int min_w, out int nat_w) {
|
||||
min_w = nat_w = get_scaled_size ();
|
||||
}
|
||||
|
||||
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 ();
|
||||
Pixbuf pixbuf;
|
||||
|
||||
Drawing.draw_rounded_rect (ctx, 0, 0, w, h, border_radius);
|
||||
if (cached != null && !cached.loading) {
|
||||
pixbuf = cached.data.scale_simple (get_scaled_size (), get_scaled_size (), InterpType.BILINEAR);
|
||||
if (account == null) {
|
||||
// This exact string makes the avatar grey.
|
||||
//
|
||||
// If left null, *each* blank Hdy.Avatar receives
|
||||
// a random color and hurts my eyes. No bueno.
|
||||
avatar.text = "abc";
|
||||
avatar.show_initials = false;
|
||||
}
|
||||
else if (cached != null) {
|
||||
avatar.text = account.display_name;
|
||||
avatar.show_initials = true;
|
||||
}
|
||||
avatar.set_image_load_func (avatar_set_pixbuf);
|
||||
}
|
||||
|
||||
Pixbuf? avatar_set_pixbuf (int size) {
|
||||
if (cached == null || cached.data == null)
|
||||
return null;
|
||||
else {
|
||||
pixbuf = IconTheme.get_default ().load_icon_for_scale (
|
||||
"avatar-default",
|
||||
get_scaled_size (),
|
||||
get_scale_factor (),
|
||||
IconLookupFlags.GENERIC_FALLBACK);
|
||||
var pb = cached.data;
|
||||
if (pb.width != size)
|
||||
return pb.scale_simple (size, size, InterpType.BILINEAR);
|
||||
else
|
||||
return pb;
|
||||
}
|
||||
Gdk.cairo_set_source_pixbuf (ctx, pixbuf, 0, 0);
|
||||
ctx.fill ();
|
||||
|
||||
return Gdk.EVENT_STOP;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -138,7 +138,7 @@ public class Tootle.Widgets.Status : ListBoxRow {
|
||||
bind_property ("subtitle_text", handle_label, "text", BindingFlags.SYNC_CREATE);
|
||||
bind_property ("date", date_label, "label", BindingFlags.SYNC_CREATE);
|
||||
status.formal.bind_property ("pinned", pin_indicator, "visible", BindingFlags.SYNC_CREATE);
|
||||
bind_property ("avatar_url", avatar, "url", BindingFlags.SYNC_CREATE);
|
||||
status.formal.bind_property ("account", avatar, "account", BindingFlags.SYNC_CREATE);
|
||||
|
||||
status.formal.bind_property ("has-spoiler", this, "reveal-spoiler", BindingFlags.SYNC_CREATE, (b, src, ref target) => {
|
||||
target.set_boolean (!src.get_boolean ());
|
||||
|
Loading…
x
Reference in New Issue
Block a user