feat: bottom navigation when drawer is open, placeholder settings screen

This commit is contained in:
Infi 2023-01-11 01:24:44 +01:00
parent 89d372d65c
commit 2e6e20939f
7 changed files with 135 additions and 21 deletions

View File

@ -12,6 +12,7 @@ import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.IntSize
import chat.revolt.screens.SplashScreen
import chat.revolt.screens.about.AboutScreen
import chat.revolt.screens.about.AttributionScreen
@ -20,6 +21,7 @@ import chat.revolt.screens.chat.ChatRouterScreen
import chat.revolt.screens.login.GreeterScreen
import chat.revolt.screens.login.LoginScreen
import chat.revolt.screens.login.MfaScreen
import chat.revolt.screens.settings.SettingsScreen
import chat.revolt.ui.theme.RevoltTheme
import com.google.accompanist.navigation.animation.AnimatedNavHost
import com.google.accompanist.navigation.animation.composable
@ -44,6 +46,7 @@ class MainActivity : ComponentActivity() {
}
val RevoltTweenInt: FiniteAnimationSpec<IntOffset> = tween(400, easing = EaseInOutExpo)
val RevoltTweenIntSize: FiniteAnimationSpec<IntSize> = tween(400, easing = EaseInOutExpo)
val RevoltTweenFloat: FiniteAnimationSpec<Float> = tween(400, easing = EaseInOutExpo)
@OptIn(ExperimentalAnimationApi::class)
@ -93,6 +96,8 @@ fun AppEntrypoint() {
composable("chat") { ChatRouterScreen(navController) }
composable("settings") { SettingsScreen(navController) }
composable("about") { AboutScreen(navController) }
composable("about/oss") { AttributionScreen(navController) }
composable("about/placeholder") { PlaceholderScreen(navController) }

View File

@ -3,6 +3,7 @@ package chat.revolt.api.realtime
import android.util.Log
import androidx.compose.runtime.mutableStateMapOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.snapshots.SnapshotStateMap
import chat.revolt.api.REVOLT_WEBSOCKET
import chat.revolt.api.RevoltAPI
import chat.revolt.api.RevoltHttp
@ -118,9 +119,7 @@ object RealtimeSocket {
RevoltAPI.messageCache[messageFrame.id!!] = messageFrame
channelCallbacks[messageFrame.channel]?.forEach { callback ->
callback.onMessage(messageFrame)
}
channelCallbacks[messageFrame.channel]?.onMessage(messageFrame)
}
"ChannelStartTyping" -> {
val typingFrame =
@ -130,9 +129,7 @@ object RealtimeSocket {
"Received channel start typing frame for ${typingFrame.id} from ${typingFrame.user}."
)
channelCallbacks[typingFrame.id]?.forEach { callback ->
callback.onStartTyping(typingFrame)
}
channelCallbacks[typingFrame.id]?.onStartTyping(typingFrame)
}
"ChannelStopTyping" -> {
val typingFrame =
@ -142,9 +139,7 @@ object RealtimeSocket {
"Received channel stop typing frame for ${typingFrame.id} from ${typingFrame.user}."
)
channelCallbacks[typingFrame.id]?.forEach { callback ->
callback.onStopTyping(typingFrame)
}
channelCallbacks[typingFrame.id]?.onStopTyping(typingFrame)
}
"UserUpdate" -> {
val userUpdateFrame =
@ -178,18 +173,16 @@ object RealtimeSocket {
fun onMessage(message: MessageFrame)
}
private val channelCallbacks: MutableMap<String, List<ChannelCallback>> = mutableStateMapOf()
private val channelCallbacks: SnapshotStateMap<String, ChannelCallback> = mutableStateMapOf()
fun registerChannelCallback(channelId: String, callback: ChannelCallback) {
val callbacks = channelCallbacks[channelId] ?: emptyList()
channelCallbacks[channelId] = callbacks + callback
channelCallbacks[channelId] = callback
Log.d("RealtimeSocket", "Registered channel callback for $channelId.")
}
fun unregisterChannelCallback(channelId: String, callback: ChannelCallback) {
val callbacks = channelCallbacks[channelId] ?: emptyList()
channelCallbacks[channelId] = callbacks - callback
channelCallbacks.remove(channelId, callback)
Log.d("RealtimeSocket", "Unregistered channel callback for $channelId")
}

View File

@ -0,0 +1,68 @@
package chat.revolt.components.screens.chat
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.expandVertically
import androidx.compose.animation.shrinkVertically
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Home
import androidx.compose.material.icons.filled.Settings
import androidx.compose.material3.BottomAppBar
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.navigation.NavController
import chat.revolt.R
import chat.revolt.RevoltTweenIntSize
import kotlinx.coroutines.launch
@Composable
fun BottomNavigation(
navController: NavController,
show: Boolean,
) {
val scope = rememberCoroutineScope()
AnimatedVisibility(
visible = show,
enter = expandVertically(
animationSpec = RevoltTweenIntSize
),
exit = shrinkVertically(
animationSpec = RevoltTweenIntSize
),
) {
BottomAppBar {
IconButton(
modifier = Modifier.weight(1f),
onClick = {
scope.launch {
if (navController.currentDestination?.route != "chat") {
navController.navigate("chat")
}
}
}) {
Icon(
imageVector = Icons.Default.Home,
contentDescription = stringResource(id = R.string.home),
)
}
IconButton(
modifier = Modifier.weight(1f),
onClick = {
scope.launch {
if (navController.currentDestination?.route != "settings") {
navController.navigate("settings")
}
}
}) {
Icon(
imageVector = Icons.Default.Settings,
contentDescription = stringResource(id = R.string.settings),
)
}
}
}
}

View File

@ -1,7 +1,6 @@
package chat.revolt.screens.chat
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.Crossfade
import androidx.compose.animation.*
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
@ -37,6 +36,7 @@ import chat.revolt.api.realtime.RealtimeSocket
import chat.revolt.api.schemas.ChannelType
import chat.revolt.components.chat.DisconnectedNotice
import chat.revolt.components.generic.RemoteImage
import chat.revolt.components.screens.chat.BottomNavigation
import chat.revolt.components.screens.chat.DrawerChannel
import chat.revolt.screens.chat.views.ChannelScreen
import chat.revolt.screens.chat.views.HomeScreen
@ -80,7 +80,7 @@ fun ChatRouterScreen(topNav: NavController, viewModel: ChatRouterViewModel = vie
val navController = rememberNavController()
val navBackStackEntry by navController.currentBackStackEntryAsState()
Column() {
Column {
AnimatedVisibility(visible = RealtimeSocket.disconnectionState != DisconnectionState.Connected) {
DisconnectedNotice(
state = RealtimeSocket.disconnectionState,
@ -174,7 +174,8 @@ fun ChatRouterScreen(topNav: NavController, viewModel: ChatRouterViewModel = vie
RevoltAPI.channelCache.values.filter { it.channelType == ChannelType.Group }
.forEach { channel ->
DrawerChannel(
name = channel.name ?: "GDM #${channel.id}",
name = channel.name
?: "GDM #${channel.id}",
channelType = ChannelType.Group,
selected = channel.id == (navBackStackEntry?.arguments?.getString(
"channelId"
@ -192,7 +193,8 @@ fun ChatRouterScreen(topNav: NavController, viewModel: ChatRouterViewModel = vie
val server = RevoltAPI.serverCache[it]
Text(
text = server?.name ?: stringResource(R.string.unknown),
text = server?.name
?: stringResource(R.string.unknown),
fontWeight = FontWeight.Black,
fontSize = 24.sp,
modifier = Modifier.padding(16.dp)
@ -245,5 +247,10 @@ fun ChatRouterScreen(topNav: NavController, viewModel: ChatRouterViewModel = vie
}
}
}
BottomNavigation(
navController = topNav,
show = channelDrawerState.currentValue == DrawerValue.Open,
)
}
}

View File

@ -78,10 +78,10 @@ fun GreeterScreen(navController: NavController) {
.padding(horizontal = 20.dp, vertical = 30.dp)
) {
ElevatedButton(
onClick = { navController.navigate("about") },
onClick = { navController.navigate("about/placeholder") },
modifier = Modifier.fillMaxWidth()
) {
Text(text = stringResource(R.string.about))
Text(text = stringResource(R.string.signup))
}
Button(

View File

@ -0,0 +1,40 @@
package chat.revolt.screens.settings
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.material3.Button
import androidx.compose.material3.ElevatedButton
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.navigation.NavController
import chat.revolt.R
import chat.revolt.components.generic.PageHeader
@Composable
fun SettingsScreen(
navController: NavController
) {
Column(
modifier = Modifier
.fillMaxSize()
) {
PageHeader(stringResource(id = R.string.settings))
ElevatedButton(
modifier = Modifier.fillMaxWidth(),
onClick = {
navController.popBackStack()
}) {
Text(text = stringResource(id = R.string.back))
}
Button(
modifier = Modifier.fillMaxWidth(),
onClick = {
navController.navigate("about")
}) {
Text(text = stringResource(id = R.string.about))
}
}
}

View File

@ -106,4 +106,5 @@
<string name="tap_to_retry">Tap to retry</string>
<string name="scroll_to_bottom">Scroll to bottom</string>
<string name="settings">Settings</string>
</resources>