From f465e495d2827f232954c212763f39cab58a1945 Mon Sep 17 00:00:00 2001 From: Matthieu <24-artectrex@users.noreply.shinice.net> Date: Sat, 28 Nov 2020 15:05:13 +0100 Subject: [PATCH] Delete posts with three-dot "more options" menu --- .../java/com/h/pixeldroid/api/PixelfedAPI.kt | 8 ++- .../db/dao/feedContent/FeedContentDao.kt | 2 + .../db/dao/feedContent/NotificationDao.kt | 3 + .../db/dao/feedContent/posts/HomePostDao.kt | 3 + .../db/dao/feedContent/posts/PublicPostDao.kt | 3 + .../h/pixeldroid/fragments/PostFragment.kt | 6 +- .../pixeldroid/fragments/StatusViewHolder.kt | 62 +++++++++++++++---- .../cachedFeeds/postFeeds/PostFeedFragment.kt | 4 +- .../search/SearchPostsFragment.kt | 5 +- app/src/main/res/menu/post_more_menu.xml | 10 +++ app/src/main/res/values/strings.xml | 4 ++ 11 files changed, 89 insertions(+), 21 deletions(-) diff --git a/app/src/main/java/com/h/pixeldroid/api/PixelfedAPI.kt b/app/src/main/java/com/h/pixeldroid/api/PixelfedAPI.kt index b5dd7814..d9c51723 100644 --- a/app/src/main/java/com/h/pixeldroid/api/PixelfedAPI.kt +++ b/app/src/main/java/com/h/pixeldroid/api/PixelfedAPI.kt @@ -107,7 +107,7 @@ interface PixelfedAPI { @Path("id") statusId: String ) : Call - @POST("/api/v1/statuses/{id}/favourited_by") + @GET("/api/v1/statuses/{id}/favourited_by") fun postLikedBy( @Path("id") statusId: String ) : Call> @@ -132,6 +132,12 @@ interface PixelfedAPI { @Field("language") language : String? = null ) : Call + @DELETE("/api/v1/statuses/{id}") + suspend fun deleteStatus( + @Header("Authorization") authorization: String, + @Path("id") statusId: String + ) + @FormUrlEncoded @POST("/api/v1/statuses/{id}/reblog") fun reblogStatus( diff --git a/app/src/main/java/com/h/pixeldroid/db/dao/feedContent/FeedContentDao.kt b/app/src/main/java/com/h/pixeldroid/db/dao/feedContent/FeedContentDao.kt index f594c30b..02221374 100644 --- a/app/src/main/java/com/h/pixeldroid/db/dao/feedContent/FeedContentDao.kt +++ b/app/src/main/java/com/h/pixeldroid/db/dao/feedContent/FeedContentDao.kt @@ -14,4 +14,6 @@ interface FeedContentDao{ @Insert(onConflict = OnConflictStrategy.REPLACE) suspend fun insertAll(feedContent: List) + suspend fun delete(id: String, userId: String, instanceUri: String) + } \ No newline at end of file diff --git a/app/src/main/java/com/h/pixeldroid/db/dao/feedContent/NotificationDao.kt b/app/src/main/java/com/h/pixeldroid/db/dao/feedContent/NotificationDao.kt index 73e5e683..31a9c9e5 100644 --- a/app/src/main/java/com/h/pixeldroid/db/dao/feedContent/NotificationDao.kt +++ b/app/src/main/java/com/h/pixeldroid/db/dao/feedContent/NotificationDao.kt @@ -14,4 +14,7 @@ interface NotificationDao: FeedContentDao { @Query("""SELECT * FROM notifications WHERE user_id=:userId AND instance_uri=:instanceUri ORDER BY CAST(created_at AS FLOAT) DESC""") override fun feedContent(userId: String, instanceUri: String): PagingSource + + @Query("DELETE FROM notifications WHERE user_id=:userId AND instance_uri=:instanceUri AND id=:id") + override suspend fun delete(id: String, userId: String, instanceUri: String) } \ No newline at end of file diff --git a/app/src/main/java/com/h/pixeldroid/db/dao/feedContent/posts/HomePostDao.kt b/app/src/main/java/com/h/pixeldroid/db/dao/feedContent/posts/HomePostDao.kt index afed0e1f..df507de6 100644 --- a/app/src/main/java/com/h/pixeldroid/db/dao/feedContent/posts/HomePostDao.kt +++ b/app/src/main/java/com/h/pixeldroid/db/dao/feedContent/posts/HomePostDao.kt @@ -15,4 +15,7 @@ interface HomePostDao: FeedContentDao { @Query("DELETE FROM homePosts") override suspend fun clearFeedContent() + @Query("DELETE FROM homePosts WHERE user_id=:userId AND instance_uri=:instanceUri AND id=:id") + override suspend fun delete(id: String, userId: String, instanceUri: String) + } \ No newline at end of file diff --git a/app/src/main/java/com/h/pixeldroid/db/dao/feedContent/posts/PublicPostDao.kt b/app/src/main/java/com/h/pixeldroid/db/dao/feedContent/posts/PublicPostDao.kt index f65fe896..a3755aea 100644 --- a/app/src/main/java/com/h/pixeldroid/db/dao/feedContent/posts/PublicPostDao.kt +++ b/app/src/main/java/com/h/pixeldroid/db/dao/feedContent/posts/PublicPostDao.kt @@ -15,4 +15,7 @@ interface PublicPostDao: FeedContentDao { @Query("DELETE FROM publicPosts") override suspend fun clearFeedContent() + @Query("DELETE FROM publicPosts WHERE user_id=:userId AND instance_uri=:instanceUri AND id=:id") + override suspend fun delete(id: String, userId: String, instanceUri: String) + } \ No newline at end of file diff --git a/app/src/main/java/com/h/pixeldroid/fragments/PostFragment.kt b/app/src/main/java/com/h/pixeldroid/fragments/PostFragment.kt index 74403ec6..dd72a5ed 100644 --- a/app/src/main/java/com/h/pixeldroid/fragments/PostFragment.kt +++ b/app/src/main/java/com/h/pixeldroid/fragments/PostFragment.kt @@ -4,6 +4,7 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.lifecycle.lifecycleScope import com.h.pixeldroid.R import com.h.pixeldroid.objects.Status import com.h.pixeldroid.objects.Status.Companion.DOMAIN_TAG @@ -26,17 +27,16 @@ class PostFragment : BaseFragment() { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? - ): View? { + ): View { val root: View = inflater.inflate(R.layout.post_fragment, container, false) val user = db.userDao().getActiveUser()!! - val accessToken = user.accessToken val api = apiHolder.api ?: apiHolder.setDomain(user.instance_uri) val holder = StatusViewHolder(root) - holder.bind(currentStatus, statusDomain, api, "Bearer $accessToken") + holder.bind(currentStatus, api, db, lifecycleScope) return root diff --git a/app/src/main/java/com/h/pixeldroid/fragments/StatusViewHolder.kt b/app/src/main/java/com/h/pixeldroid/fragments/StatusViewHolder.kt index 1a21ce6b..294a2edc 100644 --- a/app/src/main/java/com/h/pixeldroid/fragments/StatusViewHolder.kt +++ b/app/src/main/java/com/h/pixeldroid/fragments/StatusViewHolder.kt @@ -1,6 +1,7 @@ package com.h.pixeldroid.fragments import android.Manifest +import android.app.AlertDialog import android.content.Intent import android.graphics.Color import android.graphics.Typeface @@ -13,6 +14,8 @@ import android.view.View import android.view.ViewGroup import android.widget.* import androidx.core.content.ContextCompat +import androidx.lifecycle.LifecycleCoroutineScope +import androidx.paging.RemoteMediator import androidx.recyclerview.widget.RecyclerView import androidx.viewpager2.widget.ViewPager2 import at.connyduck.sparkbutton.SparkButton @@ -23,6 +26,9 @@ import com.google.android.material.tabs.TabLayoutMediator import com.h.pixeldroid.R import com.h.pixeldroid.ReportActivity import com.h.pixeldroid.api.PixelfedAPI +import com.h.pixeldroid.db.AppDatabase +import com.h.pixeldroid.db.entities.HomeStatusDatabaseEntity +import com.h.pixeldroid.db.entities.PublicFeedStatusDatabaseEntity import com.h.pixeldroid.objects.Attachment import com.h.pixeldroid.objects.Context import com.h.pixeldroid.objects.Status @@ -35,9 +41,12 @@ import com.karumi.dexter.listener.PermissionGrantedResponse import com.karumi.dexter.listener.single.BasePermissionListener import kotlinx.android.synthetic.main.comment.view.* import kotlinx.android.synthetic.main.post_fragment.view.* +import kotlinx.coroutines.launch import retrofit2.Call import retrofit2.Callback +import retrofit2.HttpException import retrofit2.Response +import java.io.IOException /** @@ -70,14 +79,9 @@ class StatusViewHolder(val view: View) : RecyclerView.ViewHolder(view) { private var status: Status? = null - init { - itemView.setOnClickListener { - //notification?.openActivity() - } - } - - fun bind(status: Status?, instanceUri: String, pixelfedAPI: PixelfedAPI, credential: String) { + fun bind(status: Status?, pixelfedAPI: PixelfedAPI, db: AppDatabase, lifecycleScope: LifecycleCoroutineScope) { + this.itemView.visibility = View.VISIBLE this.status = status val metrics = itemView.context.resources.displayMetrics @@ -89,9 +93,11 @@ class StatusViewHolder(val view: View) : RecyclerView.ViewHolder(view) { .asDrawable().fitCenter() .placeholder(ColorDrawable(Color.GRAY)) - setupPost(itemView, picRequest, instanceUri, false) + val user = db.userDao().getActiveUser()!! - activateButtons(this, pixelfedAPI, credential) + setupPost(itemView, picRequest, user.instance_uri, false) + + activateButtons(this, pixelfedAPI, db, lifecycleScope) } @@ -217,8 +223,10 @@ class StatusViewHolder(val view: View) : RecyclerView.ViewHolder(view) { } } - fun activateButtons(holder: StatusViewHolder, api: PixelfedAPI, credential: String){ + fun activateButtons(holder: StatusViewHolder, api: PixelfedAPI, db: AppDatabase, lifecycleScope: LifecycleCoroutineScope){ + val user = db.userDao().getActiveUser()!! + val credential = "Bearer ${user.accessToken}" //Set the special HTML text setDescription(holder.view, api, credential) @@ -238,7 +246,7 @@ class StatusViewHolder(val view: View) : RecyclerView.ViewHolder(view) { //Activate double tap liking activateDoubleTapLiker(holder, api, credential) - activateMoreButton(holder) + activateMoreButton(holder, api, db, lifecycleScope) } fun activateReblogger( @@ -326,7 +334,7 @@ class StatusViewHolder(val view: View) : RecyclerView.ViewHolder(view) { } } - fun activateMoreButton(holder: StatusViewHolder){ + fun activateMoreButton(holder: StatusViewHolder, api: PixelfedAPI, db: AppDatabase, lifecycleScope: LifecycleCoroutineScope){ holder.more.setOnClickListener { PopupMenu(it.context, it).apply { setOnMenuItemClickListener { item -> @@ -397,6 +405,32 @@ class StatusViewHolder(val view: View) : RecyclerView.ViewHolder(view) { }).check() true } + R.id.post_more_menu_delete -> { + val builder = AlertDialog.Builder(holder.itemView.context) + builder.apply { + setMessage(R.string.delete_dialog) + setPositiveButton(R.string.OK) { _, _ -> + + lifecycleScope.launch { + val user = db.userDao().getActiveUser()!! + status?.id?.let { id -> + db.homePostDao().delete(id, user.user_id, user.instance_uri) + db.publicPostDao().delete(id, user.user_id, user.instance_uri) + try { + api.deleteStatus("Bearer ${user.accessToken}", id) + holder.itemView.visibility = View.GONE + } catch (exception: IOException) { + } catch (exception: HttpException) { + } + } + } + } + setNegativeButton(R.string.cancel) { _, _ -> } + show() + } + + true + } else -> false } } @@ -405,6 +439,10 @@ class StatusViewHolder(val view: View) : RecyclerView.ViewHolder(view) { //make sure to disable image-related things if there aren't any menu.setGroupVisible(R.id.post_more_group_picture, false) } + if(status?.account?.id == db.userDao().getActiveUser()!!.user_id){ + //make sure to enable deleting post if it's the user's + menu.setGroupVisible(R.id.post_more_menu_group_delete, true) + } show() } } diff --git a/app/src/main/java/com/h/pixeldroid/fragments/feeds/cachedFeeds/postFeeds/PostFeedFragment.kt b/app/src/main/java/com/h/pixeldroid/fragments/feeds/cachedFeeds/postFeeds/PostFeedFragment.kt index 521d4dd7..9748e81b 100644 --- a/app/src/main/java/com/h/pixeldroid/fragments/feeds/cachedFeeds/postFeeds/PostFeedFragment.kt +++ b/app/src/main/java/com/h/pixeldroid/fragments/feeds/cachedFeeds/postFeeds/PostFeedFragment.kt @@ -5,6 +5,7 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.lifecycle.ViewModelProvider +import androidx.lifecycle.lifecycleScope import androidx.paging.ExperimentalPagingApi import androidx.paging.PagingDataAdapter import androidx.paging.RemoteMediator @@ -89,8 +90,7 @@ class PostFeedFragment: CachedFeedFragment() { val uiModel = getItem(position) as Status uiModel.let { val instanceUri = db.userDao().getActiveUser()!!.instance_uri - val accessToken = db.userDao().getActiveUser()!!.accessToken - (holder as StatusViewHolder).bind(it, instanceUri, apiHolder.setDomain(instanceUri), "Bearer $accessToken") + (holder as StatusViewHolder).bind(it, apiHolder.setDomain(instanceUri), db, lifecycleScope) } } } diff --git a/app/src/main/java/com/h/pixeldroid/fragments/feeds/uncachedFeeds/search/SearchPostsFragment.kt b/app/src/main/java/com/h/pixeldroid/fragments/feeds/uncachedFeeds/search/SearchPostsFragment.kt index 741f0513..007af135 100644 --- a/app/src/main/java/com/h/pixeldroid/fragments/feeds/uncachedFeeds/search/SearchPostsFragment.kt +++ b/app/src/main/java/com/h/pixeldroid/fragments/feeds/uncachedFeeds/search/SearchPostsFragment.kt @@ -5,6 +5,7 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.lifecycle.ViewModelProvider +import androidx.lifecycle.lifecycleScope import androidx.paging.ExperimentalPagingApi import androidx.paging.PagingDataAdapter import androidx.recyclerview.widget.DiffUtil @@ -12,7 +13,6 @@ import androidx.recyclerview.widget.RecyclerView import com.h.pixeldroid.R import com.h.pixeldroid.fragments.StatusViewHolder import com.h.pixeldroid.fragments.feeds.uncachedFeeds.* -import com.h.pixeldroid.objects.Account import com.h.pixeldroid.objects.Results import com.h.pixeldroid.objects.Status @@ -80,8 +80,7 @@ class SearchPostsFragment : UncachedFeedFragment() { val uiModel = getItem(position) as Status uiModel.let { val instanceUri = db.userDao().getActiveUser()!!.instance_uri - val accessToken = db.userDao().getActiveUser()!!.accessToken - (holder as StatusViewHolder).bind(it, instanceUri, apiHolder.setDomain(instanceUri), "Bearer $accessToken") + (holder as StatusViewHolder).bind(it, apiHolder.setDomain(instanceUri), db, lifecycleScope) } } } diff --git a/app/src/main/res/menu/post_more_menu.xml b/app/src/main/res/menu/post_more_menu.xml index ed672100..57509b38 100644 --- a/app/src/main/res/menu/post_more_menu.xml +++ b/app/src/main/res/menu/post_more_menu.xml @@ -14,4 +14,14 @@ + + + + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 9cb8721c..a358ec97 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -139,6 +139,10 @@ DISCOVER Something went wrong… This panda is not happy. Pull to refresh to try again. + Delete + OK + Delete this post? + Cancel \ No newline at end of file