InstanceAccount: Register places (#328)

This commit is contained in:
Bleak Grey 2021-09-09 14:47:11 +03:00
parent d635226a17
commit 02f918d637
6 changed files with 162 additions and 149 deletions

View File

@ -36,6 +36,7 @@ sources = files(
'src/Utils/DateTime.vala',
'src/Services/Accounts/InstanceAccount.vala',
'src/Services/Accounts/AccountStore.vala',
'src/Services/Accounts/Places.vala',
'src/Services/Accounts/SecretAccountStore.vala',
'src/Services/Accounts/AccountHolder.vala',
'src/Services/Accounts/Mastodon/Account.vala',

View File

@ -14,6 +14,10 @@ public class Tootle.InstanceAccount : API.Account, Streamable {
public string? access_token { get; set; }
public Error? error { get; set; } //TODO: use this field when server invalidates the auth token
public GLib.ListStore known_places = new GLib.ListStore (typeof (Place));
public HashMap<Type,Type> type_overrides = new HashMap<Type,Type> ();
public new string handle {
owned get { return @"@$username@$domain"; }
}
@ -26,8 +30,6 @@ public class Tootle.InstanceAccount : API.Account, Streamable {
}
}
public HashMap<Type,Type> type_overrides = new HashMap<Type,Type> ();
public virtual signal void activated () {}
public virtual signal void deactivated () {}
public virtual signal void added () {
@ -41,8 +43,9 @@ public class Tootle.InstanceAccount : API.Account, Streamable {
construct {
construct_streamable ();
stream_event[EVENT_NOTIFICATION].connect (on_notification_event);
this.construct_streamable ();
this.stream_event[EVENT_NOTIFICATION].connect (on_notification_event);
this.register_known_places (this.known_places);
}
~InstanceAccount () {
destruct_streamable ();
@ -110,13 +113,13 @@ public class Tootle.InstanceAccount : API.Account, Streamable {
return entity;
}
public virtual void populate_user_menu (GLib.ListStore model) {}
public virtual void describe_kind (string kind, out string? icon, out string? descr, API.Account account) {
icon = null;
descr = null;
}
public virtual void register_known_places (GLib.ListStore places) {}
// Notifications

View File

@ -2,13 +2,13 @@ public class Tootle.Mastodon.Account : InstanceAccount {
public const string BACKEND = "Mastodon";
public const string KIND_MENTION = "mention";
public const string KIND_REBLOG = "reblog";
public const string KIND_FAVOURITE = "favourite";
public const string KIND_FOLLOW = "follow";
public const string KIND_POLL = "poll";
public const string KIND_FOLLOW_REQUEST = "__follow-request";
public const string KIND_REMOTE_REBLOG = "__remote-reblog";
public const string KIND_MENTION = "mention";
public const string KIND_REBLOG = "reblog";
public const string KIND_FAVOURITE = "favourite";
public const string KIND_FOLLOW = "follow";
public const string KIND_POLL = "poll";
public const string KIND_FOLLOW_REQUEST = "__follow-request";
public const string KIND_REMOTE_REBLOG = "__remote-reblog";
class Test : AccountStore.BackendTest {
public override string? get_backend (Json.Object obj) {
@ -25,19 +25,65 @@ public class Tootle.Mastodon.Account : InstanceAccount {
});
}
public static Place PLACE_NOTIFICATIONS = new Place () {
title = _("Notifications"),
icon = "bell-symbolic",
open_func = win => {
win.open_view (new Views.Notifications ());
}
};
public static Place PLACE_MESSAGES = new Place () {
title = _("Direct Messages"),
icon = "mail-unread-symbolic",
open_func = (win) => {
win.open_view (new Views.Conversations ());
}
};
public Views.Sidebar.Item notifications_item;
public static Place PLACE_BOOKMARKS = new Place () {
title = _("Bookmarks"),
icon = "user-bookmarks-symbolic",
open_func = (win) => {
win.open_view (new Views.Bookmarks ());
}
};
construct {
notifications_item = new Views.Sidebar.Item () {
label = "Notifications",
icon = "bell-symbolic",
on_activated = () => {
app.main_window.open_view (new Views.Notifications ());
}
};
bind_property ("unread_count", notifications_item, "badge", BindingFlags.SYNC_CREATE);
public static Place PLACE_FAVORITES = new Place () {
title = _("Favorites"),
icon = "non-starred-symbolic",
open_func = (win) => {
win.open_view (new Views.Favorites ());
}
};
public static Place PLACE_LISTS = new Place () {
title = _("Lists"),
icon = "view-list-symbolic",
open_func = (win) => {
win.open_view (new Views.Lists ());
}
};
public static Place PLACE_SEARCH = new Place () {
title = _("Search"),
icon = "system-search-symbolic",
open_func = (win) => {
win.open_view (new Views.Search ());
}
};
public override void register_known_places (GLib.ListStore places) {
places.append (PLACE_NOTIFICATIONS);
places.append (PLACE_MESSAGES);
places.append (PLACE_BOOKMARKS);
places.append (PLACE_FAVORITES);
places.append (PLACE_LISTS);
places.append (PLACE_SEARCH);
}
construct {
// bind_property ("unread_count", notifications_item, "badge", BindingFlags.SYNC_CREATE);
// Populate possible visibility variants
set_visibility (new Visibility () {
@ -64,86 +110,43 @@ public class Tootle.Mastodon.Account : InstanceAccount {
icon_name = "mail-unread-symbolic",
description = _("Post to mentioned users only")
});
}
public override void populate_user_menu (GLib.ListStore model) {
// model.append (new Views.Sidebar.Item () {
// label = "Timelines",
// icon = "user-home-symbolic"
// });
model.append (notifications_item);
model.append (new Views.Sidebar.Item () {
label = "Direct Messages",
icon = "mail-unread-symbolic",
on_activated = () => {
app.main_window.open_view (new Views.Conversations ());
}
});
model.append (new Views.Sidebar.Item () {
label = "Bookmarks",
icon = "user-bookmarks-symbolic",
on_activated = () => {
app.main_window.open_view (new Views.Bookmarks ());
}
});
model.append (new Views.Sidebar.Item () {
label = "Favorites",
icon = "non-starred-symbolic",
on_activated = () => {
app.main_window.open_view (new Views.Favorites ());
}
});
model.append (new Views.Sidebar.Item () {
label = "Lists",
icon = "view-list-symbolic",
on_activated = () => {
app.main_window.open_view (new Views.Lists ());
}
});
model.append (new Views.Sidebar.Item () {
label = "Search",
icon = "system-search-symbolic",
on_activated = () => {
app.main_window.open_view (new Views.Search ());
}
});
}
public override void describe_kind (string kind, out string? icon, out string? descr, API.Account account) {
switch (kind) {
case KIND_MENTION:
icon = "user-available-symbolic";
descr = _("<span underline=\"none\"><a href=\"%s\">%s</a> mentioned you</span>").printf (account.url, account.display_name);
break;
case KIND_REBLOG:
icon = "media-playlist-repeat-symbolic";
descr = _("<span underline=\"none\"><a href=\"%s\">%s</a> boosted your status</span>").printf (account.url, account.display_name);
break;
case KIND_REMOTE_REBLOG:
icon = "media-playlist-repeat-symbolic";
descr = _("<span underline=\"none\"><a href=\"%s\">%s</a> boosted</span>").printf (account.url, account.display_name);
break;
case KIND_FAVOURITE:
icon = "starred-symbolic";
descr = _("<span underline=\"none\"><a href=\"%s\">%s</a> favorited your status</span>").printf (account.url, account.display_name);
break;
case KIND_FOLLOW:
icon = "contact-new-symbolic";
descr = _("<span underline=\"none\"><a href=\"%s\">%s</a> now follows you</span>").printf (account.url, account.display_name);
break;
case KIND_FOLLOW_REQUEST:
icon = "contact-new-symbolic";
descr = _("<span underline=\"none\"><a href=\"%s\">%s</a> wants to follow you</span>").printf (account.url, account.display_name);
break;
case KIND_POLL:
icon = "emblem-default-symbolic";
descr = _("Poll results");
break;
default:
icon = null;
descr = null;
break;
}
}
public override void describe_kind (string kind, out string? icon, out string? descr, API.Account account) {
switch (kind) {
case KIND_MENTION:
icon = "user-available-symbolic";
descr = _("<span underline=\"none\"><a href=\"%s\">%s</a> mentioned you</span>").printf (account.url, account.display_name);
break;
case KIND_REBLOG:
icon = "media-playlist-repeat-symbolic";
descr = _("<span underline=\"none\"><a href=\"%s\">%s</a> boosted your status</span>").printf (account.url, account.display_name);
break;
case KIND_REMOTE_REBLOG:
icon = "media-playlist-repeat-symbolic";
descr = _("<span underline=\"none\"><a href=\"%s\">%s</a> boosted</span>").printf (account.url, account.display_name);
break;
case KIND_FAVOURITE:
icon = "starred-symbolic";
descr = _("<span underline=\"none\"><a href=\"%s\">%s</a> favorited your status</span>").printf (account.url, account.display_name);
break;
case KIND_FOLLOW:
icon = "contact-new-symbolic";
descr = _("<span underline=\"none\"><a href=\"%s\">%s</a> now follows you</span>").printf (account.url, account.display_name);
break;
case KIND_FOLLOW_REQUEST:
icon = "contact-new-symbolic";
descr = _("<span underline=\"none\"><a href=\"%s\">%s</a> wants to follow you</span>").printf (account.url, account.display_name);
break;
case KIND_POLL:
icon = "emblem-default-symbolic";
descr = _("Poll results");
break;
default:
icon = null;
descr = null;
break;
}
}
}

View File

@ -0,0 +1,13 @@
public class Tootle.Place : Object {
public string title { get; set; }
public string icon { get; set; }
public int badge { get; set; default = 0; }
public bool separated { get; set; default = false; }
[CCode (has_target = false)]
public delegate void OpenFunc (Dialogs.MainWindow window);
public OpenFunc open_func { get; set; }
}

View File

@ -4,6 +4,7 @@ public class Tootle.Views.Main : Views.TabbedBase {
public Main () {
add_tab (new Views.Home ());
add_tab (new Views.Notifications ());
add_tab (new Views.Local ());
add_tab (new Views.Federated ());
}

View File

@ -13,31 +13,46 @@ public class Tootle.Views.Sidebar : Box, AccountHolder {
[GtkChild] unowned Label subtitle;
protected InstanceAccount? account { get; set; default = null; }
GLib.ListStore item_model = new GLib.ListStore (typeof (Object));
Item item_preferences = new Item () {
label = _("Preferences"),
protected GLib.ListStore app_items;
protected SliceListModel account_items;
protected FlattenListModel item_model;
public static Place PREFERENCES = new Place () {
title = _("Preferences"),
icon = "emblem-system-symbolic",
selectable = false,
//selectable = false,
separated = true,
on_activated = () => {
open_func = () => {
Dialogs.Preferences.open ();
}
};
Item item_about = new Item () {
label = _("About"),
public static Place ABOUT = new Place () {
title = _("About"),
icon = "help-about-symbolic",
selectable = false,
on_activated = () => {
//selectable = false,
open_func = () => {
app.lookup_action ("about").activate (null);
}
};
construct {
construct_account_holder ();
app_items = new GLib.ListStore (typeof (Place));
app_items.append (PREFERENCES);
app_items.append (ABOUT);
account_items = new SliceListModel (null, 0, 15);
var models = new GLib.ListStore (typeof (Object));
models.append (account_items);
models.append (app_items);
item_model = new FlattenListModel (models);
items.bind_model (item_model, on_item_create);
items.set_header_func (on_item_header_update);
saved_accounts.set_header_func (on_account_header_update);
construct_account_holder ();
}
protected virtual void on_accounts_changed (Gee.ArrayList<InstanceAccount> accounts) {
@ -56,17 +71,13 @@ public class Tootle.Views.Sidebar : Box, AccountHolder {
protected virtual void on_account_changed (InstanceAccount? account) {
this.account = account;
warning (account.handle);
accounts_button.active = false;
item_model.remove_all ();
if (account != null) {
title.label = account.display_name;
subtitle.label = account.handle;
avatar.account = account;
account.populate_user_menu (item_model);
account_items.model = account.known_places;
}
else {
saved_accounts.unselect_all ();
@ -74,18 +85,8 @@ public class Tootle.Views.Sidebar : Box, AccountHolder {
title.label = _("Anonymous");
subtitle.label = _("No account selected");
avatar.account = null;
account_items.model = null;
}
item_model.append (item_preferences);
item_model.append (item_about);
// item_model.append (new Item () {
// label = "(Debug) Empty View",
// separated = true,
// on_activated = () => {
// app.main_window.open_view (new Views.ContentBase ());
// }
// });
}
[GtkCallback] void on_mode_changed () {
@ -100,44 +101,35 @@ public class Tootle.Views.Sidebar : Box, AccountHolder {
// Item
public class Item : Object {
public VoidFunc? on_activated;
public string label { get; set; default = ""; }
public string icon { get; set; default = ""; }
public int badge { get; set; default = 0; }
public bool selectable { get; set; default = false; }
public bool separated { get; set; default = false; }
}
[GtkTemplate (ui = "/com/github/bleakgrey/tootle/ui/views/sidebar/item.ui")]
protected class ItemRow : ListBoxRow {
public Item item;
public Place place;
[GtkChild] unowned Image icon;
[GtkChild] unowned Label label;
[GtkChild] unowned Label badge;
public ItemRow (Item _item) {
item = _item;
item.bind_property ("label", label, "label", BindingFlags.SYNC_CREATE);
item.bind_property ("icon", icon, "icon-name", BindingFlags.SYNC_CREATE);
item.bind_property ("badge", badge, "label", BindingFlags.SYNC_CREATE);
item.bind_property ("badge", badge, "visible", BindingFlags.SYNC_CREATE, (b, src, ref target) => {
public ItemRow (Place place) {
this.place = place;
place.bind_property ("title", label, "label", BindingFlags.SYNC_CREATE);
place.bind_property ("icon", icon, "icon-name", BindingFlags.SYNC_CREATE);
place.bind_property ("badge", badge, "label", BindingFlags.SYNC_CREATE);
place.bind_property ("badge", badge, "visible", BindingFlags.SYNC_CREATE, (b, src, ref target) => {
target.set_boolean (src.get_int () > 0);
return true;
});
bind_property ("selectable", item, "selectable", BindingFlags.SYNC_CREATE);
// bind_property ("selectable", item, "selectable", BindingFlags.SYNC_CREATE);
}
}
Widget on_item_create (Object obj) {
return new ItemRow (obj as Item);
return new ItemRow (obj as Place);
}
[GtkCallback] void on_item_activated (ListBoxRow _row) {
var row = _row as ItemRow;
if (row.item.on_activated != null)
row.item.on_activated ();
if (row.place.open_func != null)
row.place.open_func (app.main_window);
var flap = app.main_window.flap;
if (flap.folded)
@ -150,7 +142,7 @@ public class Tootle.Views.Sidebar : Box, AccountHolder {
row.set_header (null);
if (row.item.separated && before != null && !before.item.separated) {
if (row.place.separated && before != null && !before.place.separated) {
row.set_header (new Separator (Orientation.HORIZONTAL));
}
}