chore: remove mlkit smart reply for now
Signed-off-by: Infi <infi@infi.sh>
This commit is contained in:
parent
75349f2a4d
commit
6d0d17a401
|
|
@ -292,9 +292,6 @@ dependencies {
|
||||||
|
|
||||||
// Shimmer - loading animations
|
// Shimmer - loading animations
|
||||||
implementation "com.valentinilk.shimmer:compose-shimmer:1.3.1"
|
implementation "com.valentinilk.shimmer:compose-shimmer:1.3.1"
|
||||||
|
|
||||||
// MLKit - Machine Learning
|
|
||||||
implementation 'com.google.android.gms:play-services-mlkit-smart-reply:16.0.0-beta1'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sqldelight {
|
sqldelight {
|
||||||
|
|
|
||||||
|
|
@ -50,10 +50,6 @@
|
||||||
android:name="io.sentry.auto-init"
|
android:name="io.sentry.auto-init"
|
||||||
android:value="false" />
|
android:value="false" />
|
||||||
|
|
||||||
<meta-data
|
|
||||||
android:name="com.google.mlkit.vision.DEPENDENCIES"
|
|
||||||
android:value="smart_reply" />
|
|
||||||
|
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="com.google.firebase.messaging.default_notification_icon"
|
android:name="com.google.firebase.messaging.default_notification_icon"
|
||||||
android:resource="@drawable/ic_notification_monochrome" />
|
android:resource="@drawable/ic_notification_monochrome" />
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,6 @@ class ExperimentInstance(default: Boolean) {
|
||||||
*/
|
*/
|
||||||
object Experiments {
|
object Experiments {
|
||||||
val useKotlinBasedMarkdownRenderer = ExperimentInstance(false)
|
val useKotlinBasedMarkdownRenderer = ExperimentInstance(false)
|
||||||
val useMlKitSmartReplyInApp = ExperimentInstance(false)
|
|
||||||
|
|
||||||
suspend fun hydrateWithKv() {
|
suspend fun hydrateWithKv() {
|
||||||
val kvStorage = KVStorage(RevoltApplication.instance)
|
val kvStorage = KVStorage(RevoltApplication.instance)
|
||||||
|
|
@ -41,8 +40,5 @@ object Experiments {
|
||||||
useKotlinBasedMarkdownRenderer.setEnabled(
|
useKotlinBasedMarkdownRenderer.setEnabled(
|
||||||
kvStorage.getBoolean("exp/useKotlinBasedMarkdownRenderer") ?: false
|
kvStorage.getBoolean("exp/useKotlinBasedMarkdownRenderer") ?: false
|
||||||
)
|
)
|
||||||
useMlKitSmartReplyInApp.setEnabled(
|
|
||||||
kvStorage.getBoolean("exp/useMlKitSmartReplyInApp") ?: false
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,66 +0,0 @@
|
||||||
package chat.revolt.api.settings.experiments
|
|
||||||
|
|
||||||
import android.util.Log
|
|
||||||
import chat.revolt.api.RevoltAPI
|
|
||||||
import chat.revolt.api.internals.ULID
|
|
||||||
import chat.revolt.api.schemas.Message
|
|
||||||
import chat.revolt.api.schemas.RsResult
|
|
||||||
import com.google.mlkit.nl.smartreply.SmartReply
|
|
||||||
import com.google.mlkit.nl.smartreply.TextMessage
|
|
||||||
|
|
||||||
object SmartReplyImpl {
|
|
||||||
val client = SmartReply.getClient()
|
|
||||||
|
|
||||||
fun forMessages(
|
|
||||||
messages: List<Message>,
|
|
||||||
onResult: (RsResult<List<String>, Exception>) -> Unit
|
|
||||||
) {
|
|
||||||
if (messages.size > 10) {
|
|
||||||
onResult(RsResult.err(IllegalArgumentException("Too many messages")))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
Log.d("SmartReplyImpl", "Creating conversation for ${messages.size} messages")
|
|
||||||
|
|
||||||
val conversation = messages.map {
|
|
||||||
if (it.author == RevoltAPI.selfId) {
|
|
||||||
if (it.id == null) {
|
|
||||||
Log.w("SmartReplyImpl", "Message ID is null in local user message, skipping")
|
|
||||||
return@map null
|
|
||||||
}
|
|
||||||
if (it.content?.isEmpty() == true || it.content == null) {
|
|
||||||
Log.w(
|
|
||||||
"SmartReplyImpl",
|
|
||||||
"Message content is null or empty in local user message, skipping"
|
|
||||||
)
|
|
||||||
return@map null
|
|
||||||
}
|
|
||||||
TextMessage.createForLocalUser(it.content, ULID.asTimestamp(it.id))
|
|
||||||
} else {
|
|
||||||
if (it.id == null || it.author == null) {
|
|
||||||
Log.w(
|
|
||||||
"SmartReplyImpl",
|
|
||||||
"Message ID or author is null in remote user message, skipping"
|
|
||||||
)
|
|
||||||
return@map null
|
|
||||||
}
|
|
||||||
if (it.content?.isEmpty() == true || it.content == null) {
|
|
||||||
Log.w(
|
|
||||||
"SmartReplyImpl",
|
|
||||||
"Message content is null or empty in remote user message, skipping"
|
|
||||||
)
|
|
||||||
return@map null
|
|
||||||
}
|
|
||||||
TextMessage.createForRemoteUser(it.content, ULID.asTimestamp(it.id), it.author)
|
|
||||||
}
|
|
||||||
}.filterNotNull().reversed()
|
|
||||||
|
|
||||||
Log.d("SmartReplyImpl", "Suggesting replies for ${conversation.size} messages")
|
|
||||||
|
|
||||||
client.suggestReplies(conversation).addOnSuccessListener {
|
|
||||||
onResult(RsResult.ok(it.suggestions.map { s -> s.text }))
|
|
||||||
}.addOnFailureListener {
|
|
||||||
onResult(RsResult.err(it))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -373,22 +373,6 @@ fun ChannelScreen(
|
||||||
scope.launch {
|
scope.launch {
|
||||||
ActionChannel.send(Action.ReportMessage(messageContextSheetTarget))
|
ActionChannel.send(Action.ReportMessage(messageContextSheetTarget))
|
||||||
}
|
}
|
||||||
},
|
|
||||||
lastTenMessages = {
|
|
||||||
// First we find the message in viewModel.items
|
|
||||||
val index = viewModel.items.filterIsInstance<ChannelScreenItem.RegularMessage>()
|
|
||||||
.indexOfFirst { it.message.id == messageContextSheetTarget }
|
|
||||||
|
|
||||||
Log.d("ChannelScreen", "We have index $index")
|
|
||||||
Log.d("ChannelScreen", "Items.len ${viewModel.items.size}")
|
|
||||||
|
|
||||||
// Then we take the last 10 messages before it. We take care to not go out of bounds.
|
|
||||||
val messages =
|
|
||||||
viewModel.items.filterIsInstance<ChannelScreenItem.RegularMessage>()
|
|
||||||
.subList(index, min(index + 5, (viewModel.items.size - 1)))
|
|
||||||
.map { it.message }
|
|
||||||
|
|
||||||
messages
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,6 @@ class ExperimentsSettingsScreenViewModel : ViewModel() {
|
||||||
fun init() {
|
fun init() {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
useKotlinMdRendererChecked.value = Experiments.useKotlinBasedMarkdownRenderer.isEnabled
|
useKotlinMdRendererChecked.value = Experiments.useKotlinBasedMarkdownRenderer.isEnabled
|
||||||
useMlKitSmartReplyInAppChecked.value = Experiments.useMlKitSmartReplyInApp.isEnabled
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -43,7 +42,6 @@ class ExperimentsSettingsScreenViewModel : ViewModel() {
|
||||||
}
|
}
|
||||||
|
|
||||||
val useKotlinMdRendererChecked = mutableStateOf(false)
|
val useKotlinMdRendererChecked = mutableStateOf(false)
|
||||||
val useMlKitSmartReplyInAppChecked = mutableStateOf(false)
|
|
||||||
|
|
||||||
fun setUseKotlinMdRendererChecked(value: Boolean) {
|
fun setUseKotlinMdRendererChecked(value: Boolean) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
|
|
@ -52,14 +50,6 @@ class ExperimentsSettingsScreenViewModel : ViewModel() {
|
||||||
useKotlinMdRendererChecked.value = value
|
useKotlinMdRendererChecked.value = value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setUseMlKitSmartReplyInAppChecked(value: Boolean) {
|
|
||||||
viewModelScope.launch {
|
|
||||||
kv.set("exp/useMlKitSmartReplyInApp", value)
|
|
||||||
Experiments.useMlKitSmartReplyInApp.setEnabled(value)
|
|
||||||
useMlKitSmartReplyInAppChecked.value = value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
|
@ -93,22 +83,6 @@ fun ExperimentsSettingsScreen(
|
||||||
modifier = Modifier.clickable { viewModel.setUseKotlinMdRendererChecked(!viewModel.useKotlinMdRendererChecked.value) }
|
modifier = Modifier.clickable { viewModel.setUseKotlinMdRendererChecked(!viewModel.useKotlinMdRendererChecked.value) }
|
||||||
)
|
)
|
||||||
|
|
||||||
ListItem(
|
|
||||||
headlineContent = {
|
|
||||||
Text("Smart Reply Suggestions (In-App)")
|
|
||||||
},
|
|
||||||
supportingContent = {
|
|
||||||
Text("Use a machine learning model to suggest replies to messages from the message sheet.")
|
|
||||||
},
|
|
||||||
trailingContent = {
|
|
||||||
Switch(
|
|
||||||
checked = viewModel.useMlKitSmartReplyInAppChecked.value,
|
|
||||||
onCheckedChange = viewModel::setUseMlKitSmartReplyInAppChecked
|
|
||||||
)
|
|
||||||
},
|
|
||||||
modifier = Modifier.clickable { viewModel.setUseMlKitSmartReplyInAppChecked(!viewModel.useMlKitSmartReplyInAppChecked.value) }
|
|
||||||
)
|
|
||||||
|
|
||||||
Subcategory(
|
Subcategory(
|
||||||
title = {
|
title = {
|
||||||
Text("Disable experiments")
|
Text("Disable experiments")
|
||||||
|
|
|
||||||
|
|
@ -1,62 +0,0 @@
|
||||||
package chat.revolt.sheets
|
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
|
||||||
import androidx.compose.foundation.layout.Column
|
|
||||||
import androidx.compose.foundation.layout.Spacer
|
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
|
||||||
import androidx.compose.foundation.layout.height
|
|
||||||
import androidx.compose.foundation.rememberScrollState
|
|
||||||
import androidx.compose.foundation.verticalScroll
|
|
||||||
import androidx.compose.material3.Icon
|
|
||||||
import androidx.compose.material3.MaterialTheme
|
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.ui.Alignment
|
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import androidx.compose.ui.graphics.Color
|
|
||||||
import androidx.compose.ui.res.painterResource
|
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
import chat.revolt.R
|
|
||||||
import chat.revolt.components.generic.SheetButton
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun MessageContentMLKitReplySelectSheet(
|
|
||||||
options: List<String>,
|
|
||||||
onOptionSelected: (String) -> Unit
|
|
||||||
) {
|
|
||||||
Column(
|
|
||||||
modifier = Modifier
|
|
||||||
.verticalScroll(rememberScrollState())
|
|
||||||
) {
|
|
||||||
Column(
|
|
||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
|
||||||
verticalArrangement = Arrangement.spacedBy(16.dp),
|
|
||||||
modifier = Modifier.fillMaxWidth()
|
|
||||||
) {
|
|
||||||
Icon(
|
|
||||||
painter = painterResource(R.drawable.ic_creation_24dp),
|
|
||||||
contentDescription = null,
|
|
||||||
tint = Color(0xFF977EFF)
|
|
||||||
)
|
|
||||||
Text(
|
|
||||||
"Select a reply",
|
|
||||||
style = MaterialTheme.typography.headlineLarge,
|
|
||||||
textAlign = TextAlign.Center
|
|
||||||
)
|
|
||||||
}
|
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
|
||||||
options.forEach { option ->
|
|
||||||
SheetButton(
|
|
||||||
headlineContent = { Text(option) },
|
|
||||||
leadingContent = {
|
|
||||||
Icon(
|
|
||||||
painter = painterResource(R.drawable.ic_reply_24dp),
|
|
||||||
contentDescription = null
|
|
||||||
)
|
|
||||||
},
|
|
||||||
onClick = { onOptionSelected(option) }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -18,14 +18,11 @@ import androidx.compose.material3.CircularProgressIndicator
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.HorizontalDivider
|
import androidx.compose.material3.HorizontalDivider
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.IconButton
|
|
||||||
import androidx.compose.material3.LocalContentColor
|
|
||||||
import androidx.compose.material3.ModalBottomSheet
|
import androidx.compose.material3.ModalBottomSheet
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TextButton
|
import androidx.compose.material3.TextButton
|
||||||
import androidx.compose.material3.rememberModalBottomSheetState
|
import androidx.compose.material3.rememberModalBottomSheetState
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
|
|
@ -33,7 +30,6 @@ import androidx.compose.runtime.rememberCoroutineScope
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
|
||||||
import androidx.compose.ui.platform.LocalClipboardManager
|
import androidx.compose.ui.platform.LocalClipboardManager
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
|
|
@ -48,16 +44,10 @@ import chat.revolt.api.internals.Roles
|
||||||
import chat.revolt.api.internals.has
|
import chat.revolt.api.internals.has
|
||||||
import chat.revolt.api.routes.channel.deleteMessage
|
import chat.revolt.api.routes.channel.deleteMessage
|
||||||
import chat.revolt.api.routes.channel.react
|
import chat.revolt.api.routes.channel.react
|
||||||
import chat.revolt.api.schemas.Message
|
|
||||||
import chat.revolt.api.settings.Experiments
|
|
||||||
import chat.revolt.api.settings.experiments.SmartReplyImpl
|
|
||||||
import chat.revolt.callbacks.UiCallbacks
|
import chat.revolt.callbacks.UiCallbacks
|
||||||
import chat.revolt.components.chat.Message
|
import chat.revolt.components.chat.Message
|
||||||
import chat.revolt.components.generic.SheetButton
|
import chat.revolt.components.generic.SheetButton
|
||||||
import chat.revolt.internals.Platform
|
import chat.revolt.internals.Platform
|
||||||
import com.valentinilk.shimmer.ShimmerBounds
|
|
||||||
import com.valentinilk.shimmer.rememberShimmer
|
|
||||||
import com.valentinilk.shimmer.shimmer
|
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
|
@ -65,8 +55,7 @@ import kotlinx.coroutines.launch
|
||||||
fun MessageContextSheet(
|
fun MessageContextSheet(
|
||||||
messageId: String,
|
messageId: String,
|
||||||
onHideSheet: suspend () -> Unit,
|
onHideSheet: suspend () -> Unit,
|
||||||
onReportMessage: () -> Unit,
|
onReportMessage: () -> Unit
|
||||||
lastTenMessages: (() -> List<Message>)? = null
|
|
||||||
) {
|
) {
|
||||||
val message = RevoltAPI.messageCache[messageId]
|
val message = RevoltAPI.messageCache[messageId]
|
||||||
if (message == null) {
|
if (message == null) {
|
||||||
|
|
@ -84,48 +73,6 @@ fun MessageContextSheet(
|
||||||
val clipboardManager = LocalClipboardManager.current
|
val clipboardManager = LocalClipboardManager.current
|
||||||
val coroutineScope = rememberCoroutineScope()
|
val coroutineScope = rememberCoroutineScope()
|
||||||
|
|
||||||
var mlKitSmartReplies by remember { mutableStateOf<List<String>?>(null) }
|
|
||||||
var mlKitSmartRepliesLoading by remember { mutableStateOf(false) }
|
|
||||||
LaunchedEffect(Unit) {
|
|
||||||
if (Experiments.useMlKitSmartReplyInApp.isEnabled) {
|
|
||||||
mlKitSmartReplies = null
|
|
||||||
mlKitSmartRepliesLoading = true
|
|
||||||
lastTenMessages?.let { fn ->
|
|
||||||
SmartReplyImpl.forMessages(
|
|
||||||
fn.invoke()
|
|
||||||
) {
|
|
||||||
mlKitSmartReplies = if (it.ok) {
|
|
||||||
it.unwrap()
|
|
||||||
} else {
|
|
||||||
null
|
|
||||||
}
|
|
||||||
mlKitSmartRepliesLoading = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var showMlKitSmartReplySheet by remember { mutableStateOf(false) }
|
|
||||||
if (showMlKitSmartReplySheet) {
|
|
||||||
val mlKitSmartReplySheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true)
|
|
||||||
|
|
||||||
ModalBottomSheet(
|
|
||||||
sheetState = mlKitSmartReplySheetState,
|
|
||||||
onDismissRequest = {
|
|
||||||
showMlKitSmartReplySheet = false
|
|
||||||
}
|
|
||||||
) {
|
|
||||||
MessageContentMLKitReplySelectSheet(
|
|
||||||
options = mlKitSmartReplies ?: emptyList(),
|
|
||||||
onOptionSelected = {
|
|
||||||
coroutineScope.launch {
|
|
||||||
UiCallbacks.replyToMessageWithContent(messageId, it)
|
|
||||||
onHideSheet()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var showShareSheet by remember { mutableStateOf(false) }
|
var showShareSheet by remember { mutableStateOf(false) }
|
||||||
var showReactSheet by remember { mutableStateOf(false) }
|
var showReactSheet by remember { mutableStateOf(false) }
|
||||||
var showDeleteMessageConfirmation by remember { mutableStateOf(false) }
|
var showDeleteMessageConfirmation by remember { mutableStateOf(false) }
|
||||||
|
|
@ -388,30 +335,6 @@ fun MessageContextSheet(
|
||||||
text = stringResource(id = R.string.message_context_sheet_actions_reply),
|
text = stringResource(id = R.string.message_context_sheet_actions_reply),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
trailingContent = {
|
|
||||||
if (Experiments.useMlKitSmartReplyInApp.isEnabled && (mlKitSmartRepliesLoading || (mlKitSmartReplies?.isNotEmpty() == true))) {
|
|
||||||
IconButton(onClick = {
|
|
||||||
coroutineScope.launch {
|
|
||||||
showMlKitSmartReplySheet = true
|
|
||||||
}
|
|
||||||
}) {
|
|
||||||
Icon(
|
|
||||||
painter = painterResource(id = R.drawable.ic_creation_24dp),
|
|
||||||
contentDescription = null,
|
|
||||||
tint = if (!mlKitSmartRepliesLoading && mlKitSmartReplies != null) {
|
|
||||||
Color(0xFF977EFF)
|
|
||||||
} else {
|
|
||||||
LocalContentColor.current
|
|
||||||
},
|
|
||||||
modifier = if (mlKitSmartRepliesLoading) {
|
|
||||||
Modifier.shimmer(rememberShimmer(ShimmerBounds.View))
|
|
||||||
} else {
|
|
||||||
Modifier
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onClick = {
|
onClick = {
|
||||||
coroutineScope.launch {
|
coroutineScope.launch {
|
||||||
UiCallbacks.replyToMessage(messageId)
|
UiCallbacks.replyToMessage(messageId)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue