feat: channel info sheet (shows description)
This commit is contained in:
parent
493a542ae9
commit
9c26a7ab93
|
|
@ -1,6 +1,7 @@
|
||||||
package chat.revolt.screens.chat
|
package chat.revolt.screens.chat
|
||||||
|
|
||||||
import androidx.compose.animation.*
|
import androidx.compose.animation.AnimatedVisibility
|
||||||
|
import androidx.compose.animation.Crossfade
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.layout.*
|
import androidx.compose.foundation.layout.*
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
|
|
@ -31,8 +32,13 @@ import chat.revolt.api.realtime.RealtimeSocket
|
||||||
import chat.revolt.api.schemas.ChannelType
|
import chat.revolt.api.schemas.ChannelType
|
||||||
import chat.revolt.components.chat.DisconnectedNotice
|
import chat.revolt.components.chat.DisconnectedNotice
|
||||||
import chat.revolt.components.screens.chat.*
|
import chat.revolt.components.screens.chat.*
|
||||||
|
import chat.revolt.screens.chat.sheets.ChannelInfoSheet
|
||||||
import chat.revolt.screens.chat.views.ChannelScreen
|
import chat.revolt.screens.chat.views.ChannelScreen
|
||||||
import chat.revolt.screens.chat.views.HomeScreen
|
import chat.revolt.screens.chat.views.HomeScreen
|
||||||
|
import com.google.accompanist.navigation.material.ExperimentalMaterialNavigationApi
|
||||||
|
import com.google.accompanist.navigation.material.ModalBottomSheetLayout
|
||||||
|
import com.google.accompanist.navigation.material.bottomSheet
|
||||||
|
import com.google.accompanist.navigation.material.rememberBottomSheetNavigator
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
class ChatRouterViewModel : ViewModel() {
|
class ChatRouterViewModel : ViewModel() {
|
||||||
|
|
@ -65,14 +71,17 @@ class ChatRouterViewModel : ViewModel() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterialNavigationApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun ChatRouterScreen(topNav: NavController, viewModel: ChatRouterViewModel = viewModel()) {
|
fun ChatRouterScreen(topNav: NavController, viewModel: ChatRouterViewModel = viewModel()) {
|
||||||
val channelDrawerState = rememberDrawerState(DrawerValue.Closed)
|
val channelDrawerState = rememberDrawerState(DrawerValue.Closed)
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
val navController = rememberNavController()
|
|
||||||
|
val bottomSheetNavigator = rememberBottomSheetNavigator()
|
||||||
|
val navController = rememberNavController(bottomSheetNavigator)
|
||||||
val navBackStackEntry by navController.currentBackStackEntryAsState()
|
val navBackStackEntry by navController.currentBackStackEntryAsState()
|
||||||
|
|
||||||
|
ModalBottomSheetLayout(bottomSheetNavigator = bottomSheetNavigator) {
|
||||||
Column {
|
Column {
|
||||||
AnimatedVisibility(visible = RealtimeSocket.disconnectionState != DisconnectionState.Connected) {
|
AnimatedVisibility(visible = RealtimeSocket.disconnectionState != DisconnectionState.Connected) {
|
||||||
DisconnectedNotice(
|
DisconnectedNotice(
|
||||||
|
|
@ -82,6 +91,7 @@ fun ChatRouterScreen(topNav: NavController, viewModel: ChatRouterViewModel = vie
|
||||||
scope.launch { RevoltAPI.connectWS() }
|
scope.launch { RevoltAPI.connectWS() }
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
DismissibleNavigationDrawer(
|
DismissibleNavigationDrawer(
|
||||||
drawerState = channelDrawerState,
|
drawerState = channelDrawerState,
|
||||||
drawerContent = {
|
drawerContent = {
|
||||||
|
|
@ -94,7 +104,11 @@ fun ChatRouterScreen(topNav: NavController, viewModel: ChatRouterViewModel = vie
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxHeight()
|
.fillMaxHeight()
|
||||||
.verticalScroll(rememberScrollState())
|
.verticalScroll(rememberScrollState())
|
||||||
.background(MaterialTheme.colorScheme.surfaceColorAtElevation(2.dp))
|
.background(
|
||||||
|
MaterialTheme.colorScheme.surfaceColorAtElevation(
|
||||||
|
2.dp
|
||||||
|
)
|
||||||
|
)
|
||||||
) {
|
) {
|
||||||
DrawerServerlikeIcon(
|
DrawerServerlikeIcon(
|
||||||
onClick = {
|
onClick = {
|
||||||
|
|
@ -208,7 +222,19 @@ fun ChatRouterScreen(topNav: NavController, viewModel: ChatRouterViewModel = vie
|
||||||
composable("channel/{channelId}") { backStackEntry ->
|
composable("channel/{channelId}") { backStackEntry ->
|
||||||
val channelId = backStackEntry.arguments?.getString("channelId")
|
val channelId = backStackEntry.arguments?.getString("channelId")
|
||||||
if (channelId != null) {
|
if (channelId != null) {
|
||||||
ChannelScreen(navController, channelId = channelId)
|
ChannelScreen(
|
||||||
|
navController = navController,
|
||||||
|
channelId = channelId
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bottomSheet("channel/{channelId}/info") { backStackEntry ->
|
||||||
|
val channelId = backStackEntry.arguments?.getString("channelId")
|
||||||
|
if (channelId != null) {
|
||||||
|
ChannelInfoSheet(
|
||||||
|
navController = navController,
|
||||||
|
channelId = channelId
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -220,4 +246,5 @@ fun ChatRouterScreen(topNav: NavController, viewModel: ChatRouterViewModel = vie
|
||||||
show = channelDrawerState.currentValue == DrawerValue.Open,
|
show = channelDrawerState.currentValue == DrawerValue.Open,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
package chat.revolt.screens.chat.sheets
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.*
|
||||||
|
import androidx.compose.foundation.rememberScrollState
|
||||||
|
import androidx.compose.foundation.verticalScroll
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.Surface
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.navigation.NavController
|
||||||
|
import chat.revolt.R
|
||||||
|
import chat.revolt.api.RevoltAPI
|
||||||
|
import chat.revolt.api.schemas.ChannelType
|
||||||
|
import chat.revolt.components.generic.PageHeader
|
||||||
|
import chat.revolt.components.screens.chat.ChannelIcon
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun ChannelInfoSheet(
|
||||||
|
navController: NavController,
|
||||||
|
channelId: String,
|
||||||
|
) {
|
||||||
|
val channel = RevoltAPI.channelCache[channelId]
|
||||||
|
if (channel == null) {
|
||||||
|
navController.popBackStack()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
Surface(
|
||||||
|
modifier = Modifier.fillMaxSize(),
|
||||||
|
) {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(horizontal = 16.dp)
|
||||||
|
.verticalScroll(rememberScrollState()),
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
ChannelIcon(
|
||||||
|
channelType = channel.channelType ?: ChannelType.TextChannel,
|
||||||
|
modifier = Modifier.size(32.dp)
|
||||||
|
)
|
||||||
|
PageHeader(
|
||||||
|
text = channel.name ?: channel.id ?: "",
|
||||||
|
modifier = Modifier.offset((-4).dp, 0.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
|
Text(
|
||||||
|
text = stringResource(id = R.string.channel_info_sheet_description),
|
||||||
|
style = MaterialTheme.typography.bodySmall,
|
||||||
|
modifier = Modifier.padding(bottom = 10.dp)
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
text = channel.description
|
||||||
|
?: stringResource(id = R.string.channel_info_sheet_description_empty),
|
||||||
|
modifier = Modifier.padding(bottom = 10.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -61,14 +61,14 @@ class ChannelScreenViewModel : ViewModel() {
|
||||||
get() = _channel
|
get() = _channel
|
||||||
|
|
||||||
private var _callback = mutableStateOf<RealtimeSocket.ChannelCallback?>(null)
|
private var _callback = mutableStateOf<RealtimeSocket.ChannelCallback?>(null)
|
||||||
val callback: RealtimeSocket.ChannelCallback?
|
private val callback: RealtimeSocket.ChannelCallback?
|
||||||
get() = _callback.value
|
get() = _callback.value
|
||||||
|
|
||||||
private var _renderableMessages = mutableStateListOf<MessageSchema>()
|
private var _renderableMessages = mutableStateListOf<MessageSchema>()
|
||||||
val renderableMessages: List<MessageSchema>
|
val renderableMessages: List<MessageSchema>
|
||||||
get() = _renderableMessages
|
get() = _renderableMessages
|
||||||
|
|
||||||
fun setRenderableMessages(messages: List<MessageSchema>) {
|
private fun setRenderableMessages(messages: List<MessageSchema>) {
|
||||||
_renderableMessages.clear()
|
_renderableMessages.clear()
|
||||||
_renderableMessages.addAll(messages)
|
_renderableMessages.addAll(messages)
|
||||||
}
|
}
|
||||||
|
|
@ -89,7 +89,7 @@ class ChannelScreenViewModel : ViewModel() {
|
||||||
val attachments: List<FileArgs>
|
val attachments: List<FileArgs>
|
||||||
get() = _attachments
|
get() = _attachments
|
||||||
|
|
||||||
fun setAttachments(attachments: List<FileArgs>) {
|
private fun setAttachments(attachments: List<FileArgs>) {
|
||||||
_attachments.clear()
|
_attachments.clear()
|
||||||
_attachments.addAll(attachments)
|
_attachments.addAll(attachments)
|
||||||
}
|
}
|
||||||
|
|
@ -180,7 +180,7 @@ class ChannelScreenViewModel : ViewModel() {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
val messages = arrayListOf<MessageSchema>()
|
val messages = arrayListOf<MessageSchema>()
|
||||||
|
|
||||||
if (!renderableMessages.isEmpty()) {
|
if (renderableMessages.isNotEmpty()) {
|
||||||
fetchMessagesFromChannel(
|
fetchMessagesFromChannel(
|
||||||
channel!!.id!!,
|
channel!!.id!!,
|
||||||
limit = 50,
|
limit = 50,
|
||||||
|
|
@ -383,7 +383,7 @@ fun ChannelScreen(
|
||||||
val totalItemsNumber = layoutInfo.totalItemsCount
|
val totalItemsNumber = layoutInfo.totalItemsCount
|
||||||
val lastVisibleItemIndex =
|
val lastVisibleItemIndex =
|
||||||
(layoutInfo.visibleItemsInfo.lastOrNull()?.index ?: 0) + 1
|
(layoutInfo.visibleItemsInfo.lastOrNull()?.index ?: 0) + 1
|
||||||
val buffer = if (totalItemsNumber > 6) 6 else 0
|
val buffer = 6
|
||||||
|
|
||||||
lastVisibleItemIndex > (totalItemsNumber - buffer)
|
lastVisibleItemIndex > (totalItemsNumber - buffer)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -97,7 +97,7 @@ val RevoltTypography = Typography(
|
||||||
),
|
),
|
||||||
bodySmall = TextStyle(
|
bodySmall = TextStyle(
|
||||||
fontFamily = Inter,
|
fontFamily = Inter,
|
||||||
fontWeight = FontWeight.Normal,
|
fontWeight = FontWeight.Bold,
|
||||||
fontSize = 12.sp
|
fontSize = 12.sp
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
@ -113,6 +113,9 @@
|
||||||
<string name="copy">Copy</string>
|
<string name="copy">Copy</string>
|
||||||
<string name="copied">Copied to clipboard</string>
|
<string name="copied">Copied to clipboard</string>
|
||||||
|
|
||||||
|
<string name="channel_info_sheet_description">Channel description</string>
|
||||||
|
<string name="channel_info_sheet_description_empty">There hasn\'t been a description set for this channel yet.</string>
|
||||||
|
|
||||||
<string name="settings_appearance">Appearance</string>
|
<string name="settings_appearance">Appearance</string>
|
||||||
<string name="settings_appearance_theme">Theme</string>
|
<string name="settings_appearance_theme">Theme</string>
|
||||||
<string name="settings_appearance_theme_none">System</string>
|
<string name="settings_appearance_theme_none">System</string>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue