feat(jbm): remove jbm switches on every message
Signed-off-by: Infi <infi@infi.sh>
This commit is contained in:
parent
f4085c1c93
commit
f6d9800f15
|
|
@ -42,10 +42,11 @@ import chat.revolt.RevoltApplication
|
||||||
import chat.revolt.api.HitRateLimitException
|
import chat.revolt.api.HitRateLimitException
|
||||||
import chat.revolt.api.RevoltAPI
|
import chat.revolt.api.RevoltAPI
|
||||||
import chat.revolt.api.RevoltHttp
|
import chat.revolt.api.RevoltHttp
|
||||||
|
import chat.revolt.api.api
|
||||||
import chat.revolt.api.routes.onboard.needsOnboarding
|
import chat.revolt.api.routes.onboard.needsOnboarding
|
||||||
|
import chat.revolt.api.settings.Experiments
|
||||||
import chat.revolt.api.settings.GlobalState
|
import chat.revolt.api.settings.GlobalState
|
||||||
import chat.revolt.api.settings.SyncedSettings
|
import chat.revolt.api.settings.SyncedSettings
|
||||||
import chat.revolt.api.api
|
|
||||||
import chat.revolt.ndk.NativeLibraries
|
import chat.revolt.ndk.NativeLibraries
|
||||||
import chat.revolt.persistence.KVStorage
|
import chat.revolt.persistence.KVStorage
|
||||||
import chat.revolt.screens.DefaultDestinationScreen
|
import chat.revolt.screens.DefaultDestinationScreen
|
||||||
|
|
@ -67,6 +68,7 @@ import chat.revolt.screens.settings.AppearanceSettingsScreen
|
||||||
import chat.revolt.screens.settings.ChangelogsSettingsScreen
|
import chat.revolt.screens.settings.ChangelogsSettingsScreen
|
||||||
import chat.revolt.screens.settings.ChatSettingsScreen
|
import chat.revolt.screens.settings.ChatSettingsScreen
|
||||||
import chat.revolt.screens.settings.DebugSettingsScreen
|
import chat.revolt.screens.settings.DebugSettingsScreen
|
||||||
|
import chat.revolt.screens.settings.ExperimentsSettingsScreen
|
||||||
import chat.revolt.screens.settings.ProfileSettingsScreen
|
import chat.revolt.screens.settings.ProfileSettingsScreen
|
||||||
import chat.revolt.screens.settings.SessionSettingsScreen
|
import chat.revolt.screens.settings.SessionSettingsScreen
|
||||||
import chat.revolt.screens.settings.SettingsScreen
|
import chat.revolt.screens.settings.SettingsScreen
|
||||||
|
|
@ -125,6 +127,14 @@ class MainActivityViewModel @Inject constructor(
|
||||||
isReady.emit(true)
|
isReady.emit(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun doPreStartupTasks() {
|
||||||
|
Log.d("MainActivity", "Performing pre-startup tasks")
|
||||||
|
viewModelScope.launch {
|
||||||
|
Log.d("MainActivity", "Hydrating Experiments from KV")
|
||||||
|
Experiments.hydrateWithKv()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun checkLoggedInState() {
|
fun checkLoggedInState() {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
Log.d("MainActivity", "Checking logged in state")
|
Log.d("MainActivity", "Checking logged in state")
|
||||||
|
|
@ -211,6 +221,7 @@ class MainActivityViewModel @Inject constructor(
|
||||||
|
|
||||||
init {
|
init {
|
||||||
Log.d("MainActivity", "Starting up")
|
Log.d("MainActivity", "Starting up")
|
||||||
|
doPreStartupTasks()
|
||||||
checkLoggedInState()
|
checkLoggedInState()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -400,6 +411,7 @@ fun AppEntrypoint(
|
||||||
composable("settings/appearance") { AppearanceSettingsScreen(navController) }
|
composable("settings/appearance") { AppearanceSettingsScreen(navController) }
|
||||||
composable("settings/chat") { ChatSettingsScreen(navController) }
|
composable("settings/chat") { ChatSettingsScreen(navController) }
|
||||||
composable("settings/debug") { DebugSettingsScreen(navController) }
|
composable("settings/debug") { DebugSettingsScreen(navController) }
|
||||||
|
composable("settings/experiments") { ExperimentsSettingsScreen(navController) }
|
||||||
composable("settings/changelogs") { ChangelogsSettingsScreen(navController) }
|
composable("settings/changelogs") { ChangelogsSettingsScreen(navController) }
|
||||||
|
|
||||||
composable("settings/channel/{channelId}") { backStackEntry ->
|
composable("settings/channel/{channelId}") { backStackEntry ->
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
package chat.revolt.api.settings
|
||||||
|
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import chat.revolt.RevoltApplication
|
||||||
|
import chat.revolt.persistence.KVStorage
|
||||||
|
|
||||||
|
class ExperimentInstance(default: Boolean) {
|
||||||
|
private var _isEnabled by mutableStateOf(default)
|
||||||
|
val isEnabled: Boolean
|
||||||
|
get() = GlobalState.experimentsEnabled && _isEnabled
|
||||||
|
|
||||||
|
fun setEnabled(enabled: Boolean) {
|
||||||
|
_isEnabled = enabled
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Experiments are boolean feature flags that can be toggled by the user in a self-service manner.
|
||||||
|
* Unlike regular feature flags they are created with the goal of going live in the future.
|
||||||
|
* They come with multiple safeguards:
|
||||||
|
* - Users must first enable experiments in the settings by performing a hidden action. They are then warned about potential instability.
|
||||||
|
* - Experiment states are not persisted across devices or uninstalls.
|
||||||
|
* - All experiments can be disabled at once with a single toggle.
|
||||||
|
*/
|
||||||
|
object Experiments {
|
||||||
|
val useKotlinBasedMarkdownRenderer = ExperimentInstance(false)
|
||||||
|
|
||||||
|
suspend fun hydrateWithKv() {
|
||||||
|
val kvStorage = KVStorage(RevoltApplication.instance)
|
||||||
|
|
||||||
|
GlobalState.experimentsEnabled = kvStorage.getBoolean("experimentsEnabled") ?: false
|
||||||
|
|
||||||
|
useKotlinBasedMarkdownRenderer.setEnabled(
|
||||||
|
kvStorage.getBoolean("exp/useKotlinBasedMarkdownRenderer") ?: false
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -17,6 +17,7 @@ object GlobalState {
|
||||||
var theme by mutableStateOf(getDefaultTheme())
|
var theme by mutableStateOf(getDefaultTheme())
|
||||||
var messageReplyStyle by mutableStateOf(MessageReplyStyle.SwipeFromEnd)
|
var messageReplyStyle by mutableStateOf(MessageReplyStyle.SwipeFromEnd)
|
||||||
var avatarRadius by mutableIntStateOf(50)
|
var avatarRadius by mutableIntStateOf(50)
|
||||||
|
var experimentsEnabled by mutableStateOf(false)
|
||||||
|
|
||||||
fun hydrateWithSettings(settings: SyncedSettings) {
|
fun hydrateWithSettings(settings: SyncedSettings) {
|
||||||
this.theme = settings.android.theme?.let { Theme.valueOf(it) } ?: getDefaultTheme()
|
this.theme = settings.android.theme?.let { Theme.valueOf(it) } ?: getDefaultTheme()
|
||||||
|
|
|
||||||
|
|
@ -34,17 +34,13 @@ import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.LocalContentColor
|
import androidx.compose.material3.LocalContentColor
|
||||||
import androidx.compose.material3.LocalTextStyle
|
import androidx.compose.material3.LocalTextStyle
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Switch
|
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.surfaceColorAtElevation
|
import androidx.compose.material3.surfaceColorAtElevation
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.CompositionLocalProvider
|
import androidx.compose.runtime.CompositionLocalProvider
|
||||||
import androidx.compose.runtime.getValue
|
|
||||||
import androidx.compose.runtime.key
|
import androidx.compose.runtime.key
|
||||||
import androidx.compose.runtime.mutableStateOf
|
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
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.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
|
|
@ -73,6 +69,7 @@ import chat.revolt.api.routes.channel.unreact
|
||||||
import chat.revolt.api.routes.microservices.january.asJanuaryProxyUrl
|
import chat.revolt.api.routes.microservices.january.asJanuaryProxyUrl
|
||||||
import chat.revolt.api.schemas.AutumnResource
|
import chat.revolt.api.schemas.AutumnResource
|
||||||
import chat.revolt.api.schemas.User
|
import chat.revolt.api.schemas.User
|
||||||
|
import chat.revolt.api.settings.Experiments
|
||||||
import chat.revolt.api.settings.GlobalState
|
import chat.revolt.api.settings.GlobalState
|
||||||
import chat.revolt.api.settings.MessageReplyStyle
|
import chat.revolt.api.settings.MessageReplyStyle
|
||||||
import chat.revolt.callbacks.Action
|
import chat.revolt.callbacks.Action
|
||||||
|
|
@ -199,8 +196,6 @@ fun Message(
|
||||||
|
|
||||||
val authorIsBlocked = remember(author) { author.relationship == "Blocked" }
|
val authorIsBlocked = remember(author) { author.relationship == "Blocked" }
|
||||||
|
|
||||||
var __TEMPORARY_useJbm by remember { mutableStateOf(false) }
|
|
||||||
|
|
||||||
Column(Modifier.animateContentSize()) {
|
Column(Modifier.animateContentSize()) {
|
||||||
if (message.tail == false) {
|
if (message.tail == false) {
|
||||||
Spacer(modifier = Modifier.height(10.dp))
|
Spacer(modifier = Modifier.height(10.dp))
|
||||||
|
|
@ -370,12 +365,21 @@ fun Message(
|
||||||
message.content?.let {
|
message.content?.let {
|
||||||
if (message.content.isBlank()) return@let // if only an attachment is sent
|
if (message.content.isBlank()) return@let // if only an attachment is sent
|
||||||
|
|
||||||
Switch(
|
if (Experiments.useKotlinBasedMarkdownRenderer.isEnabled) {
|
||||||
checked = __TEMPORARY_useJbm,
|
CompositionLocalProvider(
|
||||||
onCheckedChange = { __TEMPORARY_useJbm = it },
|
LocalJBMarkdownTreeState provides LocalJBMarkdownTreeState.current.copy(
|
||||||
)
|
fontSizeMultiplier = Gigamoji.useGigamojiForMessage(
|
||||||
|
message.content
|
||||||
if (__TEMPORARY_useJbm == false) {
|
)
|
||||||
|
.let {
|
||||||
|
if (it) 2f else 1f
|
||||||
|
}
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
Spacer(modifier = Modifier.height(2.dp))
|
||||||
|
JBMRenderer(message.content)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
CompositionLocalProvider(
|
CompositionLocalProvider(
|
||||||
LocalMarkdownTreeConfig provides LocalMarkdownTreeConfig.current.copy(
|
LocalMarkdownTreeConfig provides LocalMarkdownTreeConfig.current.copy(
|
||||||
currentServer = RevoltAPI.channelCache[message.channel]?.server,
|
currentServer = RevoltAPI.channelCache[message.channel]?.server,
|
||||||
|
|
@ -390,20 +394,6 @@ fun Message(
|
||||||
Spacer(modifier = Modifier.height(2.dp))
|
Spacer(modifier = Modifier.height(2.dp))
|
||||||
RichMarkdown(input = message.content)
|
RichMarkdown(input = message.content)
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
CompositionLocalProvider(
|
|
||||||
LocalJBMarkdownTreeState provides LocalJBMarkdownTreeState.current.copy(
|
|
||||||
fontSizeMultiplier = Gigamoji.useGigamojiForMessage(
|
|
||||||
message.content
|
|
||||||
)
|
|
||||||
.let {
|
|
||||||
if (it) 2f else 1f
|
|
||||||
}
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
Spacer(modifier = Modifier.height(2.dp))
|
|
||||||
JBMRenderer(message.content)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,81 @@
|
||||||
|
package chat.revolt.screens.settings
|
||||||
|
|
||||||
|
import androidx.compose.material3.ElevatedButton
|
||||||
|
import androidx.compose.material3.ListItem
|
||||||
|
import androidx.compose.material3.Switch
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
|
import androidx.navigation.NavController
|
||||||
|
import chat.revolt.api.settings.Experiments
|
||||||
|
import chat.revolt.api.settings.GlobalState
|
||||||
|
import chat.revolt.persistence.KVStorage
|
||||||
|
import chat.revolt.settings.dsl.SettingsPage
|
||||||
|
import chat.revolt.settings.dsl.SubcategoryContentInsets
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun ExperimentsSettingsScreen(navController: NavController) {
|
||||||
|
val context = LocalContext.current
|
||||||
|
val kv = remember { KVStorage(context) }
|
||||||
|
val scope = rememberCoroutineScope()
|
||||||
|
|
||||||
|
var useKotlinMdRendererChecked by remember { mutableStateOf(false) }
|
||||||
|
LaunchedEffect(Unit) {
|
||||||
|
useKotlinMdRendererChecked = kv.getBoolean("exp/useKotlinBasedMarkdownRenderer") ?: false
|
||||||
|
}
|
||||||
|
|
||||||
|
SettingsPage(
|
||||||
|
navController,
|
||||||
|
title = {
|
||||||
|
Text("Experiments", maxLines = 1, overflow = TextOverflow.Ellipsis)
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
ListItem(
|
||||||
|
headlineContent = {
|
||||||
|
Text("New Message Markdown Renderer")
|
||||||
|
},
|
||||||
|
supportingContent = {
|
||||||
|
Text("Use a Kotlin-based Markdown renderer for messages rather than the C++ one. Missing features may be present.")
|
||||||
|
},
|
||||||
|
trailingContent = {
|
||||||
|
Switch(
|
||||||
|
checked = useKotlinMdRendererChecked,
|
||||||
|
onCheckedChange = { isChecked ->
|
||||||
|
scope.launch {
|
||||||
|
kv.set("exp/useKotlinBasedMarkdownRenderer", isChecked)
|
||||||
|
Experiments.useKotlinBasedMarkdownRenderer.setEnabled(isChecked)
|
||||||
|
useKotlinMdRendererChecked = isChecked
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
Subcategory(
|
||||||
|
title = {
|
||||||
|
Text("Disable experiments")
|
||||||
|
},
|
||||||
|
contentInsets = SubcategoryContentInsets
|
||||||
|
) {
|
||||||
|
ElevatedButton(
|
||||||
|
onClick = {
|
||||||
|
scope.launch {
|
||||||
|
kv.remove("experimentsEnabled")
|
||||||
|
GlobalState.experimentsEnabled = false
|
||||||
|
navController.popBackStack()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
Text("Disable")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -261,6 +261,27 @@ fun SettingsScreen(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (GlobalState.experimentsEnabled) {
|
||||||
|
ListItem(
|
||||||
|
headlineContent = {
|
||||||
|
Text(
|
||||||
|
text = "Experiments"
|
||||||
|
)
|
||||||
|
},
|
||||||
|
leadingContent = {
|
||||||
|
Icon(
|
||||||
|
painter = painterResource(R.drawable.ic_flask_24dp),
|
||||||
|
contentDescription = null,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
modifier = Modifier
|
||||||
|
.testTag("settings_view_experiments")
|
||||||
|
.clickable {
|
||||||
|
navController.navigate("settings/experiments")
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
ListHeader {
|
ListHeader {
|
||||||
Text(
|
Text(
|
||||||
stringResource(
|
stringResource(
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
package chat.revolt.sheets
|
package chat.revolt.sheets
|
||||||
|
|
||||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
|
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||||
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
|
||||||
|
|
@ -12,22 +14,28 @@ import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.foundation.layout.width
|
import androidx.compose.foundation.layout.width
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
|
import androidx.compose.material3.AlertDialog
|
||||||
|
import androidx.compose.material3.Button
|
||||||
import androidx.compose.material3.HorizontalDivider
|
import androidx.compose.material3.HorizontalDivider
|
||||||
import androidx.compose.material3.LocalTextStyle
|
import androidx.compose.material3.LocalTextStyle
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.ScrollableTabRow
|
import androidx.compose.material3.ScrollableTabRow
|
||||||
import androidx.compose.material3.Tab
|
import androidx.compose.material3.Tab
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.material3.TextButton
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableIntStateOf
|
import androidx.compose.runtime.mutableIntStateOf
|
||||||
import androidx.compose.runtime.mutableStateListOf
|
import androidx.compose.runtime.mutableStateListOf
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
|
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.layout.ContentScale
|
import androidx.compose.ui.layout.ContentScale
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.PlatformTextStyle
|
import androidx.compose.ui.text.PlatformTextStyle
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
|
|
@ -37,15 +45,18 @@ import androidx.compose.ui.unit.sp
|
||||||
import chat.revolt.R
|
import chat.revolt.R
|
||||||
import chat.revolt.api.REVOLT_FILES
|
import chat.revolt.api.REVOLT_FILES
|
||||||
import chat.revolt.api.RevoltAPI
|
import chat.revolt.api.RevoltAPI
|
||||||
import chat.revolt.internals.text.MessageProcessor
|
|
||||||
import chat.revolt.api.internals.isUlid
|
import chat.revolt.api.internals.isUlid
|
||||||
import chat.revolt.api.routes.custom.fetchEmoji
|
import chat.revolt.api.routes.custom.fetchEmoji
|
||||||
import chat.revolt.api.routes.user.fetchUser
|
import chat.revolt.api.routes.user.fetchUser
|
||||||
import chat.revolt.api.schemas.Emoji
|
import chat.revolt.api.schemas.Emoji
|
||||||
import chat.revolt.api.schemas.User
|
import chat.revolt.api.schemas.User
|
||||||
|
import chat.revolt.api.settings.GlobalState
|
||||||
import chat.revolt.components.chat.MemberListItem
|
import chat.revolt.components.chat.MemberListItem
|
||||||
import chat.revolt.components.generic.RemoteImage
|
import chat.revolt.components.generic.RemoteImage
|
||||||
import chat.revolt.components.generic.SheetEnd
|
import chat.revolt.components.generic.SheetEnd
|
||||||
|
import chat.revolt.internals.text.MessageProcessor
|
||||||
|
import chat.revolt.persistence.KVStorage
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
@OptIn(ExperimentalFoundationApi::class)
|
@OptIn(ExperimentalFoundationApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
|
|
@ -55,6 +66,9 @@ fun ReactionInfoSheet(messageId: String, emoji: String, onDismiss: () -> Unit) {
|
||||||
val reactions = message.reactions
|
val reactions = message.reactions
|
||||||
val reactionEmoji = reactions?.keys?.toList()
|
val reactionEmoji = reactions?.keys?.toList()
|
||||||
|
|
||||||
|
val context = LocalContext.current
|
||||||
|
val scope = rememberCoroutineScope()
|
||||||
|
|
||||||
val extendedEmojiInfo = remember(emoji) { mutableStateListOf<Emoji>() }
|
val extendedEmojiInfo = remember(emoji) { mutableStateListOf<Emoji>() }
|
||||||
|
|
||||||
LaunchedEffect(reactionEmoji) {
|
LaunchedEffect(reactionEmoji) {
|
||||||
|
|
@ -120,6 +134,71 @@ fun ReactionInfoSheet(messageId: String, emoji: String, onDismiss: () -> Unit) {
|
||||||
item("info") {
|
item("info") {
|
||||||
val current = reactionEmoji[selectedReactionIndex]
|
val current = reactionEmoji[selectedReactionIndex]
|
||||||
|
|
||||||
|
// Code related to enabling of experimental features
|
||||||
|
val interactionSource = remember { MutableInteractionSource() }
|
||||||
|
val canBeUsedForTapCountIncrement =
|
||||||
|
remember(selectedReactionIndex) {
|
||||||
|
MessageProcessor.emoji.unicodeAsShortcode(
|
||||||
|
current
|
||||||
|
) == ":trolleybus:"
|
||||||
|
}
|
||||||
|
var tapCount by remember { mutableIntStateOf(0) }
|
||||||
|
var showEnabledConfirmAlert by remember { mutableStateOf(false) }
|
||||||
|
var showEnabledAlreadyAlert by remember { mutableStateOf(false) }
|
||||||
|
val incrementTapCount = remember {
|
||||||
|
{
|
||||||
|
if (canBeUsedForTapCountIncrement) {
|
||||||
|
tapCount++
|
||||||
|
if (tapCount > 9) {
|
||||||
|
tapCount = 0
|
||||||
|
if (GlobalState.experimentsEnabled) {
|
||||||
|
showEnabledAlreadyAlert = true
|
||||||
|
} else {
|
||||||
|
showEnabledConfirmAlert = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (showEnabledAlreadyAlert) {
|
||||||
|
AlertDialog(
|
||||||
|
onDismissRequest = {},
|
||||||
|
title = { Text("Traveller, you may not unsee your knowledge...") },
|
||||||
|
text = { Text("Experimental features are already unlocked.") },
|
||||||
|
confirmButton = {
|
||||||
|
TextButton(onClick = { showEnabledAlreadyAlert = false }) {
|
||||||
|
Text("OK")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (showEnabledConfirmAlert) {
|
||||||
|
AlertDialog(
|
||||||
|
onDismissRequest = {},
|
||||||
|
title = { Text("You hear a faint whisper in the wind...") },
|
||||||
|
text = { Text("Would you like to enable experimental features? They may be unstable.") },
|
||||||
|
confirmButton = {
|
||||||
|
TextButton(onClick = {
|
||||||
|
showEnabledConfirmAlert = false
|
||||||
|
GlobalState.experimentsEnabled = true
|
||||||
|
scope.launch {
|
||||||
|
KVStorage(context).set("experimentsEnabled", true)
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
Text("I dare to try!")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
dismissButton = {
|
||||||
|
Button(onClick = { showEnabledConfirmAlert = false }) {
|
||||||
|
Text("I shall not risk it.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
// End of code related to enabling of experimental features
|
||||||
|
|
||||||
Column(
|
Column(
|
||||||
verticalArrangement = Arrangement.spacedBy(16.dp),
|
verticalArrangement = Arrangement.spacedBy(16.dp),
|
||||||
modifier = Modifier.padding(
|
modifier = Modifier.padding(
|
||||||
|
|
@ -158,6 +237,12 @@ fun ReactionInfoSheet(messageId: String, emoji: String, onDismiss: () -> Unit) {
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
|
.clickable(
|
||||||
|
interactionSource = interactionSource,
|
||||||
|
indication = null,
|
||||||
|
) {
|
||||||
|
incrementTapCount()
|
||||||
|
}
|
||||||
.size(64.dp)
|
.size(64.dp)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:height="24dp"
|
||||||
|
android:width="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="#ffffff"
|
||||||
|
android:pathData="M6,22A3,3 0 0,1 3,19C3,18.4 3.18,17.84 3.5,17.37L9,7.81V6A1,1 0 0,1 8,5V4A2,2 0 0,1 10,2H14A2,2 0 0,1 16,4V5A1,1 0 0,1 15,6V7.81L20.5,17.37C20.82,17.84 21,18.4 21,19A3,3 0 0,1 18,22H6M5,19A1,1 0 0,0 6,20H18A1,1 0 0,0 19,19C19,18.79 18.93,18.59 18.82,18.43L16.53,14.47L14,17L8.93,11.93L5.18,18.43C5.07,18.59 5,18.79 5,19M13,10A1,1 0 0,0 12,11A1,1 0 0,0 13,12A1,1 0 0,0 14,11A1,1 0 0,0 13,10Z" />
|
||||||
|
</vector>
|
||||||
Loading…
Reference in New Issue