commit f854b217a2510ce5822717abc10fcc9ad190b289
parent bf5d57758c330c4a05cf1b1e0bbb081e71d1289b
Author: rhunk <101876869+rhunk@users.noreply.github.com>
Date: Thu, 2 Jan 2025 17:41:50 +0100
fix(core): feed entry table
Signed-off-by: rhunk <101876869+rhunk@users.noreply.github.com>
Diffstat:
7 files changed, 105 insertions(+), 52 deletions(-)
diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/social/AddFriendDialog.kt b/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/social/AddFriendDialog.kt
@@ -45,6 +45,7 @@ class AddFriendDialog(
id: String,
bitmoji: String? = null,
name: String,
+ participantsCount: Int? = null,
getCurrentState: () -> Boolean,
onState: (Boolean) -> Unit = {},
) {
@@ -74,12 +75,24 @@ class AddFriendDialog(
size = 32,
)
- Text(
- text = name,
- fontSize = 15.sp,
+ Column(
modifier = Modifier
.weight(1f)
- )
+ ) {
+ Text(
+ text = name,
+ fontSize = 15.sp,
+ )
+
+ participantsCount?.let {
+ Text(
+ text = translation.format("participants_text", "count" to it.toString()),
+ fontSize = 12.sp,
+ lineHeight = 12.sp,
+ color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.6f)
+ )
+ }
+ }
Checkbox(
checked = currentState,
@@ -249,6 +262,7 @@ class AddFriendDialog(
ListCardEntry(
id = group.conversationId,
name = group.name,
+ participantsCount = group.participantsCount,
getCurrentState = { actionHandler.getGroupState(group) }
) { state ->
actionHandler.onGroupState(group, state)
diff --git a/common/src/main/assets/lang/en_US.json b/common/src/main/assets/lang/en_US.json
@@ -198,7 +198,8 @@
"search_hint": "Search",
"fetch_error": "Failed to fetch data",
"category_groups": "Groups",
- "category_friends": "Friends"
+ "category_friends": "Friends",
+ "participants_text": "{count} participants"
},
"scripting_warning": {
"title": "Warning",
diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/database/impl/FriendFeedEntry.kt b/common/src/main/kotlin/me/rhunk/snapenhance/common/database/impl/FriendFeedEntry.kt
@@ -3,13 +3,14 @@ package me.rhunk.snapenhance.common.database.impl
import android.annotation.SuppressLint
import android.database.Cursor
import me.rhunk.snapenhance.common.database.DatabaseObject
+import me.rhunk.snapenhance.common.util.ktx.getBlobOrNull
import me.rhunk.snapenhance.common.util.ktx.getIntOrNull
-import me.rhunk.snapenhance.common.util.ktx.getInteger
-import me.rhunk.snapenhance.common.util.ktx.getLong
+import me.rhunk.snapenhance.common.util.ktx.getLongOrNull
import me.rhunk.snapenhance.common.util.ktx.getStringOrNull
+import java.nio.ByteBuffer
+import java.util.UUID
data class FriendFeedEntry(
- var id: Int = 0,
var feedDisplayName: String? = null,
var participantsSize: Int = 0,
var lastInteractionTimestamp: Long = 0,
@@ -18,24 +19,28 @@ data class FriendFeedEntry(
var lastInteractionUserId: Int? = null,
var key: String? = null,
var friendUserId: String? = null,
+ var participants: List<String>? = null,
+ var conversationType: Int? = null,
var friendDisplayName: String? = null,
var friendDisplayUsername: String? = null,
var friendLinkType: Int? = null,
var bitmojiAvatarId: String? = null,
var bitmojiSelfieId: String? = null,
) : DatabaseObject {
-
@SuppressLint("Range")
override fun write(cursor: Cursor) {
with(cursor) {
- id = getInteger("_id")
- feedDisplayName = getStringOrNull("feedDisplayName")
- participantsSize = getInteger("participantsSize")
- lastInteractionTimestamp = getLong("lastInteractionTimestamp")
- displayTimestamp = getLong("displayTimestamp")
+ key = getStringOrNull("client_conversation_id") ?: getStringOrNull("key")
+ feedDisplayName = (getStringOrNull("conversation_title") ?: getStringOrNull("feedDisplayName"))?.takeIf { it.isNotBlank() }
+ lastInteractionTimestamp = getLongOrNull("last_updated_timestamp") ?: getLongOrNull("lastInteractionTimestamp") ?: 0L
+
+ participants = getBlobOrNull("participants")?.toList()?.chunked(16)?.map { ByteBuffer.wrap(it.toByteArray()).run { UUID(long, long) }.toString() } ?: emptyList()
+ participantsSize = getIntOrNull("participantsSize") ?: participants?.size ?: 0
+ conversationType = getIntOrNull("conversation_type") ?: getIntOrNull("kind")
+
+ displayTimestamp = getLongOrNull("displayTimestamp") ?: 0L
displayInteractionType = getStringOrNull("displayInteractionType")
lastInteractionUserId = getIntOrNull("lastInteractionUserId")
- key = getStringOrNull("key")
friendUserId = getStringOrNull("friendUserId")
friendDisplayName = getStringOrNull("friendDisplayName")
friendDisplayUsername = getStringOrNull("friendDisplayUsername")
diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/SnapEnhance.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/SnapEnhance.kt
@@ -330,22 +330,25 @@ class SnapEnhance {
event.canceled = true
val feedEntries = appContext.database.getFeedEntries(Int.MAX_VALUE)
- val groups = feedEntries.filter { it.friendUserId == null }.map {
+ val groups = feedEntries.filter { it.conversationType == 1 }.map {
MessagingGroupInfo(
it.key!!,
- it.feedDisplayName!!,
+ it.feedDisplayName ?: "",
it.participantsSize
)
}
- val friends = feedEntries.filter { it.friendUserId != null }.map {
+ val friends = feedEntries.filter { it.conversationType == 0 }.mapNotNull {
+ val friendUserId = it.friendUserId ?: it.participants?.filter { it != appContext.database.myUserId }?.firstOrNull() ?: return@mapNotNull null
+ val friend = appContext.database.getFriendInfo(friendUserId) ?: return@mapNotNull null
+
MessagingFriendInfo(
- it.friendUserId!!,
- appContext.database.getConversationLinkFromUserId(it.friendUserId!!)?.clientConversationId,
- it.friendDisplayName,
- it.friendDisplayUsername!!.split("|")[1],
- it.bitmojiAvatarId,
- it.bitmojiSelfieId,
+ friendUserId,
+ appContext.database.getConversationLinkFromUserId(friendUserId)?.clientConversationId,
+ friend.displayName,
+ friend.mutableUsername ?: friend.usernameForSorting!!,
+ friend.bitmojiAvatarId,
+ friend.bitmojiSelfieId,
streaks = null
)
}
@@ -379,7 +382,7 @@ class SnapEnhance {
return appContext.database.getFeedEntryByConversationId(uuid)?.let {
MessagingGroupInfo(
it.key!!,
- it.feedDisplayName!!,
+ it.feedDisplayName ?: "",
it.participantsSize
).toSerialized()
}
diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/action/impl/ExportChatMessages.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/action/impl/ExportChatMessages.kt
@@ -22,10 +22,12 @@ import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
import kotlinx.coroutines.*
import me.rhunk.snapenhance.common.data.ContentType
import me.rhunk.snapenhance.common.database.impl.FriendFeedEntry
import me.rhunk.snapenhance.common.ui.createComposeAlertDialog
+import me.rhunk.snapenhance.common.ui.rememberAsyncMutableState
import me.rhunk.snapenhance.core.action.AbstractAction
import me.rhunk.snapenhance.core.features.impl.messaging.Messaging
import me.rhunk.snapenhance.core.logger.CoreLogger
@@ -72,6 +74,8 @@ class ExportChatMessages : AbstractAction() {
val messageTypeFilter = remember { mutableStateListOf<ContentType>() }
var amountOfMessages by remember { mutableIntStateOf(-1) }
var downloadMedias by remember { mutableStateOf(false) }
+ val allFriends by rememberAsyncMutableState(null) { context.database.getAllFriends().associateBy { it.userId!! } }
+ val myUserId = context.database.myUserId
Column(
modifier = Modifier
@@ -102,7 +106,7 @@ class ExportChatMessages : AbstractAction() {
LazyColumn(
modifier = Modifier.size(LocalConfiguration.current.screenWidthDp.dp, 300.dp)
) {
- items(feedEntries) { feedEntry ->
+ items(feedEntries, key = { it.key!! }) { feedEntry ->
DropdownMenuItem(
modifier = Modifier.fillMaxWidth(),
onClick = {
@@ -114,11 +118,26 @@ class ExportChatMessages : AbstractAction() {
verticalAlignment = Alignment.CenterVertically
) {
Checkbox(checked = selectedFeedEntries.contains(feedEntry), onCheckedChange = null)
- Text(
- text = feedEntry.feedDisplayName ?: feedEntry.friendDisplayName ?: "unknown",
- overflow = TextOverflow.Ellipsis,
- maxLines = 1
- )
+ Column {
+ Text(
+ text = remember(feedEntry) {
+ (if (feedEntry.conversationType == 1) feedEntry.feedDisplayName else feedEntry.participants?.filter { it != myUserId }?.firstOrNull()?.let { userId ->
+ allFriends?.get(userId)?.let { friend -> friend.displayName?.let { "$it (${friend.mutableUsername})" } ?: friend.mutableUsername }
+ }) ?: "Unknown"
+ },
+ overflow = TextOverflow.Ellipsis,
+ lineHeight = 15.sp,
+ maxLines = 1
+ )
+ if (feedEntry.conversationType == 1) {
+ Text(
+ text = "${feedEntry.participantsSize} participants",
+ fontSize = 10.sp,
+ lineHeight = 15.sp,
+ overflow = TextOverflow.Ellipsis,
+ )
+ }
+ }
}
}
)
@@ -332,12 +351,13 @@ class ExportChatMessages : AbstractAction() {
) {
//first fetch the first message
val conversationId = feedEntry.key!!
- val conversationName = feedEntry.feedDisplayName ?: feedEntry.friendDisplayName!!.split("|").lastOrNull() ?: "unknown"
val conversationParticipants = context.database.getConversationParticipants(feedEntry.key!!, useCache = false)
?.mapNotNull {
context.database.getFriendInfo(it)
}?.associateBy { it.userId!! } ?: emptyMap()
+ val conversationName = feedEntry.feedDisplayName ?: conversationParticipants.values.take(3).joinToString("_") { it.mutableUsername ?: "" }
+
val publicFolder = File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), "SnapEnhance").also { if (!it.exists()) it.mkdirs() }
val outputFile = publicFolder.resolve("conversation_${conversationName}_${System.currentTimeMillis()}.${exportParams.exportFormat.extension}")
diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/database/DatabaseAccess.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/database/DatabaseAccess.kt
@@ -152,17 +152,6 @@ class DatabaseAccess(
obj
}
- fun getFeedEntryByUserId(userId: String): FriendFeedEntry? {
- return useDatabase(DatabaseType.MAIN)?.performOperation {
- readDatabaseObject(
- FriendFeedEntry(),
- "FriendsFeedView",
- "friendUserId = ?",
- arrayOf(userId)
- )
- }
- }
-
val myUserId by lazy {
context.androidContext.getSharedPreferences("user_session_shared_pref", 0).getString("key_user_id", null) ?:
useDatabase(DatabaseType.ARROYO)?.performOperation {
@@ -178,7 +167,14 @@ class DatabaseAccess(
}
fun getFeedEntryByConversationId(conversationId: String): FriendFeedEntry? {
- return useDatabase(DatabaseType.MAIN)?.performOperation {
+ return useDatabase(DatabaseType.ARROYO)?.performOperation {
+ readDatabaseObject(
+ FriendFeedEntry(),
+ "feed_entry",
+ "client_conversation_id = ?",
+ arrayOf(conversationId)
+ )
+ } ?: useDatabase(DatabaseType.MAIN)?.performOperation {
readDatabaseObject(
FriendFeedEntry(),
"FriendsFeedView",
@@ -230,20 +226,34 @@ class DatabaseAccess(
}
fun getFeedEntries(limit: Int): List<FriendFeedEntry> {
- return useDatabase(DatabaseType.MAIN)?.performOperation {
+ val entries = mutableListOf<FriendFeedEntry>()
+ return useDatabase(DatabaseType.ARROYO)?.performOperation {
+ safeRawQuery(
+ "SELECT * FROM feed_entry ORDER BY last_updated_timestamp DESC LIMIT ?",
+ arrayOf(limit.toString())
+ )?.use { query ->
+ while (query.moveToNext()) {
+ val friendFeedEntry = FriendFeedEntry()
+ try {
+ friendFeedEntry.write(query)
+ } catch (_: Throwable) {}
+ entries.add(friendFeedEntry)
+ }
+ entries
+ }
+ }?.takeIf { it.isNotEmpty() } ?: useDatabase(DatabaseType.MAIN)?.performOperation {
safeRawQuery(
"SELECT * FROM FriendsFeedView ORDER BY _id LIMIT ?",
arrayOf(limit.toString())
)?.use { query ->
- val list = mutableListOf<FriendFeedEntry>()
while (query.moveToNext()) {
val friendFeedEntry = FriendFeedEntry()
try {
friendFeedEntry.write(query)
} catch (_: Throwable) {}
- list.add(friendFeedEntry)
+ entries.add(friendFeedEntry)
}
- list
+ entries
}
} ?: emptyList()
}
diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/spying/HalfSwipeNotifier.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/spying/HalfSwipeNotifier.kt
@@ -91,15 +91,15 @@ class HalfSwipeNotifier : Feature("Half Swipe Notifier") {
if (minDuration > peekingDuration || maxDuration < peekingDuration) return
- val groupName = context.database.getFeedEntryByConversationId(conversationId)?.feedDisplayName
+ val feedEntry = context.database.getFeedEntryByConversationId(conversationId)
val friendInfo = context.database.getFriendInfo(userId) ?: return
Notification.Builder(context.androidContext, channelId)
- .setContentTitle(groupName ?: friendInfo.displayName ?: friendInfo.mutableUsername)
- .setContentText(if (groupName != null) {
+ .setContentTitle(feedEntry?.feedDisplayName ?: friendInfo.displayName ?: friendInfo.mutableUsername)
+ .setContentText(if (feedEntry?.conversationType == 1) {
translation.format("notification_content_group",
"friend" to (friendInfo.displayName ?: friendInfo.mutableUsername).toString(),
- "group" to groupName,
+ "group" to (feedEntry.feedDisplayName ?: "Group"),
"duration" to peekingDuration.toString()
)
} else {