feat: show swipe to reply spark to upgrading users

Signed-off-by: Infi <infi@infi.sh>
This commit is contained in:
Infi 2025-04-25 22:39:17 +02:00
parent c7791716c5
commit 8156a5b28c
3 changed files with 67 additions and 13 deletions

View File

@ -92,6 +92,7 @@ import chat.revolt.sheets.ServerContextSheet
import chat.revolt.sheets.StatusSheet import chat.revolt.sheets.StatusSheet
import chat.revolt.sheets.UserInfoSheet import chat.revolt.sheets.UserInfoSheet
import chat.revolt.sheets.WebHookUserSheet import chat.revolt.sheets.WebHookUserSheet
import chat.revolt.sheets.spark.SwipeToReplySparkSheet
import com.google.android.gms.tasks.OnCompleteListener import com.google.android.gms.tasks.OnCompleteListener
import com.google.firebase.messaging.FirebaseMessaging import com.google.firebase.messaging.FirebaseMessaging
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
@ -150,6 +151,7 @@ class ChatRouterViewModel @Inject constructor(
var latestChangelogBody by mutableStateOf("") var latestChangelogBody by mutableStateOf("")
var showNotificationRationale by mutableStateOf(false) var showNotificationRationale by mutableStateOf(false)
var showEarlyAccessSpark by mutableStateOf(false) var showEarlyAccessSpark by mutableStateOf(false)
var showSwipeToReplySpark by mutableStateOf(false)
private val changelogs = Changelogs(context, kvStorage) private val changelogs = Changelogs(context, kvStorage)
@ -166,9 +168,17 @@ class ChatRouterViewModel @Inject constructor(
changelogs.markAsSeen() changelogs.markAsSeen()
} }
val seenEarlyAccess = kvStorage.get("spark/earlyAccess/dismissed") val seenEarlyAccess = kvStorage.getBoolean("spark/earlyAccess/dismissed")
val seenSwipeToReply = kvStorage.getBoolean("spark/swipeToReply/dismissed")
if (seenEarlyAccess == null) { if (seenEarlyAccess == null) {
showEarlyAccessSpark = true showEarlyAccessSpark = true
// we don't show swipe to reply to new users,
// as they would expect it to be working already
kvStorage.set("spark/swipeToReply/dismissed", true)
}
if (seenEarlyAccess == true && seenSwipeToReply != true) {
showSwipeToReplySpark = true
} }
val hasNotificationPermission = val hasNotificationPermission =
@ -228,6 +238,13 @@ class ChatRouterViewModel @Inject constructor(
} }
} }
fun dismissSwipeToReplySpark() {
showSwipeToReplySpark = false
viewModelScope.launch {
kvStorage.set("spark/swipeToReply/dismissed", true)
}
}
fun navigateToServer(serverId: String) { fun navigateToServer(serverId: String) {
viewModelScope.launch { viewModelScope.launch {
val savedLastChannel = kvStorage.get("lastChannel/$serverId") val savedLastChannel = kvStorage.get("lastChannel/$serverId")
@ -751,6 +768,31 @@ fun ChatRouterScreen(
} }
} }
if (viewModel.showSwipeToReplySpark) {
val swipeToReplySheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true)
ModalBottomSheet(
sheetState = swipeToReplySheetState,
sheetGesturesEnabled = false,
dragHandle = {},
onDismissRequest = {
// Only dismiss using button in sheet
}
) {
SwipeToReplySparkSheet(
onDismissSheet = {
scope.launch {
swipeToReplySheetState.hide()
viewModel.dismissSwipeToReplySpark()
}
},
onOpenOptions = {
topNav.navigate("settings/chat")
}
)
}
}
Column( Column(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()

View File

@ -69,6 +69,7 @@ class DebugSettingsScreenViewModel @Inject constructor(
fun forgetAllSparks() { fun forgetAllSparks() {
forgetPhysicalKeyboardSpark() forgetPhysicalKeyboardSpark()
forgetEarlyAccessSpark() forgetEarlyAccessSpark()
forgetSwipeToReplySpark()
} }
fun forgetPhysicalKeyboardSpark() { fun forgetPhysicalKeyboardSpark() {
@ -83,6 +84,12 @@ class DebugSettingsScreenViewModel @Inject constructor(
} }
} }
fun forgetSwipeToReplySpark() {
viewModelScope.launch {
kvStorage.remove("spark/swipeToReply/dismissed")
}
}
fun forgetLatestChangelog() { fun forgetLatestChangelog() {
viewModelScope.launch { viewModelScope.launch {
kvStorage.remove("latestChangelogRead") kvStorage.remove("latestChangelogRead")
@ -228,6 +235,9 @@ fun DebugSettingsScreen(
ElevatedButton(onClick = { viewModel.forgetEarlyAccessSpark() }) { ElevatedButton(onClick = { viewModel.forgetEarlyAccessSpark() }) {
Text("Forget early access spark") Text("Forget early access spark")
} }
ElevatedButton(onClick = { viewModel.forgetSwipeToReplySpark() }) {
Text("Forget swipe to reply spark")
}
Button(onClick = { viewModel.forgetAllSparks() }) { Button(onClick = { viewModel.forgetAllSparks() }) {
Text("Forget all sparks") Text("Forget all sparks")
} }

View File

@ -4,8 +4,9 @@ import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Button import androidx.compose.material3.Button
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
@ -28,8 +29,10 @@ fun SwipeToReplySparkSheet(
) { ) {
Column( Column(
verticalArrangement = Arrangement.spacedBy(16.dp), verticalArrangement = Arrangement.spacedBy(16.dp),
horizontalAlignment = Alignment.CenterHorizontally horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.padding(horizontal = 16.dp)
) { ) {
Spacer(Modifier.height(32.dp))
Image(SwipeToReplySpark, contentDescription = null) Image(SwipeToReplySpark, contentDescription = null)
Spacer(Modifier) // Counts towards the vertical arrangement Spacer(Modifier) // Counts towards the vertical arrangement
@ -45,22 +48,21 @@ fun SwipeToReplySparkSheet(
textAlign = TextAlign.Center textAlign = TextAlign.Center
) )
Row( Column(
horizontalArrangement = Arrangement.spacedBy(8.dp), verticalArrangement = Arrangement.spacedBy(8.dp)
verticalAlignment = Alignment.CenterVertically,
) { ) {
Button(
onClick = onDismissSheet,
modifier = Modifier.weight(1f)
) {
Text(stringResource(R.string.spark_swipe_to_reply_cta))
}
TextButton( TextButton(
onClick = onOpenOptions, onClick = onOpenOptions,
modifier = Modifier.weight(1f) modifier = Modifier.fillMaxWidth()
) { ) {
Text(stringResource(R.string.spark_swipe_to_reply_customise)) Text(stringResource(R.string.spark_swipe_to_reply_customise))
} }
Button(
onClick = onDismissSheet,
modifier = Modifier.fillMaxWidth()
) {
Text(stringResource(R.string.spark_swipe_to_reply_cta))
}
} }
} }
} }