Do actions
This commit is contained in:
parent
e1d3b84091
commit
17510ebeb4
|
@ -40,6 +40,7 @@ import app.fedilab.android.asynctasks.PostAdminActionAsyncTask;
|
||||||
import app.fedilab.android.client.API;
|
import app.fedilab.android.client.API;
|
||||||
import app.fedilab.android.client.APIResponse;
|
import app.fedilab.android.client.APIResponse;
|
||||||
import app.fedilab.android.client.Entities.AccountAdmin;
|
import app.fedilab.android.client.Entities.AccountAdmin;
|
||||||
|
import app.fedilab.android.client.Entities.AdminAction;
|
||||||
import app.fedilab.android.client.Entities.Report;
|
import app.fedilab.android.client.Entities.Report;
|
||||||
import app.fedilab.android.client.Entities.Status;
|
import app.fedilab.android.client.Entities.Status;
|
||||||
import app.fedilab.android.drawers.StatusReportAdapter;
|
import app.fedilab.android.drawers.StatusReportAdapter;
|
||||||
|
@ -47,10 +48,15 @@ import app.fedilab.android.helper.Helper;
|
||||||
import app.fedilab.android.interfaces.OnAdminActionInterface;
|
import app.fedilab.android.interfaces.OnAdminActionInterface;
|
||||||
import es.dmoral.toasty.Toasty;
|
import es.dmoral.toasty.Toasty;
|
||||||
|
|
||||||
|
import static app.fedilab.android.client.API.adminAction.DISABLE;
|
||||||
|
import static app.fedilab.android.client.API.adminAction.NONE;
|
||||||
|
import static app.fedilab.android.client.API.adminAction.SILENCE;
|
||||||
|
import static app.fedilab.android.client.API.adminAction.SUSPEND;
|
||||||
|
|
||||||
public class AccountReportActivity extends BaseActivity implements OnAdminActionInterface {
|
public class AccountReportActivity extends BaseActivity implements OnAdminActionInterface {
|
||||||
|
|
||||||
TextView permissions, username, email, email_status, login_status, joined, recent_ip;
|
TextView permissions, username, email, email_status, login_status, joined, recent_ip;
|
||||||
Button warn, disable, silence;
|
Button warn, disable, silence, suspend;
|
||||||
private String account_id;
|
private String account_id;
|
||||||
private CheckBox email_user;
|
private CheckBox email_user;
|
||||||
private EditText comment;
|
private EditText comment;
|
||||||
|
@ -94,6 +100,7 @@ public class AccountReportActivity extends BaseActivity implements OnAdminAction
|
||||||
warn = findViewById(R.id.warn);
|
warn = findViewById(R.id.warn);
|
||||||
disable = findViewById(R.id.disable);
|
disable = findViewById(R.id.disable);
|
||||||
silence = findViewById(R.id.silence);
|
silence = findViewById(R.id.silence);
|
||||||
|
suspend = findViewById(R.id.suspend);
|
||||||
|
|
||||||
permissions = findViewById(R.id.permissions);
|
permissions = findViewById(R.id.permissions);
|
||||||
username = findViewById(R.id.username);
|
username = findViewById(R.id.username);
|
||||||
|
@ -182,6 +189,8 @@ public class AccountReportActivity extends BaseActivity implements OnAdminAction
|
||||||
email_user.setVisibility(View.VISIBLE);
|
email_user.setVisibility(View.VISIBLE);
|
||||||
comment.setVisibility(View.VISIBLE);
|
comment.setVisibility(View.VISIBLE);
|
||||||
recent_ip.setText(accountAdmin.getIp());
|
recent_ip.setText(accountAdmin.getIp());
|
||||||
|
disable.setVisibility(View.GONE);
|
||||||
|
suspend.setVisibility(View.VISIBLE);
|
||||||
}else{
|
}else{
|
||||||
warn.setVisibility(View.GONE);
|
warn.setVisibility(View.GONE);
|
||||||
email_user.setVisibility(View.GONE);
|
email_user.setVisibility(View.GONE);
|
||||||
|
@ -190,8 +199,108 @@ public class AccountReportActivity extends BaseActivity implements OnAdminAction
|
||||||
recent_ip.setText("-");
|
recent_ip.setText("-");
|
||||||
permissions.setText("-");
|
permissions.setText("-");
|
||||||
email.setText("-");
|
email.setText("-");
|
||||||
|
disable.setVisibility(View.VISIBLE);
|
||||||
|
suspend.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
if( accountAdmin.getRole().equals("admin") || accountAdmin.getRole().equals("mod")){
|
||||||
|
warn.setVisibility(View.GONE);
|
||||||
|
suspend.setVisibility(View.GONE);
|
||||||
|
silence.setVisibility(View.GONE);
|
||||||
|
disable.setVisibility(View.GONE);
|
||||||
|
email_user.setVisibility(View.GONE);
|
||||||
|
email_user.setChecked(false);
|
||||||
|
comment.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
joined.setText(Helper.dateToString(accountAdmin.getCreated_at()));
|
joined.setText(Helper.dateToString(accountAdmin.getCreated_at()));
|
||||||
|
|
||||||
|
warn.setOnClickListener(view->{
|
||||||
|
AdminAction adminAction = new AdminAction();
|
||||||
|
adminAction.setType(NONE);
|
||||||
|
adminAction.setSend_email_notification(email_user.isChecked());
|
||||||
|
adminAction.setText(comment.getText().toString().trim());
|
||||||
|
new PostAdminActionAsyncTask(getApplicationContext(), NONE, account_id, null, AccountReportActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
if( !accountAdmin.isSilenced() ) {
|
||||||
|
silence.setText(getString(R.string.silence));
|
||||||
|
}else{
|
||||||
|
silence.setText(getString(R.string.unsilence));
|
||||||
|
}
|
||||||
|
silence.setOnClickListener(view->{
|
||||||
|
if( !accountAdmin.isSilenced() ) {
|
||||||
|
AdminAction adminAction = new AdminAction();
|
||||||
|
adminAction.setType(SILENCE);
|
||||||
|
adminAction.setSend_email_notification(email_user.isChecked());
|
||||||
|
adminAction.setText(comment.getText().toString().trim());
|
||||||
|
new PostAdminActionAsyncTask(getApplicationContext(), SILENCE, account_id, null, AccountReportActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
}else{
|
||||||
|
new PostAdminActionAsyncTask(getApplicationContext(), API.adminAction.UNSILENCE, account_id, null, AccountReportActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if( !accountAdmin.isSilenced() ) {
|
||||||
|
silence.setText(getString(R.string.disable));
|
||||||
|
}else{
|
||||||
|
silence.setText(getString(R.string.undisable));
|
||||||
|
}
|
||||||
|
disable.setOnClickListener(view->{
|
||||||
|
if( !accountAdmin.isSilenced()) {
|
||||||
|
AdminAction adminAction = new AdminAction();
|
||||||
|
adminAction.setType(DISABLE);
|
||||||
|
adminAction.setSend_email_notification(email_user.isChecked());
|
||||||
|
adminAction.setText(comment.getText().toString().trim());
|
||||||
|
new PostAdminActionAsyncTask(getApplicationContext(), DISABLE, account_id, null, AccountReportActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
}else{
|
||||||
|
new PostAdminActionAsyncTask(getApplicationContext(), API.adminAction.UNSUSPEND, account_id, null, AccountReportActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if( !accountAdmin.isSilenced() ) {
|
||||||
|
silence.setText(getString(R.string.suspend));
|
||||||
|
}else{
|
||||||
|
silence.setText(getString(R.string.unsuspend));
|
||||||
|
}
|
||||||
|
suspend.setOnClickListener(view->{
|
||||||
|
if( !accountAdmin.isSuspended() ){
|
||||||
|
AdminAction adminAction = new AdminAction();
|
||||||
|
adminAction.setType(SUSPEND);
|
||||||
|
adminAction.setSend_email_notification(email_user.isChecked());
|
||||||
|
adminAction.setText(comment.getText().toString().trim());
|
||||||
|
new PostAdminActionAsyncTask(getApplicationContext(), SUSPEND, account_id, null, AccountReportActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
}else{
|
||||||
|
new PostAdminActionAsyncTask(getApplicationContext(), API.adminAction.UNSUSPEND, account_id, null, AccountReportActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if( accountAdmin.getAction() != null) {
|
||||||
|
String message = null;
|
||||||
|
switch (accountAdmin.getAction()) {
|
||||||
|
case SILENCE:
|
||||||
|
message = getString(R.string.account_silenced);
|
||||||
|
break;
|
||||||
|
case UNSILENCE:
|
||||||
|
message = getString(R.string.account_unsilenced);
|
||||||
|
break;
|
||||||
|
case DISABLE:
|
||||||
|
message = getString(R.string.account_disabled);
|
||||||
|
break;
|
||||||
|
case UNDISABLE:
|
||||||
|
message = getString(R.string.account_undisabled);
|
||||||
|
break;
|
||||||
|
case SUSPEND:
|
||||||
|
message = getString(R.string.account_suspended);
|
||||||
|
break;
|
||||||
|
case UNSUSPEND:
|
||||||
|
message = getString(R.string.account_unsuspended);
|
||||||
|
break;
|
||||||
|
case NONE:
|
||||||
|
message = getString(R.string.account_warned);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if( message != null){
|
||||||
|
Toasty.success(getApplicationContext(), message, Toast.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -124,13 +124,17 @@ public class API {
|
||||||
ENABLE,
|
ENABLE,
|
||||||
APPROVE,
|
APPROVE,
|
||||||
REJECT,
|
REJECT,
|
||||||
|
NONE,
|
||||||
|
SILENCE,
|
||||||
|
UNDISABLE,
|
||||||
|
DISABLE,
|
||||||
UNSILENCE,
|
UNSILENCE,
|
||||||
|
SUSPEND,
|
||||||
UNSUSPEND,
|
UNSUSPEND,
|
||||||
ASSIGN_TO_SELF,
|
ASSIGN_TO_SELF,
|
||||||
UNASSIGN,
|
UNASSIGN,
|
||||||
REOPEN,
|
REOPEN,
|
||||||
RESOLVE,
|
RESOLVE,
|
||||||
MODERATION_ACTION,
|
|
||||||
GET_ACCOUNTS,
|
GET_ACCOUNTS,
|
||||||
GET_ONE_ACCOUNT,
|
GET_ONE_ACCOUNT,
|
||||||
GET_REPORTS,
|
GET_REPORTS,
|
||||||
|
@ -335,22 +339,36 @@ public class API {
|
||||||
case RESOLVE:
|
case RESOLVE:
|
||||||
endpoint = String.format("/admin/reports/%s/resolve", id);
|
endpoint = String.format("/admin/reports/%s/resolve", id);
|
||||||
break;
|
break;
|
||||||
case MODERATION_ACTION:
|
|
||||||
params = new HashMap<>();
|
|
||||||
switch (adminAction.getType()){
|
|
||||||
case NONE:
|
case NONE:
|
||||||
|
params = new HashMap<>();
|
||||||
params.put("type","none");
|
params.put("type","none");
|
||||||
|
endpoint = String.format("/admin/accounts/%s/action", id);
|
||||||
|
params.put("send_email_notification", String.valueOf(adminAction.isSend_email_notification()));
|
||||||
|
if( adminAction.getText() != null) {
|
||||||
|
params.put("text", adminAction.getText());
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case DISABLE:
|
case DISABLE:
|
||||||
|
params = new HashMap<>();
|
||||||
params.put("type","disable");
|
params.put("type","disable");
|
||||||
|
endpoint = String.format("/admin/accounts/%s/action", id);
|
||||||
|
params.put("send_email_notification", String.valueOf(adminAction.isSend_email_notification()));
|
||||||
|
if( adminAction.getText() != null) {
|
||||||
|
params.put("text", adminAction.getText());
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case SILENCE:
|
case SILENCE:
|
||||||
|
params = new HashMap<>();
|
||||||
params.put("type","silence");
|
params.put("type","silence");
|
||||||
|
endpoint = String.format("/admin/accounts/%s/action", id);
|
||||||
|
params.put("send_email_notification", String.valueOf(adminAction.isSend_email_notification()));
|
||||||
|
if( adminAction.getText() != null) {
|
||||||
|
params.put("text", adminAction.getText());
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case SUSPEND:
|
case SUSPEND:
|
||||||
|
params = new HashMap<>();
|
||||||
params.put("type","suspend");
|
params.put("type","suspend");
|
||||||
break;
|
|
||||||
}
|
|
||||||
endpoint = String.format("/admin/accounts/%s/action", id);
|
endpoint = String.format("/admin/accounts/%s/action", id);
|
||||||
params.put("send_email_notification", String.valueOf(adminAction.isSend_email_notification()));
|
params.put("send_email_notification", String.valueOf(adminAction.isSend_email_notification()));
|
||||||
if( adminAction.getText() != null) {
|
if( adminAction.getText() != null) {
|
||||||
|
@ -369,6 +387,7 @@ public class API {
|
||||||
List<AccountAdmin> accountAdmins = null;
|
List<AccountAdmin> accountAdmins = null;
|
||||||
try {
|
try {
|
||||||
AccountAdmin accountAdmin = parseAccountAdminResponse(context, new JSONObject(response));
|
AccountAdmin accountAdmin = parseAccountAdminResponse(context, new JSONObject(response));
|
||||||
|
accountAdmin.setAction(action);
|
||||||
accountAdmins = new ArrayList<>();
|
accountAdmins = new ArrayList<>();
|
||||||
accountAdmins.add(accountAdmin);
|
accountAdmins.add(accountAdmin);
|
||||||
} catch (JSONException e) {
|
} catch (JSONException e) {
|
||||||
|
@ -392,7 +411,31 @@ public class API {
|
||||||
apiResponse.setReports(reports);
|
apiResponse.setReports(reports);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case MODERATION_ACTION:
|
case NONE:
|
||||||
|
break;
|
||||||
|
case DISABLE:
|
||||||
|
accountAdmins = new ArrayList<>();
|
||||||
|
AccountAdmin accountAdmin = new AccountAdmin();
|
||||||
|
accountAdmin.setDisabled(true);
|
||||||
|
accountAdmin.setAction(action);
|
||||||
|
accountAdmins.add(accountAdmin);
|
||||||
|
apiResponse.setAccountAdmins(accountAdmins);
|
||||||
|
break;
|
||||||
|
case SILENCE:
|
||||||
|
accountAdmins = new ArrayList<>();
|
||||||
|
accountAdmin = new AccountAdmin();
|
||||||
|
accountAdmin.setSilenced(true);
|
||||||
|
accountAdmin.setAction(action);
|
||||||
|
accountAdmins.add(accountAdmin);
|
||||||
|
apiResponse.setAccountAdmins(accountAdmins);
|
||||||
|
break;
|
||||||
|
case SUSPEND:
|
||||||
|
accountAdmins = new ArrayList<>();
|
||||||
|
accountAdmin = new AccountAdmin();
|
||||||
|
accountAdmin.setSuspended(true);
|
||||||
|
accountAdmin.setAction(action);
|
||||||
|
accountAdmins.add(accountAdmin);
|
||||||
|
apiResponse.setAccountAdmins(accountAdmins);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
|
|
@ -18,6 +18,8 @@ import android.os.Parcelable;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
|
import app.fedilab.android.client.API;
|
||||||
|
|
||||||
public class AccountAdmin implements Parcelable {
|
public class AccountAdmin implements Parcelable {
|
||||||
|
|
||||||
private String id;
|
private String id;
|
||||||
|
@ -32,7 +34,7 @@ public class AccountAdmin implements Parcelable {
|
||||||
private boolean silenced;
|
private boolean silenced;
|
||||||
private boolean disabled;
|
private boolean disabled;
|
||||||
private Account account;
|
private Account account;
|
||||||
|
private API.adminAction action;
|
||||||
|
|
||||||
public String getId() {
|
public String getId() {
|
||||||
return id;
|
return id;
|
||||||
|
@ -182,4 +184,12 @@ public class AccountAdmin implements Parcelable {
|
||||||
return new AccountAdmin[size];
|
return new AccountAdmin[size];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
public API.adminAction getAction() {
|
||||||
|
return action;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAction(API.adminAction action) {
|
||||||
|
this.action = action;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
package app.fedilab.android.client.Entities;
|
package app.fedilab.android.client.Entities;
|
||||||
|
|
||||||
|
import app.fedilab.android.client.API;
|
||||||
|
|
||||||
/* Copyright 2019 Thomas Schneider
|
/* Copyright 2019 Thomas Schneider
|
||||||
*
|
*
|
||||||
* This file is a part of Fedilab
|
* This file is a part of Fedilab
|
||||||
|
@ -16,14 +19,8 @@ package app.fedilab.android.client.Entities;
|
||||||
public class AdminAction {
|
public class AdminAction {
|
||||||
|
|
||||||
|
|
||||||
public enum adminActionType{
|
|
||||||
NONE,
|
|
||||||
DISABLE,
|
|
||||||
SILENCE,
|
|
||||||
SUSPEND
|
|
||||||
}
|
|
||||||
|
|
||||||
private adminActionType type;
|
private API.adminAction type;
|
||||||
private boolean send_email_notification;
|
private boolean send_email_notification;
|
||||||
private String text;
|
private String text;
|
||||||
private boolean unresolved;
|
private boolean unresolved;
|
||||||
|
@ -96,13 +93,6 @@ public class AdminAction {
|
||||||
this.unresolved = unresolved;
|
this.unresolved = unresolved;
|
||||||
}
|
}
|
||||||
|
|
||||||
public adminActionType getType() {
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setType(adminActionType type) {
|
|
||||||
this.type = type;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isSend_email_notification() {
|
public boolean isSend_email_notification() {
|
||||||
return send_email_notification;
|
return send_email_notification;
|
||||||
|
@ -121,6 +111,11 @@ public class AdminAction {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public API.adminAction getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setType(API.adminAction type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -209,6 +209,19 @@
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/stats_bottom_barrier" />
|
app:layout_constraintTop_toBottomOf="@id/stats_bottom_barrier" />
|
||||||
|
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/silence"
|
||||||
|
style="@style/Base.Widget.AppCompat.Button.Colored"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="50dp"
|
||||||
|
android:layout_marginTop="20dp"
|
||||||
|
android:text="@string/silence"
|
||||||
|
android:textSize="16sp"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toEndOf="@id/disable"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/stats_bottom_barrier" />
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/disable"
|
android:id="@+id/disable"
|
||||||
style="@style/Base.Widget.AppCompat.Button.Colored"
|
style="@style/Base.Widget.AppCompat.Button.Colored"
|
||||||
|
@ -221,8 +234,9 @@
|
||||||
app:layout_constraintStart_toEndOf="@id/warn"
|
app:layout_constraintStart_toEndOf="@id/warn"
|
||||||
app:layout_constraintTop_toBottomOf="@id/stats_bottom_barrier" />
|
app:layout_constraintTop_toBottomOf="@id/stats_bottom_barrier" />
|
||||||
|
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/silence"
|
android:id="@+id/suspend"
|
||||||
style="@style/Base.Widget.AppCompat.Button.Colored"
|
style="@style/Base.Widget.AppCompat.Button.Colored"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="50dp"
|
android:layout_height="50dp"
|
||||||
|
@ -230,7 +244,7 @@
|
||||||
android:text="@string/silence"
|
android:text="@string/silence"
|
||||||
android:textSize="16sp"
|
android:textSize="16sp"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toEndOf="@id/disable"
|
app:layout_constraintStart_toEndOf="@id/suspend"
|
||||||
app:layout_constraintTop_toBottomOf="@id/stats_bottom_barrier" />
|
app:layout_constraintTop_toBottomOf="@id/stats_bottom_barrier" />
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.Barrier
|
<androidx.constraintlayout.widget.Barrier
|
||||||
|
|
|
@ -1059,6 +1059,17 @@
|
||||||
<string name="unconfirmed">Not confirmed</string>
|
<string name="unconfirmed">Not confirmed</string>
|
||||||
<string name="list_reported_statuses">Reported statuses</string>
|
<string name="list_reported_statuses">Reported statuses</string>
|
||||||
<string name="account">Account</string>
|
<string name="account">Account</string>
|
||||||
|
<string name="unsilence">Undo silence</string>
|
||||||
|
<string name="undisable">Undo disable</string>
|
||||||
|
<string name="suspend">Suspend</string>
|
||||||
|
<string name="unsuspend">Undo suspend</string>
|
||||||
|
<string name="account_silenced">The account is silenced!</string>
|
||||||
|
<string name="account_unsilenced">The account is no longer silenced!</string>
|
||||||
|
<string name="account_suspended">The account is suspended!</string>
|
||||||
|
<string name="account_unsuspended">The account is no longer suspended!</string>
|
||||||
|
<string name="account_disabled">The account is disabled!</string>
|
||||||
|
<string name="account_undisabled">The account is no longer disabled!</string>
|
||||||
|
<string name="account_warned">The account has been warned!</string>
|
||||||
<plurals name="number_of_vote">
|
<plurals name="number_of_vote">
|
||||||
<item quantity="one">%d vote</item>
|
<item quantity="one">%d vote</item>
|
||||||
<item quantity="other">%d votes</item>
|
<item quantity="other">%d votes</item>
|
||||||
|
|
Loading…
Reference in New Issue