Merge branch 'master' into titlebar-warning
This commit is contained in:
commit
ca127df6e2
|
@ -22,6 +22,7 @@ executable(
|
|||
'src/MainWindow.vala',
|
||||
'src/SettingsManager.vala',
|
||||
'src/AccountManager.vala',
|
||||
'src/ImageCache.vala',
|
||||
'src/NetManager.vala',
|
||||
'src/Utils.vala',
|
||||
'src/Notificator.vala',
|
||||
|
@ -35,7 +36,6 @@ executable(
|
|||
'src/API/Notification.vala',
|
||||
'src/API/NotificationType.vala',
|
||||
'src/API/Attachment.vala',
|
||||
'src/Widgets/HeaderBar.vala',
|
||||
'src/Widgets/AlignedLabel.vala',
|
||||
'src/Widgets/RichLabel.vala',
|
||||
'src/Widgets/ImageToggleButton.vala',
|
||||
|
|
|
@ -10,6 +10,7 @@ namespace Tootle{
|
|||
public static SettingsManager settings;
|
||||
public static AccountManager accounts;
|
||||
public static NetManager network;
|
||||
public static ImageCache image_cache;
|
||||
|
||||
public class Application : Granite.Application {
|
||||
|
||||
|
@ -31,6 +32,7 @@ namespace Tootle{
|
|||
settings = new SettingsManager ();
|
||||
accounts = new AccountManager ();
|
||||
network = new NetManager ();
|
||||
image_cache = new ImageCache ();
|
||||
accounts.init ();
|
||||
|
||||
app.error.connect (app.on_error);
|
||||
|
@ -59,8 +61,6 @@ namespace Tootle{
|
|||
else {
|
||||
window = new MainWindow (this);
|
||||
window.present ();
|
||||
accounts.switched (accounts.current);
|
||||
accounts.signal_current ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,143 @@
|
|||
using Soup;
|
||||
using GLib;
|
||||
using Gdk;
|
||||
using Json;
|
||||
|
||||
private struct CachedImage {
|
||||
|
||||
public string uri;
|
||||
public int size;
|
||||
|
||||
public CachedImage(string uri, int size) { this.uri=uri; this.size=size; }
|
||||
|
||||
public static uint hash(CachedImage? c) {
|
||||
assert(c != null);
|
||||
assert(c.uri != null);
|
||||
return GLib.int64_hash(c.size) ^ c.uri.hash();
|
||||
}
|
||||
|
||||
public static bool equal(CachedImage? a, CachedImage? b) {
|
||||
if (a == null || b == null)
|
||||
return false;
|
||||
return a.size == b.size && a.uri == b.uri;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public delegate void PixbufCallback (Gdk.Pixbuf pb);
|
||||
|
||||
public class Tootle.ImageCache : GLib.Object {
|
||||
|
||||
private GLib.HashTable<CachedImage?, Soup.Message> in_progress;
|
||||
private GLib.HashTable<CachedImage?, Gdk.Pixbuf> pixbufs;
|
||||
private uint total_size_est;
|
||||
private uint size_limit;
|
||||
private string cache_path;
|
||||
|
||||
construct {
|
||||
pixbufs = new GLib.HashTable<CachedImage?, Gdk.Pixbuf>(CachedImage.hash, CachedImage.equal);
|
||||
in_progress = new GLib.HashTable<CachedImage?, Soup.Message>(CachedImage.hash, CachedImage.equal);
|
||||
total_size_est = 0;
|
||||
cache_path = "%s/%s".printf (GLib.Environment.get_user_cache_dir (), app.application_id);
|
||||
|
||||
settings.changed.connect (on_settings_changed);
|
||||
on_settings_changed ();
|
||||
}
|
||||
|
||||
public ImageCache() {
|
||||
GLib.Object();
|
||||
}
|
||||
|
||||
private void on_settings_changed () {
|
||||
// assume 32BPP (divide bytes by 4 to get # pixels) and raw, overhead-free storage
|
||||
// cache_size setting is number of megabytes
|
||||
size_limit = (1024 * 1024 * settings.cache_size) / 4;
|
||||
if (settings.cache)
|
||||
enforce_size_limit ();
|
||||
else
|
||||
remove_all ();
|
||||
}
|
||||
|
||||
public void remove_all () {
|
||||
debug("Image cache cleared");
|
||||
pixbufs.remove_all ();
|
||||
total_size_est = 0;
|
||||
}
|
||||
|
||||
public void remove_one (string uri, int size) {
|
||||
CachedImage ci = CachedImage (uri, size);
|
||||
bool removed = pixbufs.remove(ci);
|
||||
if (removed) {
|
||||
assert (total_size_est >= size * size);
|
||||
total_size_est -= size * size;
|
||||
debug("Cache usage: %zd", total_size_est);
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: fix me
|
||||
// remove least used image
|
||||
private void remove_least_used () {
|
||||
var keys = pixbufs.get_keys();
|
||||
if (keys.first() != null) {
|
||||
var ci = keys.first().data;
|
||||
remove_one(ci.uri, ci.size);
|
||||
}
|
||||
}
|
||||
|
||||
private void enforce_size_limit () {
|
||||
debug("Updating size limit (%zd/%zd)", total_size_est, size_limit);
|
||||
while (total_size_est > size_limit && pixbufs.size() > 0)
|
||||
remove_least_used ();
|
||||
|
||||
assert (total_size_est <= size_limit);
|
||||
}
|
||||
|
||||
private void store_pixbuf (CachedImage ci, Gdk.Pixbuf pixbuf) {
|
||||
assert (!pixbufs.contains (ci));
|
||||
pixbufs.insert (ci, pixbuf);
|
||||
in_progress.remove (ci);
|
||||
total_size_est += ci.size * ci.size;
|
||||
enforce_size_limit ();
|
||||
}
|
||||
|
||||
public async void get_image (string uri, int size, owned PixbufCallback? cb = null) {
|
||||
CachedImage ci = CachedImage (uri, size);
|
||||
Gdk.Pixbuf? pb = pixbufs.get(ci);
|
||||
if (pb != null) {
|
||||
cb (pb);
|
||||
return;
|
||||
}
|
||||
|
||||
Soup.Message? msg = in_progress.get(ci);
|
||||
if (msg == null) {
|
||||
msg = new Soup.Message("GET", uri);
|
||||
msg.finished.connect(() => {
|
||||
debug("Caching %s@%d", uri, size);
|
||||
var data = msg.response_body.data;
|
||||
var stream = new MemoryInputStream.from_data (data);
|
||||
var pixbuf = new Gdk.Pixbuf.from_stream_at_scale (stream, size, size, true);
|
||||
store_pixbuf(ci, pixbuf);
|
||||
cb(pixbuf);
|
||||
});
|
||||
in_progress[ci] = msg;
|
||||
network.queue_custom (msg);
|
||||
} else {
|
||||
msg.finished.connect_after(() => {
|
||||
cb(pixbufs[ci]);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void load_avatar (string uri, Granite.Widgets.Avatar avatar, int size = 32) {
|
||||
get_image.begin(uri, size, (pixbuf) => avatar.pixbuf = pixbuf);
|
||||
}
|
||||
|
||||
public void load_image (string uri, Gtk.Image image) {
|
||||
load_scaled_image(uri, image, -1);
|
||||
}
|
||||
|
||||
public void load_scaled_image (string uri, Gtk.Image image, int size = 64) {
|
||||
get_image.begin(uri, size, image.set_from_pixbuf);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,19 +1,21 @@
|
|||
using Gtk;
|
||||
|
||||
public class Tootle.MainWindow: Gtk.Window {
|
||||
|
||||
private weak SettingsManager settings;
|
||||
|
||||
private Gtk.Overlay overlay;
|
||||
private Granite.Widgets.Toast toast;
|
||||
private Gtk.Grid grid;
|
||||
public Tootle.HeaderBar header;
|
||||
public Stack primary_stack;
|
||||
public Stack secondary_stack;
|
||||
private Stack primary_stack;
|
||||
private Stack secondary_stack;
|
||||
|
||||
public Gtk.HeaderBar header;
|
||||
private Granite.Widgets.ModeButton button_mode;
|
||||
private AccountsButton button_accounts;
|
||||
private Spinner spinner;
|
||||
private Button button_toot;
|
||||
private Button button_back;
|
||||
|
||||
construct {
|
||||
settings = Tootle.settings;
|
||||
|
||||
var provider = new Gtk.CssProvider ();
|
||||
provider.load_from_resource ("/com/github/bleakgrey/tootle/app.css");
|
||||
StyleContext.add_provider_for_screen (Gdk.Screen.get_default (), provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
|
||||
|
@ -33,7 +35,37 @@ public class Tootle.MainWindow: Gtk.Window {
|
|||
primary_stack.add_named (secondary_stack, "0");
|
||||
primary_stack.hexpand = true;
|
||||
primary_stack.vexpand = true;
|
||||
header = new Tootle.HeaderBar ();
|
||||
|
||||
spinner = new Spinner ();
|
||||
spinner.active = true;
|
||||
|
||||
button_accounts = new AccountsButton ();
|
||||
|
||||
button_back = new Button ();
|
||||
button_back.label = _("Back");
|
||||
button_back.get_style_context ().add_class (Granite.STYLE_CLASS_BACK_BUTTON);
|
||||
button_back.clicked.connect (() => back ());
|
||||
|
||||
button_toot = new Button ();
|
||||
button_toot.tooltip_text = _("Toot");
|
||||
button_toot.image = new Gtk.Image.from_icon_name ("document-edit-symbolic", Gtk.IconSize.LARGE_TOOLBAR);
|
||||
button_toot.clicked.connect (() => PostDialog.open ());
|
||||
|
||||
button_mode = new Granite.Widgets.ModeButton ();
|
||||
button_mode.get_style_context ().add_class ("mode");
|
||||
button_mode.mode_changed.connect (widget => {
|
||||
secondary_stack.set_visible_child_name (widget.tooltip_text);
|
||||
});
|
||||
button_mode.show ();
|
||||
|
||||
header = new Gtk.HeaderBar ();
|
||||
header.show_close_button = true;
|
||||
header.custom_title = button_mode;
|
||||
header.show_all ();
|
||||
header.pack_start (button_back);
|
||||
header.pack_start (button_toot);
|
||||
header.pack_end (button_accounts);
|
||||
header.pack_end (spinner);
|
||||
set_titlebar (header);
|
||||
|
||||
grid = new Gtk.Grid ();
|
||||
|
@ -41,8 +73,16 @@ public class Tootle.MainWindow: Gtk.Window {
|
|||
grid.attach (primary_stack, 0, 0, 1, 1);
|
||||
grid.attach (overlay, 0, 0, 1, 1);
|
||||
|
||||
add_header_view (new TimelineView ("home"));
|
||||
add_header_view (new NotificationsView ());
|
||||
add_header_view (new LocalView ());
|
||||
add_header_view (new FederatedView ());
|
||||
button_mode.set_active (0);
|
||||
|
||||
add (grid);
|
||||
show_all ();
|
||||
|
||||
button_mode.valign = Gtk.Align.FILL;
|
||||
}
|
||||
|
||||
public MainWindow (Gtk.Application application) {
|
||||
|
@ -52,37 +92,18 @@ public class Tootle.MainWindow: Gtk.Window {
|
|||
resizable: true
|
||||
);
|
||||
window_position = WindowPosition.CENTER;
|
||||
update_header ();
|
||||
|
||||
Tootle.accounts.switched.connect(on_account_switched);
|
||||
Tootle.app.toast.connect (on_toast);
|
||||
}
|
||||
|
||||
private void reset () {
|
||||
header.button_mode.clear_children ();
|
||||
secondary_stack.forall (widget => widget.destroy ());
|
||||
}
|
||||
|
||||
private void on_account_switched(Account? account){
|
||||
header.button_mode.clear_children ();
|
||||
secondary_stack.forall (widget => widget.destroy ());
|
||||
|
||||
if (account == null)
|
||||
return;
|
||||
build_main_view ();
|
||||
}
|
||||
|
||||
private void build_main_view (){
|
||||
add_header_view (new TimelineView ("home"));
|
||||
add_header_view (new NotificationsView ());
|
||||
add_header_view (new LocalView ());
|
||||
add_header_view (new FederatedView ());
|
||||
header.update (true);
|
||||
app.toast.connect (on_toast);
|
||||
network.started.connect (() => spinner.show ());
|
||||
network.finished.connect (() => spinner.hide ());
|
||||
accounts.signal_current ();
|
||||
}
|
||||
|
||||
private void add_header_view (AbstractView view) {
|
||||
var img = new Gtk.Image.from_icon_name(view.get_icon (), Gtk.IconSize.LARGE_TOOLBAR);
|
||||
img.tooltip_text = view.get_name ();
|
||||
header.button_mode.append (img);
|
||||
button_mode.append (img);
|
||||
view.image = img;
|
||||
secondary_stack.add_named(view, view.get_name ());
|
||||
|
||||
|
@ -90,13 +111,34 @@ public class Tootle.MainWindow: Gtk.Window {
|
|||
img.pixel_size = 20; // For some reason Notifications icon is too small without this
|
||||
}
|
||||
|
||||
public void open_view (Widget widget) {
|
||||
widget.show ();
|
||||
var i = int.parse (primary_stack.get_visible_child_name ());
|
||||
public int get_visible_id () {
|
||||
return int.parse (primary_stack.get_visible_child_name ());
|
||||
}
|
||||
|
||||
public void open_view (AbstractView widget) {
|
||||
var i = get_visible_id ();
|
||||
i++;
|
||||
widget.stack_pos = i;
|
||||
widget.show ();
|
||||
primary_stack.add_named (widget, i.to_string ());
|
||||
primary_stack.set_visible_child_name (i.to_string ());
|
||||
header.update (false);
|
||||
update_header ();
|
||||
}
|
||||
|
||||
public void back () {
|
||||
var i = get_visible_id ();
|
||||
var child = primary_stack.get_child_by_name (i.to_string ());
|
||||
primary_stack.set_visible_child_name ((i-1).to_string ());
|
||||
child.destroy ();
|
||||
update_header ();
|
||||
}
|
||||
|
||||
public void reopen_view (int view_id) {
|
||||
var i = get_visible_id ();
|
||||
while (i != view_id && view_id != 0) {
|
||||
back ();
|
||||
i = get_visible_id ();
|
||||
}
|
||||
}
|
||||
|
||||
private void on_toast (string msg){
|
||||
|
@ -119,8 +161,15 @@ public class Tootle.MainWindow: Gtk.Window {
|
|||
var theme = is_dark ? "dark" : "light";
|
||||
provider.load_from_resource ("/com/github/bleakgrey/tootle/%s.css".printf (theme));
|
||||
StyleContext.add_provider_for_screen (Gdk.Screen.get_default (), provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
|
||||
|
||||
Gtk.Settings.get_default ().gtk_application_prefer_dark_theme = is_dark;
|
||||
}
|
||||
|
||||
private void update_header () {
|
||||
bool primary_mode = get_visible_id () == 0;
|
||||
button_mode.set_visible (primary_mode);
|
||||
button_toot.set_visible (primary_mode);
|
||||
button_back.set_visible (!primary_mode);
|
||||
button_accounts.set_visible (true);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -14,12 +14,8 @@ public class Tootle.NetManager : GLib.Object {
|
|||
|
||||
private int requests_processing = 0;
|
||||
private Soup.Session session;
|
||||
private Soup.Cache cache;
|
||||
public string cache_path;
|
||||
|
||||
construct {
|
||||
cache_path = "%s/%s".printf (GLib.Environment.get_user_cache_dir (), Tootle.app.application_id);
|
||||
cache = new Soup.Cache (cache_path, Soup.CacheType.SINGLE_USER);
|
||||
session = new Soup.Session ();
|
||||
session.ssl_strict = true;
|
||||
session.ssl_use_system_ca_file = true;
|
||||
|
@ -31,12 +27,6 @@ public class Tootle.NetManager : GLib.Object {
|
|||
finished ();
|
||||
});
|
||||
|
||||
Tootle.app.shutdown.connect (() => {
|
||||
cache.dump ();
|
||||
});
|
||||
Tootle.settings.changed.connect (on_settings_changed);
|
||||
on_settings_changed ();
|
||||
|
||||
// Soup.Logger logger = new Soup.Logger (Soup.LoggerLogLevel.BODY, -1);
|
||||
// session.add_feature (logger);
|
||||
}
|
||||
|
@ -45,23 +35,6 @@ public class Tootle.NetManager : GLib.Object {
|
|||
GLib.Object();
|
||||
}
|
||||
|
||||
private void on_settings_changed () {
|
||||
// cache.set_max_size (1024 * 1024 * Tootle.settings.cache_size);
|
||||
// var has_cache = session.has_feature (cache.get_type ());
|
||||
// if (Tootle.settings.cache) {
|
||||
// if (!has_cache) {
|
||||
// debug ("Turning on cache");
|
||||
// session.add_feature (cache);
|
||||
// }
|
||||
// }
|
||||
// else {
|
||||
// if (has_cache) {
|
||||
// debug ("Turning off cache");
|
||||
// session.remove_feature (cache);
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
public async WebsocketConnection stream (Soup.Message msg) {
|
||||
return yield session.websocket_connect_async (msg, null, null, null);
|
||||
}
|
||||
|
@ -108,7 +81,7 @@ public class Tootle.NetManager : GLib.Object {
|
|||
return msg;
|
||||
}
|
||||
|
||||
public void queue_custom (Soup.Message msg, owned Soup.SessionCallback cb) {
|
||||
public void queue_custom (Soup.Message msg, owned Soup.SessionCallback? cb = null) {
|
||||
session.queue_message (msg, cb);
|
||||
}
|
||||
|
||||
|
@ -133,34 +106,49 @@ public class Tootle.NetManager : GLib.Object {
|
|||
}
|
||||
|
||||
public void load_avatar (string url, Granite.Widgets.Avatar avatar, int size = 32){
|
||||
if (settings.cache) {
|
||||
image_cache.load_avatar (url, avatar, size);
|
||||
return;
|
||||
}
|
||||
|
||||
var msg = new Soup.Message("GET", url);
|
||||
msg.finished.connect(() => {
|
||||
var data = msg.response_body.data;
|
||||
var stream = new MemoryInputStream.from_data (data);
|
||||
var pixbuf = new Gdk.Pixbuf.from_stream_at_scale (stream, size, size, true);
|
||||
avatar.pixbuf = pixbuf;
|
||||
var data = msg.response_body.data;
|
||||
var stream = new MemoryInputStream.from_data (data);
|
||||
var pixbuf = new Gdk.Pixbuf.from_stream_at_scale (stream, size, size, true);
|
||||
avatar.pixbuf = pixbuf;
|
||||
});
|
||||
Tootle.network.queue (msg);
|
||||
}
|
||||
|
||||
public void load_image (string url, Gtk.Image image) {
|
||||
if (settings.cache) {
|
||||
image_cache.load_image (url, image);
|
||||
return;
|
||||
}
|
||||
|
||||
var msg = new Soup.Message("GET", url);
|
||||
msg.finished.connect(() => {
|
||||
var data = msg.response_body.data;
|
||||
var stream = new MemoryInputStream.from_data (data);
|
||||
var pixbuf = new Gdk.Pixbuf.from_stream (stream);
|
||||
image.set_from_pixbuf (pixbuf);
|
||||
var data = msg.response_body.data;
|
||||
var stream = new MemoryInputStream.from_data (data);
|
||||
var pixbuf = new Gdk.Pixbuf.from_stream (stream);
|
||||
image.set_from_pixbuf (pixbuf);
|
||||
});
|
||||
Tootle.network.queue (msg);
|
||||
}
|
||||
|
||||
public void load_scaled_image (string url, Gtk.Image image, int size = 64) {
|
||||
if (settings.cache) {
|
||||
image_cache.load_scaled_image (url, image, size);
|
||||
return;
|
||||
}
|
||||
|
||||
var msg = new Soup.Message("GET", url);
|
||||
msg.finished.connect(() => {
|
||||
var data = msg.response_body.data;
|
||||
var stream = new MemoryInputStream.from_data (data);
|
||||
var pixbuf = new Gdk.Pixbuf.from_stream_at_scale (stream, size, size, true);
|
||||
image.set_from_pixbuf (pixbuf);
|
||||
var data = msg.response_body.data;
|
||||
var stream = new MemoryInputStream.from_data (data);
|
||||
var pixbuf = new Gdk.Pixbuf.from_stream_at_scale (stream, size, size, true);
|
||||
image.set_from_pixbuf (pixbuf);
|
||||
});
|
||||
Tootle.network.queue (msg);
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ using Gtk;
|
|||
|
||||
public abstract class Tootle.AbstractView : Gtk.ScrolledWindow {
|
||||
|
||||
public int stack_pos = -1;
|
||||
public Gtk.Image? image;
|
||||
public Gtk.Box view;
|
||||
protected Gtk.Box? empty;
|
||||
|
|
|
@ -2,7 +2,8 @@ using Gtk;
|
|||
|
||||
public class Tootle.SearchView : AbstractView {
|
||||
|
||||
Gtk.Entry entry;
|
||||
private string query = "";
|
||||
private Gtk.Entry entry;
|
||||
|
||||
construct {
|
||||
view.margin_bottom = 6;
|
||||
|
@ -11,6 +12,7 @@ public class Tootle.SearchView : AbstractView {
|
|||
entry.placeholder_text = _("Search");
|
||||
entry.secondary_icon_name = "system-search-symbolic";
|
||||
entry.width_chars = 25;
|
||||
entry.text = query;
|
||||
entry.show ();
|
||||
Tootle.window.header.pack_start (entry);
|
||||
|
||||
|
@ -56,14 +58,15 @@ public class Tootle.SearchView : AbstractView {
|
|||
}
|
||||
|
||||
private void request () {
|
||||
if (entry.text == "") {
|
||||
query = entry.text;
|
||||
if (query == "") {
|
||||
clear ();
|
||||
return;
|
||||
}
|
||||
Tootle.window.reopen_view (this.stack_pos);
|
||||
|
||||
var query = Soup.URI.encode (entry.text, null);
|
||||
var url = "%s/api/v1/search?q=%s".printf (Tootle.accounts.formal.instance, query);
|
||||
|
||||
var query_encoded = Soup.URI.encode (query, null);
|
||||
var url = "%s/api/v1/search?q=%s".printf (Tootle.accounts.formal.instance, query_encoded);
|
||||
var msg = new Soup.Message("GET", url);
|
||||
Tootle.network.queue(msg, (sess, mess) => {
|
||||
try{
|
||||
|
@ -100,7 +103,6 @@ public class Tootle.SearchView : AbstractView {
|
|||
}
|
||||
|
||||
empty_state ();
|
||||
|
||||
}
|
||||
catch (GLib.Error e) {
|
||||
warning ("Can't update feed");
|
||||
|
|
|
@ -105,6 +105,11 @@ public class Tootle.TimelineView : AbstractView {
|
|||
}
|
||||
|
||||
public virtual void request (){
|
||||
if (accounts.current == null) {
|
||||
empty_state ();
|
||||
return;
|
||||
}
|
||||
|
||||
var msg = new Soup.Message("GET", get_url ());
|
||||
msg.finished.connect (() => empty_state ());
|
||||
Tootle.network.queue(msg, (sess, mess) => {
|
||||
|
|
|
@ -44,7 +44,7 @@ public class Tootle.AccountsButton : Gtk.MenuButton{
|
|||
}
|
||||
|
||||
public AccountView (){
|
||||
button.clicked.connect (() => Tootle.accounts.remove (id));
|
||||
button.clicked.connect (() => accounts.remove (id));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -62,15 +62,15 @@ public class Tootle.AccountsButton : Gtk.MenuButton{
|
|||
|
||||
item_refresh = new Gtk.ModelButton ();
|
||||
item_refresh.text = _("Refresh");
|
||||
item_refresh.clicked.connect (() => Tootle.app.refresh ());
|
||||
item_refresh.clicked.connect (() => app.refresh ());
|
||||
|
||||
item_favs = new Gtk.ModelButton ();
|
||||
item_favs.text = _("Favorites");
|
||||
item_favs.clicked.connect (() => Tootle.window.open_view (new FavoritesView ()));
|
||||
item_favs.clicked.connect (() => window.open_view (new FavoritesView ()));
|
||||
|
||||
item_search = new Gtk.ModelButton ();
|
||||
item_search.text = _("Search");
|
||||
item_search.clicked.connect (() => Tootle.window.open_view (new SearchView ()));
|
||||
item_search.clicked.connect (() => window.open_view (new SearchView ()));
|
||||
|
||||
item_settings = new Gtk.ModelButton ();
|
||||
item_settings.text = _("Settings");
|
||||
|
@ -96,8 +96,8 @@ public class Tootle.AccountsButton : Gtk.MenuButton{
|
|||
add(avatar);
|
||||
show_all ();
|
||||
|
||||
Tootle.accounts.updated.connect (accounts_updated);
|
||||
Tootle.accounts.switched.connect (account_switched);
|
||||
accounts.updated.connect (accounts_updated);
|
||||
accounts.switched.connect (account_switched);
|
||||
list.row_activated.connect (row => {
|
||||
var widget = row as AccountView;
|
||||
if (widget.id == -1) {
|
||||
|
@ -107,7 +107,7 @@ public class Tootle.AccountsButton : Gtk.MenuButton{
|
|||
if (widget.id == Tootle.settings.current_account)
|
||||
return;
|
||||
else
|
||||
Tootle.accounts.switch_account (widget.id);
|
||||
accounts.switch_account (widget.id);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -135,7 +135,7 @@ public class Tootle.AccountsButton : Gtk.MenuButton{
|
|||
if (account == null)
|
||||
avatar.show_default (24);
|
||||
else
|
||||
Tootle.network.load_avatar (account.avatar, avatar, 24);
|
||||
network.load_avatar (account.avatar, avatar, 24);
|
||||
}
|
||||
|
||||
private void update_selection () {
|
||||
|
|
|
@ -1,73 +0,0 @@
|
|||
using Gtk;
|
||||
|
||||
public class Tootle.HeaderBar : Gtk.HeaderBar{
|
||||
|
||||
public Granite.Widgets.ModeButton button_mode;
|
||||
AccountsButton button_accounts;
|
||||
Spinner spinner;
|
||||
Button button_toot;
|
||||
Button button_back;
|
||||
|
||||
private int last_tab = 0;
|
||||
|
||||
construct {
|
||||
spinner = new Spinner ();
|
||||
spinner.active = true;
|
||||
|
||||
button_accounts = new AccountsButton ();
|
||||
|
||||
button_back = new Button ();
|
||||
button_back.label = _("Back");
|
||||
button_back.get_style_context ().add_class (Granite.STYLE_CLASS_BACK_BUTTON);
|
||||
button_back.clicked.connect (() => {
|
||||
var primary_stack = Tootle.window.primary_stack;
|
||||
var i = int.parse (primary_stack.get_visible_child_name ());
|
||||
primary_stack.set_visible_child_name ((i-1).to_string ());
|
||||
|
||||
var child = primary_stack.get_child_by_name (i.to_string ());
|
||||
child.destroy ();
|
||||
|
||||
var is_root = primary_stack.get_visible_child_name () == "0";
|
||||
update (is_root);
|
||||
});
|
||||
|
||||
button_toot = new Button ();
|
||||
button_toot.tooltip_text = "Toot";
|
||||
button_toot.image = new Gtk.Image.from_icon_name ("document-edit-symbolic", Gtk.IconSize.LARGE_TOOLBAR);
|
||||
button_toot.clicked.connect (() => PostDialog.open ());
|
||||
|
||||
button_mode = new Granite.Widgets.ModeButton ();
|
||||
button_mode.get_style_context ().add_class ("mode");
|
||||
button_mode.mode_changed.connect(widget => {
|
||||
last_tab = button_mode.selected;
|
||||
Tootle.window.secondary_stack.set_visible_child_name(widget.tooltip_text);
|
||||
});
|
||||
button_mode.show ();
|
||||
|
||||
Tootle.network.started.connect (() => spinner.show ());
|
||||
Tootle.network.finished.connect (() => spinner.hide ());
|
||||
|
||||
pack_start (button_back);
|
||||
pack_start (button_toot);
|
||||
pack_end (button_accounts);
|
||||
pack_end (spinner);
|
||||
}
|
||||
|
||||
public HeaderBar () {
|
||||
custom_title = button_mode;
|
||||
show_close_button = true;
|
||||
show ();
|
||||
button_mode.valign = Gtk.Align.FILL;
|
||||
}
|
||||
|
||||
public void update (bool primary_mode){
|
||||
button_mode.set_active (last_tab);
|
||||
//button_mode.opacity = primary_mode ? 1 : 0;
|
||||
//button_mode.sensitive = primary_mode ? true : false;
|
||||
button_mode.set_visible (primary_mode);
|
||||
button_toot.set_visible (primary_mode);
|
||||
button_back.set_visible (!primary_mode);
|
||||
button_accounts.set_visible (true);
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue