From b5a304be5647e213f70bf5cdf5ce5ef9ec6afad7 Mon Sep 17 00:00:00 2001 From: Thomas Date: Thu, 24 Nov 2022 12:32:33 +0100 Subject: [PATCH] Add some endpoints + ui --- app/src/main/AndroidManifest.xml | 6 +- .../app/fedilab/android/BaseMainActivity.java | 2 +- .../{ => admin}/AdminAccountActivity.java | 9 +- .../{ => admin}/AdminActionActivity.java | 42 +++- .../{ => admin}/AdminReportActivity.java | 8 +- .../endpoints/MastodonAdminService.java | 27 +++ .../android/ui/drawer/StatusAdapter.java | 2 +- .../{ => admin}/AdminAccountAdapter.java | 4 +- .../ui/drawer/admin/AdminDomainAdapter.java | 90 ++++++++ .../ui/drawer/{ => admin}/ReportAdapter.java | 2 +- .../fragment/admin/FragmentAdminAccount.java | 4 +- .../fragment/admin/FragmentAdminDomain.java | 204 ++++++++++++++++++ .../fragment/admin/FragmentAdminReport.java | 4 +- .../android/viewmodel/mastodon/AdminVM.java | 68 ++++++ .../res/layout/activity_admin_actions.xml | 14 ++ .../main/res/layout/drawer_admin_domain.xml | 56 +++++ app/src/main/res/values/strings.xml | 1 + 17 files changed, 517 insertions(+), 26 deletions(-) rename app/src/main/java/app/fedilab/android/activities/{ => admin}/AdminAccountActivity.java (98%) rename app/src/main/java/app/fedilab/android/activities/{ => admin}/AdminActionActivity.java (88%) rename app/src/main/java/app/fedilab/android/activities/{ => admin}/AdminReportActivity.java (98%) rename app/src/main/java/app/fedilab/android/ui/drawer/{ => admin}/AdminAccountAdapter.java (97%) create mode 100644 app/src/main/java/app/fedilab/android/ui/drawer/admin/AdminDomainAdapter.java rename app/src/main/java/app/fedilab/android/ui/drawer/{ => admin}/ReportAdapter.java (98%) create mode 100644 app/src/main/java/app/fedilab/android/ui/fragment/admin/FragmentAdminDomain.java create mode 100644 app/src/main/res/layout/drawer_admin_domain.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 17bec2ac..8fb92343 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -201,7 +201,7 @@ android:configChanges="keyboardHidden|orientation|screenSize" android:label="@string/account" /> @@ -259,7 +259,7 @@ android:label="@string/interactions" android:theme="@style/AppThemeBar" /> diff --git a/app/src/main/java/app/fedilab/android/BaseMainActivity.java b/app/src/main/java/app/fedilab/android/BaseMainActivity.java index 49d407c9..8fc1e428 100644 --- a/app/src/main/java/app/fedilab/android/BaseMainActivity.java +++ b/app/src/main/java/app/fedilab/android/BaseMainActivity.java @@ -95,7 +95,6 @@ import java.util.regex.Pattern; import app.fedilab.android.activities.AboutActivity; import app.fedilab.android.activities.ActionActivity; -import app.fedilab.android.activities.AdminActionActivity; import app.fedilab.android.activities.AnnouncementActivity; import app.fedilab.android.activities.BaseActivity; import app.fedilab.android.activities.CacheActivity; @@ -119,6 +118,7 @@ import app.fedilab.android.activities.SearchResultTabActivity; import app.fedilab.android.activities.SettingsActivity; import app.fedilab.android.activities.SuggestionActivity; import app.fedilab.android.activities.TrendsActivity; +import app.fedilab.android.activities.admin.AdminActionActivity; import app.fedilab.android.broadcastreceiver.NetworkStateReceiver; import app.fedilab.android.client.entities.api.Emoji; import app.fedilab.android.client.entities.api.EmojiInstance; diff --git a/app/src/main/java/app/fedilab/android/activities/AdminAccountActivity.java b/app/src/main/java/app/fedilab/android/activities/admin/AdminAccountActivity.java similarity index 98% rename from app/src/main/java/app/fedilab/android/activities/AdminAccountActivity.java rename to app/src/main/java/app/fedilab/android/activities/admin/AdminAccountActivity.java index 95b9fad9..c40cace7 100644 --- a/app/src/main/java/app/fedilab/android/activities/AdminAccountActivity.java +++ b/app/src/main/java/app/fedilab/android/activities/admin/AdminAccountActivity.java @@ -1,4 +1,4 @@ -package app.fedilab.android.activities; +package app.fedilab.android.activities.admin; /* Copyright 2022 Thomas Schneider * * This file is a part of Fedilab @@ -54,8 +54,13 @@ import java.util.concurrent.TimeUnit; import app.fedilab.android.BaseMainActivity; import app.fedilab.android.R; +import app.fedilab.android.activities.BaseActivity; +import app.fedilab.android.activities.InstanceProfileActivity; +import app.fedilab.android.activities.MainActivity; +import app.fedilab.android.activities.MediaActivity; import app.fedilab.android.client.entities.api.Attachment; import app.fedilab.android.client.entities.api.admin.AdminAccount; +import app.fedilab.android.client.entities.api.admin.AdminIp; import app.fedilab.android.databinding.ActivityAdminAccountBinding; import app.fedilab.android.helper.Helper; import app.fedilab.android.helper.MastodonHelper; @@ -204,7 +209,7 @@ public class AdminAccountActivity extends BaseActivity { StringBuilder lastActive = new StringBuilder(); if (adminAccount.ips != null) { int count = 0; - for (AdminAccount.IP ip : adminAccount.ips) { + for (AdminIp ip : adminAccount.ips) { lastActive.append(Helper.shortDateToString(ip.used_at)).append(" - ").append(ip.ip).append("\r\n"); count++; if (count > 4) { diff --git a/app/src/main/java/app/fedilab/android/activities/AdminActionActivity.java b/app/src/main/java/app/fedilab/android/activities/admin/AdminActionActivity.java similarity index 88% rename from app/src/main/java/app/fedilab/android/activities/AdminActionActivity.java rename to app/src/main/java/app/fedilab/android/activities/admin/AdminActionActivity.java index 30a3abab..db022ddc 100644 --- a/app/src/main/java/app/fedilab/android/activities/AdminActionActivity.java +++ b/app/src/main/java/app/fedilab/android/activities/admin/AdminActionActivity.java @@ -1,4 +1,4 @@ -package app.fedilab.android.activities; +package app.fedilab.android.activities.admin; /* Copyright 2022 Thomas Schneider * * This file is a part of Fedilab @@ -14,7 +14,9 @@ package app.fedilab.android.activities; * You should have received a copy of the GNU General Public License along with Fedilab; if not, * see . */ -import static app.fedilab.android.activities.AdminActionActivity.AdminEnum.REPORT; +import static app.fedilab.android.activities.admin.AdminActionActivity.AdminEnum.ACCOUNT; +import static app.fedilab.android.activities.admin.AdminActionActivity.AdminEnum.DOMAIN; +import static app.fedilab.android.activities.admin.AdminActionActivity.AdminEnum.REPORT; import android.graphics.drawable.ColorDrawable; import android.os.Bundle; @@ -31,12 +33,14 @@ import androidx.fragment.app.FragmentTransaction; import com.google.gson.annotations.SerializedName; import app.fedilab.android.R; +import app.fedilab.android.activities.BaseActivity; import app.fedilab.android.databinding.ActivityAdminActionsBinding; import app.fedilab.android.databinding.PopupAdminFilterAccountsBinding; import app.fedilab.android.databinding.PopupAdminFilterReportsBinding; import app.fedilab.android.helper.Helper; import app.fedilab.android.helper.ThemeHelper; import app.fedilab.android.ui.fragment.admin.FragmentAdminAccount; +import app.fedilab.android.ui.fragment.admin.FragmentAdminDomain; import app.fedilab.android.ui.fragment.admin.FragmentAdminReport; public class AdminActionActivity extends BaseActivity { @@ -47,6 +51,7 @@ public class AdminActionActivity extends BaseActivity { private boolean canGoBack; private FragmentAdminReport fragmentAdminReport; private FragmentAdminAccount fragmentAdminAccount; + private FragmentAdminDomain fragmentAdminDomain; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { @@ -61,13 +66,13 @@ public class AdminActionActivity extends BaseActivity { } canGoBack = false; binding.reports.setOnClickListener(v -> displayTimeline(REPORT)); - binding.accounts.setOnClickListener(v -> displayTimeline(AdminEnum.ACCOUNT)); + binding.accounts.setOnClickListener(v -> displayTimeline(ACCOUNT)); + binding.domains.setOnClickListener(v -> displayTimeline(DOMAIN)); } private void displayTimeline(AdminEnum type) { canGoBack = true; if (type == REPORT) { - ThemeHelper.slideViewsToLeft(binding.buttonContainer, binding.fragmentContainer, () -> { fragmentAdminReport = new FragmentAdminReport(); Bundle bundle = new Bundle(); @@ -80,9 +85,7 @@ public class AdminActionActivity extends BaseActivity { fragmentTransaction.replace(R.id.fragment_container, fragmentAdminReport); fragmentTransaction.commit(); }); - - } else { - + } else if (type == ACCOUNT) { ThemeHelper.slideViewsToLeft(binding.buttonContainer, binding.fragmentContainer, () -> { fragmentAdminAccount = new FragmentAdminAccount(); Bundle bundle = new Bundle(); @@ -95,7 +98,19 @@ public class AdminActionActivity extends BaseActivity { fragmentTransaction.replace(R.id.fragment_container, fragmentAdminAccount); fragmentTransaction.commit(); }); - + } else if (type == DOMAIN) { + ThemeHelper.slideViewsToLeft(binding.buttonContainer, binding.fragmentContainer, () -> { + fragmentAdminDomain = new FragmentAdminDomain(); + Bundle bundle = new Bundle(); + bundle.putSerializable(Helper.ARG_TIMELINE_TYPE, type); + bundle.putString(Helper.ARG_VIEW_MODEL_KEY, "FEDILAB_" + type.getValue()); + fragmentAdminDomain.setArguments(bundle); + FragmentManager fragmentManager = getSupportFragmentManager(); + FragmentTransaction fragmentTransaction = + fragmentManager.beginTransaction(); + fragmentTransaction.replace(R.id.fragment_container, fragmentAdminDomain); + fragmentTransaction.commit(); + }); } switch (type) { case REPORT: @@ -104,6 +119,9 @@ public class AdminActionActivity extends BaseActivity { case ACCOUNT: setTitle(R.string.accounts); break; + case DOMAIN: + setTitle(R.string.domains); + break; } invalidateOptionsMenu(); } @@ -283,6 +301,9 @@ public class AdminActionActivity extends BaseActivity { if (fragmentAdminAccount != null) { fragmentAdminAccount.onDestroyView(); } + if (fragmentAdminDomain != null) { + fragmentAdminDomain.onDestroyView(); + } setTitle(R.string.administration); invalidateOptionsMenu(); }); @@ -296,8 +317,9 @@ public class AdminActionActivity extends BaseActivity { @SerializedName("REPORT") REPORT("REPORT"), @SerializedName("ACCOUNT") - ACCOUNT("ACCOUNT"); - + ACCOUNT("ACCOUNT"), + @SerializedName("DOMAIN") + DOMAIN("DOMAIN"); private final String value; AdminEnum(String value) { diff --git a/app/src/main/java/app/fedilab/android/activities/AdminReportActivity.java b/app/src/main/java/app/fedilab/android/activities/admin/AdminReportActivity.java similarity index 98% rename from app/src/main/java/app/fedilab/android/activities/AdminReportActivity.java rename to app/src/main/java/app/fedilab/android/activities/admin/AdminReportActivity.java index 6486f651..c74897c0 100644 --- a/app/src/main/java/app/fedilab/android/activities/AdminReportActivity.java +++ b/app/src/main/java/app/fedilab/android/activities/admin/AdminReportActivity.java @@ -1,4 +1,4 @@ -package app.fedilab.android.activities; +package app.fedilab.android.activities.admin; /* Copyright 2022 Thomas Schneider * * This file is a part of Fedilab @@ -55,9 +55,13 @@ import java.util.concurrent.TimeUnit; import app.fedilab.android.BaseMainActivity; import app.fedilab.android.R; +import app.fedilab.android.activities.BaseActivity; +import app.fedilab.android.activities.InstanceProfileActivity; +import app.fedilab.android.activities.MediaActivity; import app.fedilab.android.client.entities.api.Account; import app.fedilab.android.client.entities.api.Attachment; import app.fedilab.android.client.entities.api.admin.AdminAccount; +import app.fedilab.android.client.entities.api.admin.AdminIp; import app.fedilab.android.databinding.ActivityAdminAccountBinding; import app.fedilab.android.helper.Helper; import app.fedilab.android.helper.MastodonHelper; @@ -141,7 +145,7 @@ public class AdminReportActivity extends BaseActivity { binding.email.setText(adminAccount.email); StringBuilder lastActive = new StringBuilder(); if (adminAccount.ips != null) { - for (AdminAccount.IP ip : adminAccount.ips) { + for (AdminIp ip : adminAccount.ips) { lastActive.append(Helper.shortDateToString(ip.used_at)).append(" - ").append(ip.ip).append("\r\n"); } } diff --git a/app/src/main/java/app/fedilab/android/client/endpoints/MastodonAdminService.java b/app/src/main/java/app/fedilab/android/client/endpoints/MastodonAdminService.java index 5d3aff27..ee57e8ec 100644 --- a/app/src/main/java/app/fedilab/android/client/endpoints/MastodonAdminService.java +++ b/app/src/main/java/app/fedilab/android/client/endpoints/MastodonAdminService.java @@ -164,12 +164,25 @@ public interface MastodonAdminService { @Query("limit") int limit ); + @GET("admin/domain_allows") + Call> getDomainAllows( + @Header("Authorization") String token, + @Query("max_id") String max_id, + @Query("limit") int limit + ); + @GET("admin/domain_blocks/{id}") Call getDomainBlock( @Header("Authorization") String token, @Path("id") String id ); + @GET("admin/domain_allows/{id}") + Call getDomainAllow( + @Header("Authorization") String token, + @Path("id") String id + ); + @FormUrlEncoded @POST("admin/domain_blocks") @@ -184,6 +197,13 @@ public interface MastodonAdminService { @Field("obfuscate") Boolean obfuscate ); + @FormUrlEncoded + @POST("admin/domain_allows") + Call allowDomain( + @Header("Authorization") String app_token, + @Path("domain") String domain + ); + @FormUrlEncoded @PUT("admin/domain_blocks") Call updateBlockDomain( @@ -202,4 +222,11 @@ public interface MastodonAdminService { @Header("Authorization") String app_token, @Path("id") String id ); + + + @DELETE("admin/domain_allows/{id}") + Call deleteAllowDomain( + @Header("Authorization") String app_token, + @Path("id") String id + ); } diff --git a/app/src/main/java/app/fedilab/android/ui/drawer/StatusAdapter.java b/app/src/main/java/app/fedilab/android/ui/drawer/StatusAdapter.java index ddba4f6f..cb8cfe57 100644 --- a/app/src/main/java/app/fedilab/android/ui/drawer/StatusAdapter.java +++ b/app/src/main/java/app/fedilab/android/ui/drawer/StatusAdapter.java @@ -100,7 +100,6 @@ import java.util.regex.Pattern; import app.fedilab.android.BaseMainActivity; import app.fedilab.android.R; -import app.fedilab.android.activities.AdminAccountActivity; import app.fedilab.android.activities.ComposeActivity; import app.fedilab.android.activities.ContextActivity; import app.fedilab.android.activities.CustomSharingActivity; @@ -109,6 +108,7 @@ import app.fedilab.android.activities.ProfileActivity; import app.fedilab.android.activities.ReportActivity; import app.fedilab.android.activities.StatusHistoryActivity; import app.fedilab.android.activities.StatusInfoActivity; +import app.fedilab.android.activities.admin.AdminAccountActivity; import app.fedilab.android.client.entities.api.Attachment; import app.fedilab.android.client.entities.api.Poll; import app.fedilab.android.client.entities.api.Reaction; diff --git a/app/src/main/java/app/fedilab/android/ui/drawer/AdminAccountAdapter.java b/app/src/main/java/app/fedilab/android/ui/drawer/admin/AdminAccountAdapter.java similarity index 97% rename from app/src/main/java/app/fedilab/android/ui/drawer/AdminAccountAdapter.java rename to app/src/main/java/app/fedilab/android/ui/drawer/admin/AdminAccountAdapter.java index 99ab7635..16968e41 100644 --- a/app/src/main/java/app/fedilab/android/ui/drawer/AdminAccountAdapter.java +++ b/app/src/main/java/app/fedilab/android/ui/drawer/admin/AdminAccountAdapter.java @@ -1,4 +1,4 @@ -package app.fedilab.android.ui.drawer; +package app.fedilab.android.ui.drawer.admin; /* Copyright 2022 Thomas Schneider * * This file is a part of Fedilab @@ -27,7 +27,7 @@ import androidx.recyclerview.widget.RecyclerView; import java.util.List; import java.util.Locale; -import app.fedilab.android.activities.AdminAccountActivity; +import app.fedilab.android.activities.admin.AdminAccountActivity; import app.fedilab.android.client.entities.api.admin.AdminAccount; import app.fedilab.android.databinding.DrawerAdminAccountBinding; import app.fedilab.android.helper.Helper; diff --git a/app/src/main/java/app/fedilab/android/ui/drawer/admin/AdminDomainAdapter.java b/app/src/main/java/app/fedilab/android/ui/drawer/admin/AdminDomainAdapter.java new file mode 100644 index 00000000..502a2488 --- /dev/null +++ b/app/src/main/java/app/fedilab/android/ui/drawer/admin/AdminDomainAdapter.java @@ -0,0 +1,90 @@ +package app.fedilab.android.ui.drawer.admin; +/* Copyright 2022 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.view.LayoutInflater; +import android.view.ViewGroup; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +import app.fedilab.android.client.entities.api.admin.AdminDomainBlock; +import app.fedilab.android.databinding.DrawerAdminDomainBinding; +import app.fedilab.android.helper.Helper; + + +public class AdminDomainAdapter extends RecyclerView.Adapter { + + private final List adminDomainBlockList; + private Context context; + + + public AdminDomainAdapter(List adminDomainBlocks) { + this.adminDomainBlockList = adminDomainBlocks; + } + + @NotNull + @Override + public RecyclerView.ViewHolder onCreateViewHolder(@NotNull ViewGroup parent, int viewType) { + context = parent.getContext(); + DrawerAdminDomainBinding itemBinding = DrawerAdminDomainBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false); + return new DomainViewHolder(itemBinding); + } + + @Override + public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int position) { + DomainViewHolder holder = (DomainViewHolder) viewHolder; + AdminDomainBlock adminDomainBlock = adminDomainBlockList.get(position); + + holder.binding.date.setText(Helper.shortDateToString(adminDomainBlock.created_at)); + holder.binding.title.setText(adminDomainBlock.domain); + holder.binding.severity.setText(adminDomainBlock.severity); + /*holder.binding.mainContainer.setOnClickListener(view -> { + Intent intent = new Intent(context, AccountReportActivity.class); + Bundle b = new Bundle(); + b.putSerializable(Helper.ARG_REPORT, report); + intent.putExtras(b); + context.startActivity(intent); + });*/ + + } + + @Override + public long getItemId(int position) { + return position; + } + + @Override + public int getItemCount() { + return adminDomainBlockList.size(); + } + + + public static class DomainViewHolder extends RecyclerView.ViewHolder { + DrawerAdminDomainBinding binding; + + DomainViewHolder(DrawerAdminDomainBinding itemView) { + super(itemView.getRoot()); + binding = itemView; + } + } + + +} \ No newline at end of file diff --git a/app/src/main/java/app/fedilab/android/ui/drawer/ReportAdapter.java b/app/src/main/java/app/fedilab/android/ui/drawer/admin/ReportAdapter.java similarity index 98% rename from app/src/main/java/app/fedilab/android/ui/drawer/ReportAdapter.java rename to app/src/main/java/app/fedilab/android/ui/drawer/admin/ReportAdapter.java index 6a1fa987..34dedb56 100644 --- a/app/src/main/java/app/fedilab/android/ui/drawer/ReportAdapter.java +++ b/app/src/main/java/app/fedilab/android/ui/drawer/admin/ReportAdapter.java @@ -1,4 +1,4 @@ -package app.fedilab.android.ui.drawer; +package app.fedilab.android.ui.drawer.admin; /* Copyright 2022 Thomas Schneider * * This file is a part of Fedilab diff --git a/app/src/main/java/app/fedilab/android/ui/fragment/admin/FragmentAdminAccount.java b/app/src/main/java/app/fedilab/android/ui/fragment/admin/FragmentAdminAccount.java index 6e3663c1..5400a711 100644 --- a/app/src/main/java/app/fedilab/android/ui/fragment/admin/FragmentAdminAccount.java +++ b/app/src/main/java/app/fedilab/android/ui/fragment/admin/FragmentAdminAccount.java @@ -33,14 +33,14 @@ import java.util.List; import app.fedilab.android.BaseMainActivity; import app.fedilab.android.R; -import app.fedilab.android.activities.AdminActionActivity; +import app.fedilab.android.activities.admin.AdminActionActivity; import app.fedilab.android.client.entities.api.admin.AdminAccount; import app.fedilab.android.client.entities.api.admin.AdminAccounts; import app.fedilab.android.databinding.FragmentPaginationBinding; import app.fedilab.android.helper.Helper; import app.fedilab.android.helper.MastodonHelper; import app.fedilab.android.helper.ThemeHelper; -import app.fedilab.android.ui.drawer.AdminAccountAdapter; +import app.fedilab.android.ui.drawer.admin.AdminAccountAdapter; import app.fedilab.android.viewmodel.mastodon.AdminVM; diff --git a/app/src/main/java/app/fedilab/android/ui/fragment/admin/FragmentAdminDomain.java b/app/src/main/java/app/fedilab/android/ui/fragment/admin/FragmentAdminDomain.java new file mode 100644 index 00000000..f146c0fb --- /dev/null +++ b/app/src/main/java/app/fedilab/android/ui/fragment/admin/FragmentAdminDomain.java @@ -0,0 +1,204 @@ +package app.fedilab.android.ui.fragment.admin; +/* Copyright 2022 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.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; +import androidx.lifecycle.ViewModelProvider; +import androidx.recyclerview.widget.DividerItemDecoration; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import java.util.ArrayList; +import java.util.List; + +import app.fedilab.android.BaseMainActivity; +import app.fedilab.android.R; +import app.fedilab.android.client.entities.api.admin.AdminDomainBlock; +import app.fedilab.android.client.entities.api.admin.AdminDomainBlocks; +import app.fedilab.android.databinding.FragmentPaginationBinding; +import app.fedilab.android.helper.Helper; +import app.fedilab.android.helper.ThemeHelper; +import app.fedilab.android.ui.drawer.admin.AdminDomainAdapter; +import app.fedilab.android.viewmodel.mastodon.AdminVM; + + +public class FragmentAdminDomain extends Fragment { + + + private FragmentPaginationBinding binding; + private AdminVM adminVM; + private boolean flagLoading; + private List adminDomainBlocks; + private String max_id, min_id; + private AdminDomainAdapter adminDomainAdapter; + private LinearLayoutManager mLayoutManager; + private String viewModelKey; + + public void scrollToTop() { + if (binding != null) { + binding.recyclerView.scrollToPosition(0); + } + } + + public View onCreateView(@NonNull LayoutInflater inflater, + ViewGroup container, Bundle savedInstanceState) { + + if (getArguments() != null) { + viewModelKey = getArguments().getString(Helper.ARG_VIEW_MODEL_KEY, ""); + } + + binding = FragmentPaginationBinding.inflate(inflater, container, false); + binding.getRoot().setBackgroundColor(ThemeHelper.getBackgroundColor(requireActivity())); + + int c1 = getResources().getColor(R.color.cyanea_accent_reference); + binding.swipeContainer.setProgressBackgroundColorSchemeColor(getResources().getColor(R.color.cyanea_primary_reference)); + binding.swipeContainer.setColorSchemeColors( + c1, c1, c1 + ); + + adminVM = new ViewModelProvider(FragmentAdminDomain.this).get(viewModelKey, AdminVM.class); + + binding.loader.setVisibility(View.VISIBLE); + binding.recyclerView.setVisibility(View.GONE); + flagLoading = false; + adminVM.getDomainBlocks( + BaseMainActivity.currentInstance, BaseMainActivity.currentToken, null) + .observe(getViewLifecycleOwner(), this::initializeStatusesCommonView); + return binding.getRoot(); + } + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + } + + /** + * Intialize the common view for domain block on different timelines + * + * @param adminDomainBlocks {@link AdminDomainBlocks} + */ + private void initializeStatusesCommonView(final AdminDomainBlocks adminDomainBlocks) { + if (binding == null || !isAdded() || getActivity() == null) { + return; + } + binding.loader.setVisibility(View.GONE); + binding.noAction.setVisibility(View.GONE); + binding.swipeContainer.setRefreshing(false); + binding.swipeContainer.setOnRefreshListener(() -> { + binding.swipeContainer.setRefreshing(true); + max_id = null; + flagLoading = false; + adminVM.getDomainBlocks( + BaseMainActivity.currentInstance, BaseMainActivity.currentToken, null) + .observe(getViewLifecycleOwner(), this::initializeStatusesCommonView); + }); + + if (adminDomainBlocks == null || adminDomainBlocks.adminDomainBlocks == null || adminDomainBlocks.adminDomainBlocks.size() == 0) { + binding.noAction.setVisibility(View.VISIBLE); + return; + } + flagLoading = adminDomainBlocks.pagination.max_id == null; + binding.recyclerView.setVisibility(View.VISIBLE); + if (adminDomainAdapter != null && this.adminDomainBlocks != null) { + int size = this.adminDomainBlocks.size(); + this.adminDomainBlocks.clear(); + this.adminDomainBlocks = new ArrayList<>(); + adminDomainAdapter.notifyItemRangeRemoved(0, size); + } + if (this.adminDomainBlocks == null) { + this.adminDomainBlocks = new ArrayList<>(); + } + this.adminDomainBlocks.addAll(adminDomainBlocks.adminDomainBlocks); + + if (max_id == null || (adminDomainBlocks.pagination.max_id != null && Helper.compareTo(adminDomainBlocks.pagination.max_id, max_id) < 0)) { + max_id = adminDomainBlocks.pagination.max_id; + } + if (min_id == null || (adminDomainBlocks.pagination.max_id != null && Helper.compareTo(adminDomainBlocks.pagination.min_id, min_id) > 0)) { + min_id = adminDomainBlocks.pagination.min_id; + } + + adminDomainAdapter = new AdminDomainAdapter(adminDomainBlocks.adminDomainBlocks); + + mLayoutManager = new LinearLayoutManager(requireActivity()); + binding.recyclerView.setLayoutManager(mLayoutManager); + binding.recyclerView.setAdapter(adminDomainAdapter); + DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(binding.recyclerView.getContext(), + mLayoutManager.getOrientation()); + binding.recyclerView.addItemDecoration(dividerItemDecoration); + binding.recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { + @Override + public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { + if (requireActivity() instanceof BaseMainActivity) { + if (dy < 0 && !((BaseMainActivity) requireActivity()).getFloatingVisibility()) + ((BaseMainActivity) requireActivity()).manageFloatingButton(true); + if (dy > 0 && ((BaseMainActivity) requireActivity()).getFloatingVisibility()) + ((BaseMainActivity) requireActivity()).manageFloatingButton(false); + } + int firstVisibleItem = mLayoutManager.findFirstVisibleItemPosition(); + if (dy > 0) { + int visibleItemCount = mLayoutManager.getChildCount(); + int totalItemCount = mLayoutManager.getItemCount(); + if (firstVisibleItem + visibleItemCount == totalItemCount) { + if (!flagLoading) { + flagLoading = true; + binding.loadingNextElements.setVisibility(View.VISIBLE); + adminVM.getDomainAllows( + BaseMainActivity.currentInstance, BaseMainActivity.currentToken, max_id) + .observe(getViewLifecycleOwner(), adminDomainBlocks1 -> dealWithPagination(adminDomainBlocks1)); + } + } else { + binding.loadingNextElements.setVisibility(View.GONE); + } + } + } + }); + } + + /** + * Update view and pagination when scrolling down + * + * @param admDomainBlocks AdminDomainBlocks + */ + private void dealWithPagination(AdminDomainBlocks admDomainBlocks) { + + if (binding == null || !isAdded() || getActivity() == null) { + return; + } + binding.loadingNextElements.setVisibility(View.GONE); + if (this.adminDomainBlocks != null && admDomainBlocks != null && admDomainBlocks.adminDomainBlocks != null && admDomainBlocks.adminDomainBlocks.size() > 0) { + flagLoading = admDomainBlocks.pagination.max_id == null; + //There are some adminDomainBlocks present in the timeline + int startId = this.adminDomainBlocks.size(); + this.adminDomainBlocks.addAll(admDomainBlocks.adminDomainBlocks); + adminDomainAdapter.notifyItemRangeInserted(startId, admDomainBlocks.adminDomainBlocks.size()); + if (max_id == null || (admDomainBlocks.pagination.max_id != null && Helper.compareTo(admDomainBlocks.pagination.max_id, max_id) < 0)) { + max_id = admDomainBlocks.pagination.max_id; + } + if (min_id == null || (admDomainBlocks.pagination.min_id != null && Helper.compareTo(admDomainBlocks.pagination.min_id, min_id) > 0)) { + min_id = admDomainBlocks.pagination.min_id; + } + } + } + + +} \ No newline at end of file diff --git a/app/src/main/java/app/fedilab/android/ui/fragment/admin/FragmentAdminReport.java b/app/src/main/java/app/fedilab/android/ui/fragment/admin/FragmentAdminReport.java index 6a44c743..5f8536c4 100644 --- a/app/src/main/java/app/fedilab/android/ui/fragment/admin/FragmentAdminReport.java +++ b/app/src/main/java/app/fedilab/android/ui/fragment/admin/FragmentAdminReport.java @@ -33,13 +33,13 @@ import java.util.List; import app.fedilab.android.BaseMainActivity; import app.fedilab.android.R; -import app.fedilab.android.activities.AdminActionActivity; +import app.fedilab.android.activities.admin.AdminActionActivity; import app.fedilab.android.client.entities.api.admin.AdminReport; import app.fedilab.android.client.entities.api.admin.AdminReports; import app.fedilab.android.databinding.FragmentPaginationBinding; import app.fedilab.android.helper.Helper; import app.fedilab.android.helper.ThemeHelper; -import app.fedilab.android.ui.drawer.ReportAdapter; +import app.fedilab.android.ui.drawer.admin.ReportAdapter; import app.fedilab.android.viewmodel.mastodon.AdminVM; diff --git a/app/src/main/java/app/fedilab/android/viewmodel/mastodon/AdminVM.java b/app/src/main/java/app/fedilab/android/viewmodel/mastodon/AdminVM.java index 11568c0a..9f3d17b3 100644 --- a/app/src/main/java/app/fedilab/android/viewmodel/mastodon/AdminVM.java +++ b/app/src/main/java/app/fedilab/android/viewmodel/mastodon/AdminVM.java @@ -630,4 +630,72 @@ public class AdminVM extends AndroidViewModel { }).start(); return adminDomainBlockMutableLiveData; } + + + /** + * View all allowed domains. + * + * @param instance Instance domain of the active account + * @param token Access token of the active account + * @return {@link LiveData} containing a {@link List} of {@link AdminDomainBlocks}s + */ + public LiveData getDomainAllows(@NonNull String instance, + String token, + String max_id) { + MastodonAdminService mastodonAdminService = init(instance); + adminDomainBlockListMutableLiveData = new MutableLiveData<>(); + new Thread(() -> { + List adminDomainBlockList; + Call> getDomainBlocks = mastodonAdminService.getDomainAllows(token, max_id, MastodonHelper.statusesPerCall(getApplication())); + AdminDomainBlocks adminDomainBlocks = new AdminDomainBlocks(); + if (getDomainBlocks != null) { + try { + Response> getDomainBlocksResponse = getDomainBlocks.execute(); + if (getDomainBlocksResponse.isSuccessful()) { + adminDomainBlocks.adminDomainBlocks = getDomainBlocksResponse.body(); + adminDomainBlocks.pagination = MastodonHelper.getPagination(getDomainBlocksResponse.headers()); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + Handler mainHandler = new Handler(Looper.getMainLooper()); + Runnable myRunnable = () -> adminDomainBlockListMutableLiveData.setValue(adminDomainBlocks); + mainHandler.post(myRunnable); + }).start(); + return adminDomainBlockListMutableLiveData; + } + + /** + * View a single allowed domain + * + * @param instance Instance domain of the active account + * @param token Access token of the active account + * @return {@link LiveData} containing a {@link List} of {@link AdminDomainBlocks}s + */ + public LiveData getDomainAllow(@NonNull String instance, + String token, + String id) { + MastodonAdminService mastodonAdminService = init(instance); + adminDomainBlockMutableLiveData = new MutableLiveData<>(); + new Thread(() -> { + AdminDomainBlock adminDomainBlock = null; + Call getDomainBlock = mastodonAdminService.getDomainAllow(token, id); + if (getDomainBlock != null) { + try { + Response getDomainBlocksResponse = getDomainBlock.execute(); + if (getDomainBlocksResponse.isSuccessful()) { + adminDomainBlock = getDomainBlocksResponse.body(); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + Handler mainHandler = new Handler(Looper.getMainLooper()); + AdminDomainBlock finalAdminDomainBlock = adminDomainBlock; + Runnable myRunnable = () -> adminDomainBlockMutableLiveData.setValue(finalAdminDomainBlock); + mainHandler.post(myRunnable); + }).start(); + return adminDomainBlockMutableLiveData; + } } diff --git a/app/src/main/res/layout/activity_admin_actions.xml b/app/src/main/res/layout/activity_admin_actions.xml index f6d7b102..79ea3386 100644 --- a/app/src/main/res/layout/activity_admin_actions.xml +++ b/app/src/main/res/layout/activity_admin_actions.xml @@ -41,6 +41,20 @@ app:iconTint="@color/cyanea_accent_dark_reference" app:strokeColor="@color/cyanea_accent_dark_reference" /> + diff --git a/app/src/main/res/layout/drawer_admin_domain.xml b/app/src/main/res/layout/drawer_admin_domain.xml new file mode 100644 index 00000000..57ea5204 --- /dev/null +++ b/app/src/main/res/layout/drawer_admin_domain.xml @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 9d8b5255..ae5912e8 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1914,4 +1914,5 @@ Remove pinned timeline? Are you sure to unpin that timeline? Delete the pinned timelines? + Domains \ No newline at end of file