Refactor Accounts button

This commit is contained in:
Bleak Grey 2020-08-01 02:42:14 +03:00
parent 238b4a6fee
commit 25c9daf307
7 changed files with 303 additions and 287 deletions

View File

@ -15,12 +15,6 @@
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;

View File

@ -14,6 +14,7 @@
<property name="interpolate_size">True</property>
<child>
<object class="GtkBox">
<property name="width_request">275</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="border_width">12</property>
@ -24,7 +25,7 @@
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="text" translatable="no"> </property>
<property name="text"> &lt;b&gt;&lt;span size="large"&gt;No account&lt;/span&gt;&lt;/b&gt;</property>
<property name="use_markup">True</property>
<property name="menu_name">accounts</property>
</object>
@ -34,22 +35,11 @@
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkSeparator">
<property name="can_focus">False</property>
<property name="margin_top">4</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkFlowBox" id="actions">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_top">6</property>
<property name="margin_top">12</property>
<property name="margin_bottom">6</property>
<property name="homogeneous">True</property>
<property name="column_spacing">6</property>
@ -183,7 +173,7 @@
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
<property name="position">1</property>
</packing>
</child>
<child>
@ -195,7 +185,7 @@
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">3</property>
<property name="position">2</property>
</packing>
</child>
<child>
@ -208,7 +198,7 @@
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">4</property>
<property name="position">3</property>
</packing>
</child>
<child>
@ -221,7 +211,7 @@
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">5</property>
<property name="position">4</property>
</packing>
</child>
<child>
@ -234,7 +224,7 @@
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">6</property>
<property name="position">5</property>
</packing>
</child>
</object>
@ -244,7 +234,7 @@
</child>
<child>
<object class="GtkBox">
<property name="width_request">400</property>
<property name="width_request">350</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="border_width">12</property>
@ -271,7 +261,6 @@
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="vexpand">True</property>
<property name="shadow_type">in</property>
<property name="max_content_height">300</property>
<property name="propagate_natural_height">True</property>
<child>
@ -282,6 +271,9 @@
<object class="GtkListBox" id="account_list">
<property name="visible">True</property>
<property name="can_focus">False</property>
<style>
<class name="preferences"/>
</style>
</object>
</child>
</object>
@ -301,6 +293,9 @@
</child>
</object>
</child>
<style>
<class name="app-view"/>
</style>
</object>
<template class="TootleWidgetsAccountsButton" parent="GtkMenuButton">
<property name="visible">True</property>

View File

@ -2,112 +2,123 @@
<!-- Generated with glade 3.36.0 -->
<interface>
<requires lib="gtk+" version="3.20"/>
<template class="TootleWidgetsAccountsButtonItem" parent="GtkGrid">
<template class="TootleWidgetsAccountsButtonItem" parent="GtkListBoxRow">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">8</property>
<property name="margin_right">8</property>
<property name="margin_top">8</property>
<property name="margin_bottom">8</property>
<property name="row_spacing">3</property>
<property name="column_spacing">8</property>
<property name="can_focus">True</property>
<child>
<object class="TootleWidgetsAvatar" id="avatar">
<object class="GtkStack" id="stack">
<property name="visible">True</property>
<property name="size">48</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
<property name="height">2</property>
</packing>
</child>
<child>
<object class="GtkButton" id="forget">
<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="valign">center</property>
<property name="relief">none</property>
<property name="can_focus">False</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkGrid">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_start">8</property>
<property name="margin_end">8</property>
<property name="margin_top">8</property>
<property name="margin_bottom">8</property>
<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>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
<property name="height">2</property>
</packing>
</child>
<child>
<object class="GtkButton" id="forget_button">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="tooltip_text" translatable="yes">Forget</property>
<property name="valign">center</property>
<property name="margin_end">6</property>
<property name="relief">none</property>
<signal name="clicked" handler="forget" swapped="no"/>
<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="image-button"/>
<class name="flat"/>
</style>
</object>
<packing>
<property name="left_attach">2</property>
<property name="top_attach">0</property>
<property name="height">2</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="title">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="label" translatable="yes">Title</property>
<property name="ellipsize">end</property>
<property name="single_line_mode">True</property>
<property name="xalign">0</property>
<attributes>
<attribute name="weight" value="bold"/>
</attributes>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="handle">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="opacity">0.5</property>
<property name="hexpand">True</property>
<property name="label" translatable="yes">Handle</property>
<property name="ellipsize">end</property>
<property name="single_line_mode">True</property>
<property name="xalign">0</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
</object>
</child>
<child>
<object class="GtkImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="icon_name">edit-delete-symbolic</property>
<property name="icon_name">list-add-symbolic</property>
</object>
<packing>
<property name="name">new</property>
<property name="position">1</property>
</packing>
</child>
<style>
<class name="circular"/>
<class name="image-button"/>
<class name="flat"/>
</style>
</object>
<packing>
<property name="left_attach">3</property>
<property name="top_attach">0</property>
<property name="height">2</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="title">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="label" translatable="yes">Title</property>
<property name="ellipsize">end</property>
<property name="single_line_mode">True</property>
<property name="xalign">0</property>
<attributes>
<attribute name="weight" value="bold"/>
</attributes>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="handle">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="label" translatable="yes">Handle</property>
<property name="ellipsize">end</property>
<property name="single_line_mode">True</property>
<property name="xalign">0</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">1</property>
</packing>
</child>
<child>
<object class="GtkButton" id="profile">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="tooltip_text" translatable="yes">Open profile</property>
<property name="valign">center</property>
<property name="relief">none</property>
<child>
<object class="GtkImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="icon_name">avatar-default-symbolic</property>
</object>
</child>
<style>
<class name="circular"/>
<class name="image-button"/>
<class name="flat"/>
</style>
</object>
<packing>
<property name="left_attach">2</property>
<property name="top_attach">0</property>
<property name="height">2</property>
</packing>
</child>
</template>
</interface>

View File

@ -207,6 +207,7 @@
<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>

View File

@ -3,170 +3,179 @@ using Gtk;
[GtkTemplate (ui = "/com/github/bleakgrey/tootle/ui/widgets/accounts_button.ui")]
public class Tootle.Widgets.AccountsButton : Gtk.MenuButton, IAccountListener {
[GtkTemplate (ui = "/com/github/bleakgrey/tootle/ui/widgets/accounts_button_item.ui")]
class Item : Grid {
[GtkChild]
Widgets.Avatar avatar;
[GtkChild]
Label title;
[GtkChild]
Label handle;
[GtkChild]
Button profile;
[GtkChild]
Button forget;
[GtkTemplate (ui = "/com/github/bleakgrey/tootle/ui/widgets/accounts_button_item.ui")]
class Item : ListBoxRow {
public Item (InstanceAccount acc, AccountsButton _self) {
avatar.url = acc.avatar;
title.label = acc.display_name;
handle.label = acc.handle;
AccountsButton button;
InstanceAccount account;
profile.clicked.connect (() => {
Views.Profile.open_from_id (acc.id);
_self.active = false;
});
[GtkChild]
Stack stack;
[GtkChild]
Widgets.Avatar avatar;
[GtkChild]
Label title;
[GtkChild]
Label handle;
[GtkChild]
Button forget_button;
forget.clicked.connect (() => {
_self.active = false;
accounts.remove (acc);
});
}
public Item (InstanceAccount account, AccountsButton btn) {
this.account = account;
this.button = btn;
avatar.url = account.avatar;
title.label = account.display_name;
handle.label = account.handle;
}
public Item.add_new () {
title.label = _("New Account");
handle.label = _("Click to add");
profile.destroy ();
forget.destroy ();
}
}
public Item.add_new () {
forget_button.destroy ();
stack.visible_child_name = "new";
selectable = false;
}
bool invalidated = true;
[GtkCallback]
void forget () {
var forget = app.question (
_("Forget %s?".printf (handle.label)),
_("This account will be removed from the application."),
window
);
if (forget) {
button.active = false;
accounts.remove (account);
}
}
[GtkChild]
Widgets.Avatar avatar;
[GtkCallback]
void open_profile () {
Views.Profile.open_from_id (account.id);
button.active = false;
}
[GtkChild]
ListBox account_list;
}
[GtkChild]
ModelButton item_accounts;
[GtkChild]
ModelButton item_prefs;
[GtkChild]
ModelButton item_refresh;
[GtkChild]
ModelButton item_search;
[GtkChild]
Button item_favs;
[GtkChild]
Button item_conversations;
[GtkChild]
Button item_bookmarks;
[GtkChild]
Button item_lists;
bool invalidated = true;
construct {
account_listener_init ();
[GtkChild]
Widgets.Avatar avatar;
item_refresh.clicked.connect (() => {
app.refresh ();
});
Desktop.set_hotkey_tooltip (item_refresh, null, app.ACCEL_REFRESH);
[GtkChild]
ListBox account_list;
item_favs.clicked.connect (() => {
window.open_view (new Views.Favorites ());
popover.popdown ();
});
item_conversations.clicked.connect (() => {
window.open_view (new Views.Conversations ());
popover.popdown ();
});
item_bookmarks.clicked.connect (() => {
window.open_view (new Views.Bookmarks ());
popover.popdown ();
});
item_lists.clicked.connect (() => {
window.open_view (new Views.Lists ());
popover.popdown ();
});
item_search.clicked.connect (() => {
window.open_view (new Views.Search ());
popover.popdown ();
});
item_prefs.clicked.connect (() => {
Dialogs.Preferences.open ();
popover.popdown ();
});
[GtkChild]
ModelButton item_accounts;
[GtkChild]
ModelButton item_prefs;
[GtkChild]
ModelButton item_refresh;
[GtkChild]
ModelButton item_search;
[GtkChild]
Button item_favs;
[GtkChild]
Button item_conversations;
[GtkChild]
Button item_bookmarks;
[GtkChild]
Button item_lists;
on_account_changed (null);
construct {
account_listener_init ();
notify["active"].connect (() => {
if (active && invalidated)
rebuild ();
});
item_refresh.clicked.connect (() => {
app.refresh ();
});
Desktop.set_hotkey_tooltip (item_refresh, null, app.ACCEL_REFRESH);
account_list.row_activated.connect (on_selection_changed);
}
item_favs.clicked.connect (() => {
window.open_view (new Views.Favorites ());
popover.popdown ();
});
item_conversations.clicked.connect (() => {
window.open_view (new Views.Conversations ());
popover.popdown ();
});
item_bookmarks.clicked.connect (() => {
window.open_view (new Views.Bookmarks ());
popover.popdown ();
});
item_lists.clicked.connect (() => {
window.open_view (new Views.Lists ());
popover.popdown ();
});
item_search.clicked.connect (() => {
window.open_view (new Views.Search ());
popover.popdown ();
});
item_prefs.clicked.connect (() => {
Dialogs.Preferences.open ();
popover.popdown ();
});
on_account_changed (null);
notify["active"].connect (() => {
if (active && invalidated)
rebuild ();
});
account_list.row_activated.connect (on_selection_changed);
}
~AccountsButton () {
account_listener_free ();
}
protected void on_selection_changed (ListBoxRow r) {
var i = r.get_index ();
if (i >= accounts.saved.size) {
active = false;
window.open_view (new Views.NewAccount (true));
popover.popdown ();
return;
}
protected void on_selection_changed (ListBoxRow r) {
var i = r.get_index ();
if (i >= accounts.saved.size) {
active = false;
window.open_view (new Views.NewAccount (true));
popover.popdown ();
return;
}
var account = accounts.saved.@get (i);
if (accounts.active == account)
return;
var account = accounts.saved.@get (i);
if (accounts.active == account)
return;
accounts.switch_account (i);
popover.popdown ();
}
accounts.switch_account (i);
popover.popdown ();
}
public virtual void on_accounts_changed (Gee.ArrayList<InstanceAccount> accounts) {
invalidated = true;
if (active)
rebuild ();
}
public virtual void on_accounts_changed (Gee.ArrayList<InstanceAccount> accounts) {
invalidated = true;
if (active)
rebuild ();
}
public virtual void on_account_changed (InstanceAccount? account) {
if (account == null) {
avatar.url = null;
item_accounts.text = "<b>" + _("No active account") + "</b>";
}
else {
avatar.url = account.avatar;
item_accounts.text = @"<b>$(account.display_name)</b>\n$(account.handle) ";
}
item_accounts.use_markup = true;
}
public virtual void on_account_changed (InstanceAccount? account) {
if (account == null) {
avatar.url = null;
item_accounts.text = "<b><span size=\"large\">%s</span></b>\n%s".printf (
_("Anonymous"),
_("No active account"));
}
else {
avatar.url = account.avatar;
item_accounts.text = @"<b><span size=\"large\">$(account.display_name)</span></b>\n$(account.handle)";
}
item_accounts.use_markup = true;
}
void rebuild () {
account_list.@foreach (w => account_list.remove (w));
accounts.saved.@foreach (acc => {
var item = new Item (acc, this);
var row = new ListBoxRow ();
row.add (item);
row.show ();
void rebuild () {
account_list.@foreach (w => account_list.remove (w));
accounts.saved.@foreach (acc => {
var row = new Item (acc, this);
account_list.insert (row, -1);
if (accounts.active == acc)
row.activate ();
account_list.insert (row, -1);
if (accounts.active == acc)
row.activate ();
return true;
});
account_list.insert (new Item.add_new (), -1);
return true;
});
var new_row = new ListBoxRow ();
new_row.add (new Item.add_new ());
new_row.selectable = false;
new_row.show ();
account_list.insert (new_row, -1);
invalidated = false;
}
invalidated = false;
}
}

View File

@ -1,24 +1,24 @@
using Gtk;
using Gdk;
public class Tootle.Widgets.Avatar : EventBox {
public class Tootle.Widgets.Avatar : Button {
public string? url { get; set; }
public int size { get; set; default = 48; }
private Cache.Reference? cached;
Cache.Reference? cached;
construct {
get_style_context ().add_class ("avatar");
notify["url"].connect (on_url_updated);
notify["size"].connect (on_redraw);
notify["size"].connect (on_size_changed);
// Screen.get_default ().monitors_changed.connect (on_redraw);
on_url_updated ();
}
public Avatar (int size = this.size) {
Object (size: size);
on_redraw ();
queue_draw ();
}
~Avatar () {
@ -27,26 +27,35 @@ public class Tootle.Widgets.Avatar : EventBox {
cache.unload (cached);
}
private void on_url_updated () {
void on_url_updated () {
if (cached != null)
cache.unload (cached);
cached = null;
on_redraw ();
queue_draw ();
cache.load (url, on_cache_result);
}
private void on_cache_result (Cache.Reference? result) {
void on_cache_result (Cache.Reference? result) {
cached = result;
on_redraw ();
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 ();
}
private void on_redraw () {
set_size_request (get_scaled_size (), get_scaled_size ());
queue_draw_area (0, 0, size, size);
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) {
@ -61,8 +70,11 @@ public class Tootle.Widgets.Avatar : EventBox {
pixbuf = cached.data.scale_simple (get_scaled_size (), get_scaled_size (), InterpType.BILINEAR);
}
else {
pixbuf = IconTheme.get_default ()
.load_icon_for_scale ("avatar-default", get_scaled_size (), get_scale_factor (), IconLookupFlags.GENERIC_FALLBACK);
pixbuf = IconTheme.get_default ().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 ();

View File

@ -90,10 +90,8 @@ public class Tootle.Widgets.Status : ListBoxRow {
}
public virtual signal void open () {
if (status.id == "") {
var view = new Views.Profile (status.formal.account);
window.open_view (view);
}
if (status.id == "")
on_avatar_clicked ();
else {
var formal = status.formal;
var view = new Views.ExpandedStatus (formal);
@ -150,7 +148,6 @@ public class Tootle.Widgets.Status : ListBoxRow {
content.single_line_mode = true;
content.lines = 2;
content.ellipsize = Pango.EllipsizeMode.END;
button_release_event.connect (on_avatar_clicked);
}
if (!attachments.populate (status.formal.media_attachments) || status.id == "") {
@ -158,7 +155,6 @@ public class Tootle.Widgets.Status : ListBoxRow {
}
menu_button.clicked.connect (open_menu);
avatar.button_release_event.connect (on_avatar_clicked);
}
public Status (API.Status status, API.NotificationType? _kind = null) {
@ -185,12 +181,10 @@ public class Tootle.Widgets.Status : ListBoxRow {
header_label.label = kind.get_desc (status.account);
}
public bool on_avatar_clicked (EventButton ev) {
if (ev.button == 1 && ev.type == EventType.BUTTON_RELEASE) {
var view = new Views.Profile (status.formal.account);
return window.open_view (view);
}
return false;
[GtkCallback]
public void on_avatar_clicked () {
var view = new Views.Profile (status.formal.account);
window.open_view (view);
}
protected void open_menu () {