diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index f69f8a04d..28cad2a69 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -232,6 +232,16 @@
android:configChanges="orientation|screenSize"
android:label="@string/app_name"
/>
+
+
. */
+
+import android.annotation.SuppressLint;
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.graphics.PorterDuff;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.Button;
+import android.widget.CheckBox;
+import android.widget.EditText;
+import android.widget.ImageView;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import androidx.appcompat.app.ActionBar;
+import androidx.constraintlayout.widget.Group;
+import androidx.core.content.ContextCompat;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+import java.util.ArrayList;
+
+import app.fedilab.android.R;
+import app.fedilab.android.asynctasks.PostAdminActionAsyncTask;
+import app.fedilab.android.client.API;
+import app.fedilab.android.client.APIResponse;
+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.Status;
+import app.fedilab.android.drawers.StatusReportAdapter;
+import app.fedilab.android.helper.Helper;
+import app.fedilab.android.interfaces.OnAdminActionInterface;
+import es.dmoral.toasty.Toasty;
+
+import static app.fedilab.android.client.API.adminAction.APPROVE;
+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.REJECT;
+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 {
+
+ TextView permissions, username, email, email_status, login_status, joined, recent_ip, comment_label;
+ Button warn, disable, silence, suspend, allow, reject, assign, status;
+ private String account_id;
+ private CheckBox email_user;
+ private EditText comment;
+ private Report report;
+ private Group allow_reject_group;
+
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, MODE_PRIVATE);
+
+ setTheme(R.style.AppAdminTheme);
+ report = null;
+ AccountAdmin targeted_account = null;
+ Bundle b = getIntent().getExtras();
+
+ if (b != null) {
+ account_id = b.getString("account_id", null);
+ targeted_account = b.getParcelable("targeted_account");
+ report = b.getParcelable("report");
+ }
+
+ if (getSupportActionBar() != null)
+ getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+ ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ LayoutInflater inflater = (LayoutInflater) this.getSystemService(LAYOUT_INFLATER_SERVICE);
+ assert inflater != null;
+ @SuppressLint("InflateParams") View view = inflater.inflate(R.layout.simple_bar, null);
+ actionBar.setCustomView(view, new ActionBar.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
+ actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
+ ImageView toolbar_close = actionBar.getCustomView().findViewById(R.id.toolbar_close);
+ TextView toolbar_title = actionBar.getCustomView().findViewById(R.id.toolbar_title);
+ toolbar_close.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ finish();
+ }
+ });
+ toolbar_title.setText(String.format(getString(R.string.administration) + " %s", Helper.getLiveInstance(getApplicationContext())));
+ }
+ setContentView(R.layout.activity_admin_report);
+
+ warn = findViewById(R.id.warn);
+ disable = findViewById(R.id.disable);
+ silence = findViewById(R.id.silence);
+ suspend = findViewById(R.id.suspend);
+ allow = findViewById(R.id.allow);
+ reject = findViewById(R.id.reject);
+ status = findViewById(R.id.status);
+ assign = findViewById(R.id.assign);
+ allow_reject_group = findViewById(R.id.allow_reject_group);
+ allow_reject_group.setVisibility(View.GONE);
+ allow.getBackground().setColorFilter(ContextCompat.getColor(getApplicationContext(), R.color.green_1), PorterDuff.Mode.MULTIPLY);
+ reject.getBackground().setColorFilter(ContextCompat.getColor(getApplicationContext(), R.color.red_1), PorterDuff.Mode.MULTIPLY);
+ comment_label = findViewById(R.id.comment_label);
+ permissions = findViewById(R.id.permissions);
+ username = findViewById(R.id.username);
+ email = findViewById(R.id.email);
+ email_status = findViewById(R.id.email_status);
+ login_status = findViewById(R.id.login_status);
+ joined = findViewById(R.id.joined);
+ recent_ip = findViewById(R.id.recent_ip);
+
+ email_user = findViewById(R.id.email_user);
+ comment = findViewById(R.id.comment);
+
+ if( account_id == null && report == null && targeted_account == null){
+ Toasty.error(getApplicationContext(), getString(R.string.toast_error), Toast.LENGTH_LONG).show();
+ finish();
+ }
+ assign.setVisibility(View.GONE);
+ status.setVisibility(View.GONE);
+ if( account_id != null){
+ new PostAdminActionAsyncTask(getApplicationContext(), API.adminAction.GET_ONE_ACCOUNT, account_id, null, AccountReportActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ return;
+ }
+ if( report != null) {
+ targeted_account = report.getTarget_account();
+ RecyclerView lv_statuses = findViewById(R.id.lv_statuses);
+
+ ArrayList contents = new ArrayList<>();
+ for(Status status: report.getStatuses()){
+ contents.add(status.getContent());
+ }
+ lv_statuses.setLayoutManager(new LinearLayoutManager(this));
+ StatusReportAdapter adapter = new StatusReportAdapter(this, contents);
+ lv_statuses.setAdapter(adapter);
+
+ Group statuses_group = findViewById(R.id.statuses_group);
+ statuses_group.setVisibility(View.VISIBLE);
+ }
+ account_id = targeted_account.getId();
+ fillReport(targeted_account);
+
+ }
+
+ @Override
+ public void onAdminAction(APIResponse apiResponse) {
+ if( apiResponse.getError() != null){
+ if( apiResponse.getError().getStatusCode() == 403){
+ AlertDialog.Builder builderInner;
+ builderInner = new AlertDialog.Builder(AccountReportActivity.this, R.style.AdminDialog);
+ builderInner.setTitle(R.string.reconnect_account);
+ builderInner.setMessage(R.string.reconnect_account_message);
+ builderInner.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog,int which) {
+ dialog.dismiss();
+ }
+ });
+ builderInner.setPositiveButton(R.string.validate, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog,int which) {
+ Intent intent = new Intent(AccountReportActivity.this, LoginActivity.class);
+ intent.putExtra("admin", true);
+ startActivity(intent);
+ }
+ });
+ builderInner.show();
+ }else{
+ Toasty.error(AccountReportActivity.this, apiResponse.getError().getError(),Toast.LENGTH_LONG).show();
+ }
+ return;
+ }
+ if( apiResponse.getReports() != null && apiResponse.getReports().size() > 0){
+ report = apiResponse.getReports().get(0);
+ fillReport(apiResponse.getAccountAdmins().get(0));
+ } else if( apiResponse.getAccountAdmins() != null && apiResponse.getAccountAdmins().size() > 0) {
+ fillReport(apiResponse.getAccountAdmins().get(0));
+ }
+
+ }
+
+ private void fillReport(AccountAdmin accountAdmin){
+
+ if( accountAdmin == null){
+ Toasty.error(getApplicationContext(), getString(R.string.toast_error), Toast.LENGTH_LONG).show();
+ return;
+ }
+ if(!accountAdmin.isApproved()){
+ allow_reject_group.setVisibility(View.VISIBLE);
+ }
+
+ reject.setOnClickListener(view->{
+ AdminAction adminAction = new AdminAction();
+ adminAction.setType(REJECT);
+ new PostAdminActionAsyncTask(getApplicationContext(), REJECT, account_id, adminAction, AccountReportActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ });
+
+ allow.setOnClickListener(view->{
+ AdminAction adminAction = new AdminAction();
+ adminAction.setType(APPROVE);
+ new PostAdminActionAsyncTask(getApplicationContext(), APPROVE, account_id, adminAction, AccountReportActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ });
+
+ 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, adminAction, 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, adminAction, 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.isDisabled() ) {
+ disable.setText(getString(R.string.disable));
+ }else{
+ disable.setText(getString(R.string.undisable));
+ }
+ disable.setOnClickListener(view->{
+ if( !accountAdmin.isDisabled()) {
+ 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, adminAction, AccountReportActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ }else{
+ new PostAdminActionAsyncTask(getApplicationContext(), API.adminAction.ENABLE, account_id, null, AccountReportActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ }
+ });
+ if( !accountAdmin.isSuspended() ) {
+ suspend.setText(getString(R.string.suspend));
+ }else{
+ suspend.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, adminAction, 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 ENABLE:
+ 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;
+ case APPROVE:
+ allow_reject_group.setVisibility(View.GONE);
+ message = getString(R.string.account_approved);
+ break;
+ case REJECT:
+ allow_reject_group.setVisibility(View.GONE);
+
+ message = getString(R.string.account_rejected);
+ break;
+ }
+ if( message != null){
+ Toasty.success(getApplicationContext(), message, Toast.LENGTH_LONG).show();
+ }
+ comment.setText("");
+ InputMethodManager imm = (InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE);
+ imm.hideSoftInputFromWindow(comment.getWindowToken(), 0);
+ }
+ if( accountAdmin.getRole() == null) {
+ return;
+ }
+
+ switch (accountAdmin.getRole()) {
+ case "user":
+ permissions.setText(getString(R.string.user));
+ break;
+ case "mod":
+ permissions.setText(getString(R.string.moderator));
+ break;
+ case "admin":
+ permissions.setText(getString(R.string.administrator));
+ break;
+ }
+
+
+ username.setText(String.format("@%s", accountAdmin.getAccount().getAcct()));
+
+ email.setText(accountAdmin.getEmail());
+ email_status.setText(accountAdmin.isConfirmed()?getString(R.string.confirmed):getString(R.string.unconfirmed));
+
+ if( accountAdmin.isDisabled()){
+ login_status.setText(getString(R.string.disabled));
+ }else if( accountAdmin.isSilenced()){
+ login_status.setText(getString(R.string.silenced));
+ }else if( accountAdmin.isSuspended()){
+ login_status.setText(getString(R.string.suspended));
+ }else{
+ login_status.setText(getString(R.string.active));
+ }
+ if( accountAdmin.getDomain() == null || accountAdmin.getDomain().equals("null")){
+ warn.setVisibility(View.VISIBLE);
+ email_user.setVisibility(View.VISIBLE);
+ comment_label.setVisibility(View.VISIBLE);
+ comment.setVisibility(View.VISIBLE);
+ recent_ip.setText(accountAdmin.getIp());
+ disable.setVisibility(View.VISIBLE);
+ suspend.setVisibility(View.VISIBLE);
+ }else{
+ warn.setVisibility(View.GONE);
+ email_user.setVisibility(View.GONE);
+ email_user.setChecked(false);
+ comment.setVisibility(View.GONE);
+ recent_ip.setText("-");
+ permissions.setText("-");
+ email.setText("-");
+ disable.setVisibility(View.GONE);
+ suspend.setVisibility(View.VISIBLE);
+ comment_label.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);
+ comment_label.setVisibility(View.GONE);
+ }
+ joined.setText(Helper.dateToString(accountAdmin.getCreated_at()));
+
+
+ if( report != null){
+ assign.setVisibility(View.VISIBLE);
+ status.setVisibility(View.VISIBLE);
+ if( report.getAssigned_account() == null){
+ assign.setText(getString(R.string.assign_to_me));
+ }else{
+ assign.setText(getString(R.string.unassign));
+ }
+ assign.setOnClickListener(view ->{
+ if( report.getAssigned_account() == null){
+ new PostAdminActionAsyncTask(getApplicationContext(), API.adminAction.ASSIGN_TO_SELF, report.getId(), null, AccountReportActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ }else{
+ new PostAdminActionAsyncTask(getApplicationContext(), API.adminAction.UNASSIGN, report.getId(), null, AccountReportActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ }
+ });
+
+ if( report.isAction_taken()){
+ status.setText(getString(R.string.mark_unresolved));
+ }else{
+ status.setText(getString(R.string.mark_resolved));
+ }
+ status.setOnClickListener(view ->{
+ if( report.isAction_taken() ){
+ new PostAdminActionAsyncTask(getApplicationContext(), API.adminAction.REOPEN, report.getId(), null, AccountReportActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ }else{
+ new PostAdminActionAsyncTask(getApplicationContext(), API.adminAction.RESOLVE, report.getId(), null, AccountReportActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ }
+ });
+
+ }else{
+ assign.setVisibility(View.GONE);
+ status.setVisibility(View.GONE);
+ }
+
+ }
+}
diff --git a/app/src/main/java/app/fedilab/android/activities/AdminActivity.java b/app/src/main/java/app/fedilab/android/activities/AdminActivity.java
new file mode 100644
index 000000000..26204888f
--- /dev/null
+++ b/app/src/main/java/app/fedilab/android/activities/AdminActivity.java
@@ -0,0 +1,363 @@
+/* Copyright 2019 Thomas Schneider
+ *
+ * This file is a part of Fedilab
+ *
+ * This program is free software; you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * Fedilab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with Fedilab; if not,
+ * see . */
+package app.fedilab.android.activities;
+
+import android.annotation.SuppressLint;
+import android.content.SharedPreferences;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+import androidx.appcompat.app.ActionBar;
+import androidx.appcompat.widget.PopupMenu;
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentManager;
+import androidx.fragment.app.FragmentStatePagerAdapter;
+import androidx.fragment.app.FragmentTransaction;
+import androidx.viewpager.widget.PagerAdapter;
+import androidx.viewpager.widget.ViewPager;
+import com.google.android.material.tabs.TabLayout;
+import app.fedilab.android.R;
+import app.fedilab.android.fragments.DisplayAdminAccountsFragment;
+import app.fedilab.android.fragments.DisplayAdminReportsFragment;
+import app.fedilab.android.fragments.DisplayStatusFragment;
+import app.fedilab.android.helper.Helper;
+
+import static app.fedilab.android.activities.BaseMainActivity.mPageReferenceMap;
+
+
+/**
+ * Created by Thomas on 19/06/2019.
+ * Admin activity
+ */
+
+public class AdminActivity extends BaseActivity {
+
+
+ private boolean unresolved;
+ private boolean local, remote, active, pending, disabled, silenced, suspended;
+ private DisplayAdminReportsFragment displayAdminReportsFragment;
+ private DisplayAdminAccountsFragment displayAdminAccountsFragment;
+
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, MODE_PRIVATE);
+
+ setTheme(R.style.AppAdminTheme);
+
+ if( getSupportActionBar() != null)
+ getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+ ActionBar actionBar = getSupportActionBar();
+ if( actionBar != null ) {
+ LayoutInflater inflater = (LayoutInflater) this.getSystemService(LAYOUT_INFLATER_SERVICE);
+ assert inflater != null;
+ @SuppressLint("InflateParams") View view = inflater.inflate(R.layout.simple_bar, null);
+ actionBar.setCustomView(view, new ActionBar.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
+ actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
+ ImageView toolbar_close = actionBar.getCustomView().findViewById(R.id.toolbar_close);
+ TextView toolbar_title = actionBar.getCustomView().findViewById(R.id.toolbar_title);
+ toolbar_close.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ finish();
+ }
+ });
+ toolbar_title.setText(String.format(getString(R.string.administration)+ " %s", Helper.getLiveInstance(getApplicationContext())));
+ }
+ setContentView(R.layout.activity_admin);
+ unresolved = local = active = true;
+ remote = pending = disabled = silenced = suspended = false;
+ ViewPager admin_viewpager = findViewById(R.id.admin_viewpager);
+
+ TabLayout admin_tablayout = findViewById(R.id.admin_tablayout);
+ admin_tablayout.addTab(admin_tablayout.newTab().setText(getString(R.string.reports)));
+ admin_tablayout.addTab(admin_tablayout.newTab().setText(getString(R.string.accounts)));
+
+
+ final LinearLayout tabStrip = (LinearLayout) admin_tablayout.getChildAt(0);
+ tabStrip.getChildAt(0).setOnLongClickListener(new View.OnLongClickListener() {
+ @Override
+ public boolean onLongClick(View v) {
+ PopupMenu popup = new PopupMenu(AdminActivity.this, tabStrip.getChildAt(0));
+ popup.getMenuInflater()
+ .inflate(R.menu.option_filter_admin_reports, popup.getMenu());
+ Menu menu = popup.getMenu();
+ final MenuItem itemUnresolved = menu.findItem(R.id.action_unresolved_reports);
+
+
+ itemUnresolved.setChecked(unresolved);
+
+ popup.setOnDismissListener(new PopupMenu.OnDismissListener() {
+ @Override
+ public void onDismiss(PopupMenu menu) {
+ FragmentTransaction fragTransaction = getSupportFragmentManager().beginTransaction();
+ fragTransaction.detach(displayAdminReportsFragment);
+ Bundle bundle = new Bundle();
+ bundle.putBoolean("unresolved",unresolved);
+ displayAdminReportsFragment.setArguments(bundle);
+ fragTransaction.attach(displayAdminReportsFragment);
+ fragTransaction.commit();
+ }
+ });
+ popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
+ public boolean onMenuItemClick(MenuItem item) {
+ item.setShowAsAction(MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW);
+ item.setActionView(new View(getApplicationContext()));
+ item.setOnActionExpandListener(new MenuItem.OnActionExpandListener() {
+ @Override
+ public boolean onMenuItemActionExpand(MenuItem item) {
+ return false;
+ }
+
+ @Override
+ public boolean onMenuItemActionCollapse(MenuItem item) {
+ return false;
+ }
+ });
+ if (item.getItemId() == R.id.action_unresolved_reports) {
+ unresolved = !unresolved;
+ }
+ itemUnresolved.setChecked(unresolved);
+ return false;
+ }
+ });
+ popup.show();
+ return true;
+ }
+ });
+
+
+ tabStrip.getChildAt(1).setOnLongClickListener(new View.OnLongClickListener() {
+ @Override
+ public boolean onLongClick(View v) {
+ PopupMenu popup = new PopupMenu(AdminActivity.this, tabStrip.getChildAt(1));
+ popup.getMenuInflater()
+ .inflate(R.menu.option_filter_admin_accounts, popup.getMenu());
+ Menu menu = popup.getMenu();
+ final MenuItem itemLocal = menu.findItem(R.id.action_local);
+ final MenuItem itemRemote = menu.findItem(R.id.action_remote);
+ final MenuItem itemActive = menu.findItem(R.id.action_active);
+ final MenuItem itemPending = menu.findItem(R.id.action_pending);
+ final MenuItem itemDisabled = menu.findItem(R.id.action_disabled);
+ final MenuItem itemSilenced = menu.findItem(R.id.action_silenced);
+ final MenuItem itemSuspended = menu.findItem(R.id.action_suspended);
+
+ itemLocal.setChecked(local);
+ itemRemote.setChecked(remote);
+ itemActive.setChecked(active);
+ itemPending.setChecked(pending);
+ itemDisabled.setChecked(disabled);
+ itemSilenced.setChecked(silenced);
+ itemSuspended.setChecked(suspended);
+
+ popup.setOnDismissListener(new PopupMenu.OnDismissListener() {
+ @Override
+ public void onDismiss(PopupMenu menu) {
+ FragmentTransaction fragTransaction = getSupportFragmentManager().beginTransaction();
+ fragTransaction.detach(displayAdminAccountsFragment);
+ Bundle bundle = new Bundle();
+ bundle.putBoolean("local",local);
+ bundle.putBoolean("remote",remote);
+ bundle.putBoolean("active",active);
+ bundle.putBoolean("pending",pending);
+ bundle.putBoolean("disabled",disabled);
+ bundle.putBoolean("silenced",silenced);
+ bundle.putBoolean("suspended",suspended);
+ displayAdminAccountsFragment.setArguments(bundle);
+ fragTransaction.attach(displayAdminAccountsFragment);
+ fragTransaction.commit();
+
+ }
+ });
+ popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
+ public boolean onMenuItemClick(MenuItem item) {
+ item.setShowAsAction(MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW);
+ item.setActionView(new View(getApplicationContext()));
+ item.setOnActionExpandListener(new MenuItem.OnActionExpandListener() {
+ @Override
+ public boolean onMenuItemActionExpand(MenuItem item) {
+ return false;
+ }
+
+ @Override
+ public boolean onMenuItemActionCollapse(MenuItem item) {
+ return false;
+ }
+ });
+ switch (item.getItemId()){
+ case R.id.action_local:
+ if( !local) {
+ remote = false;
+ local = true;
+ }
+ break;
+ case R.id.action_remote:
+ if( !remote) {
+ remote = true;
+ local = false;
+ }
+ break;
+ case R.id.action_active:
+ if( !active) {
+ active = true;
+ pending = false;
+ disabled = false;
+ silenced = false;
+ suspended = false;
+ }
+ break;
+ case R.id.action_pending:
+ if( !pending) {
+ pending = true;
+ active = false;
+ disabled = false;
+ silenced = false;
+ suspended = false;
+ }
+ break;
+ case R.id.action_disabled:
+ if( !disabled) {
+ disabled = true;
+ active = false;
+ pending = false;
+ silenced = false;
+ suspended = false;
+ }
+ break;
+ case R.id.action_silenced:
+ if( !silenced) {
+ silenced = true;
+ active = false;
+ pending = false;
+ disabled = false;
+ suspended = false;
+ }
+ break;
+ case R.id.action_suspended:
+ if( !suspended) {
+ suspended = true;
+ active = false;
+ pending = false;
+ disabled = false;
+ silenced = false;
+ }
+ break;
+ }
+
+ itemLocal.setChecked(local);
+ itemRemote.setChecked(remote);
+ itemActive.setChecked(active);
+ itemPending.setChecked(pending);
+ itemDisabled.setChecked(disabled);
+ itemSilenced.setChecked(silenced);
+ itemSuspended.setChecked(suspended);
+ return false;
+ }
+ });
+ popup.show();
+ return true;
+ }
+ });
+
+
+
+ PagerAdapter mPagerAdapter = new AdminPagerAdapter(getSupportFragmentManager());
+ admin_viewpager.setAdapter(mPagerAdapter);
+ admin_viewpager.setOffscreenPageLimit(2);
+ admin_viewpager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(admin_tablayout));
+ admin_tablayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
+ @Override
+ public void onTabSelected(TabLayout.Tab tab) {
+ admin_viewpager.setCurrentItem(tab.getPosition());
+ }
+
+ @Override
+ public void onTabUnselected(TabLayout.Tab tab) {
+
+ }
+
+ @Override
+ public void onTabReselected(TabLayout.Tab tab) {
+ Fragment fragment = null;
+ if( admin_viewpager.getAdapter() != null)
+ fragment = (Fragment) admin_viewpager.getAdapter().instantiateItem(admin_viewpager, tab.getPosition());
+ switch (tab.getPosition()){
+ case 0:
+ if( fragment != null) {
+ displayAdminReportsFragment = ((DisplayAdminReportsFragment) fragment);
+ displayAdminReportsFragment.scrollToTop();
+ }
+ break;
+ case 1:
+ if( fragment != null) {
+ displayAdminAccountsFragment = ((DisplayAdminAccountsFragment) fragment);
+ displayAdminAccountsFragment.scrollToTop();
+ }
+ break;
+
+ }
+ }
+ });
+
+ }
+
+
+ private class AdminPagerAdapter extends FragmentStatePagerAdapter {
+
+ AdminPagerAdapter(FragmentManager fm) {
+ super(fm);
+ }
+
+ @Override
+ public Fragment getItem(int position) {
+ Bundle bundle = new Bundle();
+ switch (position){
+ case 0:
+ displayAdminReportsFragment = new DisplayAdminReportsFragment();
+ bundle = new Bundle();
+ bundle.putBoolean("unresolved",unresolved);
+ displayAdminReportsFragment.setArguments(bundle);
+ return displayAdminReportsFragment;
+ case 1:
+ displayAdminAccountsFragment = new DisplayAdminAccountsFragment();
+ bundle = new Bundle();
+ bundle.putBoolean("local",local);
+ bundle.putBoolean("remote",remote);
+ bundle.putBoolean("active",active);
+ bundle.putBoolean("pending",pending);
+ bundle.putBoolean("disabled",disabled);
+ bundle.putBoolean("silenced",silenced);
+ bundle.putBoolean("suspended",suspended);
+ displayAdminAccountsFragment.setArguments(bundle);
+ return displayAdminAccountsFragment;
+ }
+ return null;
+ }
+
+
+ @Override
+ public int getCount() {
+ return 2;
+ }
+ }
+
+}
diff --git a/app/src/main/java/app/fedilab/android/activities/BaseMainActivity.java b/app/src/main/java/app/fedilab/android/activities/BaseMainActivity.java
index 92647cf9a..7e445e4fd 100644
--- a/app/src/main/java/app/fedilab/android/activities/BaseMainActivity.java
+++ b/app/src/main/java/app/fedilab/android/activities/BaseMainActivity.java
@@ -74,8 +74,11 @@ import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import app.fedilab.android.BuildConfig;
+import app.fedilab.android.asynctasks.PostAdminActionAsyncTask;
+import app.fedilab.android.client.API;
import app.fedilab.android.client.APIResponse;
import app.fedilab.android.client.Entities.Account;
+import app.fedilab.android.client.Entities.AdminAction;
import app.fedilab.android.client.Entities.Filters;
import app.fedilab.android.client.Entities.ManageTimelines;
import app.fedilab.android.client.Entities.Results;
@@ -83,6 +86,7 @@ import app.fedilab.android.client.Entities.Status;
import app.fedilab.android.client.Entities.TagTimeline;
import app.fedilab.android.client.Entities.Version;
import app.fedilab.android.fragments.DisplayAccountsFragment;
+import app.fedilab.android.fragments.DisplayAdminReportsFragment;
import app.fedilab.android.fragments.DisplayBookmarksFragment;
import app.fedilab.android.fragments.DisplayDraftsFragment;
import app.fedilab.android.fragments.DisplayFavoritesPeertubeFragment;
@@ -103,6 +107,7 @@ import app.fedilab.android.fragments.WhoToFollowFragment;
import app.fedilab.android.helper.CrossActions;
import app.fedilab.android.helper.Helper;
import app.fedilab.android.helper.MenuFloating;
+import app.fedilab.android.interfaces.OnAdminActionInterface;
import app.fedilab.android.services.BackupStatusService;
import app.fedilab.android.services.LiveNotificationService;
import app.fedilab.android.sqlite.AccountDAO;
@@ -279,7 +284,6 @@ public abstract class BaseMainActivity extends BaseActivity
viewPager = findViewById(R.id.viewpager);
-
display_timeline.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
@@ -1081,7 +1085,20 @@ public abstract class BaseMainActivity extends BaseActivity
partnerShipItem.setVisible(false);
}
}
-
+ if( MainActivity.social != UpdateAccountInfoAsyncTask.SOCIAL.MASTODON){
+ MenuItem adminItem = navigationView.getMenu().findItem(R.id.nav_administration);
+ if( adminItem != null){
+ adminItem.setVisible(false);
+ }
+ }else{
+ boolean display_admin_menu = sharedpreferences.getBoolean(Helper.SET_DISPLAY_ADMIN_MENU + userId + instance, false);
+ if( !display_admin_menu){
+ MenuItem adminItem = navigationView.getMenu().findItem(R.id.nav_administration);
+ if( adminItem != null){
+ adminItem.setVisible(false);
+ }
+ }
+ }
LinearLayout owner_container = headerLayout.findViewById(R.id.main_header_container);
owner_container.setOnClickListener(new View.OnClickListener() {
@Override
@@ -1507,6 +1524,10 @@ public abstract class BaseMainActivity extends BaseActivity
Intent intent = new Intent(getApplicationContext(), ReorderTimelinesActivity.class);
startActivity(intent);
return false;
+ }else if(id == R.id.nav_administration){
+ Intent intent = new Intent(getApplicationContext(), AdminActivity.class);
+ startActivity(intent);
+ return false;
} else if( id == R.id.nav_about) {
Intent intent = new Intent(getApplicationContext(), AboutActivity.class);
startActivity(intent);
diff --git a/app/src/main/java/app/fedilab/android/activities/LoginActivity.java b/app/src/main/java/app/fedilab/android/activities/LoginActivity.java
index 0d36c0864..4caf3b5c1 100644
--- a/app/src/main/java/app/fedilab/android/activities/LoginActivity.java
+++ b/app/src/main/java/app/fedilab/android/activities/LoginActivity.java
@@ -114,12 +114,14 @@ public class LoginActivity extends BaseActivity {
private TextView instance_chosen;
private ImageView info_instance;
private final int PICK_IMPORT = 5557;
+ public static boolean admin;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle b = getIntent().getExtras();
socialNetwork = UpdateAccountInfoAsyncTask.SOCIAL.MASTODON;
+ admin = false;
if(b != null) {
autofilledInstance = b.getString("instance", null);
social = b.getString("social", null);
@@ -136,6 +138,7 @@ public class LoginActivity extends BaseActivity {
break;
}
}
+ admin = b.getBoolean("admin", false);
}
if( getIntent() != null && getIntent().getData() != null && getIntent().getData().toString().contains("mastalab://backtomastalab?code=")){
@@ -547,7 +550,11 @@ public class LoginActivity extends BaseActivity {
parameters.put(Helper.CLIENT_NAME, Helper.CLIENT_NAME_VALUE);
parameters.put(Helper.REDIRECT_URIS, client_id_for_webview?Helper.REDIRECT_CONTENT_WEB:Helper.REDIRECT_CONTENT);
if( socialNetwork != UpdateAccountInfoAsyncTask.SOCIAL.PEERTUBE) {
- parameters.put(Helper.SCOPES, Helper.OAUTH_SCOPES);
+ if( admin ) {
+ parameters.put(Helper.SCOPES, Helper.OAUTH_SCOPES_ADMIN);
+ }else{
+ parameters.put(Helper.SCOPES, Helper.OAUTH_SCOPES);
+ }
}else {
parameters.put(Helper.SCOPES, Helper.OAUTH_SCOPES_PEERTUBE);
}
@@ -875,8 +882,14 @@ public class LoginActivity extends BaseActivity {
String queryString = Helper.CLIENT_ID + "="+ clientId;
queryString += "&" + Helper.REDIRECT_URI + "="+ Uri.encode(Helper.REDIRECT_CONTENT_WEB);
queryString += "&" + Helper.RESPONSE_TYPE +"=code";
- if( socialNetwork != UpdateAccountInfoAsyncTask.SOCIAL.PIXELFED )
- queryString += "&" + Helper.SCOPE +"=" + Helper.OAUTH_SCOPES;
+ if( socialNetwork != UpdateAccountInfoAsyncTask.SOCIAL.PIXELFED ) {
+
+ if( admin ) {
+ queryString += "&" + Helper.SCOPE + "=" + Helper.OAUTH_SCOPES_ADMIN;
+ }else{
+ queryString += "&" + Helper.SCOPE + "=" + Helper.OAUTH_SCOPES;
+ }
+ }
return Helper.instanceWithProtocol(context, instance) + Helper.EP_AUTHORIZE + "?" + queryString;
}
diff --git a/app/src/main/java/app/fedilab/android/asynctasks/PostAdminActionAsyncTask.java b/app/src/main/java/app/fedilab/android/asynctasks/PostAdminActionAsyncTask.java
new file mode 100644
index 000000000..eb7a5f7e6
--- /dev/null
+++ b/app/src/main/java/app/fedilab/android/asynctasks/PostAdminActionAsyncTask.java
@@ -0,0 +1,76 @@
+/* Copyright 2019 Thomas Schneider
+ *
+ * This file is a part of Fedilab
+ *
+ * This program is free software; you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * Fedilab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with Fedilab; if not,
+ * see . */
+package app.fedilab.android.asynctasks;
+
+import android.content.Context;
+import android.os.AsyncTask;
+
+import java.lang.ref.WeakReference;
+import app.fedilab.android.client.API;
+import app.fedilab.android.client.APIResponse;
+import app.fedilab.android.client.Entities.AdminAction;
+import app.fedilab.android.helper.Helper;
+import app.fedilab.android.interfaces.OnAdminActionInterface;
+
+
+
+/**
+ * Created by Thomas on 18/06/2019.
+ * Makes actions for post admin calls
+ */
+
+public class PostAdminActionAsyncTask extends AsyncTask {
+
+ private OnAdminActionInterface listener;
+ private API.adminAction action;
+ private String id;
+ private WeakReference contextReference;
+ private APIResponse apiResponse;
+ private AdminAction adminAction;
+
+
+
+ public PostAdminActionAsyncTask(Context context, API.adminAction action, String id, AdminAction adminAction, OnAdminActionInterface onAdminActionInterface){
+ this.contextReference = new WeakReference<>(context);
+ this.listener = onAdminActionInterface;
+ this.action = action;
+ this.id = id;
+ this.adminAction = adminAction;
+ }
+
+
+ @Override
+ protected Void doInBackground(Void... params) {
+ switch (action){
+ case GET_ACCOUNTS:
+ case GET_ONE_ACCOUNT:
+ case GET_REPORTS:
+ case GET_ONE_REPORT:
+ apiResponse = new API(contextReference.get()).adminGet(action, id, adminAction);
+ break;
+ default:
+ apiResponse = new API(contextReference.get()).adminDo(action, id, adminAction);
+ }
+
+
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(Void result) {
+ listener.onAdminAction(apiResponse);
+ }
+
+}
diff --git a/app/src/main/java/app/fedilab/android/client/API.java b/app/src/main/java/app/fedilab/android/client/API.java
index bf41bb57f..6cf1ed17b 100644
--- a/app/src/main/java/app/fedilab/android/client/API.java
+++ b/app/src/main/java/app/fedilab/android/client/API.java
@@ -19,6 +19,7 @@ import android.content.Intent;
import android.content.SharedPreferences;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
+import android.util.Log;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
@@ -48,10 +49,13 @@ import java.util.Map;
import app.fedilab.android.R;
import app.fedilab.android.activities.LoginActivity;
import app.fedilab.android.activities.MainActivity;
+import app.fedilab.android.asynctasks.PostAdminActionAsyncTask;
import app.fedilab.android.asynctasks.RetrieveOpenCollectiveAsyncTask;
import app.fedilab.android.asynctasks.UpdateAccountInfoAsyncTask;
import app.fedilab.android.client.Entities.Account;
+import app.fedilab.android.client.Entities.AccountAdmin;
import app.fedilab.android.client.Entities.AccountCreation;
+import app.fedilab.android.client.Entities.AdminAction;
import app.fedilab.android.client.Entities.Application;
import app.fedilab.android.client.Entities.Attachment;
import app.fedilab.android.client.Entities.Card;
@@ -71,6 +75,7 @@ import app.fedilab.android.client.Entities.Peertube;
import app.fedilab.android.client.Entities.Poll;
import app.fedilab.android.client.Entities.PollOptions;
import app.fedilab.android.client.Entities.Relationship;
+import app.fedilab.android.client.Entities.Report;
import app.fedilab.android.client.Entities.Results;
import app.fedilab.android.client.Entities.Schedule;
import app.fedilab.android.client.Entities.Status;
@@ -114,6 +119,28 @@ public class API {
ACCOUNTS
}
+
+ public enum adminAction{
+ ENABLE,
+ APPROVE,
+ REJECT,
+ NONE,
+ SILENCE,
+ DISABLE,
+ UNSILENCE,
+ SUSPEND,
+ UNSUSPEND,
+ ASSIGN_TO_SELF,
+ UNASSIGN,
+ REOPEN,
+ RESOLVE,
+ GET_ACCOUNTS,
+ GET_ONE_ACCOUNT,
+ GET_REPORTS,
+ GET_ONE_REPORT
+ }
+
+
public enum StatusAction{
FAVOURITE,
UNFAVOURITE,
@@ -149,12 +176,15 @@ public class API {
UPDATESERVERSCHEDULE,
DELETESCHEDULED,
REFRESHPOLL
-
}
+
+
public enum accountPrivacy {
PUBLIC,
LOCKED
}
+
+
public API(Context context) {
this.context = context;
if( context == null) {
@@ -184,6 +214,246 @@ public class API {
APIError = null;
}
+
+ /**
+ * Execute admin get actions
+ * @param action type of the action
+ * @param id String can for an account or a status
+ * @return APIResponse
+ */
+ public APIResponse adminGet(adminAction action, String id, AdminAction adminAction){
+ apiResponse = new APIResponse();
+ HashMap params = null;
+ String endpoint = null;
+ switch (action){
+ case GET_ACCOUNTS:
+ params = new HashMap<>();
+ if( adminAction.isLocal())
+ params.put("local", String.valueOf(adminAction.isLocal()));
+ if( adminAction.isRemote() )
+ params.put("remote", String.valueOf(adminAction.isRemote()));
+ if( adminAction.isActive() )
+ params.put("active", String.valueOf(adminAction.isActive()));
+ if( adminAction.isPending() )
+ params.put("pending", String.valueOf(adminAction.isPending()));
+ if( adminAction.isDisabled() )
+ params.put("disabled", String.valueOf(adminAction.isDisabled()));
+ if( adminAction.isSilenced() )
+ params.put("silenced", String.valueOf(adminAction.isSilenced()));
+ if( adminAction.isSuspended() )
+ params.put("suspended", String.valueOf(adminAction.isSuspended()));
+ endpoint = "/admin/accounts";
+ break;
+ case GET_ONE_ACCOUNT:
+ endpoint = String.format("/admin/accounts/%s", id);
+ break;
+ case GET_REPORTS:
+ endpoint = "/admin/reports";
+ if( !adminAction.isUnresolved()) {
+ params = new HashMap<>();
+ params.put("resolved", "present");
+ }
+ break;
+ case GET_ONE_REPORT:
+ endpoint = String.format("/admin/reports/%s", id);
+ break;
+ }
+ try {
+ String response = new HttpsConnection(context, this.instance).get(getAbsoluteUrl(endpoint), 60, params, prefKeyOauthTokenT);
+ switch (action){
+ case GET_ACCOUNTS:
+ List accountAdmins = parseAccountAdminResponse(new JSONArray(response));
+ apiResponse.setAccountAdmins(accountAdmins);
+ break;
+ case GET_ONE_ACCOUNT:
+ AccountAdmin accountAdmin = parseAccountAdminResponse(context, new JSONObject(response));
+ accountAdmins = new ArrayList<>();
+ accountAdmins.add(accountAdmin);
+ apiResponse.setAccountAdmins(accountAdmins);
+ break;
+ case GET_REPORTS:
+ List reports = parseReportAdminResponse(new JSONArray(response));
+ apiResponse.setReports(reports);
+ break;
+ case GET_ONE_REPORT:
+ reports = new ArrayList<>();
+ Report report = parseReportAdminResponse(context, new JSONObject(response));
+ reports.add(report);
+ apiResponse.setReports(reports);
+ break;
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ } catch (NoSuchAlgorithmException e) {
+ e.printStackTrace();
+ } catch (KeyManagementException e) {
+ e.printStackTrace();
+ } catch (HttpsConnection.HttpsConnectionException e) {
+ setError(e.getStatusCode(), e);
+ e.printStackTrace();
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ return apiResponse;
+ }
+
+
+ /**
+ * Execute admin post actions
+ * @param action type of the action
+ * @param id String can for an account or a status
+ * @return APIResponse
+ */
+ public APIResponse adminDo(adminAction action, String id, AdminAction adminAction){
+ apiResponse = new APIResponse();
+ String endpoint = null;
+ HashMap params = null;
+ switch (action){
+ case ENABLE:
+ endpoint = String.format("/admin/accounts/%s/enable", id);
+ break;
+ case APPROVE:
+ endpoint = String.format("/admin/accounts/%s/approve", id);
+ break;
+ case REJECT:
+ endpoint = String.format("/admin/accounts/%s/reject", id);
+ break;
+ case UNSILENCE:
+ endpoint = String.format("/admin/accounts/%s/unsilence", id);
+ break;
+ case UNSUSPEND:
+ endpoint = String.format("/admin/accounts/%s/unsuspend", id);
+ break;
+ case ASSIGN_TO_SELF:
+ endpoint = String.format("/admin/reports/%s/assign_to_self", id);
+ break;
+ case UNASSIGN:
+ endpoint = String.format("/admin/reports/%s/unassign", id);
+ break;
+ case REOPEN:
+ endpoint = String.format("/admin/reports/%s/reopen", id);
+ break;
+ case RESOLVE:
+ endpoint = String.format("/admin/reports/%s/resolve", id);
+ break;
+ case NONE:
+ params = new HashMap<>();
+ 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;
+ case DISABLE:
+ params = new HashMap<>();
+ 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;
+ case SILENCE:
+ params = new HashMap<>();
+ 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;
+ case SUSPEND:
+ params = new HashMap<>();
+ params.put("type","suspend");
+ 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;
+ }
+ try {
+ String response = new HttpsConnection(context, this.instance).post(getAbsoluteUrl(endpoint), 60, params, prefKeyOauthTokenT);
+ switch (action){
+ case ENABLE:
+ case APPROVE:
+ case REJECT:
+ case UNSILENCE:
+ // case UNDISABLE:
+ case UNSUSPEND:
+ List accountAdmins = null;
+ try {
+ AccountAdmin accountAdmin = parseAccountAdminResponse(context, new JSONObject(response));
+ accountAdmin.setAction(action);
+ accountAdmins = new ArrayList<>();
+ accountAdmins.add(accountAdmin);
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ apiResponse.setAccountAdmins(accountAdmins);
+ break;
+ case ASSIGN_TO_SELF:
+ case UNASSIGN:
+ case REOPEN:
+ case RESOLVE:
+ List reports = null;
+ Report report;
+ try {
+ reports = new ArrayList<>();
+ report = parseReportAdminResponse(context, new JSONObject(response));
+ reports.add(report);
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ apiResponse.setReports(reports);
+
+ break;
+ case NONE:
+ accountAdmins = new ArrayList<>();
+ AccountAdmin accountAdmin = new AccountAdmin();
+ accountAdmin.setAction(action);
+ accountAdmins.add(accountAdmin);
+ apiResponse.setAccountAdmins(accountAdmins);
+ break;
+ case DISABLE:
+ accountAdmins = new ArrayList<>();
+ 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;
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ } catch (NoSuchAlgorithmException e) {
+ e.printStackTrace();
+ } catch (KeyManagementException e) {
+ e.printStackTrace();
+ } catch (HttpsConnection.HttpsConnectionException e) {
+ setError(e.getStatusCode(), e);
+ e.printStackTrace();
+ }
+ return apiResponse;
+ }
+
public InstanceNodeInfo getNodeInfo(String domain){
//Try to guess URL scheme for the onion instance
@@ -327,6 +597,9 @@ public class API {
}
+
+
+
/***
* Get info on the current Instance *synchronously*
* @return APIResponse
@@ -4814,6 +5087,151 @@ public class API {
return account;
}
+
+ /**
+ * Parse json response for list of reports for admins
+ * @param jsonArray JSONArray
+ * @return List
+ */
+ private List parseReportAdminResponse(JSONArray jsonArray){
+
+ List reports = new ArrayList<>();
+ try {
+ int i = 0;
+ while (i < jsonArray.length() ) {
+ JSONObject resobj = jsonArray.getJSONObject(i);
+ Report report = parseReportAdminResponse(context, resobj);
+ reports.add(report);
+ i++;
+ }
+ } catch (JSONException e) {
+ setDefaultError(e);
+ }
+ return reports;
+ }
+
+ /**
+ * Parse json response an unique report for admins
+ * @param resobj JSONObject
+ * @return AccountAdmin
+ */
+ private static Report parseReportAdminResponse(Context context, JSONObject resobj){
+
+ Report report = new Report();
+ try {
+ report.setId(resobj.getString("id"));
+ report.setAction_taken(resobj.getBoolean("action_taken"));
+ report.setComment(resobj.getString("comment"));
+ report.setCreated_at(Helper.mstStringToDate(context, resobj.getString("created_at")));
+ report.setUpdated_at(Helper.mstStringToDate(context, resobj.getString("updated_at")));
+ if( !resobj.isNull("account")) {
+ report.setAccount(parseAccountAdminResponse(context, resobj.getJSONObject("account")));
+ }
+ if( !resobj.isNull("target_account")) {
+ report.setTarget_account(parseAccountAdminResponse(context, resobj.getJSONObject("target_account")));
+ }
+ if( !resobj.isNull("assigned_account")) {
+ report.setAssigned_account(parseAccountAdminResponse(context, resobj.getJSONObject("assigned_account")));
+ }
+ if( !resobj.isNull("action_taken_by_account")) {
+ report.setAction_taken_by_account(parseAccountAdminResponse(context, resobj.getJSONObject("action_taken_by_account")));
+ }
+ report.setStatuses(parseStatuses(context, resobj.getJSONArray("statuses")));
+ }catch (Exception ignored){ignored.printStackTrace();}
+ return report;
+ }
+
+
+ /**
+ * Parse json response for list of accounts for admins
+ * @param jsonArray JSONArray
+ * @return List
+ */
+ private List parseAccountAdminResponse(JSONArray jsonArray){
+
+ List accountAdmins = new ArrayList<>();
+ try {
+ int i = 0;
+ while (i < jsonArray.length() ) {
+ JSONObject resobj = jsonArray.getJSONObject(i);
+ AccountAdmin accountAdmin = parseAccountAdminResponse(context, resobj);
+ accountAdmins.add(accountAdmin);
+ i++;
+ }
+ } catch (JSONException e) {
+ setDefaultError(e);
+ }
+ return accountAdmins;
+ }
+
+ /**
+ * Parse json response an unique account for admins
+ * @param resobj JSONObject
+ * @return Account
+ */
+ private static AccountAdmin parseAccountAdminResponse(Context context, JSONObject resobj){
+
+ AccountAdmin accountAdmin = new AccountAdmin();
+ try {
+ accountAdmin.setId(resobj.get("id").toString());
+ accountAdmin.setUsername(resobj.getString("username"));
+ accountAdmin.setCreated_at(Helper.mstStringToDate(context, resobj.getString("created_at")));
+ accountAdmin.setEmail(resobj.getString("email"));
+ accountAdmin.setRole(resobj.getString("role"));
+ accountAdmin.setIp(resobj.getString("ip"));
+ accountAdmin.setDomain(resobj.getString("domain"));
+ accountAdmin.setAccount(parseAccountResponse(context, resobj.getJSONObject("account")));
+ if( !resobj.isNull("confirmed")) {
+ accountAdmin.setConfirmed(resobj.getBoolean("confirmed"));
+ }else{
+ accountAdmin.setConfirmed(true);
+ }
+ if( !resobj.isNull("suspended")) {
+ accountAdmin.setSuspended(resobj.getBoolean("suspended"));
+ }else{
+ accountAdmin.setSuspended(false);
+ }
+ if( !resobj.isNull("silenced")) {
+ accountAdmin.setSilenced(resobj.getBoolean("silenced"));
+ }else{
+ accountAdmin.setSilenced(false);
+ }
+ if( !resobj.isNull("disabled")) {
+ accountAdmin.setDisabled(resobj.getBoolean("disabled"));
+ }else{
+ accountAdmin.setDisabled(false);
+ }
+ if( !resobj.isNull("approved")) {
+ accountAdmin.setApproved(resobj.getBoolean("approved"));
+ }else{
+ accountAdmin.setApproved(false);
+ }
+ }catch (Exception ignored){}
+ return accountAdmin;
+ }
+
+ /**
+ * Parse json response for list of accounts
+ * @param jsonArray JSONArray
+ * @return List
+ */
+ private List parseAccountResponse(JSONArray jsonArray){
+
+ List accounts = new ArrayList<>();
+ try {
+ int i = 0;
+ while (i < jsonArray.length() ) {
+ JSONObject resobj = jsonArray.getJSONObject(i);
+ Account account = parseAccountResponse(context, resobj);
+ accounts.add(account);
+ i++;
+ }
+ } catch (JSONException e) {
+ setDefaultError(e);
+ }
+ return accounts;
+ }
+
/**
* Parse json response an unique account
* @param resobj JSONObject
@@ -5029,27 +5447,7 @@ public class API {
} catch (JSONException ignored) {}
return account;
}
- /**
- * Parse json response for list of accounts
- * @param jsonArray JSONArray
- * @return List
- */
- private List parseAccountResponse(JSONArray jsonArray){
- List accounts = new ArrayList<>();
- try {
- int i = 0;
- while (i < jsonArray.length() ) {
- JSONObject resobj = jsonArray.getJSONObject(i);
- Account account = parseAccountResponse(context, resobj);
- accounts.add(account);
- i++;
- }
- } catch (JSONException e) {
- setDefaultError(e);
- }
- return accounts;
- }
/**
diff --git a/app/src/main/java/app/fedilab/android/client/APIResponse.java b/app/src/main/java/app/fedilab/android/client/APIResponse.java
index f869dc467..f588973fd 100644
--- a/app/src/main/java/app/fedilab/android/client/APIResponse.java
+++ b/app/src/main/java/app/fedilab/android/client/APIResponse.java
@@ -19,6 +19,7 @@ import android.content.Context;
import java.util.List;
import app.fedilab.android.client.Entities.Account;
+import app.fedilab.android.client.Entities.AccountAdmin;
import app.fedilab.android.client.Entities.Conversation;
import app.fedilab.android.client.Entities.Emojis;
import app.fedilab.android.client.Entities.Error;
@@ -31,6 +32,7 @@ import app.fedilab.android.client.Entities.Peertube;
import app.fedilab.android.client.Entities.PeertubeNotification;
import app.fedilab.android.client.Entities.Playlist;
import app.fedilab.android.client.Entities.Relationship;
+import app.fedilab.android.client.Entities.Report;
import app.fedilab.android.client.Entities.Results;
import app.fedilab.android.client.Entities.Status;
import app.fedilab.android.client.Entities.StoredStatus;
@@ -64,7 +66,8 @@ public class APIResponse {
private boolean fetchmore = false;
private List playlistForVideos;
private List instanceRegs = null;
-
+ private List accountAdmins = null;
+ private List reports = null;
public List getAccounts() {
return accounts;
@@ -249,4 +252,20 @@ public class APIResponse {
public void setInstanceRegs(List instanceRegs) {
this.instanceRegs = instanceRegs;
}
+
+ public List getAccountAdmins() {
+ return accountAdmins;
+ }
+
+ public void setAccountAdmins(List accountAdmins) {
+ this.accountAdmins = accountAdmins;
+ }
+
+ public List getReports() {
+ return reports;
+ }
+
+ public void setReports(List reports) {
+ this.reports = reports;
+ }
}
diff --git a/app/src/main/java/app/fedilab/android/client/Entities/Account.java b/app/src/main/java/app/fedilab/android/client/Entities/Account.java
index dc98e6ed6..e6884bf97 100644
--- a/app/src/main/java/app/fedilab/android/client/Entities/Account.java
+++ b/app/src/main/java/app/fedilab/android/client/Entities/Account.java
@@ -120,6 +120,11 @@ public class Account implements Parcelable {
private String privacy = "public";
private boolean sensitive = false;
+ private String locale;
+ private String invite_request;
+ private String created_by_application_id;
+ private String invited_by_account_id;
+
@@ -176,6 +181,10 @@ public class Account implements Parcelable {
dest.writeByte(this.isAdmin ? (byte) 1 : (byte) 0);
dest.writeString(this.privacy);
dest.writeByte(this.sensitive ? (byte) 1 : (byte) 0);
+ dest.writeString(this.locale);
+ dest.writeString(this.invite_request);
+ dest.writeString(this.created_by_application_id);
+ dest.writeString(this.invited_by_account_id);
}
public Account() {
@@ -231,6 +240,10 @@ public class Account implements Parcelable {
this.isAdmin = in.readByte() != 0;
this.privacy = in.readString();
this.sensitive =in.readByte() != 0;
+ this.locale = in.readString();
+ this.invite_request = in.readString();
+ this.created_by_application_id = in.readString();
+ this.invited_by_account_id = in.readString();
}
public static final Creator CREATOR = new Creator() {
@@ -406,6 +419,38 @@ public class Account implements Parcelable {
this.sensitive = sensitive;
}
+ public String getLocale() {
+ return locale;
+ }
+
+ public void setLocale(String locale) {
+ this.locale = locale;
+ }
+
+ public String getInvite_request() {
+ return invite_request;
+ }
+
+ public void setInvite_request(String invite_request) {
+ this.invite_request = invite_request;
+ }
+
+ public String getCreated_by_application_id() {
+ return created_by_application_id;
+ }
+
+ public void setCreated_by_application_id(String created_by_application_id) {
+ this.created_by_application_id = created_by_application_id;
+ }
+
+ public String getInvited_by_account_id() {
+ return invited_by_account_id;
+ }
+
+ public void setInvited_by_account_id(String invited_by_account_id) {
+ this.invited_by_account_id = invited_by_account_id;
+ }
+
public enum followAction{
FOLLOW,
diff --git a/app/src/main/java/app/fedilab/android/client/Entities/AccountAdmin.java b/app/src/main/java/app/fedilab/android/client/Entities/AccountAdmin.java
new file mode 100644
index 000000000..112567a7b
--- /dev/null
+++ b/app/src/main/java/app/fedilab/android/client/Entities/AccountAdmin.java
@@ -0,0 +1,209 @@
+package app.fedilab.android.client.Entities;
+/* Copyright 2019 Thomas Schneider
+ *
+ * This file is a part of Fedilab
+ *
+ * This program is free software; you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * Fedilab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with Fedilab; if not,
+ * see . */
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Date;
+
+import app.fedilab.android.client.API;
+
+public class AccountAdmin implements Parcelable {
+
+ private String id;
+ private String username;
+ private Date created_at;
+ private String email;
+ private String role;
+ private String ip;
+ private String domain;
+ private boolean confirmed;
+ private boolean suspended;
+ private boolean silenced;
+ private boolean disabled;
+ private Account account;
+ private API.adminAction action;
+ private boolean approved;
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ public Date getCreated_at() {
+ return created_at;
+ }
+
+ public void setCreated_at(Date created_at) {
+ this.created_at = created_at;
+ }
+
+ public String getEmail() {
+ return email;
+ }
+
+ public void setEmail(String email) {
+ this.email = email;
+ }
+
+ public String getRole() {
+ return role;
+ }
+
+ public void setRole(String role) {
+ this.role = role;
+ }
+
+ public String getIp() {
+ return ip;
+ }
+
+ public void setIp(String ip) {
+ this.ip = ip;
+ }
+
+ public boolean isConfirmed() {
+ return confirmed;
+ }
+
+ public void setConfirmed(boolean confirmed) {
+ this.confirmed = confirmed;
+ }
+
+ public boolean isSuspended() {
+ return suspended;
+ }
+
+ public void setSuspended(boolean suspended) {
+ this.suspended = suspended;
+ }
+
+ public boolean isSilenced() {
+ return silenced;
+ }
+
+ public void setSilenced(boolean silenced) {
+ this.silenced = silenced;
+ }
+
+ public boolean isDisabled() {
+ return disabled;
+ }
+
+ public void setDisabled(boolean disabled) {
+ this.disabled = disabled;
+ }
+
+ public Account getAccount() {
+ return account;
+ }
+
+ public void setAccount(Account account) {
+ this.account = account;
+ }
+
+
+ public AccountAdmin() {
+ }
+
+ public String getDomain() {
+ return domain;
+ }
+
+ public void setDomain(String domain) {
+ this.domain = domain;
+ }
+
+ public API.adminAction getAction() {
+ return action;
+ }
+
+ public void setAction(API.adminAction action) {
+ this.action = action;
+ }
+
+ public boolean isApproved() {
+ return approved;
+ }
+
+ public void setApproved(boolean approved) {
+ this.approved = approved;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString(this.id);
+ dest.writeString(this.username);
+ dest.writeLong(this.created_at != null ? this.created_at.getTime() : -1);
+ dest.writeString(this.email);
+ dest.writeString(this.role);
+ dest.writeString(this.ip);
+ dest.writeString(this.domain);
+ dest.writeByte(this.confirmed ? (byte) 1 : (byte) 0);
+ dest.writeByte(this.suspended ? (byte) 1 : (byte) 0);
+ dest.writeByte(this.silenced ? (byte) 1 : (byte) 0);
+ dest.writeByte(this.disabled ? (byte) 1 : (byte) 0);
+ dest.writeParcelable(this.account, flags);
+ dest.writeInt(this.action == null ? -1 : this.action.ordinal());
+ dest.writeByte(this.approved ? (byte) 1 : (byte) 0);
+ }
+
+ protected AccountAdmin(Parcel in) {
+ this.id = in.readString();
+ this.username = in.readString();
+ long tmpCreated_at = in.readLong();
+ this.created_at = tmpCreated_at == -1 ? null : new Date(tmpCreated_at);
+ this.email = in.readString();
+ this.role = in.readString();
+ this.ip = in.readString();
+ this.domain = in.readString();
+ this.confirmed = in.readByte() != 0;
+ this.suspended = in.readByte() != 0;
+ this.silenced = in.readByte() != 0;
+ this.disabled = in.readByte() != 0;
+ this.account = in.readParcelable(Account.class.getClassLoader());
+ int tmpAction = in.readInt();
+ this.action = tmpAction == -1 ? null : API.adminAction.values()[tmpAction];
+ this.approved = in.readByte() != 0;
+ }
+
+ public static final Creator CREATOR = new Creator() {
+ @Override
+ public AccountAdmin createFromParcel(Parcel source) {
+ return new AccountAdmin(source);
+ }
+
+ @Override
+ public AccountAdmin[] newArray(int size) {
+ return new AccountAdmin[size];
+ }
+ };
+}
diff --git a/app/src/main/java/app/fedilab/android/client/Entities/AccountCreation.java b/app/src/main/java/app/fedilab/android/client/Entities/AccountCreation.java
index 70787fd33..2d38eba37 100644
--- a/app/src/main/java/app/fedilab/android/client/Entities/AccountCreation.java
+++ b/app/src/main/java/app/fedilab/android/client/Entities/AccountCreation.java
@@ -1,5 +1,18 @@
package app.fedilab.android.client.Entities;
-
+/* Copyright 2019 Thomas Schneider
+ *
+ * This file is a part of Fedilab
+ *
+ * This program is free software; you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * Fedilab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with Fedilab; if not,
+ * see . */
public class AccountCreation {
private String username;
diff --git a/app/src/main/java/app/fedilab/android/client/Entities/AdminAction.java b/app/src/main/java/app/fedilab/android/client/Entities/AdminAction.java
new file mode 100644
index 000000000..05703feb7
--- /dev/null
+++ b/app/src/main/java/app/fedilab/android/client/Entities/AdminAction.java
@@ -0,0 +1,121 @@
+package app.fedilab.android.client.Entities;
+
+import app.fedilab.android.client.API;
+
+/* Copyright 2019 Thomas Schneider
+ *
+ * This file is a part of Fedilab
+ *
+ * This program is free software; you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * Fedilab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with Fedilab; if not,
+ * see . */
+public class AdminAction {
+
+
+
+ private API.adminAction type;
+ private boolean send_email_notification;
+ private String text;
+ private boolean unresolved;
+ private boolean local, remote, active, pending, disabled, silenced, suspended;
+
+
+ public boolean isLocal() {
+ return local;
+ }
+
+ public void setLocal(boolean local) {
+ this.local = local;
+ }
+
+ public boolean isRemote() {
+ return remote;
+ }
+
+ public void setRemote(boolean remote) {
+ this.remote = remote;
+ }
+
+ public boolean isActive() {
+ return active;
+ }
+
+ public void setActive(boolean active) {
+ this.active = active;
+ }
+
+ public boolean isPending() {
+ return pending;
+ }
+
+ public void setPending(boolean pending) {
+ this.pending = pending;
+ }
+
+ public boolean isDisabled() {
+ return disabled;
+ }
+
+ public void setDisabled(boolean disabled) {
+ this.disabled = disabled;
+ }
+
+ public boolean isSilenced() {
+ return silenced;
+ }
+
+ public void setSilenced(boolean silenced) {
+ this.silenced = silenced;
+ }
+
+ public boolean isSuspended() {
+ return suspended;
+ }
+
+ public void setSuspended(boolean suspended) {
+ this.suspended = suspended;
+ }
+
+
+
+ public boolean isUnresolved() {
+ return unresolved;
+ }
+
+ public void setUnresolved(boolean unresolved) {
+ this.unresolved = unresolved;
+ }
+
+
+ public boolean isSend_email_notification() {
+ return send_email_notification;
+ }
+
+ public void setSend_email_notification(boolean send_email_notification) {
+ this.send_email_notification = send_email_notification;
+ }
+
+ public String getText() {
+ return text;
+ }
+
+ public void setText(String text) {
+ this.text = text;
+ }
+
+
+ public API.adminAction getType() {
+ return type;
+ }
+
+ public void setType(API.adminAction type) {
+ this.type = type;
+ }
+}
diff --git a/app/src/main/java/app/fedilab/android/client/Entities/Report.java b/app/src/main/java/app/fedilab/android/client/Entities/Report.java
new file mode 100644
index 000000000..3fd8025d4
--- /dev/null
+++ b/app/src/main/java/app/fedilab/android/client/Entities/Report.java
@@ -0,0 +1,168 @@
+package app.fedilab.android.client.Entities;
+/* Copyright 2019 Thomas Schneider
+ *
+ * This file is a part of Fedilab
+ *
+ * This program is free software; you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * Fedilab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with Fedilab; if not,
+ * see . */
+
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Date;
+import java.util.List;
+
+public class Report implements Parcelable {
+
+ private String id;
+ private boolean action_taken;
+ private String comment;
+ private Date created_at;
+ private Date updated_at;
+ private AccountAdmin account;
+ private AccountAdmin target_account;
+ private AccountAdmin assigned_account;
+ private AccountAdmin action_taken_by_account;
+ private List statuses;
+
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+
+ public String getComment() {
+ return comment;
+ }
+
+ public void setComment(String comment) {
+ this.comment = comment;
+ }
+
+ public Date getCreated_at() {
+ return created_at;
+ }
+
+ public void setCreated_at(Date created_at) {
+ this.created_at = created_at;
+ }
+
+ public Date getUpdated_at() {
+ return updated_at;
+ }
+
+ public void setUpdated_at(Date updated_at) {
+ this.updated_at = updated_at;
+ }
+
+ public List getStatuses() {
+ return statuses;
+ }
+
+ public void setStatuses(List statuses) {
+ this.statuses = statuses;
+ }
+
+
+ public Report() {
+ }
+
+ public AccountAdmin getAccount() {
+ return account;
+ }
+
+ public void setAccount(AccountAdmin account) {
+ this.account = account;
+ }
+
+ public AccountAdmin getTarget_account() {
+ return target_account;
+ }
+
+ public void setTarget_account(AccountAdmin target_account) {
+ this.target_account = target_account;
+ }
+
+ public AccountAdmin getAssigned_account() {
+ return assigned_account;
+ }
+
+ public void setAssigned_account(AccountAdmin assigned_account) {
+ this.assigned_account = assigned_account;
+ }
+
+ public boolean isAction_taken() {
+ return action_taken;
+ }
+
+ public void setAction_taken(boolean action_taken) {
+ this.action_taken = action_taken;
+ }
+
+ public AccountAdmin getAction_taken_by_account() {
+ return action_taken_by_account;
+ }
+
+ public void setAction_taken_by_account(AccountAdmin action_taken_by_account) {
+ this.action_taken_by_account = action_taken_by_account;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString(this.id);
+ dest.writeByte(this.action_taken ? (byte) 1 : (byte) 0);
+ dest.writeString(this.comment);
+ dest.writeLong(this.created_at != null ? this.created_at.getTime() : -1);
+ dest.writeLong(this.updated_at != null ? this.updated_at.getTime() : -1);
+ dest.writeParcelable(this.account, flags);
+ dest.writeParcelable(this.target_account, flags);
+ dest.writeParcelable(this.assigned_account, flags);
+ dest.writeParcelable(this.action_taken_by_account, flags);
+ dest.writeTypedList(this.statuses);
+ }
+
+ protected Report(Parcel in) {
+ this.id = in.readString();
+ this.action_taken = in.readByte() != 0;
+ this.comment = in.readString();
+ long tmpCreated_at = in.readLong();
+ this.created_at = tmpCreated_at == -1 ? null : new Date(tmpCreated_at);
+ long tmpUpdated_at = in.readLong();
+ this.updated_at = tmpUpdated_at == -1 ? null : new Date(tmpUpdated_at);
+ this.account = in.readParcelable(AccountAdmin.class.getClassLoader());
+ this.target_account = in.readParcelable(AccountAdmin.class.getClassLoader());
+ this.assigned_account = in.readParcelable(AccountAdmin.class.getClassLoader());
+ this.action_taken_by_account = in.readParcelable(AccountAdmin.class.getClassLoader());
+ this.statuses = in.createTypedArrayList(Status.CREATOR);
+ }
+
+ public static final Creator CREATOR = new Creator() {
+ @Override
+ public Report createFromParcel(Parcel source) {
+ return new Report(source);
+ }
+
+ @Override
+ public Report[] newArray(int size) {
+ return new Report[size];
+ }
+ };
+}
diff --git a/app/src/main/java/app/fedilab/android/drawers/AccountsAdminListAdapter.java b/app/src/main/java/app/fedilab/android/drawers/AccountsAdminListAdapter.java
new file mode 100644
index 000000000..af980fba5
--- /dev/null
+++ b/app/src/main/java/app/fedilab/android/drawers/AccountsAdminListAdapter.java
@@ -0,0 +1,169 @@
+package app.fedilab.android.drawers;
+/* Copyright 2019 Thomas Schneider
+ *
+ * This file is a part of Fedilab
+ *
+ * This program is free software; you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * Fedilab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with Fedilab; if not,
+ * see . */
+
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.RecyclerView;
+
+import java.util.List;
+
+import app.fedilab.android.R;
+import app.fedilab.android.activities.AccountReportActivity;
+import app.fedilab.android.asynctasks.RetrieveAccountsAsyncTask;
+import app.fedilab.android.client.Entities.Account;
+import app.fedilab.android.client.Entities.AccountAdmin;
+import app.fedilab.android.client.Entities.Report;
+import app.fedilab.android.helper.Helper;
+import app.fedilab.android.interfaces.OnRetrieveEmojiAccountInterface;
+
+
+/**
+ * Created by Thomas on 19/06/2019.
+ * Adapter for account admins
+ */
+public class AccountsAdminListAdapter extends RecyclerView.Adapter implements OnRetrieveEmojiAccountInterface {
+
+ private List accountAdmins;
+ private LayoutInflater layoutInflater;
+ private RetrieveAccountsAsyncTask.Type action;
+ private Context context;
+ private AccountsAdminListAdapter accountsAdminListAdapter;
+ private String targetedId;
+
+ public AccountsAdminListAdapter(Context context, List accountAdmins){
+ this.context = context;
+ this.accountAdmins = accountAdmins;
+ layoutInflater = LayoutInflater.from(context);
+ this.accountsAdminListAdapter = this;
+ }
+
+
+
+
+ @NonNull
+ @Override
+ public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+ return new ViewHolder(layoutInflater.inflate(R.layout.drawer_account_admin, parent, false));
+ }
+
+ @Override
+ public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int position) {
+ final AccountsAdminListAdapter.ViewHolder holder = (AccountsAdminListAdapter.ViewHolder) viewHolder;
+ AccountAdmin accountAdmin = accountAdmins.get(position);
+ Account account = accountAdmin.getAccount();
+
+
+ account.makeAccountNameEmoji(context, AccountsAdminListAdapter.this, account);
+ if( account.getdisplayNameSpan() == null || account.getdisplayNameSpan().toString().trim().equals("")) {
+ if( account.getDisplay_name() != null && !account.getDisplay_name().trim().equals(""))
+ holder.account_dn.setText(Helper.shortnameToUnicode(account.getDisplay_name(), true));
+ else
+ holder.account_dn.setText(account.getDisplay_name().replace("@",""));
+ }else
+ holder.account_dn.setText( account.getdisplayNameSpan(), TextView.BufferType.SPANNABLE);
+
+ if( account.getdisplayNameSpan() == null || account.getdisplayNameSpan().toString().trim().equals("")) {
+ if( account.getDisplay_name() != null && !account.getDisplay_name().trim().equals(""))
+ holder.account_dn.setText(Helper.shortnameToUnicode(account.getDisplay_name(), true));
+ else
+ holder.account_dn.setText(account.getDisplay_name().replace("@",""));
+ }else
+ holder.account_dn.setText( account.getdisplayNameSpan(), TextView.BufferType.SPANNABLE);
+ holder.account_un.setText(String.format("@%s",account.getUsername()));
+ holder.account_ac.setText(account.getAcct());
+ if( account.getDisplay_name().equals(account.getAcct()))
+ holder.account_ac.setVisibility(View.GONE);
+ else
+ holder.account_ac.setVisibility(View.VISIBLE);
+
+ holder.report_action_taken.setText(accountAdmin.getIp());
+ Helper.loadGiF(context, account.getAvatar(), holder.account_pp);
+
+
+ holder.main_container.setOnClickListener(view ->{
+ Intent intent = new Intent(context, AccountReportActivity.class);
+ Bundle b = new Bundle();
+ b.putParcelable("targeted_account", accountAdmin);
+ intent.putExtras(b);
+ context.startActivity(intent);
+ });
+ }
+
+ @Override
+ public long getItemId(int position) {
+ return position;
+ }
+
+ @Override
+ public int getItemCount() {
+ return accountAdmins.size();
+ }
+
+ private AccountAdmin getItemAt(int position){
+ if( accountAdmins.size() > position)
+ return accountAdmins.get(position);
+ else
+ return null;
+ }
+
+ @Override
+ public void onRetrieveEmojiAccount(Account account) {
+ notifyAccountChanged(account);
+ }
+
+ private void notifyAccountChanged(Account account){
+ for (int i = 0; i < accountsAdminListAdapter.getItemCount(); i++) {
+ //noinspection ConstantConditions
+ if (accountsAdminListAdapter.getItemAt(i) != null && accountsAdminListAdapter.getItemAt(i).getAccount().getId().equals(account.getId())) {
+ try {
+ accountsAdminListAdapter.notifyItemChanged(i);
+ } catch (Exception ignored) {
+ }
+ }
+ }
+ }
+
+
+ private class ViewHolder extends RecyclerView.ViewHolder{
+ ImageView account_pp;
+ TextView account_ac;
+ TextView account_dn;
+ TextView account_un;
+ TextView report_action_taken;
+
+ LinearLayout main_container;
+
+ ViewHolder(View itemView) {
+ super(itemView);
+ account_pp = itemView.findViewById(R.id.account_pp);
+ account_dn = itemView.findViewById(R.id.account_dn);
+ account_ac = itemView.findViewById(R.id.account_ac);
+ account_un = itemView.findViewById(R.id.account_un);
+ report_action_taken = itemView.findViewById(R.id.report_action_taken);
+ main_container = itemView.findViewById(R.id.main_container);
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/app/fedilab/android/drawers/AccountsListAdapter.java b/app/src/main/java/app/fedilab/android/drawers/AccountsListAdapter.java
index 393bf1518..1e4554f9b 100644
--- a/app/src/main/java/app/fedilab/android/drawers/AccountsListAdapter.java
+++ b/app/src/main/java/app/fedilab/android/drawers/AccountsListAdapter.java
@@ -179,12 +179,12 @@ public class AccountsListAdapter extends RecyclerView.Adapter implements OnPostA
if( account.getDisplay_name() != null && !account.getDisplay_name().trim().equals(""))
holder.account_dn.setText(Helper.shortnameToUnicode(account.getDisplay_name(), true));
else
- holder.account_dn.setText(account.getDisplay_name().replace("@",""));
+ holder.account_dn.setText(account.getUsername().replace("@",""));
}else
holder.account_dn.setText( account.getdisplayNameSpan(), TextView.BufferType.SPANNABLE);
holder.account_un.setText(String.format("@%s",account.getUsername()));
holder.account_ac.setText(account.getAcct());
- if( account.getDisplay_name().equals(account.getAcct()))
+ if( account.getUsername().equals(account.getAcct()))
holder.account_ac.setVisibility(View.GONE);
else
holder.account_ac.setVisibility(View.VISIBLE);
diff --git a/app/src/main/java/app/fedilab/android/drawers/ReportsListAdapter.java b/app/src/main/java/app/fedilab/android/drawers/ReportsListAdapter.java
new file mode 100644
index 000000000..e9a427464
--- /dev/null
+++ b/app/src/main/java/app/fedilab/android/drawers/ReportsListAdapter.java
@@ -0,0 +1,176 @@
+package app.fedilab.android.drawers;
+/* Copyright 2019 Thomas Schneider
+ *
+ * This file is a part of Fedilab
+ *
+ * This program is free software; you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * Fedilab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with Fedilab; if not,
+ * see . */
+
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.RecyclerView;
+
+
+import java.util.List;
+import app.fedilab.android.R;
+import app.fedilab.android.activities.AccountReportActivity;
+import app.fedilab.android.asynctasks.RetrieveAccountsAsyncTask;
+import app.fedilab.android.client.Entities.Account;
+import app.fedilab.android.client.Entities.Report;
+import app.fedilab.android.helper.Helper;
+import app.fedilab.android.interfaces.OnRetrieveEmojiAccountInterface;
+
+
+/**
+ * Created by Thomas on 19/06/2019.
+ * Adapter for reports
+ */
+public class ReportsListAdapter extends RecyclerView.Adapter implements OnRetrieveEmojiAccountInterface {
+
+ private List reports;
+ private LayoutInflater layoutInflater;
+ private RetrieveAccountsAsyncTask.Type action;
+ private Context context;
+ private ReportsListAdapter reportsListAdapter;
+ private String targetedId;
+
+ public ReportsListAdapter(Context context, List reports){
+ this.context = context;
+ this.reports = reports;
+ layoutInflater = LayoutInflater.from(context);
+ this.reportsListAdapter = this;
+ }
+
+
+
+
+ @NonNull
+ @Override
+ public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+ return new ViewHolder(layoutInflater.inflate(R.layout.drawer_report, parent, false));
+ }
+
+ @Override
+ public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int position) {
+ final ReportsListAdapter.ViewHolder holder = (ReportsListAdapter.ViewHolder) viewHolder;
+ Report report = reports.get(position);
+ Account account = report.getAccount().getAccount();
+ Account target_account = report.getTarget_account().getAccount();
+
+
+ account.makeAccountNameEmoji(context, ReportsListAdapter.this, account);
+ target_account.makeAccountNameEmoji(context, ReportsListAdapter.this, target_account);
+ if( account.getdisplayNameSpan() == null || account.getdisplayNameSpan().toString().trim().equals("")) {
+ if( account.getDisplay_name() != null && !account.getDisplay_name().trim().equals(""))
+ holder.account_dn_reporter.setText(Helper.shortnameToUnicode(account.getDisplay_name(), true));
+ else
+ holder.account_dn_reporter.setText(account.getUsername().replace("@",""));
+ }else
+ holder.account_dn_reporter.setText( account.getdisplayNameSpan(), TextView.BufferType.SPANNABLE);
+
+ if( target_account.getdisplayNameSpan() == null || target_account.getdisplayNameSpan().toString().trim().equals("")) {
+ if( target_account.getDisplay_name() != null && !target_account.getDisplay_name().trim().equals(""))
+ holder.account_dn.setText(Helper.shortnameToUnicode(target_account.getDisplay_name(), true));
+ else
+ holder.account_dn.setText(target_account.getUsername().replace("@",""));
+ }else
+ holder.account_dn.setText( target_account.getdisplayNameSpan(), TextView.BufferType.SPANNABLE);
+
+
+
+ Helper.loadGiF(context, target_account.getAvatar(), holder.account_pp);
+ Helper.loadGiF(context, account.getAvatar(), holder.account_pp_reporter);
+ holder.account_ac.setText(target_account.getAcct());
+
+ holder.report_comment.setText(report.getComment());
+
+ if( report.getStatuses() != null){
+ holder.report_number_status.setText(String.valueOf(report.getStatuses().size()));
+ }else{
+ holder.report_number_status.setText("0");
+ }
+
+ holder.main_container.setOnClickListener(view ->{
+ Intent intent = new Intent(context, AccountReportActivity.class);
+ Bundle b = new Bundle();
+ b.putParcelable("report", report);
+ intent.putExtras(b);
+ context.startActivity(intent);
+ });
+
+ }
+
+ @Override
+ public long getItemId(int position) {
+ return position;
+ }
+
+ @Override
+ public int getItemCount() {
+ return reports.size();
+ }
+
+ private Report getItemAt(int position){
+ if( reports.size() > position)
+ return reports.get(position);
+ else
+ return null;
+ }
+
+ @Override
+ public void onRetrieveEmojiAccount(Account account) {
+ notifyAccountChanged(account);
+ }
+
+ private void notifyAccountChanged(Account account){
+ for (int i = 0; i < reportsListAdapter.getItemCount(); i++) {
+ //noinspection ConstantConditions
+ if (reportsListAdapter.getItemAt(i) != null && reportsListAdapter.getItemAt(i).getStatuses().get(0).getAccount().getId().equals(account.getId())) {
+ try {
+ reportsListAdapter.notifyItemChanged(i);
+ } catch (Exception ignored) {
+ }
+ }
+ }
+ }
+
+
+ private class ViewHolder extends RecyclerView.ViewHolder{
+ ImageView account_pp, account_pp_reporter;
+ TextView account_ac;
+ TextView account_dn, account_dn_reporter;
+ TextView report_comment, report_number_status;
+
+ LinearLayout main_container;
+
+ ViewHolder(View itemView) {
+ super(itemView);
+ account_pp = itemView.findViewById(R.id.account_pp);
+ account_pp_reporter = itemView.findViewById(R.id.account_pp_reporter);
+ account_dn = itemView.findViewById(R.id.account_dn);
+ account_dn_reporter = itemView.findViewById(R.id.account_dn_reporter);
+ account_ac = itemView.findViewById(R.id.account_ac);
+ report_comment = itemView.findViewById(R.id.report_comment);
+ main_container = itemView.findViewById(R.id.main_container);
+ report_number_status = itemView.findViewById(R.id.report_number_status);
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/app/fedilab/android/drawers/StatusListAdapter.java b/app/src/main/java/app/fedilab/android/drawers/StatusListAdapter.java
index b0da9250c..247943837 100644
--- a/app/src/main/java/app/fedilab/android/drawers/StatusListAdapter.java
+++ b/app/src/main/java/app/fedilab/android/drawers/StatusListAdapter.java
@@ -97,6 +97,7 @@ import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import app.fedilab.android.activities.AccountReportActivity;
import app.fedilab.android.client.API;
import app.fedilab.android.client.APIResponse;
import app.fedilab.android.client.Entities.Account;
@@ -2361,7 +2362,14 @@ public class StatusListAdapter extends RecyclerView.Adapter implements OnPostAct
popup.getMenu().findItem(R.id.action_schedule_boost).setVisible(false);
popup.getMenu().findItem(R.id.action_mention).setVisible(false);
}
-
+ if( MainActivity.social != UpdateAccountInfoAsyncTask.SOCIAL.MASTODON){
+ popup.getMenu().findItem(R.id.action_admin).setVisible(false);
+ }else{
+ boolean display_admin_statuses = sharedpreferences.getBoolean(Helper.SET_DISPLAY_ADMIN_STATUSES + userId + Helper.getLiveInstance(context), false);
+ if( !display_admin_statuses){
+ popup.getMenu().findItem(R.id.action_admin).setVisible(false);
+ }
+ }
boolean custom_sharing = sharedpreferences.getBoolean(Helper.SET_CUSTOM_SHARING, false);
if( custom_sharing && status.getVisibility().equals("public"))
@@ -2393,7 +2401,14 @@ public class StatusListAdapter extends RecyclerView.Adapter implements OnPostAct
break;
case R.id.action_schedule_boost:
scheduleBoost(status);
-
+ return true;
+ case R.id.action_admin:
+ String account_id = status.getReblog() != null ? status.getReblog().getAccount().getId() : status.getAccount().getId();
+ Intent intent = new Intent(context, AccountReportActivity.class);
+ Bundle b = new Bundle();
+ b.putString("account_id", account_id);
+ intent.putExtras(b);
+ context.startActivity(intent);
return true;
case R.id.action_info:
tootInformation(status);
diff --git a/app/src/main/java/app/fedilab/android/drawers/StatusReportAdapter.java b/app/src/main/java/app/fedilab/android/drawers/StatusReportAdapter.java
new file mode 100644
index 000000000..8052f0810
--- /dev/null
+++ b/app/src/main/java/app/fedilab/android/drawers/StatusReportAdapter.java
@@ -0,0 +1,99 @@
+package app.fedilab.android.drawers;
+/* Copyright 2019 Thomas Schneider
+ *
+ * This file is a part of Fedilab
+ *
+ * This program is free software; you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * Fedilab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with Fedilab; if not,
+ * see . */
+
+import android.content.Context;
+import android.os.Build;
+import android.text.Html;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+import androidx.recyclerview.widget.RecyclerView;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+
+import app.fedilab.android.R;
+
+public class StatusReportAdapter extends RecyclerView.Adapter {
+
+ private List mData;
+ private LayoutInflater mInflater;
+ private ItemClickListener mClickListener;
+
+
+ public StatusReportAdapter(Context context, List data) {
+ this.mInflater = LayoutInflater.from(context);
+ this.mData = data;
+ }
+
+
+ @NotNull
+ @Override
+ public ViewHolder onCreateViewHolder(@NotNull ViewGroup parent, int viewType) {
+ View view = mInflater.inflate(R.layout.drawer_status_report, parent, false);
+ return new ViewHolder(view);
+ }
+
+
+ @Override
+ public void onBindViewHolder(@NotNull ViewHolder holder, int position) {
+ String content;
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
+ content = Html.fromHtml(mData.get(position), Html.FROM_HTML_MODE_LEGACY).toString();
+ else
+ content = Html.fromHtml(mData.get(position)).toString();
+ holder.report_content.setText(content);
+ }
+
+ // total number of rows
+ @Override
+ public int getItemCount() {
+ return mData.size();
+ }
+
+
+
+ public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
+ TextView report_content;
+
+ ViewHolder(View itemView) {
+ super(itemView);
+ report_content = itemView.findViewById(R.id.report_content);
+ itemView.setOnClickListener(this);
+ }
+
+ @Override
+ public void onClick(View view) {
+ if (mClickListener != null) mClickListener.onItemClick(view, getAdapterPosition());
+ }
+ }
+
+ String getItem(int id) {
+ return mData.get(id);
+ }
+
+ void setClickListener(ItemClickListener itemClickListener) {
+ this.mClickListener = itemClickListener;
+ }
+
+ public interface ItemClickListener {
+ void onItemClick(View view, int position);
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/app/fedilab/android/fragments/DisplayAdminAccountsFragment.java b/app/src/main/java/app/fedilab/android/fragments/DisplayAdminAccountsFragment.java
new file mode 100644
index 000000000..ce822f75f
--- /dev/null
+++ b/app/src/main/java/app/fedilab/android/fragments/DisplayAdminAccountsFragment.java
@@ -0,0 +1,259 @@
+package app.fedilab.android.fragments;
+/* Copyright 2019 Thomas Schneider
+ *
+ * This file is a part of Fedilab
+ *
+ * This program is free software; you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * Fedilab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with Fedilab; if not,
+ * see . */
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.RelativeLayout;
+import android.widget.Toast;
+
+import androidx.annotation.NonNull;
+import androidx.core.content.ContextCompat;
+import androidx.fragment.app.Fragment;
+import androidx.recyclerview.widget.DividerItemDecoration;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import app.fedilab.android.R;
+import app.fedilab.android.asynctasks.PostAdminActionAsyncTask;
+import app.fedilab.android.asynctasks.RetrieveAccountsAsyncTask;
+import app.fedilab.android.client.API;
+import app.fedilab.android.client.APIResponse;
+import app.fedilab.android.client.Entities.AccountAdmin;
+import app.fedilab.android.client.Entities.AdminAction;
+import app.fedilab.android.drawers.AccountsAdminListAdapter;
+import app.fedilab.android.helper.Helper;
+import app.fedilab.android.interfaces.OnAdminActionInterface;
+import es.dmoral.toasty.Toasty;
+
+
+/**
+ * Created by Thomas on 19/06/2019.
+ * Fragment to display content related to accounts
+ */
+public class DisplayAdminAccountsFragment extends Fragment implements OnAdminActionInterface {
+
+ private boolean flag_loading;
+ private Context context;
+ private AsyncTask asyncTask;
+ private AccountsAdminListAdapter accountsAdminListAdapter;
+ private String max_id;
+ private List accountAdmins;
+ private RetrieveAccountsAsyncTask.Type type;
+ private RelativeLayout mainLoader, nextElementLoader, textviewNoAction;
+ private boolean firstLoad;
+ private SwipeRefreshLayout swipeRefreshLayout;
+ private boolean swiped;
+ private RecyclerView lv_admin_accounts;
+ private boolean local, remote, active, pending, disabled, silenced, suspended;
+
+ @Override
+ public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+
+ View rootView = inflater.inflate(R.layout.fragment_admin_accounts, container, false);
+
+ context = getContext();
+
+ accountAdmins = new ArrayList<>();
+
+
+ Bundle bundle = this.getArguments();
+ if (bundle != null) {
+ local = bundle.getBoolean("local", false);
+ remote = bundle.getBoolean("remote", false);
+ active = bundle.getBoolean("active", false);
+ pending = bundle.getBoolean("pending", false);
+ disabled = bundle.getBoolean("disabled", false);
+ silenced = bundle.getBoolean("silenced", false);
+ suspended = bundle.getBoolean("suspended", false);
+ }
+
+ max_id = null;
+ firstLoad = true;
+ flag_loading = true;
+ swiped = false;
+
+ swipeRefreshLayout = rootView.findViewById(R.id.swipeContainer);
+ lv_admin_accounts = rootView.findViewById(R.id.lv_admin_accounts);
+ lv_admin_accounts.addItemDecoration(new DividerItemDecoration(context, DividerItemDecoration.VERTICAL));
+ mainLoader = rootView.findViewById(R.id.loader);
+ nextElementLoader = rootView.findViewById(R.id.loading_next_accounts);
+ textviewNoAction = rootView.findViewById(R.id.no_action);
+ mainLoader.setVisibility(View.VISIBLE);
+ nextElementLoader.setVisibility(View.GONE);
+ accountsAdminListAdapter = new AccountsAdminListAdapter(context, this.accountAdmins);
+ lv_admin_accounts.setAdapter(accountsAdminListAdapter);
+
+ final LinearLayoutManager mLayoutManager;
+ mLayoutManager = new LinearLayoutManager(context);
+ lv_admin_accounts.setLayoutManager(mLayoutManager);
+ lv_admin_accounts.addOnScrollListener(new RecyclerView.OnScrollListener() {
+ public void onScrolled(RecyclerView recyclerView, int dx, int dy)
+ {
+ if(dy > 0) {
+ int visibleItemCount = mLayoutManager.getChildCount();
+ int totalItemCount = mLayoutManager.getItemCount();
+ int firstVisibleItem = mLayoutManager.findFirstVisibleItemPosition();
+ if (firstVisibleItem + visibleItemCount == totalItemCount) {
+ if (!flag_loading) {
+ flag_loading = true;
+ AdminAction adminAction = new AdminAction();
+ adminAction.setLocal(local);
+ adminAction.setRemote(remote);
+ adminAction.setActive(active);
+ adminAction.setPending(pending);
+ adminAction.setDisabled(disabled);
+ adminAction.setSilenced(silenced);
+ adminAction.setSuspended(suspended);
+ asyncTask = new PostAdminActionAsyncTask(context, API.adminAction.GET_ACCOUNTS, null, adminAction, DisplayAdminAccountsFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ nextElementLoader.setVisibility(View.VISIBLE);
+ }
+ } else {
+ nextElementLoader.setVisibility(View.GONE);
+ }
+ }
+ }
+ });
+
+ swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
+ @Override
+ public void onRefresh() {
+ max_id = null;
+ accountAdmins = new ArrayList<>();
+ firstLoad = true;
+ flag_loading = true;
+ swiped = true;
+ AdminAction adminAction = new AdminAction();
+ adminAction.setLocal(local);
+ adminAction.setRemote(remote);
+ adminAction.setActive(active);
+ adminAction.setPending(pending);
+ adminAction.setDisabled(disabled);
+ adminAction.setSilenced(silenced);
+ adminAction.setSuspended(suspended);
+ asyncTask = new PostAdminActionAsyncTask(context, API.adminAction.GET_ACCOUNTS, null, adminAction, DisplayAdminAccountsFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ }
+ });
+ SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
+ int theme = sharedpreferences.getInt(Helper.SET_THEME, Helper.THEME_DARK);
+ switch (theme){
+ case Helper.THEME_LIGHT:
+ swipeRefreshLayout.setColorSchemeResources(R.color.mastodonC4,
+ R.color.mastodonC2,
+ R.color.mastodonC3);
+ swipeRefreshLayout.setProgressBackgroundColorSchemeColor(ContextCompat.getColor(context, R.color.white));
+ break;
+ case Helper.THEME_DARK:
+ swipeRefreshLayout.setColorSchemeResources(R.color.mastodonC4__,
+ R.color.mastodonC4,
+ R.color.mastodonC4);
+ swipeRefreshLayout.setProgressBackgroundColorSchemeColor(ContextCompat.getColor(context, R.color.mastodonC1_));
+ break;
+ case Helper.THEME_BLACK:
+ swipeRefreshLayout.setColorSchemeResources(R.color.dark_icon,
+ R.color.mastodonC2,
+ R.color.mastodonC3);
+ swipeRefreshLayout.setProgressBackgroundColorSchemeColor(ContextCompat.getColor(context, R.color.black_3));
+ break;
+ }
+ AdminAction adminAction = new AdminAction();
+ adminAction.setLocal(local);
+ adminAction.setRemote(remote);
+ adminAction.setActive(active);
+ adminAction.setPending(pending);
+ adminAction.setDisabled(disabled);
+ adminAction.setSilenced(silenced);
+ adminAction.setSuspended(suspended);
+ asyncTask = new PostAdminActionAsyncTask(context, API.adminAction.GET_ACCOUNTS, null, adminAction, DisplayAdminAccountsFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ return rootView;
+ }
+
+ @Override
+ public void onCreate(Bundle saveInstance)
+ {
+ super.onCreate(saveInstance);
+ }
+
+
+
+ /**
+ * Refresh accounts in list
+ */
+ public void refreshFilter(){
+ accountsAdminListAdapter.notifyDataSetChanged();
+ }
+
+ @Override
+ public void onAttach(Context context) {
+ super.onAttach(context);
+ this.context = context;
+ }
+
+ public void onDestroy() {
+ super.onDestroy();
+ if(asyncTask != null && asyncTask.getStatus() == AsyncTask.Status.RUNNING)
+ asyncTask.cancel(true);
+ }
+
+ public void scrollToTop(){
+ if( lv_admin_accounts != null)
+ lv_admin_accounts.setAdapter(accountsAdminListAdapter);
+ }
+
+
+ @Override
+ public void onAdminAction(APIResponse apiResponse) {
+ mainLoader.setVisibility(View.GONE);
+ nextElementLoader.setVisibility(View.GONE);
+ if( apiResponse.getError() != null){
+ Toasty.error(context, apiResponse.getError().getError(),Toast.LENGTH_LONG).show();
+ swipeRefreshLayout.setRefreshing(false);
+ swiped = false;
+ flag_loading = false;
+ return;
+ }
+ flag_loading = (apiResponse.getMax_id() == null );
+ List accountAdmins = apiResponse.getAccountAdmins();
+
+ if( !swiped && firstLoad && (accountAdmins == null || accountAdmins.size() == 0))
+ textviewNoAction.setVisibility(View.VISIBLE);
+ else
+ textviewNoAction.setVisibility(View.GONE);
+
+ max_id = apiResponse.getMax_id();
+
+ if( swiped ){
+ accountsAdminListAdapter = new AccountsAdminListAdapter(context, this.accountAdmins);
+ lv_admin_accounts.setAdapter(accountsAdminListAdapter);
+ swiped = false;
+ }
+ if( accountAdmins != null && accountAdmins.size() > 0) {
+ int currentPosition = this.accountAdmins.size();
+ this.accountAdmins.addAll(accountAdmins);
+ accountsAdminListAdapter.notifyItemRangeChanged(currentPosition,accountAdmins.size());
+ }
+ swipeRefreshLayout.setRefreshing(false);
+ firstLoad = false;
+ }
+}
diff --git a/app/src/main/java/app/fedilab/android/fragments/DisplayAdminReportsFragment.java b/app/src/main/java/app/fedilab/android/fragments/DisplayAdminReportsFragment.java
new file mode 100644
index 000000000..d139b208e
--- /dev/null
+++ b/app/src/main/java/app/fedilab/android/fragments/DisplayAdminReportsFragment.java
@@ -0,0 +1,262 @@
+package app.fedilab.android.fragments;
+/* Copyright 2019 Thomas Schneider
+ *
+ * This file is a part of Fedilab
+ *
+ * This program is free software; you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * Fedilab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with Fedilab; if not,
+ * see . */
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.EditText;
+import android.widget.LinearLayout;
+import android.widget.RelativeLayout;
+import android.widget.Toast;
+
+import androidx.annotation.NonNull;
+import androidx.core.content.ContextCompat;
+import androidx.fragment.app.Fragment;
+import androidx.recyclerview.widget.DividerItemDecoration;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import app.fedilab.android.R;
+import app.fedilab.android.activities.LoginActivity;
+import app.fedilab.android.activities.PeertubeActivity;
+import app.fedilab.android.asynctasks.PostActionAsyncTask;
+import app.fedilab.android.asynctasks.PostAdminActionAsyncTask;
+import app.fedilab.android.asynctasks.RetrieveAccountsAsyncTask;
+import app.fedilab.android.client.API;
+import app.fedilab.android.client.APIResponse;
+import app.fedilab.android.client.Entities.AdminAction;
+import app.fedilab.android.client.Entities.Report;
+import app.fedilab.android.drawers.ReportsListAdapter;
+import app.fedilab.android.helper.Helper;
+import app.fedilab.android.interfaces.OnAdminActionInterface;
+import es.dmoral.toasty.Toasty;
+
+
+/**
+ * Created by Thomas on 19/06/2019.
+ * Fragment to display content related to reports
+ */
+public class DisplayAdminReportsFragment extends Fragment implements OnAdminActionInterface {
+
+ private boolean flag_loading;
+ private Context context;
+ private AsyncTask asyncTask;
+ private ReportsListAdapter reportsListAdapter;
+ private String max_id;
+ private List reports;
+ private RetrieveAccountsAsyncTask.Type type;
+ private RelativeLayout mainLoader, nextElementLoader, textviewNoAction;
+ private boolean firstLoad;
+ private SwipeRefreshLayout swipeRefreshLayout;
+ private boolean swiped;
+ private RecyclerView lv_reports;
+ private boolean unresolved;
+ @Override
+ public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+
+ View rootView = inflater.inflate(R.layout.fragment_admin_reports, container, false);
+
+ context = getContext();
+
+ reports = new ArrayList<>();
+
+ Bundle bundle = this.getArguments();
+ if (bundle != null) {
+ unresolved = bundle.getBoolean("unresolved", true);
+ }
+ max_id = null;
+ firstLoad = true;
+ flag_loading = true;
+ swiped = false;
+
+ swipeRefreshLayout = rootView.findViewById(R.id.swipeContainer);
+ lv_reports = rootView.findViewById(R.id.lv_reports);
+ lv_reports.addItemDecoration(new DividerItemDecoration(context, DividerItemDecoration.VERTICAL));
+ mainLoader = rootView.findViewById(R.id.loader);
+ nextElementLoader = rootView.findViewById(R.id.loading_next_accounts);
+ textviewNoAction = rootView.findViewById(R.id.no_action);
+ mainLoader.setVisibility(View.VISIBLE);
+ nextElementLoader.setVisibility(View.GONE);
+ reportsListAdapter = new ReportsListAdapter(context, this.reports);
+ lv_reports.setAdapter(reportsListAdapter);
+
+ final LinearLayoutManager mLayoutManager;
+ mLayoutManager = new LinearLayoutManager(context);
+ lv_reports.setLayoutManager(mLayoutManager);
+ lv_reports.addOnScrollListener(new RecyclerView.OnScrollListener() {
+ public void onScrolled(RecyclerView recyclerView, int dx, int dy)
+ {
+ if(dy > 0) {
+ int visibleItemCount = mLayoutManager.getChildCount();
+ int totalItemCount = mLayoutManager.getItemCount();
+ int firstVisibleItem = mLayoutManager.findFirstVisibleItemPosition();
+ if (firstVisibleItem + visibleItemCount == totalItemCount) {
+ if (!flag_loading) {
+ flag_loading = true;
+ AdminAction adminAction = new AdminAction();
+ adminAction.setUnresolved(unresolved);
+ asyncTask = new PostAdminActionAsyncTask(context, API.adminAction.GET_REPORTS, null, adminAction, DisplayAdminReportsFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ nextElementLoader.setVisibility(View.VISIBLE);
+ }
+ } else {
+ nextElementLoader.setVisibility(View.GONE);
+ }
+ }
+ }
+ });
+
+ swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
+ @Override
+ public void onRefresh() {
+ max_id = null;
+ reports = new ArrayList<>();
+ firstLoad = true;
+ flag_loading = true;
+ swiped = true;
+ AdminAction adminAction = new AdminAction();
+ adminAction.setUnresolved(unresolved);
+ asyncTask = new PostAdminActionAsyncTask(context, API.adminAction.GET_REPORTS, null, adminAction, DisplayAdminReportsFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ }
+ });
+ SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
+ int theme = sharedpreferences.getInt(Helper.SET_THEME, Helper.THEME_DARK);
+ switch (theme){
+ case Helper.THEME_LIGHT:
+ swipeRefreshLayout.setColorSchemeResources(R.color.mastodonC4,
+ R.color.mastodonC2,
+ R.color.mastodonC3);
+ swipeRefreshLayout.setProgressBackgroundColorSchemeColor(ContextCompat.getColor(context, R.color.white));
+ break;
+ case Helper.THEME_DARK:
+ swipeRefreshLayout.setColorSchemeResources(R.color.mastodonC4__,
+ R.color.mastodonC4,
+ R.color.mastodonC4);
+ swipeRefreshLayout.setProgressBackgroundColorSchemeColor(ContextCompat.getColor(context, R.color.mastodonC1_));
+ break;
+ case Helper.THEME_BLACK:
+ swipeRefreshLayout.setColorSchemeResources(R.color.dark_icon,
+ R.color.mastodonC2,
+ R.color.mastodonC3);
+ swipeRefreshLayout.setProgressBackgroundColorSchemeColor(ContextCompat.getColor(context, R.color.black_3));
+ break;
+ }
+ AdminAction adminAction = new AdminAction();
+ adminAction.setUnresolved(unresolved);
+ asyncTask = new PostAdminActionAsyncTask(context, API.adminAction.GET_REPORTS, null, adminAction, DisplayAdminReportsFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ return rootView;
+ }
+
+ @Override
+ public void onCreate(Bundle saveInstance)
+ {
+ super.onCreate(saveInstance);
+ }
+
+
+ /**
+ * Refresh report in list
+ */
+ public void refreshFilter(){
+ reportsListAdapter.notifyDataSetChanged();
+ }
+
+ @Override
+ public void onAttach(Context context) {
+ super.onAttach(context);
+ this.context = context;
+ }
+
+ public void onDestroy() {
+ super.onDestroy();
+ if(asyncTask != null && asyncTask.getStatus() == AsyncTask.Status.RUNNING)
+ asyncTask.cancel(true);
+ }
+
+ public void scrollToTop(){
+ if( lv_reports != null)
+ lv_reports.setAdapter(reportsListAdapter);
+ }
+
+
+ @Override
+ public void onAdminAction(APIResponse apiResponse) {
+ mainLoader.setVisibility(View.GONE);
+ nextElementLoader.setVisibility(View.GONE);
+ if( apiResponse.getError() != null){
+ swipeRefreshLayout.setRefreshing(false);
+ swiped = false;
+ flag_loading = false;
+ //Admin right not granted through the API?
+ if( apiResponse.getError().getStatusCode() == 403){
+ AlertDialog.Builder builderInner;
+ builderInner = new AlertDialog.Builder(context, R.style.AdminDialog);
+ builderInner.setTitle(R.string.reconnect_account);
+ builderInner.setMessage(R.string.reconnect_account_message);
+ builderInner.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog,int which) {
+ dialog.dismiss();
+ }
+ });
+ builderInner.setPositiveButton(R.string.validate, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog,int which) {
+ Intent intent = new Intent(context, LoginActivity.class);
+ intent.putExtra("admin", true);
+ context.startActivity(intent);
+ }
+ });
+ builderInner.show();
+ }else{
+ Toasty.error(context, apiResponse.getError().getError(),Toast.LENGTH_LONG).show();
+ }
+ return;
+ }
+ flag_loading = (apiResponse.getMax_id() == null );
+ List reports = apiResponse.getReports();
+
+ if( !swiped && firstLoad && (reports == null || reports.size() == 0))
+ textviewNoAction.setVisibility(View.VISIBLE);
+ else
+ textviewNoAction.setVisibility(View.GONE);
+
+ max_id = apiResponse.getMax_id();
+
+ if( swiped ){
+ reportsListAdapter = new ReportsListAdapter(context, this.reports);
+ lv_reports.setAdapter(reportsListAdapter);
+ swiped = false;
+ }
+ if( reports != null && reports.size() > 0) {
+ int currentPosition = this.reports.size();
+ this.reports.addAll(reports);
+ reportsListAdapter.notifyItemRangeChanged(currentPosition,reports.size());
+ }
+ swipeRefreshLayout.setRefreshing(false);
+ firstLoad = false;
+ }
+}
diff --git a/app/src/main/java/app/fedilab/android/fragments/SettingsFragment.java b/app/src/main/java/app/fedilab/android/fragments/SettingsFragment.java
index 3ef99fa6f..cc2d46cda 100644
--- a/app/src/main/java/app/fedilab/android/fragments/SettingsFragment.java
+++ b/app/src/main/java/app/fedilab/android/fragments/SettingsFragment.java
@@ -342,6 +342,41 @@ public class SettingsFragment extends Fragment {
}
});
+ String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null);
+ String instance = sharedpreferences.getString(Helper.PREF_INSTANCE, Helper.getLiveInstance(context));
+
+ boolean display_admin_menu = sharedpreferences.getBoolean(Helper.SET_DISPLAY_ADMIN_MENU + userId + instance, false);
+
+ final CheckBox set_display_admin_menu = rootView.findViewById(R.id.set_display_admin_menu);
+ set_display_admin_menu.setChecked(display_admin_menu);
+ set_display_admin_menu.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ SharedPreferences.Editor editor = sharedpreferences.edit();
+ editor.putBoolean(Helper.SET_DISPLAY_ADMIN_MENU + userId + instance, set_display_admin_menu.isChecked());
+ editor.apply();
+ }
+ });
+
+ boolean display_admin_statuses = sharedpreferences.getBoolean(Helper.SET_DISPLAY_ADMIN_STATUSES + userId + instance, false);
+
+ final CheckBox set_display_admin_statuses = rootView.findViewById(R.id.set_display_admin_statuses);
+ set_display_admin_statuses.setChecked(display_admin_statuses);
+ set_display_admin_statuses.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ SharedPreferences.Editor editor = sharedpreferences.edit();
+ editor.putBoolean(Helper.SET_DISPLAY_ADMIN_STATUSES + userId + instance, set_display_admin_statuses.isChecked());
+ editor.apply();
+ }
+ });
+
+ if( MainActivity.social != UpdateAccountInfoAsyncTask.SOCIAL.MASTODON){
+ LinearLayout admin_container = rootView.findViewById(R.id.admin_container);
+ if( admin_container != null){
+ admin_container.setVisibility(View.GONE);
+ }
+ }
boolean show_media_urls = sharedpreferences.getBoolean(Helper.SET_MEDIA_URLS, false);
final CheckBox set_auto_add_media_url = rootView.findViewById(R.id.set_auto_add_media_url);
@@ -1022,8 +1057,7 @@ public class SettingsFragment extends Fragment {
LinearLayout toot_visibility_container = rootView.findViewById(R.id.toot_visibility_container);
SQLiteDatabase db = Sqlite.getInstance(context, Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
- String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null);
- String instance = sharedpreferences.getString(Helper.PREF_INSTANCE, Helper.getLiveInstance(context));
+
final Account account = new AccountDAO(context, db).getUniqAccount(userId, instance);
final ImageView set_toot_visibility = rootView.findViewById(R.id.set_toot_visibility);
if( theme == Helper.THEME_DARK){
diff --git a/app/src/main/java/app/fedilab/android/helper/Helper.java b/app/src/main/java/app/fedilab/android/helper/Helper.java
index f11ba2e77..2c19c8215 100644
--- a/app/src/main/java/app/fedilab/android/helper/Helper.java
+++ b/app/src/main/java/app/fedilab/android/helper/Helper.java
@@ -228,6 +228,7 @@ public class Helper {
public static final String TAG = "mastodon_etalab";
public static final String CLIENT_NAME_VALUE = "Fedilab";
public static final String OAUTH_SCOPES = "read write follow";
+ public static final String OAUTH_SCOPES_ADMIN = "read write follow admin:read admin:write admin";
public static final String OAUTH_SCOPES_PIXELFED = "write follow";
public static final String OAUTH_SCOPES_PEERTUBE = "user";
public static final String PREF_KEY_OAUTH_TOKEN = "oauth_token";
@@ -348,6 +349,9 @@ public class Helper {
public static final String SET_DISPLAY_TIMELINE_IN_LIST = "set_display_timeline_in_list";
public static final String SET_ONION_SCHEME = "set_onion_scheme";
public static final String SET_REMEMBER_POSITION_HOME = "set_remember_position";
+ public static final String SET_DISPLAY_ADMIN_MENU = "set_display_admin_menu";
+ public static final String SET_DISPLAY_ADMIN_STATUSES = "set_display_admin_statuses";
+
public static final int S_NO = 0;
static final int S_512KO = 1;
public static final int S_1MO = 2;
diff --git a/app/src/main/java/app/fedilab/android/interfaces/OnAdminActionInterface.java b/app/src/main/java/app/fedilab/android/interfaces/OnAdminActionInterface.java
new file mode 100644
index 000000000..f5ee194c6
--- /dev/null
+++ b/app/src/main/java/app/fedilab/android/interfaces/OnAdminActionInterface.java
@@ -0,0 +1,25 @@
+/* Copyright 2019 Thomas Schneider
+ *
+ * This file is a part of Fedilab
+ *
+ * This program is free software; you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * Fedilab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with Fedilab; if not,
+ * see . */
+package app.fedilab.android.interfaces;
+
+import app.fedilab.android.client.APIResponse;
+
+/**
+ * Created by Thomas on 08/06/2019.
+ * Interface when an admin action is done GET/POST
+ */
+public interface OnAdminActionInterface {
+ void onAdminAction(APIResponse apiResponse);
+}
diff --git a/app/src/main/res/drawable/ic_mode_comment_white.xml b/app/src/main/res/drawable/ic_mode_comment_white.xml
new file mode 100644
index 000000000..480b87a57
--- /dev/null
+++ b/app/src/main/res/drawable/ic_mode_comment_white.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_security_admin.xml b/app/src/main/res/drawable/ic_security_admin.xml
new file mode 100644
index 000000000..d66f92794
--- /dev/null
+++ b/app/src/main/res/drawable/ic_security_admin.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/app/src/main/res/layout-sw600dp/fragment_settings.xml b/app/src/main/res/layout-sw600dp/fragment_settings.xml
index 17cca313f..334725c4e 100644
--- a/app/src/main/res/layout-sw600dp/fragment_settings.xml
+++ b/app/src/main/res/layout-sw600dp/fragment_settings.xml
@@ -155,6 +155,54 @@
android:text="@string/set_display_news_from_fedilab"
android:layout_height="wrap_content" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_admin_report.xml b/app/src/main/res/layout/activity_admin_report.xml
new file mode 100644
index 000000000..97a8f6a5f
--- /dev/null
+++ b/app/src/main/res/layout/activity_admin_report.xml
@@ -0,0 +1,390 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/drawer_account_admin.xml b/app/src/main/res/layout/drawer_account_admin.xml
new file mode 100644
index 000000000..17ae31a2b
--- /dev/null
+++ b/app/src/main/res/layout/drawer_account_admin.xml
@@ -0,0 +1,81 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/drawer_report.xml b/app/src/main/res/layout/drawer_report.xml
new file mode 100644
index 000000000..8625eda10
--- /dev/null
+++ b/app/src/main/res/layout/drawer_report.xml
@@ -0,0 +1,108 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/drawer_status_report.xml b/app/src/main/res/layout/drawer_status_report.xml
new file mode 100644
index 000000000..bd128a515
--- /dev/null
+++ b/app/src/main/res/layout/drawer_status_report.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_admin_accounts.xml b/app/src/main/res/layout/fragment_admin_accounts.xml
new file mode 100644
index 000000000..e9bc00da4
--- /dev/null
+++ b/app/src/main/res/layout/fragment_admin_accounts.xml
@@ -0,0 +1,82 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/fragment_admin_reports.xml b/app/src/main/res/layout/fragment_admin_reports.xml
new file mode 100644
index 000000000..1e6b84a18
--- /dev/null
+++ b/app/src/main/res/layout/fragment_admin_reports.xml
@@ -0,0 +1,82 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/fragment_settings.xml b/app/src/main/res/layout/fragment_settings.xml
index 2b8b0772b..98f2ffd78 100644
--- a/app/src/main/res/layout/fragment_settings.xml
+++ b/app/src/main/res/layout/fragment_settings.xml
@@ -158,6 +158,59 @@
android:text="@string/set_display_news_from_fedilab"
android:layout_height="wrap_content" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/menu/option_filter_admin_accounts.xml b/app/src/main/res/menu/option_filter_admin_accounts.xml
new file mode 100644
index 000000000..37b9dfe16
--- /dev/null
+++ b/app/src/main/res/menu/option_filter_admin_accounts.xml
@@ -0,0 +1,54 @@
+
+
diff --git a/app/src/main/res/menu/option_filter_admin_reports.xml b/app/src/main/res/menu/option_filter_admin_reports.xml
new file mode 100644
index 000000000..ef03cbe1b
--- /dev/null
+++ b/app/src/main/res/menu/option_filter_admin_reports.xml
@@ -0,0 +1,13 @@
+
+
diff --git a/app/src/main/res/menu/option_toot.xml b/app/src/main/res/menu/option_toot.xml
index e0b1d0f3f..4a5449109 100644
--- a/app/src/main/res/menu/option_toot.xml
+++ b/app/src/main/res/menu/option_toot.xml
@@ -10,6 +10,10 @@
android:title="@string/bookmark_add"
android:actionLayout="@layout/bookmark_layout"
app:showAsAction="never" />
+
- Important: If your instance required validation, you will receive an email once it is validated!
Save the message in drafts?
+ Administration
+ Reports
+ No reports to display!
+ Reconnect the account
+ The application failed to access the admin features. You might need to reconnect the account for having the correct scope.
+ Unresolved
+ Resolved
+ Remote
+ Active
+ Pending
+ Disabled
+ Silenced
+ Suspended
+ Permissions
+ Email status
+ Login status
+ Joined
+ Most recent IP
+ Warn
+ Disable
+ Silence
+ Notify the user per e-mail
+ Perform action
+ Custom warning
+ User
+ Moderator
+ Administrator
+ Confirmed
+ Not confirmed
+ Reported statuses
+ Account
+ Undo silence
+ Undo disable
+ Suspend
+ Undo suspend
+ The account is silenced!
+ The account is no longer silenced!
+ The account is suspended!
+ The account is no longer suspended!
+ The account is disabled!
+ The account is no longer disabled!
+ The account has been warned!
+ Display the admin menu
+ Display the admin feature in statuses
+ Allow
+ The account is approved!
+ The account is rejected!
+ Assign to me
+ Unassign
+ Mark as resolved
+ Mark as unresolved
- %d vote
- %d votes
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
index da3485a32..f7c992029 100644
--- a/app/src/main/res/values/styles.xml
+++ b/app/src/main/res/values/styles.xml
@@ -392,4 +392,48 @@
+
+
+
+
+
+
+
+