mirror of
https://github.com/TakeV-Lambda/Tooth.git
synced 2024-10-02 23:39:08 +00:00
169 lines
4.5 KiB
Vala
169 lines
4.5 KiB
Vala
using Gtk;
|
|
using Gdk;
|
|
|
|
public class Tootle.Views.Timeline : IAccountListener, IStreamListener, Views.Base {
|
|
|
|
public string timeline { get; construct set; }
|
|
public bool is_public { get; construct set; default = false; }
|
|
|
|
protected InstanceAccount? account = null;
|
|
protected int limit = 25;
|
|
protected bool is_last_page = false;
|
|
protected string? page_next;
|
|
protected string? page_prev;
|
|
protected string? stream;
|
|
|
|
construct {
|
|
app.refresh.connect (on_refresh);
|
|
status_button.clicked.connect (on_refresh);
|
|
connect_account ();
|
|
|
|
on_status_added.connect (add_status);
|
|
on_status_removed.connect (remove_status);
|
|
}
|
|
~Timeline () {
|
|
streams.unsubscribe (stream, this);
|
|
}
|
|
|
|
public virtual bool is_status_owned (API.Status status) {
|
|
return status.is_owned ();
|
|
}
|
|
|
|
public virtual GLib.Object? to_entity (Json.Object? json) {
|
|
return new API.Status (json);
|
|
}
|
|
|
|
public virtual Widget? widgetize (GLib.Object? entity) {
|
|
var status = entity as API.Status;
|
|
if (status == null)
|
|
return null;
|
|
|
|
var w = new Widgets.Status (status);
|
|
w.button_press_event.connect (w.open);
|
|
if (!is_status_owned (status))
|
|
w.avatar.button_press_event.connect (w.on_avatar_clicked);
|
|
|
|
return w;
|
|
}
|
|
|
|
public void prepend (Widget? w) {
|
|
append (w, true);
|
|
}
|
|
|
|
public virtual void append (Widget? w, bool first = false) {
|
|
if (w == null)
|
|
return;
|
|
|
|
content.pack_start (w, false, false, 0);
|
|
if (first)
|
|
content.reorder_child (w, 0);
|
|
on_content_changed ();
|
|
}
|
|
|
|
public override void clear () {
|
|
this.page_prev = null;
|
|
this.page_next = null;
|
|
this.is_last_page = 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_url () {
|
|
if (page_next != null)
|
|
return page_next;
|
|
|
|
return @"/api/v1/timelines/$timeline";
|
|
}
|
|
|
|
public virtual Request append_params (Request req) {
|
|
return req.with_param ("limit", limit.to_string ());
|
|
}
|
|
|
|
public virtual bool request () {
|
|
append_params (new Request.GET (get_url ()))
|
|
.with_account (account)
|
|
.then_parse_array ((node, msg) => {
|
|
var obj = node.get_object ();
|
|
if (obj == null)
|
|
warning ("Received invalid Json.Object");
|
|
else {
|
|
var entity = to_entity (obj);
|
|
if (entity == null)
|
|
warning ("Can't convert Json.Object to required entity");
|
|
else
|
|
append (widgetize (entity));
|
|
}
|
|
get_pages (msg.response_headers.get_one ("Link"));
|
|
})
|
|
.on_error (on_error)
|
|
.exec ();
|
|
return GLib.Source.REMOVE;
|
|
}
|
|
|
|
public virtual void on_refresh () {
|
|
status_button.sensitive = false;
|
|
clear ();
|
|
status_message = STATUS_LOADING;
|
|
GLib.Idle.add (request);
|
|
}
|
|
|
|
public virtual string? get_stream_url () {
|
|
return null;
|
|
}
|
|
|
|
public virtual void on_account_changed (InstanceAccount? acc) {
|
|
account = acc;
|
|
streams.unsubscribe (stream, this);
|
|
streams.subscribe (get_stream_url (), this, out stream);
|
|
on_refresh ();
|
|
}
|
|
|
|
protected override void on_bottom_reached () {
|
|
if (is_last_page) {
|
|
info ("Last page reached");
|
|
return;
|
|
}
|
|
request ();
|
|
}
|
|
|
|
protected virtual void add_status (API.Status status) {
|
|
var allow_update = true;
|
|
if (is_public)
|
|
allow_update = settings.public_live_updates;
|
|
|
|
if (settings.live_updates && allow_update)
|
|
prepend (widgetize (status));
|
|
}
|
|
|
|
protected virtual void remove_status (int64 id) {
|
|
if (settings.live_updates) {
|
|
content.get_children ().@foreach (w => {
|
|
var sw = w as Widgets.Status;
|
|
if (sw != null && sw.status.id == id)
|
|
sw.destroy ();
|
|
});
|
|
}
|
|
}
|
|
|
|
}
|