From fd24f0425413aa65b13d7a4f6296b814e9327c3b Mon Sep 17 00:00:00 2001 From: Balazs Toldi Date: Thu, 17 Aug 2023 15:46:18 +0200 Subject: [PATCH] Report posts and comments. Closes #92 --- .../toldi/infinityforlemmy/AppComponent.java | 3 + .../toldi/infinityforlemmy/NetworkModule.java | 18 ++++-- .../toldi/infinityforlemmy/apis/LemmyAPI.java | 10 ++++ .../CommentMoreBottomSheetFragment.java | 59 ++++++++++++++++++- .../fragments/ViewPostDetailFragment.java | 44 +++++++++++++- .../comment/LemmyCommentAPI.kt | 35 +++++++++++ .../toldi/infinityforlemmy/dto/ReportDTOs.kt | 5 ++ app/src/main/res/layout/dialog_report.xml | 15 +++++ app/src/main/res/values/strings.xml | 2 + 9 files changed, 183 insertions(+), 8 deletions(-) create mode 100644 app/src/main/kotlin/eu/toldi/infinityforlemmy/comment/LemmyCommentAPI.kt create mode 100644 app/src/main/kotlin/eu/toldi/infinityforlemmy/dto/ReportDTOs.kt create mode 100644 app/src/main/res/layout/dialog_report.xml diff --git a/app/src/main/java/eu/toldi/infinityforlemmy/AppComponent.java b/app/src/main/java/eu/toldi/infinityforlemmy/AppComponent.java index a689db7a..59fc2a8a 100644 --- a/app/src/main/java/eu/toldi/infinityforlemmy/AppComponent.java +++ b/app/src/main/java/eu/toldi/infinityforlemmy/AppComponent.java @@ -66,6 +66,7 @@ import eu.toldi.infinityforlemmy.activities.ViewVideoActivity; import eu.toldi.infinityforlemmy.activities.WebViewActivity; import eu.toldi.infinityforlemmy.activities.WikiActivity; import eu.toldi.infinityforlemmy.bottomsheetfragments.AccountChooserBottomSheetFragment; +import eu.toldi.infinityforlemmy.bottomsheetfragments.CommentMoreBottomSheetFragment; import eu.toldi.infinityforlemmy.bottomsheetfragments.FlairBottomSheetFragment; import eu.toldi.infinityforlemmy.fragments.BlockedCommunitiesListingFragment; import eu.toldi.infinityforlemmy.fragments.BlockedUsersListingFragment; @@ -316,6 +317,8 @@ public interface AppComponent { void inject(BlockedUsersListingFragment blockedUsersListingFragment); + void inject(CommentMoreBottomSheetFragment commentMoreBottomSheetFragment); + @Component.Factory interface Factory { diff --git a/app/src/main/java/eu/toldi/infinityforlemmy/NetworkModule.java b/app/src/main/java/eu/toldi/infinityforlemmy/NetworkModule.java index 3960113d..85909e06 100644 --- a/app/src/main/java/eu/toldi/infinityforlemmy/NetworkModule.java +++ b/app/src/main/java/eu/toldi/infinityforlemmy/NetworkModule.java @@ -10,15 +10,13 @@ import javax.inject.Singleton; import dagger.Module; import dagger.Provides; import eu.toldi.infinityforlemmy.apis.StreamableAPI; -import eu.toldi.infinityforlemmy.network.SortTypeConverterFactory; +import eu.toldi.infinityforlemmy.comment.LemmyCommentAPI; +import eu.toldi.infinityforlemmy.post.LemmyPostAPI; import eu.toldi.infinityforlemmy.utils.APIUtils; import okhttp3.ConnectionPool; import okhttp3.Interceptor; import okhttp3.OkHttpClient; import retrofit2.Retrofit; -import retrofit2.adapter.guava.GuavaCallAdapterFactory; -import retrofit2.converter.gson.GsonConverterFactory; -import retrofit2.converter.scalars.ScalarsConverterFactory; @Module(includes = AppModule.class) abstract class NetworkModule { @@ -216,4 +214,16 @@ abstract class NetworkModule { static StreamableAPI provideStreamableApi(@Named("streamable") Retrofit streamableRetrofit) { return streamableRetrofit.create(StreamableAPI.class); } + + @Provides + @Singleton + static LemmyPostAPI providePostAPI(@Named("no_oauth") RetrofitHolder retrofitHolder) { + return new LemmyPostAPI(retrofitHolder); + } + + @Provides + @Singleton + static LemmyCommentAPI provideCommentAPI(@Named("no_oauth") RetrofitHolder retrofitHolder) { + return new LemmyCommentAPI(retrofitHolder); + } } diff --git a/app/src/main/java/eu/toldi/infinityforlemmy/apis/LemmyAPI.java b/app/src/main/java/eu/toldi/infinityforlemmy/apis/LemmyAPI.java index 0f384a49..4ef15b11 100644 --- a/app/src/main/java/eu/toldi/infinityforlemmy/apis/LemmyAPI.java +++ b/app/src/main/java/eu/toldi/infinityforlemmy/apis/LemmyAPI.java @@ -18,6 +18,8 @@ import eu.toldi.infinityforlemmy.dto.PostVoteDTO; import eu.toldi.infinityforlemmy.dto.ReadCommentDTO; import eu.toldi.infinityforlemmy.dto.ReadMessageDTO; import eu.toldi.infinityforlemmy.dto.ReadPostDTO; +import eu.toldi.infinityforlemmy.dto.ReportCommentDTO; +import eu.toldi.infinityforlemmy.dto.ReportPostDTO; import eu.toldi.infinityforlemmy.dto.SaveCommentDTO; import eu.toldi.infinityforlemmy.dto.SavePostDTO; import eu.toldi.infinityforlemmy.dto.SubmitPostDTO; @@ -82,6 +84,10 @@ public interface LemmyAPI { @POST("api/v3/post") Call postCreate(@Body SubmitPostDTO params); + @Headers("Content-Type: application/json") + @POST("api/v3/post/report") + Call postReport(@Body ReportPostDTO params); + @Headers("Content-Type: application/json") @PUT("api/v3/post") Call postUpdate(@Body EditPostDTO params); @@ -138,6 +144,10 @@ public interface LemmyAPI { @POST("api/v3/comment/like") Call commentLike(@Body CommentVoteDTO params); + @Headers("Content-Type: application/json") + @POST("api/v3/comment/report") + Call commentReport(@Body ReportCommentDTO params); + @Headers("Content-Type: application/json") @POST("api/v3/community/follow") Call communityFollow(@Body FollowCommunityDTO params); diff --git a/app/src/main/java/eu/toldi/infinityforlemmy/bottomsheetfragments/CommentMoreBottomSheetFragment.java b/app/src/main/java/eu/toldi/infinityforlemmy/bottomsheetfragments/CommentMoreBottomSheetFragment.java index eacf058b..09f622be 100644 --- a/app/src/main/java/eu/toldi/infinityforlemmy/bottomsheetfragments/CommentMoreBottomSheetFragment.java +++ b/app/src/main/java/eu/toldi/infinityforlemmy/bottomsheetfragments/CommentMoreBottomSheetFragment.java @@ -10,24 +10,32 @@ import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.Button; +import android.widget.EditText; import android.widget.TextView; import android.widget.Toast; import androidx.annotation.NonNull; +import androidx.appcompat.app.AlertDialog; import androidx.core.content.ContextCompat; import androidx.fragment.app.Fragment; +import com.google.android.material.dialog.MaterialAlertDialogBuilder; + +import javax.inject.Inject; + import butterknife.BindView; import butterknife.ButterKnife; +import eu.toldi.infinityforlemmy.Infinity; import eu.toldi.infinityforlemmy.R; import eu.toldi.infinityforlemmy.activities.BaseActivity; import eu.toldi.infinityforlemmy.activities.CommentActivity; import eu.toldi.infinityforlemmy.activities.EditCommentActivity; -import eu.toldi.infinityforlemmy.activities.GiveAwardActivity; -import eu.toldi.infinityforlemmy.activities.ReportActivity; import eu.toldi.infinityforlemmy.activities.ViewPostDetailActivity; import eu.toldi.infinityforlemmy.activities.ViewUserDetailActivity; import eu.toldi.infinityforlemmy.comment.Comment; +import eu.toldi.infinityforlemmy.comment.LemmyCommentAPI; +import eu.toldi.infinityforlemmy.customtheme.CustomThemeWrapper; import eu.toldi.infinityforlemmy.customviews.LandscapeExpandedRoundedBottomSheetDialogFragment; import eu.toldi.infinityforlemmy.utils.Utils; @@ -57,6 +65,13 @@ public class CommentMoreBottomSheetFragment extends LandscapeExpandedRoundedBott TextView copyTextView; @BindView(R.id.report_view_comment_more_bottom_sheet_fragment) TextView reportTextView; + + @Inject + LemmyCommentAPI lemmyCommentAPI; + + @Inject + CustomThemeWrapper mCustomThemeWrapper; + private BaseActivity activity; public CommentMoreBottomSheetFragment() { @@ -66,6 +81,7 @@ public class CommentMoreBottomSheetFragment extends LandscapeExpandedRoundedBott @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + ((Infinity) activity.getApplication()).getAppComponent().inject(this); View rootView = inflater.inflate(R.layout.fragment_comment_more_bottom_sheet, container, false); ButterKnife.bind(this, rootView); @@ -181,7 +197,44 @@ public class CommentMoreBottomSheetFragment extends LandscapeExpandedRoundedBott intent.putExtra(ReportActivity.EXTRA_SUBREDDIT_NAME, comment.getCommunityName()); intent.putExtra(ReportActivity.EXTRA_THING_FULLNAME, comment.getFullName()); activity.startActivity(intent);*/ - Toast.makeText(activity, R.string.not_implemented, Toast.LENGTH_SHORT).show(); + if (accessToken == null) { + Toast.makeText(activity, R.string.login_first, Toast.LENGTH_SHORT).show(); + dismiss(); + return; + } + LayoutInflater dialog_inflater = LayoutInflater.from(activity); + View dialog_view = dialog_inflater.inflate(R.layout.dialog_report, null); + EditText reasonEditText = dialog_view.findViewById(R.id.reasonEditText); + + MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(activity) + .setTitle(R.string.report_post) + .setView(dialog_view) + .setNegativeButton(R.string.cancel, (dialogInterface, i) -> dialogInterface.dismiss()) + .setPositiveButton(R.string.send_report, (dialogInterface, i) -> { + String reason = reasonEditText.getText().toString(); + if (reason.isEmpty()) { + Toast.makeText(activity, "A report reason must be provided", Toast.LENGTH_SHORT).show(); + return; + } + lemmyCommentAPI.reportComment(comment.getId(), reason, accessToken, new LemmyCommentAPI.ReportCommentCallback() { + @Override + public void onSuccess() { + Toast.makeText(activity, R.string.report_successful, Toast.LENGTH_SHORT).show(); + } + + @Override + public void onFailure() { + Toast.makeText(activity, R.string.report_failed, Toast.LENGTH_SHORT).show(); + } + }); + }); + AlertDialog dialog = builder.create(); + dialog.show(); + + Button positiveButton = dialog.getButton(AlertDialog.BUTTON_POSITIVE); + Button negativeButton = dialog.getButton(AlertDialog.BUTTON_NEGATIVE); + positiveButton.setTextColor(mCustomThemeWrapper.getSecondaryTextColor()); + negativeButton.setTextColor(mCustomThemeWrapper.getSecondaryTextColor()); dismiss(); }); diff --git a/app/src/main/java/eu/toldi/infinityforlemmy/fragments/ViewPostDetailFragment.java b/app/src/main/java/eu/toldi/infinityforlemmy/fragments/ViewPostDetailFragment.java index f2e7aeb1..52d60cb7 100644 --- a/app/src/main/java/eu/toldi/infinityforlemmy/fragments/ViewPostDetailFragment.java +++ b/app/src/main/java/eu/toldi/infinityforlemmy/fragments/ViewPostDetailFragment.java @@ -24,6 +24,8 @@ import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; +import android.widget.Button; +import android.widget.EditText; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; @@ -31,6 +33,7 @@ import android.widget.Toast; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.appcompat.app.AlertDialog; import androidx.appcompat.content.res.AppCompatResources; import androidx.appcompat.view.menu.MenuItemImpl; import androidx.core.content.res.ResourcesCompat; @@ -106,6 +109,7 @@ import eu.toldi.infinityforlemmy.message.ReadMessage; import eu.toldi.infinityforlemmy.post.FetchPost; import eu.toldi.infinityforlemmy.post.FetchRemovedPost; import eu.toldi.infinityforlemmy.post.HidePost; +import eu.toldi.infinityforlemmy.post.LemmyPostAPI; import eu.toldi.infinityforlemmy.post.MarkPostAsRead; import eu.toldi.infinityforlemmy.post.Post; import eu.toldi.infinityforlemmy.readpost.InsertReadPost; @@ -194,6 +198,8 @@ public class ViewPostDetailFragment extends Fragment implements FragmentCommunic Executor mExecutor; @Inject MarkPostAsRead markPostAsRead; + @Inject + LemmyPostAPI mLemmyPostAPI; @State Post mPost; @State @@ -1153,7 +1159,43 @@ public class ViewPostDetailFragment extends Fragment implements FragmentCommunic Toast.makeText(activity, R.string.login_first, Toast.LENGTH_SHORT).show(); return true; } - Toast.makeText(activity, R.string.not_implemented, Toast.LENGTH_SHORT).show(); + if (mAccessToken == null) { + Toast.makeText(activity, R.string.login_first, Toast.LENGTH_SHORT).show(); + return true; + } + LayoutInflater inflater = LayoutInflater.from(activity); + View view = inflater.inflate(R.layout.dialog_report, null); + EditText reasonEditText = view.findViewById(R.id.reasonEditText); + + MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(activity) + .setTitle(R.string.report_post) + .setView(view) + .setNegativeButton(R.string.cancel, (dialogInterface, i) -> dialogInterface.dismiss()) + .setPositiveButton(R.string.send_report, (dialogInterface, i) -> { + String reason = reasonEditText.getText().toString(); + if (reason.isEmpty()) { + Toast.makeText(activity, "A report reason must be provided", Toast.LENGTH_SHORT).show(); + return; + } + mLemmyPostAPI.reportPost(mPost.getId(), reason, mAccessToken, new LemmyPostAPI.ReportPostCallback() { + @Override + public void onSuccess() { + Toast.makeText(activity, R.string.report_successful, Toast.LENGTH_SHORT).show(); + } + + @Override + public void onFailure() { + Toast.makeText(activity, R.string.report_failed, Toast.LENGTH_SHORT).show(); + } + }); + }); + AlertDialog dialog = builder.create(); + dialog.show(); + + Button positiveButton = dialog.getButton(AlertDialog.BUTTON_POSITIVE); + Button negativeButton = dialog.getButton(AlertDialog.BUTTON_NEGATIVE); + positiveButton.setTextColor(mCustomThemeWrapper.getSecondaryTextColor()); + negativeButton.setTextColor(mCustomThemeWrapper.getSecondaryTextColor()); return true; } else if (itemId == R.id.action_see_removed_view_post_detail_fragment) { showRemovedPost(); diff --git a/app/src/main/kotlin/eu/toldi/infinityforlemmy/comment/LemmyCommentAPI.kt b/app/src/main/kotlin/eu/toldi/infinityforlemmy/comment/LemmyCommentAPI.kt new file mode 100644 index 00000000..559ffe85 --- /dev/null +++ b/app/src/main/kotlin/eu/toldi/infinityforlemmy/comment/LemmyCommentAPI.kt @@ -0,0 +1,35 @@ +package eu.toldi.infinityforlemmy.comment + +import eu.toldi.infinityforlemmy.RetrofitHolder +import eu.toldi.infinityforlemmy.apis.LemmyAPI +import eu.toldi.infinityforlemmy.dto.ReportCommentDTO +import retrofit2.Call +import retrofit2.Callback + +class LemmyCommentAPI(val retrofitHolder: RetrofitHolder) { + + fun reportComment(id: Int, reason: String, auth: String, callback: ReportCommentCallback) { + val api = retrofitHolder.retrofit.create(LemmyAPI::class.java) + api.commentReport(ReportCommentDTO(id, reason, auth)).enqueue(object : Callback { + override fun onResponse( + call: retrofit2.Call, + response: retrofit2.Response + ) { + if (response.isSuccessful) { + callback.onSuccess() + } else { + callback.onFailure() + } + } + + override fun onFailure(call: Call, t: Throwable) { + callback.onFailure() + } + }) + } + + public interface ReportCommentCallback { + fun onSuccess() + fun onFailure() + } +} \ No newline at end of file diff --git a/app/src/main/kotlin/eu/toldi/infinityforlemmy/dto/ReportDTOs.kt b/app/src/main/kotlin/eu/toldi/infinityforlemmy/dto/ReportDTOs.kt new file mode 100644 index 00000000..4d7e6272 --- /dev/null +++ b/app/src/main/kotlin/eu/toldi/infinityforlemmy/dto/ReportDTOs.kt @@ -0,0 +1,5 @@ +package eu.toldi.infinityforlemmy.dto + +data class ReportPostDTO(val post_id: Int, val reason: String, val auth: String) + +data class ReportCommentDTO(val comment_id: Int, val reason: String, val auth: String) \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_report.xml b/app/src/main/res/layout/dialog_report.xml new file mode 100644 index 00000000..e562bdec --- /dev/null +++ b/app/src/main/res/layout/dialog_report.xml @@ -0,0 +1,15 @@ + + + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 8238e3d7..faa62bbc 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1367,4 +1367,6 @@ Failed to unblock user Hide community and user instance Show community and user display names + Report Post + Send Report