fix(core): feed entry table

Signed-off-by: rhunk <101876869+rhunk@users.noreply.github.com>
This commit is contained in:
rhunk 2025-01-02 17:41:50 +01:00
parent bf5d57758c
commit f854b217a2
7 changed files with 106 additions and 53 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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 FriendsFeedView ORDER BY _id LIMIT ?",
"SELECT * FROM feed_entry ORDER BY last_updated_timestamp DESC 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
}
}?.takeIf { it.isNotEmpty() } ?: useDatabase(DatabaseType.MAIN)?.performOperation {
safeRawQuery(
"SELECT * FROM FriendsFeedView ORDER BY _id LIMIT ?",
arrayOf(limit.toString())
)?.use { query ->
while (query.moveToNext()) {
val friendFeedEntry = FriendFeedEntry()
try {
friendFeedEntry.write(query)
} catch (_: Throwable) {}
entries.add(friendFeedEntry)
}
entries
}
} ?: emptyList()
}

View File

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