feat: sparks & settings button location spark
Signed-off-by: Infi <wingit@geist.ga>
This commit is contained in:
parent
a35f550172
commit
02d6fa0dbf
|
|
@ -156,6 +156,9 @@ dependencies {
|
|||
// AboutLibraries - automated OSS library attribution
|
||||
implementation "com.mikepenz:aboutlibraries-compose:$aboutlibraries_version"
|
||||
|
||||
// Lottie - animated vector graphics
|
||||
implementation "com.airbnb.android:lottie-compose:6.0.0"
|
||||
|
||||
// Sentry - crash reporting
|
||||
implementation 'io.sentry:sentry-android:6.15.0'
|
||||
implementation 'io.sentry:sentry-compose-android:6.15.0'
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ import chat.revolt.screens.login.GreeterScreen
|
|||
import chat.revolt.screens.login.LoginScreen
|
||||
import chat.revolt.screens.login.MfaScreen
|
||||
import chat.revolt.screens.settings.AppearanceSettingsScreen
|
||||
import chat.revolt.screens.settings.DebugSettingsScreen
|
||||
import chat.revolt.screens.settings.SettingsScreen
|
||||
import chat.revolt.ui.theme.RevoltTheme
|
||||
import com.google.accompanist.navigation.animation.AnimatedNavHost
|
||||
|
|
@ -111,6 +112,7 @@ fun AppEntrypoint() {
|
|||
|
||||
composable("settings") { SettingsScreen(navController) }
|
||||
composable("settings/appearance") { AppearanceSettingsScreen(navController) }
|
||||
composable("settings/debug") { DebugSettingsScreen(navController) }
|
||||
dialog("settings/feedback") { FeedbackDialog(navController) }
|
||||
|
||||
composable("about") { AboutScreen(navController) }
|
||||
|
|
|
|||
|
|
@ -29,6 +29,16 @@ class KVStorage @Inject constructor(
|
|||
return dataStore.data.firstOrNull()?.get(stringPreferencesKey(key))
|
||||
}
|
||||
|
||||
suspend fun set(key: String, value: Boolean) {
|
||||
dataStore.edit { preferences ->
|
||||
preferences[stringPreferencesKey(key)] = value.toString()
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun getBoolean(key: String): Boolean? {
|
||||
return dataStore.data.firstOrNull()?.get(stringPreferencesKey(key))?.toBoolean()
|
||||
}
|
||||
|
||||
suspend fun remove(key: String) {
|
||||
dataStore.edit { preferences ->
|
||||
preferences.remove(stringPreferencesKey(key))
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import androidx.compose.foundation.background
|
|||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.aspectRatio
|
||||
import androidx.compose.foundation.layout.fillMaxHeight
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
|
|
@ -16,13 +17,17 @@ import androidx.compose.foundation.shape.RoundedCornerShape
|
|||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Add
|
||||
import androidx.compose.material3.AlertDialog
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.material3.surfaceColorAtElevation
|
||||
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.snapshotFlow
|
||||
import androidx.compose.ui.Alignment
|
||||
|
|
@ -64,6 +69,11 @@ import chat.revolt.screens.chat.sheets.StatusSheet
|
|||
import chat.revolt.screens.chat.views.HomeScreen
|
||||
import chat.revolt.screens.chat.views.NoCurrentChannelScreen
|
||||
import chat.revolt.screens.chat.views.channel.ChannelScreen
|
||||
import com.airbnb.lottie.RenderMode
|
||||
import com.airbnb.lottie.compose.LottieAnimation
|
||||
import com.airbnb.lottie.compose.LottieCompositionSpec
|
||||
import com.airbnb.lottie.compose.animateLottieCompositionAsState
|
||||
import com.airbnb.lottie.compose.rememberLottieComposition
|
||||
import com.google.accompanist.navigation.material.ExperimentalMaterialNavigationApi
|
||||
import com.google.accompanist.navigation.material.ModalBottomSheetLayout
|
||||
import com.google.accompanist.navigation.material.bottomSheet
|
||||
|
|
@ -85,10 +95,19 @@ class ChatRouterViewModel @Inject constructor(
|
|||
val currentChannel: String?
|
||||
get() = _currentChannel.value
|
||||
|
||||
private var _sidebarSparkDisplayed = mutableStateOf(true)
|
||||
val sidebarSparkDisplayed: Boolean
|
||||
get() = _sidebarSparkDisplayed.value
|
||||
|
||||
init {
|
||||
viewModelScope.launch {
|
||||
_currentServer.value = kvStorage.get("currentServer") ?: "home"
|
||||
_currentChannel.value = kvStorage.get("currentChannel")
|
||||
_sidebarSparkDisplayed.value = if (kvStorage.getBoolean("sidebarSpark") == null) {
|
||||
false
|
||||
} else {
|
||||
kvStorage.getBoolean("sidebarSpark")!!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -108,6 +127,10 @@ class ChatRouterViewModel @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
suspend fun setSettingsHintDisplayed() {
|
||||
kvStorage.set("sidebarSpark", true)
|
||||
}
|
||||
|
||||
fun navigateToServer(serverId: String, navController: NavController) {
|
||||
if (serverId == "home") {
|
||||
navController.navigate("home") {
|
||||
|
|
@ -155,6 +178,12 @@ fun ChatRouterScreen(topNav: NavController, viewModel: ChatRouterViewModel = hil
|
|||
val bottomSheetNavigator = rememberBottomSheetNavigator()
|
||||
val navController = rememberNavController(bottomSheetNavigator)
|
||||
|
||||
val showSidebarSpark = remember { mutableStateOf(false) }
|
||||
val sidebarSparkComposition by rememberLottieComposition(LottieCompositionSpec.RawRes(R.raw.open_settings_tutorial))
|
||||
val sidebarSparkProgress by animateLottieCompositionAsState(
|
||||
composition = sidebarSparkComposition,
|
||||
)
|
||||
|
||||
LaunchedEffect(drawerState) {
|
||||
snapshotFlow { drawerState.currentValue }
|
||||
.distinctUntilChanged()
|
||||
|
|
@ -175,11 +204,52 @@ fun ChatRouterScreen(topNav: NavController, viewModel: ChatRouterViewModel = hil
|
|||
}
|
||||
}
|
||||
|
||||
LaunchedEffect(viewModel.sidebarSparkDisplayed) {
|
||||
snapshotFlow { viewModel.sidebarSparkDisplayed }
|
||||
.distinctUntilChanged()
|
||||
.collect { displayed ->
|
||||
showSidebarSpark.value = !displayed
|
||||
}
|
||||
}
|
||||
|
||||
ModalBottomSheetLayout(
|
||||
sheetShape = RoundedCornerShape(topStart = 16.dp, topEnd = 16.dp),
|
||||
sheetBackgroundColor = MaterialTheme.colorScheme.surface,
|
||||
bottomSheetNavigator = bottomSheetNavigator,
|
||||
) {
|
||||
if (showSidebarSpark.value) {
|
||||
AlertDialog(
|
||||
onDismissRequest = {},
|
||||
title = {
|
||||
Text(stringResource(id = R.string.spark_sidebar_settings_tutorial))
|
||||
},
|
||||
text = {
|
||||
Column {
|
||||
LottieAnimation(
|
||||
composition = sidebarSparkComposition,
|
||||
progress = { sidebarSparkProgress },
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.aspectRatio(1f),
|
||||
renderMode = RenderMode.HARDWARE
|
||||
)
|
||||
Text(stringResource(id = R.string.spark_sidebar_settings_tutorial_description_1))
|
||||
Text(stringResource(id = R.string.spark_sidebar_settings_tutorial_description_2))
|
||||
}
|
||||
},
|
||||
confirmButton = {
|
||||
TextButton(onClick = {
|
||||
scope.launch {
|
||||
viewModel.setSettingsHintDisplayed()
|
||||
}
|
||||
showSidebarSpark.value = false
|
||||
}) {
|
||||
Text(stringResource(id = R.string.spark_sidebar_settings_tutorial_acknowledge))
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
Column {
|
||||
AnimatedVisibility(visible = RealtimeSocket.disconnectionState != DisconnectionState.Connected) {
|
||||
DisconnectedNotice(
|
||||
|
|
@ -255,7 +325,10 @@ fun ChatRouterScreen(topNav: NavController, viewModel: ChatRouterViewModel = hil
|
|||
}
|
||||
}
|
||||
|
||||
Crossfade(targetState = viewModel.currentServer) {
|
||||
Crossfade(
|
||||
targetState = viewModel.currentServer,
|
||||
label = "Channel List"
|
||||
) {
|
||||
ChannelList(
|
||||
serverId = it,
|
||||
drawerState = drawerState,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,82 @@
|
|||
package chat.revolt.screens.settings
|
||||
|
||||
import androidx.compose.foundation.horizontalScroll
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material3.ElevatedButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import androidx.navigation.NavController
|
||||
import chat.revolt.components.generic.PageHeader
|
||||
import chat.revolt.persistence.KVStorage
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltViewModel
|
||||
class DebugSettingsScreenViewModel @Inject constructor(
|
||||
private val kvStorage: KVStorage,
|
||||
) : ViewModel() {
|
||||
fun forgetSidebarSparkShown() {
|
||||
viewModelScope.launch {
|
||||
kvStorage.remove("sidebarSpark")
|
||||
}
|
||||
}
|
||||
|
||||
fun forgetAllSparks() {
|
||||
this.forgetSidebarSparkShown()
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun DebugSettingsScreen(
|
||||
navController: NavController,
|
||||
viewModel: DebugSettingsScreenViewModel = hiltViewModel()
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
) {
|
||||
PageHeader(
|
||||
text = "Debug",
|
||||
showBackButton = true,
|
||||
onBackButtonClicked = {
|
||||
navController.popBackStack()
|
||||
})
|
||||
|
||||
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.verticalScroll(rememberScrollState())
|
||||
.padding(20.dp)
|
||||
) {
|
||||
Text(
|
||||
text = "Sparks",
|
||||
style = MaterialTheme.typography.headlineSmall,
|
||||
modifier = Modifier.padding(bottom = 10.dp)
|
||||
)
|
||||
Row(
|
||||
modifier = Modifier.horizontalScroll(rememberScrollState())
|
||||
) {
|
||||
TextButton(onClick = { viewModel.forgetSidebarSparkShown() }) {
|
||||
Text("Forget sidebar spark")
|
||||
}
|
||||
ElevatedButton(onClick = { viewModel.forgetAllSparks() }) {
|
||||
Text("Forget all sparks")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -8,6 +8,7 @@ import androidx.compose.material.icons.Icons
|
|||
import androidx.compose.material.icons.filled.Build
|
||||
import androidx.compose.material.icons.filled.Close
|
||||
import androidx.compose.material.icons.filled.Info
|
||||
import androidx.compose.material.icons.filled.Settings
|
||||
import androidx.compose.material3.Divider
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.Text
|
||||
|
|
@ -18,6 +19,7 @@ import androidx.compose.ui.res.painterResource
|
|||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.navigation.NavController
|
||||
import chat.revolt.BuildConfig
|
||||
import chat.revolt.R
|
||||
import chat.revolt.components.generic.PageHeader
|
||||
import chat.revolt.components.generic.SheetClickable
|
||||
|
|
@ -78,6 +80,24 @@ fun SettingsScreen(
|
|||
navController.navigate("about")
|
||||
}
|
||||
|
||||
if (BuildConfig.DEBUG) {
|
||||
SheetClickable(
|
||||
icon = { modifier ->
|
||||
Icon(
|
||||
imageVector = Icons.Default.Settings,
|
||||
contentDescription = "Debug",
|
||||
modifier = modifier
|
||||
)
|
||||
},
|
||||
label = { textStyle ->
|
||||
Text(text = "Debug", style = textStyle)
|
||||
},
|
||||
modifier = Modifier.testTag("settings_view_debug")
|
||||
) {
|
||||
navController.navigate("settings/debug")
|
||||
}
|
||||
}
|
||||
|
||||
Divider()
|
||||
|
||||
SheetClickable(
|
||||
|
|
@ -109,7 +129,8 @@ fun SettingsScreen(
|
|||
},
|
||||
modifier = Modifier.testTag("settings_view_logout")
|
||||
) {
|
||||
Toast.makeText(navController.context, "Not implemented yet", Toast.LENGTH_SHORT).show()
|
||||
Toast.makeText(navController.context, "Not implemented yet", Toast.LENGTH_SHORT)
|
||||
.show()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -244,6 +244,11 @@
|
|||
<string name="media_viewer_share_video">Share video</string>
|
||||
<string name="media_viewer_share_image">Share image</string>
|
||||
|
||||
<string name="spark_sidebar_settings_tutorial">The settings are in the sidebar</string>
|
||||
<string name="spark_sidebar_settings_tutorial_description_1">You can open the sidebar by swiping from the left edge of the screen.</string>
|
||||
<string name="spark_sidebar_settings_tutorial_description_2">Then long tap your profile picture to open the settings.</string>
|
||||
<string name="spark_sidebar_settings_tutorial_acknowledge">Got it</string>
|
||||
|
||||
<string name="settings_appearance">Appearance</string>
|
||||
<string name="settings_appearance_theme">Theme</string>
|
||||
<string name="settings_appearance_theme_none">System</string>
|
||||
|
|
|
|||
Loading…
Reference in New Issue