tootle-linux-client/src/Views/Timeline.vala

160 lines
3.6 KiB
Vala

using Gtk;
using Gdk;
public class Tootle.Views.Timeline : AccountHolder, Streamable, Views.ContentBase {
public string url { get; construct set; }
public bool is_public { get; construct set; default = false; }
public Type accepts { get; set; default = typeof (API.Status); }
protected InstanceAccount? account { get; set; default = null; }
public bool is_last_page { get; set; default = false; }
public string? page_next { get; set; }
public string? page_prev { get; set; }
construct {
app.refresh.connect (on_refresh);
status_button.clicked.connect (on_refresh);
construct_account_holder ();
construct_streamable ();
stream_event[InstanceAccount.EVENT_NEW_POST].connect (on_new_post);
stream_event[InstanceAccount.EVENT_DELETE_POST].connect (on_delete_post);
content.bind_model (model, on_create_model_widget);
}
~Timeline () {
destruct_account_holder ();
destruct_streamable ();
content.bind_model (null, null);
}
public virtual bool is_status_owned (API.Status status) {
return status.is_owned ();
}
public override void clear () {
this.page_prev = null;
this.page_next = null;
this.is_last_page = false;
this.needs_attention = false;
base.clear ();
}
public void get_pages (string? header) {
page_next = page_prev = null;
if (header == null)
return;
var pages = header.split (",");
foreach (var page in pages) {
var sanitized = page
.replace ("<","")
.replace (">", "")
.split (";")[0];
if ("rel=\"prev\"" in page)
page_prev = sanitized;
else
page_next = sanitized;
}
is_last_page = page_prev != null & page_next == null;
}
public virtual string get_req_url () {
if (page_next != null)
return page_next;
return url;
}
public virtual Request append_params (Request req) {
if (page_next == null)
return req.with_param ("limit", @"$(settings.timeline_page_size)");
else
return req;
}
public virtual void on_request_finish () {}
public virtual bool request () {
var req = append_params (new Request.GET (get_req_url ()))
.with_account (account)
.with_ctx (this)
.then ((sess, msg) => {
Network.parse_array (msg, node => {
try {
var e = entity_cache.lookup_or_insert (node, accepts);
model.append (e); //FIXME: use splice();
}
catch (Error e) {
warning (@"Timeline item parse error: $(e.message)");
}
});
get_pages (msg.response_headers.get_one ("Link"));
on_content_changed ();
on_request_finish ();
})
.on_error (on_error);
req.exec ();
return GLib.Source.REMOVE;
}
public virtual void on_refresh () {
scrolled.vadjustment.value = 0;
status_button.sensitive = false;
clear ();
status_message = STATUS_LOADING;
GLib.Idle.add (request);
}
protected virtual void on_account_changed (InstanceAccount? acc) {
account = acc;
update_stream ();
on_refresh ();
}
protected override void on_bottom_reached () {
if (is_last_page) {
info ("Last page reached");
return;
}
request ();
}
// Streamable
public string? connection_url { get; set; }
public bool subscribed { get; set; }
protected override void on_streaming_policy_changed () {
var allow_streaming = settings.live_updates;
if (is_public)
allow_streaming = allow_streaming && settings.public_live_updates;
subscribed = allow_streaming;
}
public virtual string? get_stream_url () {
return null;
}
public virtual void on_new_post (Streamable.Event ev) {
var entity = Entity.from_json (accepts, ev.get_node ());
model.insert (0, entity);
}
public virtual void on_delete_post (Streamable.Event ev) {
//TODO: This
}
}