Skip to content
This repository has been archived by the owner on Dec 15, 2022. It is now read-only.

Port to GTK4 #310

Merged
merged 52 commits into from
Jul 23, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
77a37d4
Let's do this
Apr 6, 2021
42eafdf
Almost made it compile
Apr 6, 2021
8fb55a8
Now it compiles
Apr 7, 2021
0618b18
Fix base.ui
Apr 8, 2021
e3f4c8a
Fix TabbedBase
Apr 8, 2021
04a1033
Add sidebar view
Apr 9, 2021
138c6b8
Clean ui files
Apr 9, 2021
2e80689
Sidebar: add account switching mode
Apr 9, 2021
514ee97
Populate sidebar with account actions
Apr 11, 2021
3392547
Fix preferences
Apr 11, 2021
d6bdbd7
Fix view title
Apr 12, 2021
48c1d01
Fix thread view
Apr 13, 2021
d17bd2d
Refactor Streams. Again.
Apr 14, 2021
192b32d
Initial Profile view redesign
Apr 17, 2021
161a5c5
New cache system idea
Apr 20, 2021
808fb95
Save window size
Apr 20, 2021
b80a4ec
Account switching
Apr 21, 2021
b7f5559
Fix NewAccount dialog
Apr 21, 2021
b91cb3d
Sidebar: implement account manager mode
Apr 22, 2021
e501716
Add sidebar toggle button
May 15, 2021
4f51c19
Change some timeline icons
May 15, 2021
3d58e44
Rework image cache
May 16, 2021
5c1a9fe
Leaks. Leaks everywhere.
May 16, 2021
5d49e98
Fix Adw.Avatars not being destroyed. Kinda.
May 18, 2021
59c6013
Fix some leaks for GTK 4.3
Jun 15, 2021
a2d5cbf
Doing something controversial
Jun 18, 2021
cdfe8da
Clean up
Jun 18, 2021
6e10056
Reimplement status actions
Jul 2, 2021
1d25465
Cosmetic tweaks
Jul 5, 2021
9e13b5f
Add desktop notifications
Jul 10, 2021
c454e9c
Profile View: move note field up
Jul 10, 2021
04a062f
Work on notifications
Jul 11, 2021
190eb49
Notifications...
Jul 12, 2021
4344d43
Stuff
Jul 14, 2021
12838b3
Add Background widget
Jul 14, 2021
e7a8d54
Remove old Compose dialog
Jul 16, 2021
2b07c00
Add cw field to Composer
Jul 16, 2021
22f42de
Figure out DropDowns
Jul 16, 2021
960da9f
Make composer actually work
Jul 17, 2021
041fcba
Fix symbolic icon recoloring
Jul 17, 2021
81eb396
Initial attachment box
Jul 18, 2021
f059607
Attachment styling
Jul 19, 2021
b2f589a
Open attachments on click
Jul 19, 2021
414825f
Rename Desktop to Host
Jul 19, 2021
e2c6088
Display attachment descriptions
Jul 19, 2021
01f8a82
ImageCache: Store paintables instead of pixbufs
Jul 19, 2021
1709d41
Cosmetics
Jul 19, 2021
eae389f
Composer: Support replies
Jul 23, 2021
179e721
Remove NYI stuff
Jul 23, 2021
f8458ba
Make sidebar useful
Jul 23, 2021
1b60716
Lists are broken
Jul 23, 2021
bb7c1a8
Bump version
Jul 23, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Add desktop notifications
  • Loading branch information
Bleak Grey committed Jul 10, 2021
commit 9e13b5f5d628d597ff7012b91295ef583984e718
4 changes: 2 additions & 2 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,13 @@ sources = files(
'src/Services/Accounts/SecretAccountStore.vala',
'src/Services/Accounts/AccountHolder.vala',
'src/Services/Accounts/Mastodon/Account.vala',
'src/Services/Streams/Streams.vala',
'src/Services/Streams/Streamable.vala',
'src/Services/Cache/AbstractCache.vala',
'src/Services/Cache/EntityCache.vala',
'src/Services/Cache/ImageCache.vala',
'src/Services/Network/Network.vala',
'src/Services/Network/Request.vala',
'src/Services/Network/Streams.vala',
'src/Services/Network/Streamable.vala',
'src/Services/Settings.vala',
'src/API/Account.vala',
'src/API/AccountField.vala',
Expand Down
56 changes: 31 additions & 25 deletions src/Services/Accounts/InstanceAccount.vala
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,17 @@ public class Tootle.InstanceAccount : API.Account, Streamable {
public string? access_token { get; set; }
public Error? error { get; set; }

public int64 last_seen_notification { get; set; default = 0; }
public bool has_unread_notifications { get; set; default = false; }
public ArrayList<API.Notification> cached_notifications { get; set; default = new ArrayList<API.Notification> (); }
public ArrayList<GLib.Notification> desktop_inbox { get; set; default = new ArrayList<GLib.Notification> (); }
public int64 last_read_notification { get; set; default = 0; }
public uint unread_notifications { get; set; default = 0; }

public new string handle {
owned get { return @"@$username@$domain"; }
}

construct {
//TODO: Show notifications
// on_notification.connect (show_notification);
construct_streamable ();
stream_event[Mastodon.Account.EVENT_NOTIFICATION].connect (on_notification);
}

public InstanceAccount.empty (string instance){
Expand Down Expand Up @@ -57,27 +56,13 @@ public class Tootle.InstanceAccount : API.Account, Streamable {
return entity;
}

// TODO: notification actions
void show_notification (API.Notification obj) {
// var title = HtmlUtils.remove_tags (obj.kind.get_desc (obj.account));
// var notification = new GLib.Notification (title);
// if (obj.status != null) {
// var body = "";
// body += domain;
// body += "\n";
// body += HtmlUtils.remove_tags (obj.status.content);
// notification.set_body (body);
// }

// app.send_notification (app.application_id + ":" + obj.id.to_string (), notification);
}

public virtual void populate_user_menu (GLib.ListStore model) {}

public virtual void describe_kind (string kind, out string? icon, out string? descr, API.Account account) {
icon = null;
descr = null;
}
public virtual void describe_kind (string kind, out string? icon, out string? descr, API.Account account) {
icon = null;
descr = null;
}



// Streamable
Expand All @@ -89,8 +74,29 @@ public class Tootle.InstanceAccount : API.Account, Streamable {
return @"$instance/api/v1/streaming/?stream=user&access_token=$access_token";
}

public virtual void on_stream_event (Streamable.Event ev) {
public virtual void on_notification (Streamable.Event ev) {
var obj = Entity.from_json (typeof (API.Notification), ev.get_node ()) as API.Notification;
var toast = create_desktop_toast (obj);
app.send_notification (obj.id.to_string (), toast);
}

// TODO: notification actions
public virtual GLib.Notification create_desktop_toast (API.Notification obj) {
string descr;
describe_kind (obj.kind, null, out descr, obj.account);

var toast = new GLib.Notification ( HtmlUtils.remove_tags (descr) );
if (obj.status != null) {
var body = "";
body += HtmlUtils.remove_tags (obj.status.content);
toast.set_body (body);
}

var file = GLib.File.new_for_uri (avatar);
var icon = new FileIcon (file);
toast.set_icon (icon);

return toast;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,11 @@ public abstract interface Tootle.Streamable : Object {
public abstract string? _connection_url { get; set; }
public abstract bool subscribed { get; set; default = false; }

public abstract void on_stream_event (Event ev);
public abstract string? get_stream_url ();

[Signal (detailed = true)]
public signal void stream_event (Event ev);

void subscribe () {
streams.unsubscribe (_connection_url, this);
streams.subscribe (get_stream_url (), this);
Expand Down Expand Up @@ -63,8 +65,6 @@ public abstract interface Tootle.Streamable : Object {
subscribe ();
}

protected virtual void on_streaming_policy_changed () {

}
protected virtual void on_streaming_policy_changed () {}

}
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,8 @@ public class Tootle.Streams : Object {
decode (bytes, out ev);

subscribers.@foreach (s => {
// message (@"$(name): $(ev.type) for $(s.get_subscriber_name ())");
s.on_stream_event (ev);
message (@"$(name): $(ev.type) for $(s.get_subscriber_name ())");
s.stream_event[ev.type] (ev);
return true;
});
}
Expand Down
22 changes: 11 additions & 11 deletions src/Views/Federated.vala
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
public class Tootle.Views.Federated : Views.Timeline {

public Federated () {
Object (
url: "/api/v1/timelines/public",
is_public: true,
label: _("Federated"),
icon: "globe-symbolic"
);
}
public Federated () {
Object (
url: "/api/v1/timelines/public",
is_public: true,
label: _("Federated"),
icon: "globe-symbolic"
);
}

public override string? get_stream_url () {
return account != null ? @"$(account.instance)/api/v1/streaming/?stream=public&access_token=$(account.access_token)" : null;
}
public override string? get_stream_url () {
return account != null ? @"$(account.instance)/api/v1/streaming/?stream=public&access_token=$(account.access_token)" : null;
}

}
104 changes: 45 additions & 59 deletions src/Views/Notifications.vala
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ using Gdk;

public class Tootle.Views.Notifications : Views.Timeline, AccountHolder, Streamable {

protected int64 last_id = 0;

public Notifications () {
Object (
url: "/api/v1/notifications",
Expand All @@ -18,69 +16,57 @@ public class Tootle.Views.Notifications : Views.Timeline, AccountHolder, Streama
return account.get_stream_url ();
}

public override void on_shown () {
if (has_unread ()) {
needs_attention = false;
account.has_unread_notifications = false;
account.last_seen_notification = last_id;
accounts.safe_save ();
}
}
// public override void on_shown () {
// if (has_unread ()) {
// needs_attention = false;
// account.has_unread_notifications = false;
// account.last_seen_notification = last_id;
// accounts.safe_save ();
// }
// }

//FIXME: Display unread dot
// public override void append (Widget? w, bool reverse = false) {
// base.append (w, reverse);
// var nw = w as Widgets.Notification;
// var notification = nw.notification;

// if (int64.parse (notification.id) > last_id)
// last_id = int64.parse (notification.id);

// needs_attention = has_unread () && !current;
// if (needs_attention)
// accounts.safe_save ();
// public override void on_account_changed (InstanceAccount? acc) {
// base.on_account_changed (acc);
// if (account == null) {
// last_id = 0;
// needs_attention = false;
// }
// else {
// last_id = account.last_seen_notification;
// needs_attention = account.has_unread_notifications;
// }
// }

public override void on_account_changed (InstanceAccount? acc) {
base.on_account_changed (acc);
if (account == null) {
last_id = 0;
needs_attention = false;
}
else {
last_id = account.last_seen_notification;
needs_attention = account.has_unread_notifications;
}
}
// public override bool request () {
// if (account != null) {
// account.cached_notifications.@foreach (n => {
// model.append (n);
// return true;
// });
// }
// return base.request ();
// }

public override bool request () {
if (account != null) {
account.cached_notifications.@foreach (n => {
model.append (n);
return true;
});
}
return base.request ();
}

bool has_unread () {
if (account == null)
return false;
return last_id > account.last_seen_notification || needs_attention;
}
// bool has_unread () {
// if (account == null)
// return false;
// return last_id > account.last_seen_notification || needs_attention;
// }

public override void on_stream_event (Streamable.Event ev) {
try {
switch (ev.type) {
case Mastodon.Account.EVENT_NOTIFICATION:
var entity = Entity.from_json (accepts, ev.get_node ());
model.insert (0, entity);
return;
}
}
catch (Error e) {
warning ("Couldn't process stream event: " + e.message);
}
}
// public override void on_stream_event (Streamable.Event ev) {
// try {
// switch (ev.type) {
// case Mastodon.Account.EVENT_NOTIFICATION:
// var entity = Entity.from_json (accepts, ev.get_node ());
// model.insert (0, entity);
// return;
// }
// }
// catch (Error e) {
// warning ("Couldn't process stream event: " + e.message);
// }
// }

}
26 changes: 10 additions & 16 deletions src/Views/Timeline.vala
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ public class Tootle.Views.Timeline : AccountHolder, Streamable, Views.ContentBas
status_button.clicked.connect (on_refresh);

construct_account_holder ();

construct_streamable ();
stream_event[Mastodon.Account.EVENT_NEW_POST].connect (on_new_post);
stream_event[Mastodon.Account.EVENT_DELETE_POST].connect (on_delete_post);

content.bind_model (model, on_create_model_widget);
}
Expand Down Expand Up @@ -144,22 +147,13 @@ public class Tootle.Views.Timeline : AccountHolder, Streamable, Views.ContentBas
return null;
}

public virtual void on_stream_event (Streamable.Event ev) {
try {
switch (ev.type) {
case Mastodon.Account.EVENT_NEW_POST:
var entity = Entity.from_json (accepts, ev.get_node ());
model.insert (0, entity);
return;
case Mastodon.Account.EVENT_DELETE_POST:
return;
default:
return;
}
}
catch (Error e) {
warning (@"Couldn't process stream event \"$(ev.type)\": $(e.message)");
}
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
}

}