Skip to content

Commit

Permalink
InstantScores refactor + Int to Long changes (#1337)
Browse files Browse the repository at this point in the history
* InstantScores refactor + Int to Long changes

* Fix lint
  • Loading branch information
MV-GH authored Jan 28, 2024
1 parent d469006 commit 8b5c6fe
Show file tree
Hide file tree
Showing 57 changed files with 500 additions and 600 deletions.
2 changes: 1 addition & 1 deletion app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ dependencies {

implementation("org.jetbrains.kotlinx:kotlinx-collections-immutable:0.3.7")

implementation("it.vercruysse.lemmyapi:lemmy-api:0.2.3-SNAPSHOT")
implementation("it.vercruysse.lemmyapi:lemmy-api:0.2.8-SNAPSHOT")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.2")
// Ktor uses SLF4J
implementation("org.slf4j:slf4j-api:2.0.11")
Expand Down
20 changes: 12 additions & 8 deletions app/src/main/java/com/jerboa/JerboaAppState.kt
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,15 @@ import com.jerboa.ui.components.privatemessage.PrivateMessage
import com.jerboa.ui.components.remove.comment.CommentRemoveReturn
import com.jerboa.ui.components.remove.post.PostRemoveReturn
import it.vercruysse.lemmyapi.v0x19.datatypes.Comment
import it.vercruysse.lemmyapi.v0x19.datatypes.CommentId
import it.vercruysse.lemmyapi.v0x19.datatypes.CommentView
import it.vercruysse.lemmyapi.v0x19.datatypes.Community
import it.vercruysse.lemmyapi.v0x19.datatypes.CommunityId
import it.vercruysse.lemmyapi.v0x19.datatypes.CommunityView
import it.vercruysse.lemmyapi.v0x19.datatypes.Person
import it.vercruysse.lemmyapi.v0x19.datatypes.PersonId
import it.vercruysse.lemmyapi.v0x19.datatypes.Post
import it.vercruysse.lemmyapi.v0x19.datatypes.PostId
import it.vercruysse.lemmyapi.v0x19.datatypes.PostView
import it.vercruysse.lemmyapi.v0x19.datatypes.PrivateMessageView
import kotlinx.coroutines.CoroutineScope
Expand Down Expand Up @@ -68,11 +72,11 @@ class JerboaAppState(
navController.navigate(Route.PRIVATE_MESSAGE_REPLY)
}

fun toCommentReport(id: Int) {
fun toCommentReport(id: CommentId) {
navController.navigate(Route.CommentReportArgs.makeRoute(id = "$id"))
}

fun toPostReport(id: Int) {
fun toPostReport(id: PostId) {
navController.navigate(Route.PostReportArgs.makeRoute(id = "$id"))
}

Expand Down Expand Up @@ -128,7 +132,7 @@ class JerboaAppState(
navController.navigate(Route.COMMENT_REPLY)
}

fun toComment(id: Int) {
fun toComment(id: CommunityId) {
navController.navigate(Route.CommentArgs.makeRoute(id = "$id"))
}

Expand All @@ -139,15 +143,15 @@ class JerboaAppState(
navController.navigate(Route.CREATE_POST)
}

fun toPost(id: Int) {
fun toPost(id: PostId) {
navController.navigate(Route.PostArgs.makeRoute(id = "$id"))
}

fun toLogin() = navController.navigate(Route.LOGIN)

fun toHome() = navController.navigate(Route.HOME) { popUpTo(navController.graph.id) }

fun toCommunity(id: Int) {
fun toCommunity(id: CommunityId) {
navController.navigate(Route.CommunityFromIdArgs.makeRoute(id = "$id"))
}

Expand All @@ -157,7 +161,7 @@ class JerboaAppState(
}

fun toProfile(
id: Int,
id: PersonId,
saved: Boolean = false,
) {
navController.navigate(Route.ProfileFromIdArgs.makeRoute(id = "$id", saved = "$saved"))
Expand Down Expand Up @@ -218,7 +222,7 @@ class JerboaAppState(
navController.currentBackStackEntry?.savedStateHandle?.set(key, Json.encodeToString(value))
}

fun toPostWithPopUpTo(postId: Int) {
fun toPostWithPopUpTo(postId: PostId) {
navController.navigate(
Route.PostArgs.makeRoute(id = "$postId"),
) {
Expand All @@ -227,7 +231,7 @@ class JerboaAppState(
}

fun toCreatePrivateMessage(
id: Int,
id: PersonId,
name: String,
) {
navController.navigate(Route.CreatePrivateMessageArgs.makeRoute(personId = "$id", personName = name))
Expand Down
221 changes: 12 additions & 209 deletions app/src/main/java/com/jerboa/Utils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,6 @@ 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 All @@ -90,151 +88,8 @@ fun loginFirstToast(ctx: Context) {
Toast.makeText(ctx, ctx.getString(R.string.utils_login_first), Toast.LENGTH_SHORT).show()
}

enum class VoteType {
Upvote,
Downvote,
}

fun calculateNewInstantScores(
instantScores: InstantScores,
voteType: VoteType,
): InstantScores {
val newVote =
newVote(
currentVote = instantScores.myVote,
voteType = voteType,
)
val score =
newScore(
instantScores.score,
instantScores.myVote,
voteType,
)
val votes =
newVoteCount(
Pair(instantScores.upvotes, instantScores.downvotes),
instantScores.myVote,
voteType,
)

return InstantScores(
myVote = newVote,
upvotes = votes.first,
downvotes = votes.second,
score = score,
)
}

/*
* User changed their vote, so calculate score difference given this user's new vote.
*/
fun newVote(
currentVote: Int?,
voteType: VoteType,
): Int {
return if (voteType == VoteType.Upvote) {
if (currentVote == 1) {
0
} else {
1
}
} else {
if (currentVote == -1) {
0
} else {
-1
}
}
}

/*
* Calculate the new score after the user votes.
*/
fun newScore(
currentScore: Int,
currentVote: Int?,
voteType: VoteType,
): Int {
return if (voteType == VoteType.Upvote) {
when (currentVote) {
1 -> {
currentScore - 1
}

-1 -> {
currentScore + 2
}

else -> {
currentScore + 1
}
}
} else {
when (currentVote) {
-1 -> {
currentScore + 1
}

1 -> {
currentScore - 2
}

else -> {
currentScore - 1
}
}
}
}

fun newVoteCount(
votes: Pair<Int, Int>,
currentVote: Int?,
voteType: VoteType,
): Pair<Int, Int> {
return if (voteType == VoteType.Upvote) {
when (currentVote) {
1 -> {
Pair(votes.first - 1, votes.second)
}

-1 -> {
Pair(votes.first + 1, votes.second - 1)
}

else -> {
Pair(votes.first + 1, votes.second)
}
}
} else {
when (currentVote) {
-1 -> {
Pair(votes.first, votes.second - 1)
}

1 -> {
Pair(votes.first - 1, votes.second + 1)
}

else -> {
Pair(votes.first, votes.second + 1)
}
}
}
}

/**
* This stores live info about votes / scores, in order to update the front end without waiting
* for an API result
*/
data class InstantScores(
val myVote: Int?,
val score: Int,
val upvotes: Int,
val downvotes: Int,
)

data class MissingCommentView(
val commentId: Int,
val commentId: CommentId,
val path: String,
)

Expand All @@ -244,7 +99,7 @@ sealed class CommentNodeData(
val children: SnapshotStateList<CommentNodeData> = mutableStateListOf(),
var parent: CommentNodeData? = null,
) {
abstract fun getId(): Int
abstract fun getId(): Long

abstract fun getPath(): String
}
Expand Down Expand Up @@ -285,7 +140,7 @@ fun commentsToFlatNodes(comments: List<CommentView>): ImmutableList<CommentNode>
fun buildCommentsTree(
comments: List<CommentView>,
// If it's in CommentView, then we need to know the root comment id
rootCommentId: Int?,
rootCommentId: CommentId?,
): ImmutableList<CommentNodeData> {
val isCommentView = rootCommentId != null

Expand Down Expand Up @@ -328,7 +183,7 @@ fun recCreateAndGenMissingCommentData(
tree: MutableList<CommentNodeData>,
currCommentPath: String,
currCommentNodeData: CommentNodeData,
rootCommentId: Int?,
rootCommentId: CommentId?,
) {
val parentId = getCommentParentId(currCommentPath)

Expand Down Expand Up @@ -813,9 +668,9 @@ fun validateUrl(
}
}

fun siFormat(num: Int): String {
fun siFormat(num: Long): String {
// Weird bug where if num is zero, it won't format
if (num == 0) return "0"
if (num == 0L) return "0"
var value = num.toDouble()
val suffix = " KMBT"
val formatter = DecimalFormat("#,###.#")
Expand Down Expand Up @@ -965,14 +820,14 @@ fun isSameInstance(
return hostName(url) == instance
}

fun getCommentParentId(comment: Comment): Int? = getCommentParentId(comment.path)
fun getCommentParentId(comment: Comment): CommentId? = getCommentParentId(comment.path)

fun getCommentParentId(commentPath: String): Int? {
fun getCommentParentId(commentPath: String): CommentId? {
val split = commentPath.split(".").toMutableList()
// remove the 0
split.removeFirst()
return if (split.size > 1) {
split[split.size - 2].toInt()
split[split.size - 2].toLong()
} else {
null
}
Expand All @@ -993,7 +848,7 @@ fun getDepthFromComment(comment: Comment): Int = getDepthFromComment(comment.pat

fun getCommentIdDepthFromPath(
commentPath: String,
commentId: Int,
commentId: CommentId,
): Int {
val split = commentPath.split(".").toMutableList()
return split.indexOf(commentId.toString()).minus(1)
Expand Down Expand Up @@ -1562,7 +1417,7 @@ fun <T> appendData(
fun <T> getDeduplicatedList(
oldList: List<T>,
uniqueNewList: List<T>,
getId: (T) -> Int,
getId: (T) -> PostId,
): List<T> {
val mapIds = oldList.map { getId(it) }
return uniqueNewList.filterNot { mapIds.contains(getId(it)) }
Expand All @@ -1571,7 +1426,7 @@ fun <T> getDeduplicatedList(
fun <T> getDeduplicateMerge(
oldItems: List<T>,
newItems: List<T>,
getId: (T) -> Int,
getId: (T) -> PostId,
): List<T> {
return appendData(oldItems, getDeduplicatedList(oldItems, newItems, getId))
}
Expand Down Expand Up @@ -1601,55 +1456,3 @@ fun String.padUrlWithHttps(): String {
"https://$this"
}
}

/**
* Determines whether someone can moderate an item. Uses a hierarchy of admins then mods.
*/
fun canMod(
creatorId: PersonId,
admins: ImmutableList<PersonView>?,
moderators: ImmutableList<CommunityModeratorView>?,
myId: PersonId?,
onSelf: Boolean = false,
): Boolean {
return if (myId !== null) {
// You can do moderator actions only on the mods added after you.
val adminIds = admins?.map { a -> a.person.id }.orEmpty()
val modIds = moderators?.map { m -> m.moderator.id }.orEmpty()

val adminsThenMods = adminIds.toMutableList()
adminsThenMods.addAll(modIds)

val myIndex = adminsThenMods.indexOf(myId)
if (myIndex == -1) {
false
} else {
// onSelf +1 on mod actions not for yourself, IE ban, remove, etc
val subList = adminsThenMods.subList(0, myIndex.plus(if (onSelf) 0 else 1))

!subList.contains(creatorId)
}
} else {
false
}
}

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

fun amMod(
moderators: ImmutableList<CommunityModeratorView>?,
myId: PersonId?,
): Boolean {
return moderators?.map { it.moderator.id }?.contains(myId) ?: false
}

fun amAdmin(
admins: ImmutableList<PersonView>?,
myId: PersonId?,
): Boolean {
return admins?.map { it.person.id }?.contains(myId) ?: false
}
Loading

0 comments on commit 8b5c6fe

Please sign in to comment.