feat: instance info (#63)

* chore: status_reactions => compat_status_reactions

let's prefix all instance compatibility properties with compat_

* feat: deserialize ArrayLists of string

* feat: instance info

* fix(SecretAccountStore): set instance_info as null
This commit is contained in:
GeopJr 2023-02-01 17:07:12 +02:00 committed by GitHub
parent faa879be59
commit d3d3596210
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 125 additions and 4 deletions

View File

@ -63,6 +63,12 @@ sources = files(
'src/API/Emoji.vala',
'src/API/EmojiReaction.vala',
'src/API/Entity.vala',
'src/API/Instance.vala',
'src/API/Instance/Mastodon/Configuration.vala',
'src/API/Instance/Mastodon/Configuration/MediaAttachments.vala',
'src/API/Instance/Mastodon/Configuration/Polls.vala',
'src/API/Instance/Mastodon/Configuration/Reactions.vala',
'src/API/Instance/Mastodon/Configuration/Statuses.vala',
'src/API/List.vala',
'src/API/Mention.vala',
'src/API/Notification.vala',

View File

@ -72,6 +72,9 @@ public class Tooth.Entity : GLib.Object, Widgetizable, Json.Serializable {
//There has to be a better way
switch (prop) {
case "supported-mime-types":
case "languages":
return des_list_string(out val, node);
case "media-attachments":
contains = typeof (API.Attachment);
break;
@ -123,6 +126,18 @@ public class Tooth.Entity : GLib.Object, Widgetizable, Json.Serializable {
return true;
}
public static bool des_list_string (out Value val, Json.Node node) {
var arr = new Gee.ArrayList<string> ();
if (!node.is_null ()) {
node.get_array ().foreach_element ((array, i, elem) => {
var obj = (string) elem.get_string();
arr.add (obj);
});
}
val = arr;
return true;
}
public override Json.Node serialize_property (string prop, Value val, ParamSpec spec) {
var type = spec.value_type;
// debug (@"serializing $prop of type $(val.type_name ())");

51
src/API/Instance.vala Normal file
View File

@ -0,0 +1,51 @@
public class Tooth.API.Instance : Entity {
public Gee.ArrayList<string>? languages { get; set; }
public API.Mastodon.Configurations? configuration { get; set; default = null; }
public int64 max_toot_chars { get; set; default = 0; }
public API.Mastodon.Configuration.Polls? poll_limits { get; set; default = null; }
public int64 upload_limit { get; set; default = 0; }
public int64 compat_status_max_characters {
get {
if (configuration != null) {
return configuration.statuses.max_characters;
}
return max_toot_chars;
}
}
public int64 compat_status_max_image_size {
get {
if (configuration != null) {
return configuration.media_attachments.image_size_limit;
}
return upload_limit;
}
}
public int64 compat_status_max_video_size {
get {
if (configuration != null) {
return configuration.media_attachments.video_size_limit;
}
return upload_limit;
}
}
public API.Mastodon.Configuration.Polls? compat_status_polls {
get {
if (configuration != null) {
return configuration.polls;
}
return poll_limits;
}
}
public static API.Instance from (Json.Node node) throws Error {
return Entity.from_json (typeof (API.Instance), node) as API.Instance;
}
}

View File

@ -0,0 +1,6 @@
public class Tooth.API.Mastodon.Configurations : Entity {
public API.Mastodon.Configuration.Statuses statuses { get; set; }
public API.Mastodon.Configuration.MediaAttachments media_attachments { get; set; }
public API.Mastodon.Configuration.Polls polls { get; set; }
public API.Mastodon.Configuration.Reactions? reactions { get; set; default = null; }
}

View File

@ -0,0 +1,8 @@
public class Tooth.API.Mastodon.Configuration.MediaAttachments : Entity {
public Gee.ArrayList<string> supported_mime_types { get; set; }
public int64 image_size_limit { get; set; }
public int64 image_matrix_limit { get; set; }
public int64 video_size_limit { get; set; }
public int64 video_frame_rate_limit { get; set; }
public int64 video_matrix_limit { get; set; }
}

View File

@ -0,0 +1,13 @@
public class Tooth.API.Mastodon.Configuration.Polls : Entity {
public int64 max_options { get; set; }
public int64 max_characters_per_option { get; set; default = -1; }
public int64 max_option_chars { get; set; default = -1; }
public int64 min_expiration { get; set; }
public int64 max_expiration { get; set; }
public int64 compat_status_poll_max_characters {
get {
return max_characters_per_option != -1 ? max_characters_per_option : max_option_chars;
}
}
}

View File

@ -0,0 +1,3 @@
public class Tooth.API.Mastodon.Configuration.Reactions : Entity {
public int64 max_reactions { get; set; }
}

View File

@ -0,0 +1,5 @@
public class Tooth.API.Mastodon.Configuration.Statuses : Entity {
public int64 max_characters { get; set; }
public int64 max_media_attachments { get; set; }
public int64 characters_reserved_per_url { get; set; default = 0; }
}

View File

@ -33,7 +33,7 @@ public class Tooth.API.Status : Entity, Widgetizable {
public ArrayList<API.Attachment>? media_attachments { get; set; default = null; }
public API.Poll? poll { get; set; default = null; }
public ArrayList<API.EmojiReaction>? status_reactions {
public ArrayList<API.EmojiReaction>? compat_status_reactions {
get {
if (emoji_reactions != null) {
return emoji_reactions;

View File

@ -16,6 +16,7 @@ public class Tooth.InstanceAccount : API.Account, Streamable {
public const string KIND_REMOTE_REBLOG = "__remote-reblog";
public string? backend { set; get; }
public API.Instance? instance_info { get; set; }
public string? instance { get; set; }
public string? client_id { get; set; }
public string? client_secret { get; set; }
@ -42,7 +43,9 @@ public class Tooth.InstanceAccount : API.Account, Streamable {
}
}
public virtual signal void activated () {}
public virtual signal void activated () {
gather_instance_info ();
}
public virtual signal void deactivated () {}
public virtual signal void added () {
subscribed = true;
@ -179,6 +182,16 @@ public class Tooth.InstanceAccount : API.Account, Streamable {
public ArrayList<Object> notification_inhibitors { get; set; default = new ArrayList<Object> (); }
private bool passed_init_notifications = false;
public void gather_instance_info () {
new Request.GET ("/api/v1/instance")
.with_account (this)
.then ((sess, msg) => {
var node = network.parse_node (msg);
instance_info = API.Instance.from (node);
})
.exec ();
}
public void init_notifications () {
if (passed_init_notifications) return;

View File

@ -73,6 +73,7 @@ public class Tooth.SecretAccountStore : AccountStore {
attrs["version"] = VERSION;
var generator = new Json.Generator ();
account.instance_info = null;
generator.set_root (account.to_json ());
var secret = generator.to_data (null);
var label = _("%s Account").printf (account.backend);

View File

@ -85,7 +85,7 @@ public class Tooth.Widgets.Status : ListBoxRow {
public bool is_conversation_open { get; set; default = false; }
public Gee.ArrayList<API.EmojiReaction>? reactions {
get { return status.formal.status_reactions; }
get { return status.formal.compat_status_reactions; }
set {
if (value == null) return;
@ -298,7 +298,7 @@ public class Tooth.Widgets.Status : ListBoxRow {
return true;
});
formal_bindings.bind_property ("account", avatar, "account", BindingFlags.SYNC_CREATE);
formal_bindings.bind_property ("status-reactions", this, "reactions", BindingFlags.SYNC_CREATE);
formal_bindings.bind_property ("compat-status-reactions", this, "reactions", BindingFlags.SYNC_CREATE);
formal_bindings.bind_property ("has-spoiler", this, "reveal-spoiler", BindingFlags.SYNC_CREATE, (b, src, ref target) => {
target.set_boolean (!src.get_boolean () || settings.show_spoilers);
return true;