Merge branch 'post-context-menu' into 'master'

Delete posts with three-dot "more options" menu

See merge request pixeldroid/PixelDroid!238
This commit is contained in:
Matthieu 2020-11-28 15:05:13 +01:00
commit 18df0d030b
11 changed files with 89 additions and 21 deletions

View File

@ -107,7 +107,7 @@ interface PixelfedAPI {
@Path("id") statusId: String
) : Call<Status>
@POST("/api/v1/statuses/{id}/favourited_by")
@GET("/api/v1/statuses/{id}/favourited_by")
fun postLikedBy(
@Path("id") statusId: String
) : Call<List<Account>>
@ -132,6 +132,12 @@ interface PixelfedAPI {
@Field("language") language : String? = null
) : Call<Status>
@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(

View File

@ -14,4 +14,6 @@ interface FeedContentDao<T: FeedContentDatabase>{
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertAll(feedContent: List<T>)
suspend fun delete(id: String, userId: String, instanceUri: String)
}

View File

@ -14,4 +14,7 @@ interface NotificationDao: FeedContentDao<Notification> {
@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<Int, Notification>
@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)
}

View File

@ -15,4 +15,7 @@ interface HomePostDao: FeedContentDao<HomeStatusDatabaseEntity> {
@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)
}

View File

@ -15,4 +15,7 @@ interface PublicPostDao: FeedContentDao<PublicFeedStatusDatabaseEntity> {
@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)
}

View File

@ -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

View File

@ -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()
}
}

View File

@ -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<T: FeedContentDatabase>: CachedFeedFragment<T>() {
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)
}
}
}

View File

@ -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<Status>() {
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)
}
}
}

View File

@ -14,4 +14,14 @@
<item android:id="@+id/post_more_menu_save_to_gallery"
android:title="@string/save_to_gallery"/>
</group>
<!-- Group that should only be shown if this is the user's post -->
<group
android:id="@+id/post_more_menu_group_delete"
android:visible="false">
<item android:id="@+id/post_more_menu_delete"
android:title="@string/delete"/>
</group>
</menu>

View File

@ -139,6 +139,10 @@
<string name="discover">DISCOVER</string>
<string name="something_went_wrong">Something went wrong…</string>
<string name="panda_pull_to_refresh_to_try_again">This panda is not happy. Pull to refresh to try again.</string>
<string name="delete">Delete</string>
<string name="OK">OK</string>
<string name="delete_dialog">Delete this post?</string>
<string name="cancel">Cancel</string>
</resources>