mirror of
https://gitlab.gnome.org/World/tootle
synced 2025-02-17 03:51:11 +01:00
Convert NotificationsView into Timeline
This commit is contained in:
parent
7faca4090e
commit
d79023b605
@ -3,9 +3,6 @@ project('com.github.bleakgrey.tootle', 'vala', 'c')
|
||||
gnome = import('gnome')
|
||||
i18n = import('i18n')
|
||||
|
||||
#add_project_arguments(['--disable-warnings', '-g', '-X', '-rdynamic'], language: 'vala')
|
||||
#add_project_arguments(['-g', '-rdynamic', '-export-dynamic'], language: 'c')
|
||||
|
||||
add_global_arguments([
|
||||
'-DGETTEXT_PACKAGE="@0@"'.format(meson.project_name()),
|
||||
'-DHANDY_USE_UNSTABLE_API',
|
||||
@ -82,7 +79,6 @@ executable(
|
||||
dependency('libhandy-0.0', version: '>=0.0.13'),
|
||||
],
|
||||
install: true,
|
||||
link_args: '-export-dynamic'
|
||||
)
|
||||
|
||||
subdir('data')
|
||||
|
@ -45,6 +45,8 @@ public class Tootle.InstanceAccount : API.Account, IStreamListener {
|
||||
var notification = new API.Notification (node.get_object ());
|
||||
cached_notifications.add (notification);
|
||||
});
|
||||
|
||||
on_notification.connect (show_notification);
|
||||
}
|
||||
~InstanceAccount () {
|
||||
unsubscribe ();
|
||||
@ -119,7 +121,7 @@ public class Tootle.InstanceAccount : API.Account, IStreamListener {
|
||||
return builder.get_root ();
|
||||
}
|
||||
|
||||
public override void on_notification (API.Notification obj) {
|
||||
protected void show_notification (API.Notification obj) {
|
||||
var title = Html.remove_tags (obj.kind.get_desc (obj.account));
|
||||
var notification = new GLib.Notification (title);
|
||||
if (obj.status != null) {
|
||||
@ -139,12 +141,7 @@ public class Tootle.InstanceAccount : API.Account, IStreamListener {
|
||||
}
|
||||
}
|
||||
|
||||
// public override void on_status_removed (int64 id) {
|
||||
// if (is_current ())
|
||||
// streams.force_delete (id);
|
||||
// }
|
||||
|
||||
// public override void on_status_added (API.Status status) {
|
||||
// protected void on_status_added (API.Status status) { //TODO: Watchlist
|
||||
// if (!is_current ())
|
||||
// return;
|
||||
|
||||
|
@ -1,11 +1,7 @@
|
||||
public interface Tootle.IStreamListener : GLib.Object {
|
||||
|
||||
public virtual void on_status_removed (int64 id) {}
|
||||
public virtual void on_status_added (API.Status s) {}
|
||||
public virtual void on_notification (API.Notification n) {}
|
||||
|
||||
public virtual bool accepts (ref string event) {
|
||||
return true;
|
||||
}
|
||||
public signal void on_status_removed (int64 id);
|
||||
public signal void on_status_added (API.Status s);
|
||||
public signal void on_notification (API.Notification n);
|
||||
|
||||
}
|
||||
|
@ -144,24 +144,21 @@ public class Tootle.Streams : Object {
|
||||
case "update":
|
||||
var obj = new API.Status (sanitize (root));
|
||||
c.subscribers.@foreach (s => {
|
||||
if (s.accepts (ref e))
|
||||
s.on_status_added (obj);
|
||||
s.on_status_added (obj);
|
||||
return true;
|
||||
});
|
||||
break;
|
||||
case "delete":
|
||||
var id = int64.parse (root.get_string_member ("payload"));
|
||||
c.subscribers.@foreach (s => {
|
||||
if (s.accepts (ref e))
|
||||
s.on_status_removed (id);
|
||||
s.on_status_removed (id);
|
||||
return true;
|
||||
});
|
||||
break;
|
||||
case "notification":
|
||||
var obj = new API.Notification (sanitize (root));
|
||||
c.subscribers.@foreach (s => {
|
||||
if (s.accepts (ref e))
|
||||
s.on_notification (obj);
|
||||
s.on_notification (obj);
|
||||
return true;
|
||||
});
|
||||
break;
|
||||
|
@ -1,24 +1,17 @@
|
||||
using Gtk;
|
||||
using Gdk;
|
||||
|
||||
public class Tootle.Views.Notifications : Views.Base, IAccountListener, IStreamListener { //TODO: make this a timeline
|
||||
public class Tootle.Views.Notifications : Views.Timeline, IAccountListener, IStreamListener {
|
||||
|
||||
protected InstanceAccount? account = null;
|
||||
protected int64 last_id = 0;
|
||||
protected bool force_dot = false;
|
||||
|
||||
protected string? stream;
|
||||
|
||||
public Notifications () {
|
||||
app.refresh.connect (on_refresh);
|
||||
status_button.clicked.connect (on_refresh);
|
||||
connect_account ();
|
||||
}
|
||||
~Notifications () {
|
||||
streams.unsubscribe (stream, this);
|
||||
Object ();
|
||||
on_notification.connect (add_notification);
|
||||
}
|
||||
|
||||
private bool has_unread () {
|
||||
public bool has_unread () {
|
||||
if (account == null)
|
||||
return false;
|
||||
return last_id > account.last_seen_notification || force_dot;
|
||||
@ -35,35 +28,21 @@ public class Tootle.Views.Notifications : Views.Base, IAccountListener, IStreamL
|
||||
return _("Notifications");
|
||||
}
|
||||
|
||||
public void prepend (API.Notification notification) {
|
||||
append (notification, true);
|
||||
public override string? get_stream_url () {
|
||||
return account != null ? @"$(account.instance)/api/v1/streaming/?stream=user&access_token=$(account.token)" : null;
|
||||
}
|
||||
|
||||
public void append (API.Notification notification, bool reverse = false) {
|
||||
GLib.Idle.add (() => {
|
||||
var widget = new Widgets.Notification (notification);
|
||||
content.pack_start (widget, false, false, 0);
|
||||
public override string get_url () {
|
||||
if (page_next != null)
|
||||
return page_next;
|
||||
|
||||
if (reverse) {
|
||||
content.reorder_child (widget, 0);
|
||||
return "/api/v1/notifications";
|
||||
}
|
||||
|
||||
if (!current) {
|
||||
force_dot = true;
|
||||
accounts.active.has_unread_notifications = force_dot;
|
||||
}
|
||||
}
|
||||
|
||||
on_content_changed ();
|
||||
|
||||
if (notification.id > last_id)
|
||||
last_id = notification.id;
|
||||
|
||||
if (has_unread ()) {
|
||||
accounts.save ();
|
||||
image.icon_name = get_icon ();
|
||||
}
|
||||
return GLib.Source.REMOVE;
|
||||
});
|
||||
public override void on_content_changed () {
|
||||
base.on_content_changed ();
|
||||
if (image != null && empty)
|
||||
image.icon_name = get_icon ();
|
||||
}
|
||||
|
||||
public override void on_set_current () {
|
||||
@ -76,20 +55,43 @@ public class Tootle.Views.Notifications : Views.Base, IAccountListener, IStreamL
|
||||
}
|
||||
}
|
||||
|
||||
public override void on_content_changed () {
|
||||
base.on_content_changed ();
|
||||
if (image != null && empty)
|
||||
public override void append (Widget? w, bool reverse = false) {
|
||||
base.append (w, reverse);
|
||||
var nw = w as Widgets.Notification;
|
||||
var notification = nw.notification;
|
||||
|
||||
if (reverse && !current) {
|
||||
force_dot = true;
|
||||
accounts.active.has_unread_notifications = force_dot;
|
||||
}
|
||||
|
||||
if (notification.id > last_id)
|
||||
last_id = notification.id;
|
||||
|
||||
if (has_unread ()) {
|
||||
accounts.save ();
|
||||
image.icon_name = get_icon ();
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void on_refresh () {
|
||||
clear ();
|
||||
GLib.Idle.add (request);
|
||||
public override GLib.Object? to_entity (Json.Object? json) {
|
||||
if (json != null)
|
||||
return new API.Notification (json);
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
public virtual void on_account_changed (InstanceAccount? acc) {
|
||||
account = acc;
|
||||
streams.unsubscribe (stream, this);
|
||||
public override Widget? widgetize (GLib.Object? entity) {
|
||||
var n = entity as API.Notification;
|
||||
if (n == null)
|
||||
return null;
|
||||
|
||||
var w = new Widgets.Notification (n);
|
||||
return w;
|
||||
}
|
||||
|
||||
public override void on_account_changed (InstanceAccount? acc) {
|
||||
base.on_account_changed (acc);
|
||||
if (account == null) {
|
||||
last_id = 0;
|
||||
force_dot = false;
|
||||
@ -97,51 +99,21 @@ public class Tootle.Views.Notifications : Views.Base, IAccountListener, IStreamL
|
||||
else {
|
||||
last_id = account.last_seen_notification;
|
||||
force_dot = account.has_unread_notifications;
|
||||
streams.subscribe (get_stream_url (), this, out stream);
|
||||
}
|
||||
on_refresh ();
|
||||
}
|
||||
|
||||
public virtual string? get_stream_url () {
|
||||
return account != null ? @"$(account.instance)/api/v1/streaming/?stream=user&access_token=$(account.token)" : null;
|
||||
}
|
||||
|
||||
public override bool accepts (ref string event) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void on_notification (API.Notification n) {
|
||||
prepend (n);
|
||||
}
|
||||
|
||||
public bool request () {
|
||||
public override bool request () {
|
||||
if (account != null) {
|
||||
account.cached_notifications.@foreach (notification => {
|
||||
append (notification);
|
||||
account.cached_notifications.@foreach (n => {
|
||||
append (widgetize (n));
|
||||
return true;
|
||||
});
|
||||
}
|
||||
return base.request ();
|
||||
}
|
||||
|
||||
// new Request.GET ("/api/v1/follow_requests") //TODO: this
|
||||
// .with_account ()
|
||||
// .then_parse_array (node => {
|
||||
// var notification = API.Notification.parse_follow_request (node.get_object ());
|
||||
// append (notification);
|
||||
// })
|
||||
// .on_error (on_error)
|
||||
// .exec ();
|
||||
|
||||
new Request.GET ("/api/v1/notifications")
|
||||
.with_account (account)
|
||||
.with_param ("limit", "30")
|
||||
.then_parse_array (node => {
|
||||
var notification = new API.Notification (node.get_object ());
|
||||
append (notification);
|
||||
})
|
||||
.on_error (on_error)
|
||||
.exec ();
|
||||
|
||||
return GLib.Source.REMOVE;
|
||||
protected virtual void add_notification (API.Notification n) {
|
||||
prepend (widgetize (n));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -154,28 +154,13 @@ public class Tootle.Views.Profile : Views.Timeline {
|
||||
return base.append_params (req);
|
||||
}
|
||||
|
||||
public override 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) {
|
||||
API.Status status;
|
||||
if (posts_tab.active)
|
||||
status = new API.Status (obj);
|
||||
else {
|
||||
var account = new API.Account (obj);
|
||||
status = new API.Status.from_account (account);
|
||||
}
|
||||
|
||||
append (status);
|
||||
}
|
||||
get_pages (msg.response_headers.get_one ("Link"));
|
||||
})
|
||||
.on_error (on_error)
|
||||
.exec ();
|
||||
|
||||
return GLib.Source.REMOVE;
|
||||
public override GLib.Object? to_entity (Json.Object? json) {
|
||||
if (posts_tab.active)
|
||||
return new API.Status (json);
|
||||
else {
|
||||
var account = new API.Account (json);
|
||||
return new API.Status.from_account (account);
|
||||
}
|
||||
}
|
||||
|
||||
public static void open_from_id (int64 id){
|
||||
|
@ -1,7 +1,7 @@
|
||||
using Gtk;
|
||||
using Gdk;
|
||||
|
||||
public class Tootle.Views.Timeline : Views.Base, IAccountListener, IStreamListener {
|
||||
public class Tootle.Views.Timeline : IAccountListener, IStreamListener, Views.Base {
|
||||
|
||||
public string timeline { get; construct set; }
|
||||
public bool is_public { get; construct set; default = false; }
|
||||
@ -17,6 +17,9 @@ public class Tootle.Views.Timeline : Views.Base, IAccountListener, IStreamListen
|
||||
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);
|
||||
@ -30,32 +33,39 @@ public class Tootle.Views.Timeline : Views.Base, IAccountListener, IStreamListen
|
||||
return _("Home");
|
||||
}
|
||||
|
||||
public override void on_status_added (API.Status status) {
|
||||
prepend (status);
|
||||
}
|
||||
|
||||
public virtual bool is_status_owned (API.Status status) {
|
||||
return status.is_owned ();
|
||||
}
|
||||
|
||||
public void prepend (API.Status status) {
|
||||
append (status, true);
|
||||
public virtual GLib.Object? to_entity (Json.Object? json) {
|
||||
return new API.Status (json);
|
||||
}
|
||||
|
||||
public void append (API.Status status, bool first = false) {
|
||||
GLib.Idle.add (() => {
|
||||
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);
|
||||
public virtual Widget? widgetize (GLib.Object? entity) {
|
||||
var status = entity as API.Status;
|
||||
if (status == null)
|
||||
return null;
|
||||
|
||||
content.pack_start (w, false, false, 0);
|
||||
if (first || status.pinned)
|
||||
content.reorder_child (w, 0);
|
||||
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);
|
||||
|
||||
on_content_changed ();
|
||||
return GLib.Source.REMOVE;
|
||||
});
|
||||
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 () {
|
||||
@ -101,16 +111,20 @@ public class Tootle.Views.Timeline : Views.Base, IAccountListener, IStreamListen
|
||||
append_params (new Request.GET (get_url ()))
|
||||
.with_account (account)
|
||||
.then_parse_array ((node, msg) => {
|
||||
var obj = node.get_object ();
|
||||
if (obj != null) {
|
||||
var status = new API.Status (obj);
|
||||
append (status);
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
@ -125,7 +139,7 @@ public class Tootle.Views.Timeline : Views.Base, IAccountListener, IStreamListen
|
||||
return null;
|
||||
}
|
||||
|
||||
public override void on_account_changed (InstanceAccount? acc) {
|
||||
public virtual void on_account_changed (InstanceAccount? acc) {
|
||||
account = acc;
|
||||
streams.unsubscribe (stream, this);
|
||||
streams.subscribe (get_stream_url (), this, out stream);
|
||||
@ -140,18 +154,14 @@ public class Tootle.Views.Timeline : Views.Base, IAccountListener, IStreamListen
|
||||
request ();
|
||||
}
|
||||
|
||||
public override bool accepts (ref string event) {
|
||||
var allowed_public = true;
|
||||
if (is_public)
|
||||
allowed_public = settings.live_updates_public;
|
||||
|
||||
return settings.live_updates && allowed_public;
|
||||
protected virtual void add_status (API.Status status) {
|
||||
prepend (widgetize (status));
|
||||
}
|
||||
|
||||
public override void on_status_removed (int64 id) {
|
||||
protected virtual void remove_status (int64 id) {
|
||||
content.get_children ().@foreach (w => {
|
||||
var sw = w as Widgets.Status;
|
||||
if (sw.status.id == id)
|
||||
if (sw != null && sw.status.id == id)
|
||||
sw.destroy ();
|
||||
});
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user