Move from using Lists to arrays
This commit is contained in:
parent
f6df2200b7
commit
c9465dc1c0
@ -164,8 +164,8 @@ public interface Matrix.API : GLib.Object {
|
||||
update_presence_list([CCode (delegate_target_pos = 1.5, scope = "async")]
|
||||
owned Matrix.API.Callback? @callback,
|
||||
string user_id,
|
||||
GLib.List<string> drop_ids,
|
||||
GLib.List<string> invite_ids)
|
||||
string[] drop_ids,
|
||||
string[] invite_ids)
|
||||
throws Matrix.Error;
|
||||
|
||||
/**
|
||||
@ -299,8 +299,8 @@ public interface Matrix.API : GLib.Object {
|
||||
string rule_id,
|
||||
string? before,
|
||||
string? after,
|
||||
GLib.List<string> actions,
|
||||
GLib.List<Matrix.PusherConditionKind>? conditions)
|
||||
string[] actions,
|
||||
Matrix.PusherConditionKind[] conditions)
|
||||
throws Matrix.Error;
|
||||
|
||||
/**
|
||||
@ -357,9 +357,9 @@ public interface Matrix.API : GLib.Object {
|
||||
string? topic,
|
||||
Matrix.RoomVisibility visibility,
|
||||
Json.Node? creation_content,
|
||||
GLib.List<Matrix.Event.State>? initial_state,
|
||||
GLib.List<string>? invitees,
|
||||
GLib.List<Matrix.3PidCredential>? invite_3pids)
|
||||
Matrix.Event.State[] initial_state,
|
||||
string[] invitees,
|
||||
Matrix.3PidCredential[] invite_3pids)
|
||||
throws Matrix.Error;
|
||||
|
||||
/* Room directory */
|
||||
|
@ -41,22 +41,10 @@ namespace Matrix {
|
||||
* Class to hold a filter.
|
||||
*/
|
||||
public class Filter : JsonCompact {
|
||||
private List<string>? _event_fields;
|
||||
|
||||
/**
|
||||
* The event fields to include in the filtered events.
|
||||
*/
|
||||
public List<string>? event_fields {
|
||||
get {
|
||||
return _event_fields;
|
||||
}
|
||||
|
||||
set {
|
||||
_event_fields = value.copy();
|
||||
}
|
||||
|
||||
default = null;
|
||||
}
|
||||
public string[] event_fields { get; set; }
|
||||
|
||||
/**
|
||||
* The desired event format for the filtered events (e.g. for
|
||||
@ -179,13 +167,6 @@ namespace Matrix {
|
||||
* Class to hold filtering rules.
|
||||
*/
|
||||
public class FilterRules : JsonCompact {
|
||||
private List<string>? _types;
|
||||
private List<string>? _excluded_types;
|
||||
private List<string>? _senders;
|
||||
private List<string>? _excluded_senders;
|
||||
private List<string>? _rooms;
|
||||
private List<string>? _excluded_rooms;
|
||||
|
||||
/**
|
||||
* The limit of the count of returned events.
|
||||
*/
|
||||
@ -194,98 +175,38 @@ namespace Matrix {
|
||||
/**
|
||||
* List of message types to include in the filtered result.
|
||||
*/
|
||||
public List<string>? types {
|
||||
get {
|
||||
return _types;
|
||||
}
|
||||
|
||||
set {
|
||||
_types = value.copy();
|
||||
}
|
||||
|
||||
default = null;
|
||||
}
|
||||
public string[] types { get; set; }
|
||||
|
||||
/**
|
||||
* List of message types to exclude from the filtered
|
||||
* result. A matching type will be excluded from the result
|
||||
* even if it is listed in the types to include.
|
||||
*/
|
||||
public List<string>? excluded_types {
|
||||
get {
|
||||
return _excluded_types;
|
||||
}
|
||||
|
||||
set {
|
||||
_excluded_types = value.copy();
|
||||
}
|
||||
|
||||
default = null;
|
||||
}
|
||||
public string[] excluded_types { get; set; }
|
||||
|
||||
/**
|
||||
* List of senders to include in the filtered results.
|
||||
*/
|
||||
public List<string>? senders {
|
||||
get {
|
||||
return _senders;
|
||||
}
|
||||
|
||||
set {
|
||||
_senders = value.copy();
|
||||
}
|
||||
|
||||
default = null;
|
||||
}
|
||||
public string[] senders { get; set; }
|
||||
|
||||
/**
|
||||
* List of senders to exclude from the filtered result. A
|
||||
* matching sender will be excluded from the result even if it
|
||||
* is listed in the senders to include.
|
||||
*/
|
||||
public List<string>? excluded_senders {
|
||||
get {
|
||||
return _excluded_senders;
|
||||
}
|
||||
|
||||
set {
|
||||
_excluded_senders = value.copy();
|
||||
}
|
||||
|
||||
default = null;
|
||||
}
|
||||
public string[] excluded_senders { get; set; }
|
||||
|
||||
/**
|
||||
* List of rooms to include in the filtered results.
|
||||
*/
|
||||
public List<string>? rooms {
|
||||
get {
|
||||
return _rooms;
|
||||
}
|
||||
|
||||
set {
|
||||
_rooms = value.copy();
|
||||
}
|
||||
|
||||
default = null;
|
||||
}
|
||||
public string[] rooms { get; set; }
|
||||
|
||||
/**
|
||||
* List of rooms to exclude from the filtered result. A
|
||||
* matching room will be excluded from the result even if it
|
||||
* is listed in the rooms to include.
|
||||
*/
|
||||
public List<string>? excluded_rooms {
|
||||
get {
|
||||
return _excluded_rooms;
|
||||
}
|
||||
|
||||
set {
|
||||
_excluded_rooms = value.copy();
|
||||
}
|
||||
|
||||
default = null;
|
||||
}
|
||||
public string[] excluded_rooms { get; set; }
|
||||
|
||||
/**
|
||||
* Get the filtering rules as a JSON node.
|
||||
@ -609,18 +530,7 @@ namespace Matrix {
|
||||
}
|
||||
|
||||
public class SearchGroupings : JsonCompact {
|
||||
private List<SearchGrouping>? _group_by = null;
|
||||
public List<SearchGrouping>? group_by {
|
||||
get {
|
||||
return _group_by;
|
||||
}
|
||||
|
||||
set {
|
||||
_group_by = value.copy();
|
||||
}
|
||||
|
||||
default = null;
|
||||
}
|
||||
public SearchGrouping[] group_by { get; set; }
|
||||
|
||||
public override Json.Node?
|
||||
get_json_node()
|
||||
@ -654,19 +564,8 @@ namespace Matrix {
|
||||
}
|
||||
|
||||
public class SearchRoomEvents : JsonCompact {
|
||||
private List<SearchKey?>? _keys = null;
|
||||
|
||||
public SearchOrder? order_by { get; set; default = SearchOrder.RECENT; }
|
||||
public List<SearchKey?>? keys {
|
||||
get {
|
||||
return _keys;
|
||||
}
|
||||
|
||||
set {
|
||||
_keys = value.copy();
|
||||
}
|
||||
|
||||
default = null; }
|
||||
public SearchOrder order_by { get; set; default = SearchOrder.RECENT; }
|
||||
public SearchKey[] keys { get; set; }
|
||||
public EventContext? event_context { get; set; default = null; }
|
||||
public bool? include_state { get; set; default = false; }
|
||||
public string? filter_id { get; set; default = null; }
|
||||
@ -689,24 +588,20 @@ namespace Matrix {
|
||||
|
||||
builder.begin_object();
|
||||
|
||||
if (order_by != null) {
|
||||
builder.set_member_name("order_by");
|
||||
builder.add_string_value(
|
||||
_g_enum_value_to_nick(typeof(SearchOrder), order_by));
|
||||
}
|
||||
builder.set_member_name("order_by");
|
||||
builder.add_string_value(
|
||||
_g_enum_value_to_nick(typeof(SearchOrder), order_by));
|
||||
|
||||
if (keys != null) {
|
||||
if (keys.length > 0) {
|
||||
EnumClass key_class = (EnumClass)(typeof(SearchKey).class_ref());
|
||||
var key_array = new Json.Array();
|
||||
|
||||
foreach (var entry in keys) {
|
||||
if (entry != null) {
|
||||
unowned EnumValue? key_value = key_class.get_value(entry);
|
||||
unowned EnumValue? key_value = key_class.get_value(entry);
|
||||
|
||||
if (key_value != null) {
|
||||
key_array.add_string_element(
|
||||
key_value.value_nick.replace("-", "."));
|
||||
}
|
||||
if (key_value != null) {
|
||||
key_array.add_string_element(
|
||||
key_value.value_nick.replace("-", "."));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -33,19 +33,7 @@ public class Matrix.Event.CallCandidates : Matrix.Event.Call {
|
||||
/**
|
||||
* The list of candidates.
|
||||
*/
|
||||
public List<Candidate?>? candidates {
|
||||
get {
|
||||
return _candidates;
|
||||
}
|
||||
|
||||
set {
|
||||
_candidates = value.copy();
|
||||
}
|
||||
|
||||
default = null;
|
||||
}
|
||||
|
||||
private List<Candidate?>? _candidates;
|
||||
public Candidate[] candidates { get; set; }
|
||||
|
||||
protected override void
|
||||
from_json(Json.Node json_data)
|
||||
@ -56,6 +44,8 @@ public class Matrix.Event.CallCandidates : Matrix.Event.Call {
|
||||
Json.Node? node;
|
||||
|
||||
if ((node = content_root.get_member("candidates")) != null) {
|
||||
_candidates = new Candidate[node.get_array().get_length()];
|
||||
|
||||
node.get_array().foreach_element((ary, idx, cand_node) => {
|
||||
var cand_root = cand_node.get_object();
|
||||
var cand = Candidate();
|
||||
@ -78,7 +68,7 @@ public class Matrix.Event.CallCandidates : Matrix.Event.Call {
|
||||
warning("candidate is missing from a candidate of a m.call.candidates event");
|
||||
}
|
||||
|
||||
_candidates.prepend(cand);
|
||||
_candidates[idx] = cand;
|
||||
});
|
||||
} else {
|
||||
warning("content.candidates is missing from a m.call.candidates event");
|
||||
@ -91,7 +81,7 @@ public class Matrix.Event.CallCandidates : Matrix.Event.Call {
|
||||
to_json(Json.Node json_data)
|
||||
throws Matrix.Error
|
||||
{
|
||||
if ((_candidates == null) || (_candidates.length() < 1)) {
|
||||
if (_candidates.length < 1) {
|
||||
throw new Matrix.Error.INCOMPLETE(
|
||||
"Won't generate a m.call.candidates event without candidates");
|
||||
}
|
||||
|
@ -34,22 +34,10 @@
|
||||
* whether it receives the correct room ID.
|
||||
*/
|
||||
public class Matrix.Event.RoomAliases : Matrix.Event.State {
|
||||
private List<string>? _aliases = null;
|
||||
|
||||
/**
|
||||
* A list of room aliases.
|
||||
*/
|
||||
public List<string>? aliases {
|
||||
get {
|
||||
return _aliases;
|
||||
}
|
||||
|
||||
set {
|
||||
_aliases = value.copy();
|
||||
}
|
||||
|
||||
default = null;
|
||||
}
|
||||
public string[] aliases { get; set; }
|
||||
|
||||
protected override void
|
||||
from_json(Json.Node json_data)
|
||||
@ -60,10 +48,10 @@ public class Matrix.Event.RoomAliases : Matrix.Event.State {
|
||||
Json.Node? node;
|
||||
|
||||
if ((node = content_root.get_member("aliases")) != null) {
|
||||
_aliases = null;
|
||||
_aliases = new string[node.get_array().get_length()];
|
||||
|
||||
node.get_array().foreach_element((ary, idx, member_node) => {
|
||||
_aliases.prepend(member_node.get_string());
|
||||
_aliases[idx] = member_node.get_string();
|
||||
});
|
||||
} else if (Config.DEBUG) {
|
||||
warning("content.aliases is missing from a m.room.aliases event");
|
||||
@ -76,7 +64,7 @@ public class Matrix.Event.RoomAliases : Matrix.Event.State {
|
||||
to_json(Json.Node json_data)
|
||||
throws Matrix.Error
|
||||
{
|
||||
if ((_aliases == null) || (_aliases.length() == 0)) {
|
||||
if (_aliases.length == 0) {
|
||||
throw new Matrix.Error.INCOMPLETE(
|
||||
"Won't generate a m.room.aliases event without aliases");
|
||||
}
|
||||
|
@ -55,8 +55,6 @@
|
||||
* events such as the room name.
|
||||
*/
|
||||
public class Matrix.Event.RoomMember : Matrix.Event.State {
|
||||
private List<Matrix.Event.State>? _invite_room_state = null;
|
||||
|
||||
/**
|
||||
* The membership state of the user.
|
||||
*/
|
||||
@ -106,17 +104,7 @@ public class Matrix.Event.RoomMember : Matrix.Event.State {
|
||||
* A subset of the state of the room at the time of the invite, if
|
||||
* membership is invite.
|
||||
*/
|
||||
public List<Matrix.Event.State>? invite_room_state {
|
||||
get {
|
||||
return _invite_room_state;
|
||||
}
|
||||
|
||||
set {
|
||||
_invite_room_state = value.copy();
|
||||
}
|
||||
|
||||
default = null;
|
||||
}
|
||||
public Matrix.Event.State[] invite_room_state { get; set; }
|
||||
|
||||
/**
|
||||
* The user ID whom this event relates to.
|
||||
@ -207,14 +195,14 @@ public class Matrix.Event.RoomMember : Matrix.Event.State {
|
||||
var events = node.get_array();
|
||||
|
||||
if (events.get_length() > 0) {
|
||||
_invite_room_state = null;
|
||||
_invite_room_state = new Matrix.Event.State[node.get_array().get_length()];
|
||||
|
||||
events.foreach_element((ary, idx, member_node) => {
|
||||
try {
|
||||
var evt = Matrix.Event.Base.new_from_json(
|
||||
null, member_node);
|
||||
|
||||
_invite_room_state.prepend((Matrix.Event.State)evt);
|
||||
_invite_room_state[idx] = (Matrix.Event.State)evt;
|
||||
} catch (GLib.Error e) {}
|
||||
});
|
||||
}
|
||||
|
@ -31,8 +31,6 @@ public class Matrix.Event.RoomThirdPartyInvite : Matrix.Event.State {
|
||||
string? validity_url;
|
||||
}
|
||||
|
||||
private List<PublicKey?> _public_keys = null;
|
||||
|
||||
/**
|
||||
* A user-readable string which represents the user who has been
|
||||
* invited. This should not contain the user's third party ID, as
|
||||
@ -59,17 +57,7 @@ public class Matrix.Event.RoomThirdPartyInvite : Matrix.Event.State {
|
||||
/**
|
||||
* Keys with which the token may be signed.
|
||||
*/
|
||||
List<PublicKey?>? public_keys {
|
||||
get {
|
||||
return _public_keys;
|
||||
}
|
||||
|
||||
set {
|
||||
_public_keys = value.copy();
|
||||
}
|
||||
|
||||
default = null;
|
||||
}
|
||||
public PublicKey[] public_keys { get; set; }
|
||||
|
||||
/**
|
||||
* The token, of which a signature must be produced in order to
|
||||
@ -161,11 +149,6 @@ public class Matrix.Event.RoomThirdPartyInvite : Matrix.Event.State {
|
||||
var key_list = new Json.Array();
|
||||
|
||||
foreach (var entry in _public_keys) {
|
||||
if (entry == null) {
|
||||
throw new Matrix.Error.INCOMPLETE(
|
||||
"Won't generate a m.room.third_party_invite with an empty public_key under additional keys");
|
||||
}
|
||||
|
||||
if (entry.key == null) {
|
||||
throw new Matrix.Error.INCOMPLETE(
|
||||
"Won't generate a m.room.third_party_invite with a missing key under public_keys");
|
||||
|
@ -30,19 +30,7 @@ public class Matrix.Event.Typing : Matrix.Event.Base {
|
||||
/**
|
||||
* The list of user IDs typing in this room, if any.
|
||||
*/
|
||||
public List<string>? user_ids {
|
||||
get {
|
||||
return _user_ids;
|
||||
}
|
||||
|
||||
set {
|
||||
_user_ids = value.copy();
|
||||
}
|
||||
|
||||
default = null;
|
||||
}
|
||||
|
||||
private List<string>? _user_ids = null;
|
||||
public string[] user_ids { get; set; }
|
||||
|
||||
protected override void
|
||||
from_json(Json.Node json_data)
|
||||
@ -59,10 +47,10 @@ public class Matrix.Event.Typing : Matrix.Event.Base {
|
||||
}
|
||||
|
||||
if ((node = content_root.get_member("user_ids")) != null) {
|
||||
_user_ids = null;
|
||||
_user_ids = new string[node.get_array().get_length()];
|
||||
|
||||
node.get_array().foreach_element((ary, idx, user_node) => {
|
||||
_user_ids.prepend(user_node.get_string());
|
||||
_user_ids[idx] = user_node.get_string();
|
||||
});
|
||||
} else if (Config.DEBUG) {
|
||||
warning("content.user_ids is missing from a m.typing event");
|
||||
|
@ -551,8 +551,8 @@ public class Matrix.HTTPAPI : GLib.Object, Matrix.API {
|
||||
public void
|
||||
update_presence_list(API.Callback? cb,
|
||||
string user_id,
|
||||
List<string> drop_ids,
|
||||
List<string> invite_ids)
|
||||
string[] drop_ids,
|
||||
string[] invite_ids)
|
||||
throws Matrix.Error
|
||||
{
|
||||
Json.Builder builder;
|
||||
@ -563,23 +563,25 @@ public class Matrix.HTTPAPI : GLib.Object, Matrix.API {
|
||||
builder = new Json.Builder();
|
||||
builder.begin_object();
|
||||
|
||||
if (drop_ids != null) {
|
||||
if (drop_ids.length > 0) {
|
||||
builder.set_member_name("drop");
|
||||
builder.begin_array();
|
||||
drop_ids.foreach(
|
||||
(entry) => {
|
||||
builder.add_string_value(entry);
|
||||
});
|
||||
|
||||
foreach (var entry in drop_ids) {
|
||||
builder.add_string_value(entry);
|
||||
}
|
||||
|
||||
builder.end_array();
|
||||
}
|
||||
|
||||
if (invite_ids != null) {
|
||||
if (invite_ids.length > 0) {
|
||||
builder.set_member_name("invite");
|
||||
builder.begin_array();
|
||||
invite_ids.foreach(
|
||||
(entry) => {
|
||||
builder.add_string_value(entry);
|
||||
});
|
||||
|
||||
foreach (var entry in invite_ids) {
|
||||
builder.add_string_value(entry);
|
||||
}
|
||||
|
||||
builder.end_array();
|
||||
}
|
||||
|
||||
@ -718,8 +720,8 @@ public class Matrix.HTTPAPI : GLib.Object, Matrix.API {
|
||||
string rule_id,
|
||||
string? before,
|
||||
string? after,
|
||||
List<string> actions,
|
||||
List<PusherConditionKind?>? conditions)
|
||||
string[] actions,
|
||||
PusherConditionKind[] conditions)
|
||||
throws Matrix.Error
|
||||
{
|
||||
Json.Builder builder;
|
||||
@ -738,32 +740,32 @@ public class Matrix.HTTPAPI : GLib.Object, Matrix.API {
|
||||
|
||||
builder.set_member_name("actions");
|
||||
builder.begin_array();
|
||||
actions.foreach(
|
||||
(entry) => {
|
||||
builder.add_string_value(entry);
|
||||
});
|
||||
foreach (var entry in actions) {
|
||||
builder.add_string_value(entry);
|
||||
}
|
||||
builder.end_array();
|
||||
|
||||
if (conditions != null) {
|
||||
if (conditions.length > 0) {
|
||||
builder.set_member_name("conditions");
|
||||
builder.begin_array();
|
||||
conditions.foreach(
|
||||
(entry) => {
|
||||
string? kind_string = _g_enum_value_to_nick(
|
||||
typeof(Matrix.PusherConditionKind),
|
||||
entry);
|
||||
|
||||
if (kind_string == null) {
|
||||
warning("Invalid condition kind");
|
||||
foreach (var entry in conditions) {
|
||||
string? kind_string = _g_enum_value_to_nick(
|
||||
typeof(Matrix.PusherConditionKind),
|
||||
entry);
|
||||
|
||||
return;
|
||||
}
|
||||
if (kind_string == null) {
|
||||
warning("Invalid condition kind");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
builder.begin_object();
|
||||
builder.set_member_name("kind");
|
||||
builder.add_string_value(kind_string);
|
||||
builder.end_object();
|
||||
}
|
||||
|
||||
builder.begin_object();
|
||||
builder.set_member_name("kind");
|
||||
builder.add_string_value(kind_string);
|
||||
builder.end_object();
|
||||
});
|
||||
builder.end_array();
|
||||
}
|
||||
|
||||
@ -809,9 +811,9 @@ public class Matrix.HTTPAPI : GLib.Object, Matrix.API {
|
||||
string? topic,
|
||||
RoomVisibility visibility,
|
||||
Json.Node? creation_content,
|
||||
List<Matrix.Event.State>? initial_state,
|
||||
List<string>? invitees,
|
||||
List<3PidCredential>? invite_3pids)
|
||||
Matrix.Event.State[] initial_state,
|
||||
string[] invitees,
|
||||
3PidCredential[] invite_3pids)
|
||||
throws Matrix.Error
|
||||
{
|
||||
Json.Builder builder = new Json.Builder();
|
||||
@ -823,37 +825,39 @@ public class Matrix.HTTPAPI : GLib.Object, Matrix.API {
|
||||
builder.add_value(creation_content);
|
||||
}
|
||||
|
||||
if (initial_state != null) {
|
||||
if (initial_state.length > 0) {
|
||||
builder.set_member_name("initial_state");
|
||||
builder.begin_array();
|
||||
initial_state.foreach(
|
||||
(entry) => {
|
||||
builder.add_value(entry.json);
|
||||
});
|
||||
|
||||
foreach (var entry in initial_state) {
|
||||
builder.add_value(entry.json);
|
||||
}
|
||||
|
||||
builder.end_array();
|
||||
}
|
||||
|
||||
if (invitees != null) {
|
||||
if (invitees.length > 0) {
|
||||
builder.set_member_name("invite");
|
||||
builder.begin_array();
|
||||
invitees.foreach(
|
||||
(entry) => {
|
||||
builder.add_string_value(entry);
|
||||
});
|
||||
|
||||
foreach (var entry in invitees) {
|
||||
builder.add_string_value(entry);
|
||||
}
|
||||
|
||||
builder.end_array();
|
||||
}
|
||||
|
||||
if (invite_3pids != null) {
|
||||
if (invite_3pids.length > 0) {
|
||||
builder.set_member_name("invite_3pid");
|
||||
builder.begin_array();
|
||||
invite_3pids.foreach(
|
||||
(entry) => {
|
||||
try {
|
||||
builder.add_value(entry.get_json_node());
|
||||
// TODO exceptions should be handled
|
||||
// here somehow
|
||||
} catch (Matrix.Error e) {}
|
||||
});
|
||||
|
||||
foreach (var entry in invite_3pids) {
|
||||
try {
|
||||
builder.add_value(entry.get_json_node());
|
||||
// TODO exceptions should be handled here somehow
|
||||
} catch (Matrix.Error e) {}
|
||||
}
|
||||
|
||||
builder.end_array();
|
||||
}
|
||||
|
||||
|
@ -135,13 +135,13 @@ login_finished(MatrixAPI *api,
|
||||
initial_sync_finished,
|
||||
data, 10, TRUE,
|
||||
NULL);
|
||||
matrix_api_create_room(api,
|
||||
create_room_finished, NULL,
|
||||
MATRIX_ROOM_PRESET_PUBLIC,
|
||||
"GLib SDK test room", "matrix-glib-sdk-test",
|
||||
"GLib SDK test room",
|
||||
MATRIX_ROOM_VISIBILITY_DEFAULT,
|
||||
NULL, NULL, NULL, NULL, NULL);
|
||||
matrix_api_create_room (api,
|
||||
create_room_finished, NULL,
|
||||
MATRIX_ROOM_PRESET_PUBLIC,
|
||||
"GLib SDK test room", "matrix-glib-sdk-test",
|
||||
"GLib SDK test room",
|
||||
MATRIX_ROOM_VISIBILITY_DEFAULT,
|
||||
NULL, NULL, 0, NULL, 0, NULL, 0, NULL);
|
||||
matrix_api_get_presence_list(api, NULL, NULL, user_id, NULL);
|
||||
matrix_api_get_presence(api,
|
||||
get_presence_finished, NULL,
|
||||
|
Loading…
Reference in New Issue
Block a user