This commit is contained in:
bleakgrey 2018-05-05 18:38:01 +03:00
parent fc5b92257f
commit ce6c0f8760
16 changed files with 83 additions and 77 deletions

View File

@ -1,4 +1,4 @@
public class Tootle.Status{ public class Tootle.Status {
public abstract signal void updated (); public abstract signal void updated ();

View File

@ -6,7 +6,7 @@ public class Tootle.AccountManager : Object{
public abstract signal void added(Account account); public abstract signal void added(Account account);
public abstract signal void removed(Account account); public abstract signal void removed(Account account);
public Account current; public Account? current;
public AccountManager(){ public AccountManager(){
Object(); Object();

View File

@ -13,8 +13,9 @@ namespace Tootle{
public class Application : Granite.Application { public class Application : Granite.Application {
public abstract signal void toast(string title); public abstract signal void refresh ();
public abstract signal void error(string title, string text); public abstract signal void toast (string title);
public abstract signal void error (string title, string text);
construct { construct {
application_id = "com.github.bleakgrey.tootle"; application_id = "com.github.bleakgrey.tootle";

View File

@ -3,10 +3,10 @@ using GLib;
public class Tootle.CacheManager : GLib.Object{ public class Tootle.CacheManager : GLib.Object{
private static string path_images; private static string path_downloads;
construct{ construct{
path_images = GLib.Environment.get_user_special_dir (UserDirectory.DOWNLOAD); path_downloads = GLib.Environment.get_user_special_dir (UserDirectory.DOWNLOAD);
} }
//TODO: actually cache images //TODO: actually cache images
@ -23,7 +23,7 @@ public class Tootle.CacheManager : GLib.Object{
loader.close(); loader.close();
avatar.pixbuf = loader.get_pixbuf (); avatar.pixbuf = loader.get_pixbuf ();
}); });
Tootle.network.queue(msg, (sess, mess) => {}); Tootle.network.queue(msg);
} }
public void load_image (string url, Gtk.Image image){ public void load_image (string url, Gtk.Image image){
@ -34,7 +34,7 @@ public class Tootle.CacheManager : GLib.Object{
loader.close(); loader.close();
image.set_from_pixbuf (loader.get_pixbuf ()); image.set_from_pixbuf (loader.get_pixbuf ());
}); });
Tootle.network.queue(msg, (sess, mess) => {}); Tootle.network.queue(msg);
} }
} }

View File

@ -137,7 +137,7 @@ public class Tootle.PostDialog : Gtk.Dialog {
try{ try{
var root = Tootle.network.parse (mess); var root = Tootle.network.parse (mess);
var status = Status.parse (root); var status = Status.parse (root);
Tootle.window.home.prepend (status); debug (status.id.to_string ()); //TODO: Live updates
this.destroy (); this.destroy ();
} }
catch (GLib.Error e) { catch (GLib.Error e) {

View File

@ -8,11 +8,6 @@ public class Tootle.MainWindow: Gtk.Window {
public Stack primary_stack; public Stack primary_stack;
public Stack secondary_stack; public Stack secondary_stack;
public HomeView home = new HomeView ();
public LocalView feed_local = new LocalView ();
public FederatedView feed_federated = new FederatedView ();
public NotificationsView notifications = new NotificationsView ();
construct { construct {
var provider = new Gtk.CssProvider (); var provider = new Gtk.CssProvider ();
provider.load_from_resource ("/com/github/bleakgrey/tootle/Application.css"); provider.load_from_resource ("/com/github/bleakgrey/tootle/Application.css");
@ -57,45 +52,45 @@ public class Tootle.MainWindow: Gtk.Window {
Tootle.accounts.init (); Tootle.accounts.init ();
} }
private void on_account_switched(Account? account){ private void reset () {
secondary_stack.forall (widget => secondary_stack.remove (widget)); header.button_mode.clear_children ();
secondary_stack.forall (widget => widget.destroy ());
if(account == null)
show_setup_views ();
else
show_main_views ();
} }
private void show_setup_views (){ private void on_account_switched(Account? account = Tootle.accounts.current){
reset ();
if(account == null)
build_setup_view ();
else
build_main_view ();
}
private void build_setup_view (){
var add_account = new AddAccountView (); var add_account = new AddAccountView ();
secondary_stack.add_named (add_account, add_account.get_name ()); secondary_stack.add_named (add_account, add_account.get_name ());
header.update (false, true); header.update (false, true);
} }
private void show_main_views (){ private void build_main_view (){
header.button_mode.clear_children (); add_header_view (new HomeView ());
add_view (home); add_header_view (new NotificationsView ());
add_view (notifications); add_header_view (new LocalView ());
add_view (feed_local); add_header_view (new FederatedView ());
add_view (feed_federated);
header.button_mode.set_active (0);
header.update (true); header.update (true);
} }
private void add_view (AbstractView view) { private void add_header_view (AbstractView view) {
if (view.show_in_header){ var img = new Gtk.Image.from_icon_name(view.get_icon (), Gtk.IconSize.LARGE_TOOLBAR);
var img = new Gtk.Image.from_icon_name(view.get_icon (), Gtk.IconSize.LARGE_TOOLBAR); img.tooltip_text = view.get_name ();
img.tooltip_text = view.get_name (); header.button_mode.append (img);
header.button_mode.append (img); view.image = img;
view.image = img; secondary_stack.add_named(view, view.get_name ());
secondary_stack.add_named(view, view.get_name ());
if (view is NotificationsView) if (view is NotificationsView)
img.pixel_size = 20; // For some reason Notifications icon is too small without this img.pixel_size = 20; // For some reason Notifications icon is too small without this
}
} }
public void open_secondary_view (Widget widget) { public void open_view (Widget widget) {
widget.show (); widget.show ();
var i = int.parse (primary_stack.get_visible_child_name ()); var i = int.parse (primary_stack.get_visible_child_name ());
i++; i++;

View File

@ -6,7 +6,6 @@ public class Tootle.NetManager : GLib.Object {
public abstract signal void started(); public abstract signal void started();
public abstract signal void finished(); public abstract signal void finished();
public abstract signal void refresh();
private int requests_processing = 0; private int requests_processing = 0;
private Soup.Session session; private Soup.Session session;
@ -16,11 +15,15 @@ public class Tootle.NetManager : GLib.Object {
session.ssl_strict = true; session.ssl_strict = true;
session.ssl_use_system_ca_file = true; session.ssl_use_system_ca_file = true;
session.timeout = 20; session.timeout = 20;
session.max_conns = 15;
session.request_unqueued.connect (() => { session.request_unqueued.connect (() => {
requests_processing--; requests_processing--;
if(requests_processing <= 0) if(requests_processing <= 0)
finished (); finished ();
}); });
// Soup.Logger logger = new Soup.Logger (Soup.LoggerLogLevel.MINIMAL, -1);
// session.add_feature (logger);
} }
public NetManager() { public NetManager() {

View File

@ -3,7 +3,6 @@ using Gtk;
public abstract class Tootle.AbstractView : Gtk.ScrolledWindow { public abstract class Tootle.AbstractView : Gtk.ScrolledWindow {
public int64 max_id = -1; public int64 max_id = -1;
public bool show_in_header;
public Gtk.Image image; public Gtk.Image image;
public Gtk.Box view; public Gtk.Box view;
@ -21,8 +20,7 @@ public abstract class Tootle.AbstractView : Gtk.ScrolledWindow {
pre_construct (); pre_construct ();
} }
public AbstractView (bool show) { public AbstractView () {
show_in_header = show;
show_all (); show_all ();
} }

View File

@ -99,7 +99,6 @@ public class Tootle.AccountView : Tootle.HomeView {
} }
public AccountView (Account acc) { public AccountView (Account acc) {
base ("account_"+acc.id.to_string ());
account = acc; account = acc;
account.updated.connect(rebind); account.updated.connect(rebind);
@ -177,16 +176,20 @@ public class Tootle.AccountView : Tootle.HomeView {
return status.get_formal ().account.id == account.id; return status.get_formal ().account.id == account.id;
} }
public override string get_url (){ public override string get_url () {
var url = "%s/api/v1/accounts/%lld/statuses".printf (Tootle.settings.instance_url, account.id); var url = "%s/api/v1/accounts/%lld/statuses".printf (Tootle.settings.instance_url, account.id);
url += "?limit=25"; url += "?limit=25";
if (max_id > 0) if (max_id > 0)
url += "&max_id=" + max_id.to_string (); url += "&max_id=" + max_id.to_string ();
return url; return url;
} }
public override void request (){
if(account != null)
base.request ();
}
public static void open_from_id (int64 id){ public static void open_from_id (int64 id){
var url = "%s/api/v1/accounts/%lld".printf (Tootle.settings.instance_url, id); var url = "%s/api/v1/accounts/%lld".printf (Tootle.settings.instance_url, id);
var msg = new Soup.Message("GET", url); var msg = new Soup.Message("GET", url);
@ -195,7 +198,7 @@ public class Tootle.AccountView : Tootle.HomeView {
try{ try{
var root = Tootle.network.parse (mess); var root = Tootle.network.parse (mess);
var acc = Account.parse (root); var acc = Account.parse (root);
Tootle.window.open_secondary_view (new AccountView (acc)); Tootle.window.open_view (new AccountView (acc));
} }
catch (GLib.Error e) { catch (GLib.Error e) {
warning ("Can't update feed"); warning ("Can't update feed");
@ -214,7 +217,7 @@ public class Tootle.AccountView : Tootle.HomeView {
var object = node.get_object (); var object = node.get_object ();
if (object != null){ if (object != null){
var acc = Account.parse(object); var acc = Account.parse(object);
Tootle.window.open_secondary_view (new AccountView (acc)); Tootle.window.open_view (new AccountView (acc));
} }
else else
warning ("No results found for account: "+name); //TODO: toast notifications warning ("No results found for account: "+name); //TODO: toast notifications

View File

@ -110,7 +110,7 @@ public class Tootle.AddAccountView : Tootle.AbstractView {
} }
public AddAccountView () { public AddAccountView () {
base (false); base ();
} }
public override string get_name () { public override string get_name () {

View File

@ -6,16 +6,17 @@ public class Tootle.HomeView : Tootle.AbstractView {
private string timeline; private string timeline;
public HomeView (string timeline = "home") { public HomeView (string timeline = "home") {
base (true); base ();
this.timeline = timeline; this.timeline = timeline;
view.remove.connect (on_remove); view.remove.connect (on_remove);
Tootle.accounts.switched.connect(on_account_changed); Tootle.accounts.switched.connect(on_account_changed);
Tootle.network.refresh.connect(on_refresh); Tootle.app.refresh.connect(on_refresh);
// var s = new Status(1); // var s = new Status(1);
// s.content = "Test content, wow!"; // s.content = "Test content, wow!";
// prepend (s); // prepend (s);
request ();
} }
public override string get_icon () { public override string get_icon () {
@ -50,7 +51,7 @@ public class Tootle.HomeView : Tootle.AbstractView {
//TODO: empty state //TODO: empty state
} }
public virtual string get_url (){ public virtual string get_url () {
var url = Tootle.settings.instance_url; var url = Tootle.settings.instance_url;
url += "api/v1/timelines/"; url += "api/v1/timelines/";
url += this.timeline; url += this.timeline;
@ -62,7 +63,7 @@ public class Tootle.HomeView : Tootle.AbstractView {
return url; return url;
} }
public void request (){ public virtual void request (){
var msg = new Soup.Message("GET", get_url ()); var msg = new Soup.Message("GET", get_url ());
Tootle.network.queue(msg, (sess, mess) => { Tootle.network.queue(msg, (sess, mess) => {
try{ try{
@ -90,8 +91,8 @@ public class Tootle.HomeView : Tootle.AbstractView {
public virtual void on_account_changed (Account? account){ public virtual void on_account_changed (Account? account){
if(account == null) if(account == null)
return; return;
clear ();
request (); on_refresh ();
} }
public override void bottom_reached (){ public override void bottom_reached (){

View File

@ -4,11 +4,13 @@ using Gdk;
public class Tootle.NotificationsView : Tootle.AbstractView { public class Tootle.NotificationsView : Tootle.AbstractView {
public NotificationsView () { public NotificationsView () {
base (true); base ();
view.remove.connect (on_remove); view.remove.connect (on_remove);
Tootle.accounts.switched.connect(on_account_changed); Tootle.accounts.switched.connect(on_account_changed);
Tootle.network.refresh.connect(on_refresh); Tootle.app.refresh.connect(on_refresh);
request ();
} }
public override string get_icon () { public override string get_icon () {
@ -47,8 +49,7 @@ public class Tootle.NotificationsView : Tootle.AbstractView {
if(account == null) if(account == null)
return; return;
clear (); on_refresh ();
request ();
} }
public void request (){ public void request (){

View File

@ -6,7 +6,7 @@ public class Tootle.StatusView : Tootle.AbstractView {
bool last_was_a_root = false; bool last_was_a_root = false;
public StatusView (Status status) { public StatusView (Status status) {
base (false); base ();
root_status = status; root_status = status;
request_context (); request_context ();
} }

View File

@ -54,11 +54,11 @@ public class Tootle.AccountsButton : Gtk.MenuButton{
item_refresh = new Gtk.ModelButton (); item_refresh = new Gtk.ModelButton ();
item_refresh.text = _("Refresh"); item_refresh.text = _("Refresh");
item_refresh.clicked.connect (() => Tootle.network.refresh ()); item_refresh.clicked.connect (() => Tootle.app.refresh ());
item_favs = new Gtk.ModelButton (); item_favs = new Gtk.ModelButton ();
item_favs.text = _("Favorites"); item_favs.text = _("Favorites");
item_favs.clicked.connect (() => Tootle.window.open_secondary_view (new FavoritesView ())); item_favs.clicked.connect (() => Tootle.window.open_view (new FavoritesView ()));
item_settings = new Gtk.ModelButton (); item_settings = new Gtk.ModelButton ();
item_settings.text = _("Settings"); item_settings.text = _("Settings");

View File

@ -8,6 +8,8 @@ public class Tootle.HeaderBar : Gtk.HeaderBar{
Button button_toot; Button button_toot;
Button button_back; Button button_back;
private int last_tab = 0;
construct { construct {
spinner = new Spinner (); spinner = new Spinner ();
spinner.active = true; spinner.active = true;
@ -39,6 +41,7 @@ public class Tootle.HeaderBar : Gtk.HeaderBar{
button_mode = new Granite.Widgets.ModeButton (); button_mode = new Granite.Widgets.ModeButton ();
button_mode.get_style_context ().add_class ("mode"); button_mode.get_style_context ().add_class ("mode");
button_mode.mode_changed.connect(widget => { button_mode.mode_changed.connect(widget => {
last_tab = button_mode.selected;
Tootle.window.secondary_stack.set_visible_child_name(widget.tooltip_text); Tootle.window.secondary_stack.set_visible_child_name(widget.tooltip_text);
}); });
button_mode.show (); button_mode.show ();
@ -60,6 +63,7 @@ public class Tootle.HeaderBar : Gtk.HeaderBar{
} }
public void update (bool primary_mode, bool hide_all = false){ public void update (bool primary_mode, bool hide_all = false){
button_mode.set_active (last_tab);
if (hide_all){ if (hide_all){
button_mode.opacity = 0; button_mode.opacity = 0;
button_mode.sensitive = false; button_mode.sensitive = false;

View File

@ -120,7 +120,7 @@ public class Tootle.StatusWidget : Gtk.EventBox {
status.updated.connect (rebind); status.updated.connect (rebind);
get_style_context ().add_class ("status"); get_style_context ().add_class ("status");
if (status.reblog != null){ if (status.reblog != null) {
var image = new Gtk.Image.from_icon_name("go-up-symbolic", Gtk.IconSize.SMALL_TOOLBAR); var image = new Gtk.Image.from_icon_name("go-up-symbolic", Gtk.IconSize.SMALL_TOOLBAR);
image.halign = Gtk.Align.END; image.halign = Gtk.Align.END;
image.margin_end = 6; image.margin_end = 6;
@ -137,7 +137,7 @@ public class Tootle.StatusWidget : Gtk.EventBox {
grid.attach (label, 2, 0, 2, 1); grid.attach (label, 2, 0, 2, 1);
} }
if (is_spoiler ()){ if (is_spoiler ()) {
revealer.reveal_child = false; revealer.reveal_child = false;
var spoiler_box = new Box (Gtk.Orientation.HORIZONTAL, 6); var spoiler_box = new Box (Gtk.Orientation.HORIZONTAL, 6);
spoiler_box.margin_end = 12; spoiler_box.margin_end = 12;
@ -184,12 +184,12 @@ public class Tootle.StatusWidget : Gtk.EventBox {
rebind (); rebind ();
} }
public void highlight (){ public void highlight () {
grid.get_style_context ().add_class ("card"); grid.get_style_context ().add_class ("card");
grid.margin_bottom = 6; grid.margin_bottom = 6;
} }
public void rebind (){ public void rebind () {
title_user.label = "<b>%s</b>".printf (status.get_formal ().account.display_name); title_user.label = "<b>%s</b>".printf (status.get_formal ().account.display_name);
title_acct.label = "@" + status.account.acct; title_acct.label = "@" + status.account.acct;
content_label.label = status.content; content_label.label = status.content;
@ -209,13 +209,13 @@ public class Tootle.StatusWidget : Gtk.EventBox {
Tootle.cache.load_avatar (status.get_formal ().account.avatar, this.avatar, this.avatar_size); Tootle.cache.load_avatar (status.get_formal ().account.avatar, this.avatar, this.avatar_size);
} }
public bool is_spoiler (){ public bool is_spoiler () {
return status.spoiler_text != null || status.sensitive; return status.spoiler_text != null || status.sensitive;
} }
// elementary OS has old GLib, so I have to improvise // elementary OS has old GLib, so I have to improvise
// Version >=2.56 provides DateTime.from_iso8601 // Version >=2.56 provides DateTime.from_iso8601
public void parse_date_iso8601 (string date){ public void parse_date_iso8601 (string date) {
var cmd = "date -d " + date + " +%s"; var cmd = "date -d " + date + " +%s";
var runner = new CmdRunner ("/bin/", cmd); //Workaround for Granite SimpleCommand pipes bug var runner = new CmdRunner ("/bin/", cmd); //Workaround for Granite SimpleCommand pipes bug
runner.done.connect (exit => { runner.done.connect (exit => {
@ -226,19 +226,19 @@ public class Tootle.StatusWidget : Gtk.EventBox {
runner.run (); runner.run ();
} }
public bool on_avatar_clicked (){ public bool on_avatar_clicked () {
var view = new AccountView (status.get_formal ().account); var view = new AccountView (status.get_formal ().account);
Tootle.window.open_secondary_view (view); Tootle.window.open_view (view);
return true; return true;
} }
public bool open (){ public bool open () {
var view = new StatusView (status.get_formal ()); var view = new StatusView (status.get_formal ());
Tootle.window.open_secondary_view (view); Tootle.window.open_view (view);
return false; return false;
} }
private Gtk.ToggleButton get_action_button (string icon_path){ private Gtk.ToggleButton get_action_button (string icon_path) {
var icon = new Gtk.Image.from_icon_name (icon_path, Gtk.IconSize.SMALL_TOOLBAR); var icon = new Gtk.Image.from_icon_name (icon_path, Gtk.IconSize.SMALL_TOOLBAR);
var button = new Gtk.ToggleButton (); var button = new Gtk.ToggleButton ();
button.can_default = false; button.can_default = false;