Continuous scrolling

This commit is contained in:
bleakgrey 2018-04-26 17:05:03 +03:00
parent 67a5ac06f0
commit e138d83150
7 changed files with 94 additions and 29 deletions

View File

@ -2,6 +2,7 @@ using Gtk;
public abstract class Tootle.AbstractView : Gtk.ScrolledWindow {
public int64 max_id = -1;
public bool show_in_header;
public Gtk.Image image;
public Gtk.Box view;
@ -10,6 +11,13 @@ public abstract class Tootle.AbstractView : Gtk.ScrolledWindow {
view = new Gtk.Box (Gtk.Orientation.VERTICAL, 0);
hscrollbar_policy = Gtk.PolicyType.NEVER;
add (view);
edge_reached.connect(pos => {
if (pos == Gtk.PositionType.BOTTOM)
bottom_reached ();
});
pre_construct ();
}
public AbstractView (bool show) {
@ -25,4 +33,15 @@ public abstract class Tootle.AbstractView : Gtk.ScrolledWindow {
return "unnamed";
}
public void clear (){
max_id = -1;
view.forall (widget => view.remove (widget));
pre_construct ();
}
public virtual void pre_construct () {}
public virtual void bottom_reached (){}
}

View File

@ -1,7 +1,7 @@
using Gtk;
using Granite;
public class Tootle.AccountView : Tootle.AbstractView {
public class Tootle.AccountView : Tootle.HomeView {
Account account;
@ -13,7 +13,7 @@ public class Tootle.AccountView : Tootle.AbstractView {
Gtk.Label note;
Gtk.Grid counters;
construct {
public override void pre_construct () {
header = new Gtk.Grid ();
avatar = new Granite.Widgets.Avatar.with_default_icon (128);
@ -51,8 +51,8 @@ public class Tootle.AccountView : Tootle.AbstractView {
view.pack_start (header, false, false, 0);
}
public AccountView (Account acc){
base (false);
public AccountView (Account acc) {
base ("account_"+acc.id.to_string ());
account = acc;
display_name.label = account.display_name;
@ -68,13 +68,29 @@ public class Tootle.AccountView : Tootle.AbstractView {
var stylesheet = ".header{background-image: url(\"%s\")}".printf (account.header);
var css_provider = Granite.Widgets.Utils.get_css_provider (stylesheet);
header_image.get_style_context ().add_provider (css_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
request ();
}
private void add_counter (string name, int i, int64 val){
private void add_counter (string name, int i, int64 val) {
var label_name = new Gtk.Label (name);
var label_val = new Gtk.Label (val.to_string ());
counters.attach (label_name, i, 1, 1, 1);
counters.attach (label_val, i, 2, 1, 1);
}
public override bool is_status_owned (Status status){
return status.account.id == account.id;
}
public override string get_url (){
var url = "%s/api/v1/accounts/%lld/statuses".printf (Settings.instance.instance_url, account.id);
url += "?limit=25";
if (max_id > 0)
url += "&max_id=" + max_id.to_string ();
return url;
}
}

View File

@ -4,12 +4,10 @@ using Gdk;
public class Tootle.HomeView : Tootle.AbstractView {
private string timeline;
private string pars;
public HomeView (string timeline = "home", string pars = "") {
public HomeView (string timeline = "home") {
base (true);
this.timeline = timeline;
this.pars = pars;
view.remove.connect (on_remove);
AccountManager.instance.switched.connect(on_account_changed);
@ -24,22 +22,23 @@ public class Tootle.HomeView : Tootle.AbstractView {
}
public override string get_name () {
return "Home Timeline";
return "Home";
}
public void prepend(Status status){ //TODO: clear all on account switch
public virtual bool is_status_owned (Status status){
return false;
}
public void prepend(Status status){
var separator = new Gtk.Separator (Gtk.Orientation.HORIZONTAL);
separator.show ();
var widget = new StatusWidget(status);
widget.separator = separator;
widget.rebind (status);
widget.button_press_event.connect(() => {
var open_status = status.reblog != null ? status.reblog : status;
var view = new StatusView (open_status);
Tootle.window.open_secondary_view (view);
return false;
});
widget.button_press_event.connect(widget.open);
if (!is_status_owned (status))
widget.avatar.button_press_event.connect(widget.on_avatar_clicked);
view.pack_start(separator, false, false, 0);
view.pack_start(widget, false, false, 0);
}
@ -48,25 +47,30 @@ public class Tootle.HomeView : Tootle.AbstractView {
if (!(widget is StatusWidget))
return;
//debug ("removed");
//TODO: empty state
}
public virtual void on_account_changed (Account? account){
if(account == null)
return;
public virtual string get_url (){
var url = Settings.instance.instance_url;
url += "api/v1/timelines/";
url += this.timeline;
url += this.pars;
url += "?limit=25";
var msg = new Soup.Message("GET", url);
if (max_id > 0)
url += "&max_id=" + max_id.to_string ();
return url;
}
public void request (){
var msg = new Soup.Message("GET", get_url ());
NetManager.instance.queue(msg, (sess, mess) => {
try{
NetManager.parse_array (mess).foreach_element ((array, i, node) => {
var object = node.get_object ();
if (object != null){
var status = Status.parse(object);
max_id = status.id;
prepend (status);
}
});
@ -77,5 +81,17 @@ public class Tootle.HomeView : Tootle.AbstractView {
}
});
}
public virtual void on_account_changed (Account? account){
if(account == null)
return;
clear ();
request ();
}
public override void bottom_reached (){
request ();
}
}

View File

@ -3,7 +3,7 @@ using Gtk;
public class Tootle.LocalView : Tootle.HomeView {
public LocalView () {
base ("public", "?local=true");
base ("public");
}
public override string get_icon () {
@ -13,5 +13,11 @@ public class Tootle.LocalView : Tootle.HomeView {
public override string get_name () {
return "Local Timeline";
}
public override string get_url (){
string url = base.get_url ();
url += "&local=true";
return url;
}
}

View File

@ -22,6 +22,7 @@ public class Tootle.StatusView : Tootle.AbstractView {
widget.content.selectable = true;
if (widget.spoiler_content != null)
widget.spoiler_content.selectable = true;
widget.avatar.button_press_event.connect(widget.on_avatar_clicked);
view.pack_start (widget, false, false, 0);
}

View File

@ -45,6 +45,8 @@ public class Tootle.NotificationWidget : Gtk.Grid {
if (notification.status != null){
status_widget = new StatusWidget (this.notification.status);
status_widget.rebind (this.notification.status);
status_widget.button_press_event.connect(status_widget.open);
status_widget.avatar.button_press_event.connect(status_widget.on_avatar_clicked);
attach(status_widget, 1, 3, 3, 1);
}

View File

@ -29,12 +29,12 @@ public class Tootle.StatusWidget : Gtk.EventBox {
avatar = new Granite.Widgets.Avatar.with_default_icon (avatar_size);
avatar.valign = Gtk.Align.START;
avatar.margin_end = 6;
user = new Gtk.Label (_("Anonymous"));
user = new Gtk.Label ("");
user.hexpand = true;
user.halign = Gtk.Align.START;
user.use_markup = true;
content = new Gtk.Label (_("Error parsing text :c"));
content = new Gtk.Label ("");
content.halign = Gtk.Align.START;
content.use_markup = true;
content.single_line_mode = false;
@ -146,17 +146,22 @@ public class Tootle.StatusWidget : Gtk.EventBox {
var avatar_url = status.reblog != null ? status.reblog.account.avatar : status.account.avatar;
CacheManager.instance.load_avatar (avatar_url, this.avatar, this.avatar_size);
avatar.button_press_event.connect(on_avatar_clicked);
}
private bool on_avatar_clicked (){
public bool on_avatar_clicked (){
var account = status.reblog != null ? status.reblog.account : status.account;
var view = new AccountView (account);
Tootle.window.open_secondary_view (view);
return true;
}
public bool open (){
var open_status = status.reblog != null ? status.reblog : status;
var view = new StatusView (open_status);
Tootle.window.open_secondary_view (view);
return false;
}
private Gtk.ToggleButton get_action_button (string icon_path){
var icon = new Gtk.Image.from_icon_name (icon_path, Gtk.IconSize.SMALL_TOOLBAR);
var button = new Gtk.ToggleButton ();