Skip to content

Commit

Permalink
Add ability to Ban and Ban from Community for posts and comments. (#1325
Browse files Browse the repository at this point in the history
)

* Adding ability to remove and restore comments. #1182

* Fix weird formatting miss.

* Use ImmutableList instead of List.

* Surrounding canMod with remember.

* Adding ability to remove and restore posts. #1182

* Fixing jerboaappstate.

* Removing extra RemoveViewModel.

* Changing remove icon to gavel.

* Change a few strings to non-contextual.

* Add remove comment to commentmentionnode.

* Remove non-optional body from compiler warning.

* Adding ban and ban from community.

- Adding appropriate viewModels and activities.
- Adds functions to search for and update lists of posts and comments
- Context: #1182

* Fixing some formatting issues.

* Adding admin key to canMod remember.

* Simplifying futureDaysToUnixTime function.
  • Loading branch information
dessalines committed Jan 25, 2024
1 parent 39be12c commit d1b348e
Show file tree
Hide file tree
Showing 34 changed files with 1,104 additions and 62 deletions.
14 changes: 14 additions & 0 deletions app/src/main/java/com/jerboa/JerboaAppState.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@ import androidx.compose.runtime.saveable.Saver
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.navigation.NavHostController
import androidx.navigation.compose.rememberNavController
import com.jerboa.datatypes.BanFromCommunityData
import com.jerboa.model.ReplyItem
import com.jerboa.ui.components.ban.BanFromCommunityReturn
import com.jerboa.ui.components.ban.BanPersonReturn
import com.jerboa.ui.components.comment.edit.CommentEditReturn
import com.jerboa.ui.components.comment.reply.CommentReplyReturn
import com.jerboa.ui.components.common.Route
Expand All @@ -25,6 +28,7 @@ import it.vercruysse.lemmyapi.v0x19.datatypes.Comment
import it.vercruysse.lemmyapi.v0x19.datatypes.CommentView
import it.vercruysse.lemmyapi.v0x19.datatypes.Community
import it.vercruysse.lemmyapi.v0x19.datatypes.CommunityView
import it.vercruysse.lemmyapi.v0x19.datatypes.Person
import it.vercruysse.lemmyapi.v0x19.datatypes.Post
import it.vercruysse.lemmyapi.v0x19.datatypes.PostView
import it.vercruysse.lemmyapi.v0x19.datatypes.PrivateMessageView
Expand Down Expand Up @@ -82,6 +86,16 @@ class JerboaAppState(
navController.navigate(Route.COMMENT_REMOVE)
}

fun toBanPerson(person: Person) {
sendReturnForwards(BanPersonReturn.PERSON_SEND, person)
navController.navigate(Route.BAN_PERSON)
}

fun toBanFromCommunity(banData: BanFromCommunityData) {
sendReturnForwards(BanFromCommunityReturn.BAN_DATA_SEND, banData)
navController.navigate(Route.BAN_FROM_COMMUNITY)
}

fun toSettings() = navController.navigate(Route.SETTINGS)

fun toAccountSettings() = navController.navigate(Route.ACCOUNT_SETTINGS)
Expand Down
51 changes: 40 additions & 11 deletions app/src/main/java/com/jerboa/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ import com.jerboa.model.AccountViewModelFactory
import com.jerboa.model.AppSettingsViewModel
import com.jerboa.model.AppSettingsViewModelFactory
import com.jerboa.model.SiteViewModel
import com.jerboa.ui.components.ban.BanFromCommunityActivity
import com.jerboa.ui.components.ban.BanPersonActivity
import com.jerboa.ui.components.comment.edit.CommentEditActivity
import com.jerboa.ui.components.comment.reply.CommentReplyActivity
import com.jerboa.ui.components.common.LinkDropDownMenu
Expand Down Expand Up @@ -542,19 +544,11 @@ class MainActivity : AppCompatActivity() {
}

composable(
route = Route.COMMENT_REPORT,
arguments =
listOf(
navArgument(Route.CommentReportArgs.ID) {
type = Route.CommentReportArgs.ID_TYPE
},
),
route = Route.POST_REMOVE,
) {
val args = Route.CommentReportArgs(it)
CreateCommentReportActivity(
commentId = args.id,
PostRemoveActivity(
appState = appState,
accountViewModel = accountViewModel,
onBack = appState::navigateUp,
)
}

Expand All @@ -576,6 +570,24 @@ class MainActivity : AppCompatActivity() {
)
}

composable(
route = Route.BAN_PERSON,
) {
BanPersonActivity(
appState = appState,
accountViewModel = accountViewModel,
)
}

composable(
route = Route.BAN_FROM_COMMUNITY,
) {
BanFromCommunityActivity(
appState = appState,
accountViewModel = accountViewModel,
)
}

composable(
route = Route.POST_REPORT,
arguments =
Expand All @@ -593,6 +605,23 @@ class MainActivity : AppCompatActivity() {
)
}

composable(
route = Route.COMMENT_REPORT,
arguments =
listOf(
navArgument(Route.CommentReportArgs.ID) {
type = Route.CommentReportArgs.ID_TYPE
},
),
) {
val args = Route.CommentReportArgs(it)
CreateCommentReportActivity(
commentId = args.id,
accountViewModel = accountViewModel,
onBack = appState::navigateUp,
)
}

composable(route = Route.SETTINGS) {
SettingsActivity(
accountViewModel = accountViewModel,
Expand Down
75 changes: 73 additions & 2 deletions app/src/main/java/com/jerboa/Utils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ import coil.annotation.ExperimentalCoilApi
import coil.imageLoader
import com.jerboa.api.API
import com.jerboa.api.ApiState
import com.jerboa.datatypes.BanFromCommunityData
import com.jerboa.db.APP_SETTINGS_DEFAULT
import com.jerboa.db.entity.AppSettings
import com.jerboa.ui.components.common.Route
Expand All @@ -70,6 +71,8 @@ import java.io.InputStream
import java.net.MalformedURLException
import java.net.URL
import java.text.DecimalFormat
import java.time.Instant
import java.time.temporal.ChronoUnit
import java.util.*
import kotlin.math.abs
import kotlin.math.pow
Expand Down Expand Up @@ -281,7 +284,8 @@ fun commentsToFlatNodes(comments: List<CommentView>): ImmutableList<CommentNode>
*/
fun buildCommentsTree(
comments: List<CommentView>,
rootCommentId: Int?, // If it's in CommentView, then we need to know the root comment id
// If it's in CommentView, then we need to know the root comment id
rootCommentId: Int?,
): ImmutableList<CommentNodeData> {
val isCommentView = rootCommentId != null

Expand Down Expand Up @@ -1050,7 +1054,8 @@ fun saveMediaP(
inputStream: InputStream,
mimeType: String?,
displayName: String,
mediaType: PostType, // Link is here more like other media (think of PDF, doc, txt)
// Link is here more like other media (think of PDF, doc, txt)
mediaType: PostType,
) {
val dir = Environment.getExternalStoragePublicDirectory(mediaType.toMediaDir())
val mediaDir = File(dir, "Jerboa")
Expand Down Expand Up @@ -1204,6 +1209,66 @@ fun findAndUpdateComment(
}
}

fun findAndUpdatePostCreator(
posts: List<PostView>,
person: Person,
): List<PostView> {
val newPosts = posts.toMutableList()
newPosts.replaceAll {
if (it.creator.id == person.id) {
it.copy(creator = person)
} else {
it
}
}
return newPosts
}

fun findAndUpdatePostCreatorBannedFromCommunity(
posts: List<PostView>,
banData: BanFromCommunityData,
): List<PostView> {
val newPosts = posts.toMutableList()
newPosts.replaceAll {
if (it.creator.id == banData.person.id && it.community.id == banData.community.id) {
it.copy(creator_banned_from_community = banData.banned)
} else {
it
}
}
return newPosts
}

fun findAndUpdateCommentCreator(
comments: List<CommentView>,
person: Person,
): List<CommentView> {
val newComments = comments.toMutableList()
newComments.replaceAll {
if (it.creator.id == person.id) {
it.copy(creator = person)
} else {
it
}
}
return newComments
}

fun findAndUpdateCommentCreatorBannedFromCommunity(
comments: List<CommentView>,
banData: BanFromCommunityData,
): List<CommentView> {
val newComments = comments.toMutableList()
newComments.replaceAll {
if (it.creator.id == banData.person.id && it.community.id == banData.community.id) {
it.copy(creator_banned_from_community = banData.banned)
} else {
it
}
}
return newComments
}

fun findAndUpdateCommentReply(
replies: List<CommentReplyView>,
updatedCommentView: CommentView,
Expand Down Expand Up @@ -1569,6 +1634,12 @@ fun canMod(
}
}

fun futureDaysToUnixTime(days: Int?): Int? {
return days?.let {
Instant.now().plus(it.toLong(), ChronoUnit.DAYS).epochSecond.toInt()
}
}

fun amMod(
moderators: ImmutableList<CommunityModeratorView>?,
myId: PersonId?,
Expand Down
16 changes: 16 additions & 0 deletions app/src/main/java/com/jerboa/datatypes/Others.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ import it.vercruysse.lemmyapi.dto.CommentSortType
import it.vercruysse.lemmyapi.dto.ListingType
import it.vercruysse.lemmyapi.dto.PostFeatureType
import it.vercruysse.lemmyapi.dto.SortType
import it.vercruysse.lemmyapi.v0x19.datatypes.Community
import it.vercruysse.lemmyapi.v0x19.datatypes.Person
import kotlinx.serialization.Serializable
import it.vercruysse.lemmyapi.v0x19.datatypes.Post


Expand Down Expand Up @@ -190,6 +193,19 @@ fun getLocalizedStringForInboxTab(
return returnString
}

/**
* A container to store extra community ban info
*/
@Serializable
data class BanFromCommunityData(
val person: Person,
val community: Community,
val banned: Boolean,
)

/**
* A container to store extra post feature info
*/
data class PostFeatureData(
val post: Post,
val type: PostFeatureType,
Expand Down
3 changes: 2 additions & 1 deletion app/src/main/java/com/jerboa/db/AppDB.kt
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,8 @@ abstract class AppDB : RoomDatabase() {
Executors.newSingleThreadExecutor().execute {
db.insert(
"AppSettings",
CONFLICT_IGNORE, // Ensures it won't overwrite the existing data
// Ensures it won't overwrite the existing data
CONFLICT_IGNORE,
ContentValues(2).apply {
put("id", 1)
},
Expand Down
3 changes: 2 additions & 1 deletion app/src/main/java/com/jerboa/db/entity/AppSettings.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ data class AppSettings(
@PrimaryKey(autoGenerate = true) val id: Int,
@ColumnInfo(
name = "font_size",
defaultValue = DEFAULT_FONT_SIZE.toString(), // This is changed to 16
// This is changed to 16
defaultValue = DEFAULT_FONT_SIZE.toString(),
)
val fontSize: Int,
@ColumnInfo(
Expand Down
95 changes: 95 additions & 0 deletions app/src/main/java/com/jerboa/model/BanFromCommunityViewModel.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package com.jerboa.model

import android.content.Context
import android.util.Log
import android.widget.Toast
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.ui.focus.FocusManager
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.jerboa.R
import com.jerboa.api.API
import com.jerboa.api.ApiState
import com.jerboa.api.toApiState
import com.jerboa.communityNameShown
import com.jerboa.datatypes.BanFromCommunityData
import com.jerboa.futureDaysToUnixTime
import com.jerboa.personNameShown
import com.jerboa.ui.components.common.apiErrorToast
import it.vercruysse.lemmyapi.v0x19.datatypes.BanFromCommunity
import it.vercruysse.lemmyapi.v0x19.datatypes.BanFromCommunityResponse
import it.vercruysse.lemmyapi.v0x19.datatypes.Community
import it.vercruysse.lemmyapi.v0x19.datatypes.PersonId
import kotlinx.coroutines.launch

class BanFromCommunityViewModel : ViewModel() {
var banFromCommunityRes: ApiState<BanFromCommunityResponse> by mutableStateOf(ApiState.Empty)
private set

fun banOrUnbanFromCommunity(
personId: PersonId,
community: Community,
ban: Boolean,
removeData: Boolean? = null,
reason: String,
expireDays: Int? = null,
ctx: Context,
focusManager: FocusManager,
onSuccess: (BanFromCommunityData) -> Unit,
) {
viewModelScope.launch {
val form =
BanFromCommunity(
person_id = personId,
community_id = community.id,
ban = ban,
remove_data = removeData,
reason = reason,
expires = futureDaysToUnixTime(expireDays),
)

banFromCommunityRes = ApiState.Loading
banFromCommunityRes = API.getInstance().banFromCommunity(form).toApiState()

when (val res = banFromCommunityRes) {
is ApiState.Failure -> {
Log.d("banFromCommunity", "failed", res.msg)
apiErrorToast(msg = res.msg, ctx = ctx)
}

is ApiState.Success -> {
val personNameShown = personNameShown(res.data.person_view.person, true)
val communityNameShown = communityNameShown(community)
val message =
if (ban) {
if (expireDays !== null) {
ctx.getString(
R.string.person_banned_from_community_for_x_days,
personNameShown,
communityNameShown,
expireDays,
)
} else {
ctx.getString(R.string.person_banned_from_community, personNameShown, communityNameShown)
}
} else {
ctx.getString(R.string.person_unbanned_from_community, personNameShown, communityNameShown)
}
Toast.makeText(ctx, message, Toast.LENGTH_SHORT).show()

focusManager.clearFocus()
onSuccess(
BanFromCommunityData(
person = res.data.person_view.person,
community = community,
banned = res.data.banned,
),
)
}
else -> {}
}
}
}
}
Loading

0 comments on commit d1b348e

Please sign in to comment.