feat: add chat settings and quick reply options
(for future use) Signed-off-by: Infi <infi@infi.sh>
This commit is contained in:
parent
72e16cf591
commit
5875f3ded7
|
|
@ -63,6 +63,7 @@ import chat.revolt.screens.register.RegisterVerifyScreen
|
|||
import chat.revolt.screens.services.DiscoverScreen
|
||||
import chat.revolt.screens.settings.AppearanceSettingsScreen
|
||||
import chat.revolt.screens.settings.ChangelogsSettingsScreen
|
||||
import chat.revolt.screens.settings.ChatSettingsScreen
|
||||
import chat.revolt.screens.settings.DebugSettingsScreen
|
||||
import chat.revolt.screens.settings.ProfileSettingsScreen
|
||||
import chat.revolt.screens.settings.SessionSettingsScreen
|
||||
|
|
@ -377,6 +378,7 @@ fun AppEntrypoint(
|
|||
composable("settings/profile") { ProfileSettingsScreen(navController) }
|
||||
composable("settings/sessions") { SessionSettingsScreen(navController) }
|
||||
composable("settings/appearance") { AppearanceSettingsScreen(navController) }
|
||||
composable("settings/chat") { ChatSettingsScreen(navController) }
|
||||
composable("settings/debug") { DebugSettingsScreen(navController) }
|
||||
composable("settings/changelogs") { ChangelogsSettingsScreen(navController) }
|
||||
|
||||
|
|
|
|||
|
|
@ -20,4 +20,9 @@ data class AndroidSpecificSettings(
|
|||
* Map of `primary, onPrimary, primaryContainer, onPrimaryContainer, inversePrimary, secondary, onSecondary, secondaryContainer, onSecondaryContainer, tertiary, onTertiary, tertiaryContainer, onTertiaryContainer, background, onBackground, surface, onSurface, surfaceVariant, onSurfaceVariant, surfaceTint, inverseSurface, inverseOnSurface, error, onError, errorContainer, onErrorContainer, outline, outlineVariant, scrim` to int colours.
|
||||
*/
|
||||
var colourOverrides: OverridableColourScheme? = null,
|
||||
/**
|
||||
* Message reply style.
|
||||
* Can be one of `{ None, SwipeFromEnd, DoubleTap }`
|
||||
*/
|
||||
var messageReplyStyle: String? = null,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -6,14 +6,25 @@ import androidx.compose.runtime.setValue
|
|||
import chat.revolt.ui.theme.Theme
|
||||
import chat.revolt.ui.theme.getDefaultTheme
|
||||
|
||||
enum class MessageReplyStyle {
|
||||
None,
|
||||
SwipeFromEnd,
|
||||
DoubleTap
|
||||
}
|
||||
|
||||
object GlobalState {
|
||||
var theme by mutableStateOf(getDefaultTheme())
|
||||
var messageReplyStyle by mutableStateOf(MessageReplyStyle.SwipeFromEnd)
|
||||
|
||||
fun hydrateWithSettings(settings: SyncedSettings) {
|
||||
settings.android.theme?.let { this.theme = Theme.valueOf(it) }
|
||||
this.theme = settings.android.theme?.let { Theme.valueOf(it) } ?: getDefaultTheme()
|
||||
this.messageReplyStyle =
|
||||
settings.android.messageReplyStyle?.let { MessageReplyStyle.valueOf(it) }
|
||||
?: MessageReplyStyle.SwipeFromEnd
|
||||
}
|
||||
|
||||
fun reset() {
|
||||
theme = getDefaultTheme()
|
||||
messageReplyStyle = MessageReplyStyle.SwipeFromEnd
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,13 @@ import chat.revolt.api.schemas.OrderingSettings
|
|||
|
||||
object SyncedSettings {
|
||||
private val _ordering = mutableStateOf(OrderingSettings())
|
||||
private val _android = mutableStateOf(AndroidSpecificSettings("None"))
|
||||
private val _android = mutableStateOf(
|
||||
AndroidSpecificSettings(
|
||||
theme = "None",
|
||||
colourOverrides = null,
|
||||
messageReplyStyle = "None"
|
||||
)
|
||||
)
|
||||
|
||||
val ordering: OrderingSettings
|
||||
get() = _ordering.value
|
||||
|
|
|
|||
|
|
@ -0,0 +1,48 @@
|
|||
package chat.revolt.components.generic
|
||||
|
||||
import androidx.compose.foundation.layout.Row
|
||||
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.width
|
||||
import androidx.compose.foundation.selection.selectable
|
||||
import androidx.compose.material3.LocalTextStyle
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.RadioButton
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.semantics.Role
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
@Composable
|
||||
fun RadioItem(
|
||||
selected: Boolean,
|
||||
onClick: () -> Unit,
|
||||
label: @Composable () -> Unit,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
Row(
|
||||
modifier
|
||||
.fillMaxWidth()
|
||||
.height(56.dp)
|
||||
.selectable(
|
||||
selected = selected,
|
||||
onClick = onClick,
|
||||
role = Role.RadioButton
|
||||
)
|
||||
.padding(horizontal = 16.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
RadioButton(
|
||||
selected = selected,
|
||||
onClick = null
|
||||
)
|
||||
Spacer(Modifier.width(16.dp))
|
||||
CompositionLocalProvider(LocalTextStyle provides MaterialTheme.typography.bodyLarge) {
|
||||
label()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,105 @@
|
|||
package chat.revolt.screens.settings
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.imePadding
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.selection.selectableGroup
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.ArrowBack
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.LargeTopAppBar
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TopAppBarDefaults
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import androidx.navigation.NavController
|
||||
import chat.revolt.R
|
||||
import chat.revolt.api.settings.GlobalState
|
||||
import chat.revolt.api.settings.MessageReplyStyle
|
||||
import chat.revolt.api.settings.SyncedSettings
|
||||
import chat.revolt.components.generic.ListHeader
|
||||
import chat.revolt.components.generic.RadioItem
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class ChatSettingsScreenViewModel : ViewModel() {
|
||||
fun updateMessageReplyStyle(next: MessageReplyStyle) {
|
||||
viewModelScope.launch {
|
||||
SyncedSettings.updateAndroid(SyncedSettings.android.copy(messageReplyStyle = next.name))
|
||||
GlobalState.messageReplyStyle = next
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun ChatSettingsScreen(
|
||||
navController: NavController,
|
||||
viewModel: ChatSettingsScreenViewModel = viewModel()
|
||||
) {
|
||||
val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior()
|
||||
|
||||
Scaffold(
|
||||
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
|
||||
topBar = {
|
||||
LargeTopAppBar(
|
||||
scrollBehavior = scrollBehavior,
|
||||
title = {
|
||||
Text(
|
||||
text = stringResource(R.string.settings_chat),
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
},
|
||||
navigationIcon = {
|
||||
IconButton(onClick = {
|
||||
navController.popBackStack()
|
||||
}) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.ArrowBack,
|
||||
contentDescription = stringResource(id = R.string.back)
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
},
|
||||
) { pv ->
|
||||
Column(
|
||||
Modifier
|
||||
.padding(pv)
|
||||
.imePadding()
|
||||
) {
|
||||
ListHeader {
|
||||
Text(
|
||||
text = stringResource(R.string.settings_chat_quick_reply)
|
||||
)
|
||||
}
|
||||
|
||||
Column(Modifier.selectableGroup()) {
|
||||
RadioItem(
|
||||
selected = GlobalState.messageReplyStyle == MessageReplyStyle.None,
|
||||
onClick = { viewModel.updateMessageReplyStyle(MessageReplyStyle.None) },
|
||||
label = { Text(text = stringResource(R.string.settings_chat_quick_reply_none)) }
|
||||
)
|
||||
RadioItem(
|
||||
selected = GlobalState.messageReplyStyle == MessageReplyStyle.SwipeFromEnd,
|
||||
onClick = { viewModel.updateMessageReplyStyle(MessageReplyStyle.SwipeFromEnd) },
|
||||
label = { Text(text = stringResource(R.string.settings_chat_quick_reply_swipe_from_end)) }
|
||||
)
|
||||
RadioItem(
|
||||
selected = GlobalState.messageReplyStyle == MessageReplyStyle.DoubleTap,
|
||||
onClick = { viewModel.updateMessageReplyStyle(MessageReplyStyle.DoubleTap) },
|
||||
label = { Text(text = stringResource(R.string.settings_chat_quick_reply_double_tap)) }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -178,6 +178,25 @@ fun SettingsScreen(
|
|||
}
|
||||
)
|
||||
|
||||
ListItem(
|
||||
headlineContent = {
|
||||
Text(
|
||||
text = stringResource(id = R.string.settings_chat)
|
||||
)
|
||||
},
|
||||
leadingContent = {
|
||||
Icon(
|
||||
painter = painterResource(R.drawable.ic_message_text_24dp),
|
||||
contentDescription = null,
|
||||
)
|
||||
},
|
||||
modifier = Modifier
|
||||
.testTag("settings_view_chat")
|
||||
.clickable {
|
||||
navController.navigate("settings/chat")
|
||||
}
|
||||
)
|
||||
|
||||
ListHeader {
|
||||
Text(stringResource(R.string.settings_category_miscellaneous))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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="M20,2H4A2,2 0 0,0 2,4V22L6,18H20A2,2 0 0,0 22,16V4A2,2 0 0,0 20,2M6,9H18V11H6M14,14H6V12H14M18,8H6V6H18" />
|
||||
</vector>
|
||||
|
|
@ -536,6 +536,12 @@
|
|||
<string name="settings_appearance_colour_overrides_import">Import</string>
|
||||
<string name="settings_appearance_colour_overrides_import_error">This file is not a valid colour override file.</string>
|
||||
|
||||
<string name="settings_chat">Chat</string>
|
||||
<string name="settings_chat_quick_reply">Quick Reply</string>
|
||||
<string name="settings_chat_quick_reply_none">Long press to reply</string>
|
||||
<string name="settings_chat_quick_reply_swipe_from_end">Swipe to reply</string>
|
||||
<string name="settings_chat_quick_reply_double_tap">Double tap to reply</string>
|
||||
|
||||
<string name="settings_feedback">Feedback</string>
|
||||
<string name="settings_feedback_description">Join the Revolt server to give feedback or suggestions and report bugs.</string>
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue