diff --git a/app/build.gradle b/app/build.gradle index a58f5cf2..7ca0f50a 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -61,6 +61,7 @@ dependencies { // Jetpack Compose implementation "androidx.compose.ui:ui:$compose_libraries_version" + implementation "androidx.compose.ui:ui-util:$compose_libraries_version" implementation 'androidx.compose.material3:material3:1.0.1' implementation "androidx.compose.ui:ui-tooling-preview:$compose_libraries_version" implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.5.1' diff --git a/app/src/main/java/chat/revolt/api/realtime/RealtimeSocket.kt b/app/src/main/java/chat/revolt/api/realtime/RealtimeSocket.kt index 5e9d4e46..578fa84a 100644 --- a/app/src/main/java/chat/revolt/api/realtime/RealtimeSocket.kt +++ b/app/src/main/java/chat/revolt/api/realtime/RealtimeSocket.kt @@ -156,6 +156,16 @@ object RealtimeSocket { RevoltAPI.userCache[userUpdateFrame.id] = existing.mergeWithPartial(userUpdateFrame.data) } + "ChannelUpdate" -> { + val channelUpdateFrame = + RevoltJson.decodeFromString(ChannelUpdateFrame.serializer(), rawFrame) + + val existing = RevoltAPI.channelCache[channelUpdateFrame.id] + ?: return // if we don't have the channel no point in updating it + + RevoltAPI.channelCache[channelUpdateFrame.id] = + existing.mergeWithPartial(channelUpdateFrame.data) + } else -> { Log.i("RealtimeSocket", "Unknown frame: $rawFrame") } diff --git a/app/src/main/java/chat/revolt/api/realtime/frames/receivable/ReceivableFrames.kt b/app/src/main/java/chat/revolt/api/realtime/frames/receivable/ReceivableFrames.kt index 2e017403..a3e928c8 100644 --- a/app/src/main/java/chat/revolt/api/realtime/frames/receivable/ReceivableFrames.kt +++ b/app/src/main/java/chat/revolt/api/realtime/frames/receivable/ReceivableFrames.kt @@ -168,12 +168,6 @@ data class ServerDeleteFrame( val id: String ) -@Serializable -data class ServerUserChoice( - val server: String, - val user: String, -) - @Serializable data class ServerMemberUpdateFrame( val type: String = "ServerMemberUpdate", diff --git a/app/src/main/java/chat/revolt/api/schemas/Channel.kt b/app/src/main/java/chat/revolt/api/schemas/Channel.kt index a6fc5e53..b878a332 100644 --- a/app/src/main/java/chat/revolt/api/schemas/Channel.kt +++ b/app/src/main/java/chat/revolt/api/schemas/Channel.kt @@ -12,10 +12,16 @@ data class MessagesInChannel( val members: List? = null ) +@Serializable +data class ServerUserChoice( + val server: String, + val user: String, +) + @Serializable data class Member( @SerialName("_id") - val id: String? = null, + val id: ServerUserChoice? = null, @SerialName("joined_at") val joinedAt: String? = null, diff --git a/app/src/main/java/chat/revolt/components/chat/Message.kt b/app/src/main/java/chat/revolt/components/chat/Message.kt index 0051e2e4..f62f5856 100644 --- a/app/src/main/java/chat/revolt/components/chat/Message.kt +++ b/app/src/main/java/chat/revolt/components/chat/Message.kt @@ -1,28 +1,44 @@ package chat.revolt.components.chat -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size +import android.net.Uri +import androidx.browser.customtabs.CustomTabsIntent +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.* import androidx.compose.foundation.shape.CircleShape import androidx.compose.material3.CircularProgressIndicator +import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import chat.revolt.api.REVOLT_BASE import chat.revolt.api.REVOLT_FILES import chat.revolt.api.RevoltAPI +import chat.revolt.api.schemas.AutumnResource import chat.revolt.components.generic.RemoteImage import chat.revolt.api.schemas.Message as MessageSchema +fun viewAttachmentInBrowser(ctx: android.content.Context, attachment: AutumnResource) { + val customTab = CustomTabsIntent + .Builder() + .build() + customTab.launchUrl( + ctx, + Uri.parse("$REVOLT_FILES/attachments/${attachment.id}/${attachment.filename}") + ) +} + @Composable fun Message( message: MessageSchema ) { val author = RevoltAPI.userCache[message.author] ?: return CircularProgressIndicator() + val context = LocalContext.current Row(modifier = Modifier.padding(8.dp)) { if (author.avatar != null) { @@ -55,6 +71,39 @@ fun Message( text = it ) } + + message.attachments?.let { + if (message.attachments.isNotEmpty()) { + message.attachments.forEach { attachment -> + if (attachment.metadata?.type == "Image") { + RemoteImage( + url = "$REVOLT_FILES/attachments/${attachment.id}/image.png", + modifier = Modifier + .padding(top = 5.dp) + .clickable { + viewAttachmentInBrowser(context, attachment) + }, + width = attachment.metadata.width?.toInt() ?: 0, + height = attachment.metadata.height?.toInt() ?: 0, + contentScale = ContentScale.Fit, + description = "Attached image ${attachment.filename}" + ) + } else { + Text( + text = attachment.filename ?: "Attachment", + fontWeight = FontWeight.Medium, + modifier = Modifier + .clip(MaterialTheme.shapes.medium) + .clickable { + viewAttachmentInBrowser(context, attachment) + } + .background(MaterialTheme.colorScheme.surface) + .padding(8.dp) + ) + } + } + } + } } } } \ No newline at end of file diff --git a/app/src/main/java/chat/revolt/components/generic/CollapsibleCard.kt b/app/src/main/java/chat/revolt/components/generic/CollapsibleCard.kt index 5fe4b4fc..37056c9f 100644 --- a/app/src/main/java/chat/revolt/components/generic/CollapsibleCard.kt +++ b/app/src/main/java/chat/revolt/components/generic/CollapsibleCard.kt @@ -28,9 +28,9 @@ fun CollapsibleCard( Column { Row( modifier = Modifier + .clickable { expanded = !expanded } .fillMaxWidth() - .padding(16.dp) - .clickable { expanded = !expanded }, + .padding(16.dp), ) { Text( text = title, diff --git a/app/src/main/java/chat/revolt/components/generic/PageHeader.kt b/app/src/main/java/chat/revolt/components/generic/PageHeader.kt new file mode 100644 index 00000000..44d85169 --- /dev/null +++ b/app/src/main/java/chat/revolt/components/generic/PageHeader.kt @@ -0,0 +1,36 @@ +package chat.revolt.components.generic + +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp + +@Composable +fun PageHeader( + text: String, +) { + Text( + text = text, + style = MaterialTheme.typography.displaySmall.copy( + fontWeight = FontWeight.Bold, + textAlign = TextAlign.Left, + fontSize = 24.sp + ), + modifier = Modifier + .padding(horizontal = 15.dp, vertical = 15.dp) + .fillMaxWidth(), + ) +} + +@Preview +@Composable +fun PageHeaderPreview() { + PageHeader(text = "Page Header") +} \ No newline at end of file diff --git a/app/src/main/java/chat/revolt/components/generic/RemoteImage.kt b/app/src/main/java/chat/revolt/components/generic/RemoteImage.kt index 9f634775..3e84a48c 100644 --- a/app/src/main/java/chat/revolt/components/generic/RemoteImage.kt +++ b/app/src/main/java/chat/revolt/components/generic/RemoteImage.kt @@ -19,15 +19,26 @@ fun RemoteImage( url: String, description: String, modifier: Modifier = Modifier, - contentScale: ContentScale = ContentScale.Crop + contentScale: ContentScale = ContentScale.Crop, + width: Int = 0, + height: Int = 0, ) { val context = LocalContext.current - AsyncImage( - model = ImageRequest.Builder(context) - .data(url) + fun imageRequest() = run { + val builder = ImageRequest.Builder(context) .crossfade(true) - .build(), + .data(url) + + if (width != 0 && height != 0) { + builder.size(width, height) + } + + builder.build() + } + + AsyncImage( + model = imageRequest(), imageLoader = ImageLoader.Builder(context) .components { if (Build.VERSION.SDK_INT >= 28) { @@ -45,7 +56,7 @@ fun RemoteImage( .build(), contentDescription = description, contentScale = contentScale, - modifier = modifier + modifier = modifier, ) } diff --git a/app/src/main/java/chat/revolt/components/screens/chat/ChannelIcon.kt b/app/src/main/java/chat/revolt/components/screens/chat/ChannelIcon.kt new file mode 100644 index 00000000..a044d3ba --- /dev/null +++ b/app/src/main/java/chat/revolt/components/screens/chat/ChannelIcon.kt @@ -0,0 +1,56 @@ +package chat.revolt.components.screens.chat + +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.AccountBox +import androidx.compose.material.icons.filled.AccountCircle +import androidx.compose.material3.Icon +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import chat.revolt.api.schemas.ChannelType +import chat.revolt.R + +@Composable +fun ChannelIcon( + channelType: ChannelType, + modifier: Modifier = Modifier, +) { + when (channelType) { + ChannelType.TextChannel -> { + Icon( + painter = painterResource(R.drawable.ic_pound_24dp), + contentDescription = stringResource(R.string.channel_text), + modifier = modifier, + ) + } + ChannelType.VoiceChannel -> { + Icon( + painter = painterResource(R.drawable.ic_volume_up_24dp), + contentDescription = stringResource(R.string.channel_voice), + modifier = modifier, + ) + } + ChannelType.SavedMessages -> { + Icon( + painter = painterResource(R.drawable.ic_note_24dp), + contentDescription = stringResource(R.string.channel_notes), + modifier = modifier, + ) + } + ChannelType.DirectMessage -> { + Icon( + imageVector = Icons.Default.AccountCircle, + contentDescription = stringResource(R.string.channel_dm), + modifier = modifier, + ) + } + ChannelType.Group -> { + Icon( + imageVector = Icons.Default.AccountBox, + contentDescription = stringResource(R.string.channel_group), + modifier = modifier, + ) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/chat/revolt/components/screens/chat/DrawerChannel.kt b/app/src/main/java/chat/revolt/components/screens/chat/DrawerChannel.kt index e2f028cf..2ba65a23 100644 --- a/app/src/main/java/chat/revolt/components/screens/chat/DrawerChannel.kt +++ b/app/src/main/java/chat/revolt/components/screens/chat/DrawerChannel.kt @@ -5,20 +5,14 @@ import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.* -import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import chat.revolt.api.schemas.ChannelType -import chat.revolt.R @Composable fun DrawerChannel( @@ -36,36 +30,7 @@ fun DrawerChannel( .clickable(onClick = onClick) .padding(vertical = 8.dp, horizontal = 16.dp) ) { - when (channelType) { - ChannelType.TextChannel -> { - Icon( - modifier = Modifier.padding(end = 8.dp), - painter = painterResource(R.drawable.ic_pound_24dp), - contentDescription = stringResource(R.string.channel_text) - ) - } - ChannelType.VoiceChannel -> { - Icon( - modifier = Modifier.padding(end = 8.dp), - painter = painterResource(R.drawable.ic_volume_up_24dp), - contentDescription = stringResource(R.string.channel_voice) - ) - } - ChannelType.SavedMessages -> { - Icon( - modifier = Modifier.padding(end = 8.dp), - painter = painterResource(R.drawable.ic_note_24dp), - contentDescription = stringResource(R.string.channel_notes) - ) - } - else -> { - Icon( - modifier = Modifier.padding(end = 8.dp), - imageVector = Icons.Default.List, - contentDescription = "Channel" - ) - } - } + ChannelIcon(channelType = channelType, modifier = Modifier.padding(end = 8.dp)) Text( text = name, fontWeight = FontWeight.Medium, diff --git a/app/src/main/java/chat/revolt/components/screens/splash/DisconnectedScreen.kt b/app/src/main/java/chat/revolt/components/screens/splash/DisconnectedScreen.kt index be1d68a1..08fa3df4 100644 --- a/app/src/main/java/chat/revolt/components/screens/splash/DisconnectedScreen.kt +++ b/app/src/main/java/chat/revolt/components/screens/splash/DisconnectedScreen.kt @@ -34,7 +34,6 @@ fun DisconnectedScreen( textAlign = TextAlign.Center ), modifier = Modifier - .padding(horizontal = 20.dp, vertical = 10.dp) .fillMaxWidth(), ) @@ -46,7 +45,7 @@ fun DisconnectedScreen( fontWeight = FontWeight.Normal, ), modifier = Modifier - .padding(horizontal = 20.dp, vertical = 10.dp) + .padding(vertical = 10.dp, horizontal = 20.dp) .fillMaxWidth() ) diff --git a/app/src/main/java/chat/revolt/screens/SplashScreen.kt b/app/src/main/java/chat/revolt/screens/SplashScreen.kt index 0cf20b46..f78e9280 100644 --- a/app/src/main/java/chat/revolt/screens/SplashScreen.kt +++ b/app/src/main/java/chat/revolt/screens/SplashScreen.kt @@ -55,14 +55,14 @@ class SplashScreenViewModel @Inject constructor( val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager - val networkCapabilities = connectivityManager.activeNetwork ?: return false - val actNw = - connectivityManager.getNetworkCapabilities(networkCapabilities) ?: return false + val network = connectivityManager.activeNetwork ?: return false + val capabilities = + connectivityManager.getNetworkCapabilities(network) ?: return false return when { - actNw.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> true - actNw.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> true - actNw.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> true + capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> true + capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> true + capabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> true else -> false } } diff --git a/app/src/main/java/chat/revolt/screens/chat/ChatRouterScreen.kt b/app/src/main/java/chat/revolt/screens/chat/ChatRouterScreen.kt index c1f8173b..0e626327 100644 --- a/app/src/main/java/chat/revolt/screens/chat/ChatRouterScreen.kt +++ b/app/src/main/java/chat/revolt/screens/chat/ChatRouterScreen.kt @@ -51,8 +51,24 @@ class ChatRouterViewModel : ViewModel() { _currentServer.value = serverId } - fun goToHome() { - _currentServer.value = "home" + fun navigateToServer(serverId: String, navController: NavController) { + setCurrentServer(serverId) + + if (serverId == "home") { + navController.navigate("home") { + popUpTo("home") { + inclusive = true + } + } + return + } + + val channelId = RevoltAPI.serverCache[serverId]?.channels?.firstOrNull() + navController.navigate("channel/$channelId") { + popUpTo("home") { + inclusive = true + } + } } } @@ -85,7 +101,9 @@ fun ChatRouterScreen(topNav: NavController, viewModel: ChatRouterViewModel = vie .background(MaterialTheme.colorScheme.surface) ) { IconButton( - onClick = { viewModel.goToHome() }, + onClick = { + viewModel.navigateToServer("home", navController) + }, modifier = Modifier .padding(8.dp) .size(48.dp) @@ -107,7 +125,12 @@ fun ChatRouterScreen(topNav: NavController, viewModel: ChatRouterViewModel = vie .padding(8.dp) .size(48.dp) .clip(CircleShape) - .clickable { viewModel.setCurrentServer(server.id!!) }, + .clickable { + viewModel.navigateToServer( + server.id!!, + navController + ) + }, description = "${server.name}" ) } else { @@ -119,7 +142,12 @@ fun ChatRouterScreen(topNav: NavController, viewModel: ChatRouterViewModel = vie .size(48.dp) .clip(CircleShape) .background(MaterialTheme.colorScheme.surfaceVariant) - .clickable { viewModel.setCurrentServer(server.id!!) } + .clickable { + viewModel.navigateToServer( + server.id!!, + navController + ) + } ) { Text( text = server.name.first().toString(), @@ -143,11 +171,11 @@ fun ChatRouterScreen(topNav: NavController, viewModel: ChatRouterViewModel = vie .weight(1f) .verticalScroll(rememberScrollState()) ) { - RevoltAPI.channelCache.values.filter { it.channelType == ChannelType.DirectMessage } + RevoltAPI.channelCache.values.filter { it.channelType == ChannelType.Group } .forEach { channel -> DrawerChannel( - name = "DM #${channel.id}", // TODO get user or group name - channelType = ChannelType.DirectMessage, + name = channel.name ?: "GDM #${channel.id}", + channelType = ChannelType.Group, selected = channel.id == (navBackStackEntry?.arguments?.getString( "channelId" ) ?: false), @@ -185,7 +213,11 @@ fun ChatRouterScreen(topNav: NavController, viewModel: ChatRouterViewModel = vie ) == ch.id, onClick = { scope.launch { channelDrawerState.close() } - navController.navigate("channel/${ch.id}") + navController.navigate("channel/${ch.id}") { + popUpTo("home") { + inclusive = true + } + } }) } } diff --git a/app/src/main/java/chat/revolt/screens/chat/views/ChannelScreen.kt b/app/src/main/java/chat/revolt/screens/chat/views/ChannelScreen.kt index a62cfdb6..435a08e6 100644 --- a/app/src/main/java/chat/revolt/screens/chat/views/ChannelScreen.kt +++ b/app/src/main/java/chat/revolt/screens/chat/views/ChannelScreen.kt @@ -1,18 +1,29 @@ package chat.revolt.screens.chat.views import android.util.Log +import android.widget.Toast import androidx.compose.animation.* import androidx.compose.foundation.background +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items import androidx.compose.foundation.rememberScrollState import androidx.compose.material3.* import androidx.compose.runtime.* +import androidx.compose.ui.Alignment +import androidx.compose.ui.ExperimentalComposeUiApi import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.ClipboardManager +import androidx.compose.ui.platform.LocalClipboardManager +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.AnnotatedString +import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp +import androidx.compose.ui.window.Dialog +import androidx.compose.ui.window.DialogProperties import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewmodel.compose.viewModel @@ -33,6 +44,9 @@ import chat.revolt.RevoltTweenFloat import chat.revolt.RevoltTweenInt import chat.revolt.api.routes.channel.fetchMessagesFromChannel import chat.revolt.components.chat.MessageField +import chat.revolt.components.generic.CollapsibleCard +import chat.revolt.components.generic.PageHeader +import chat.revolt.components.screens.chat.ChannelIcon class ChannelScreenViewModel : ViewModel() { private var _channel by mutableStateOf(null) @@ -109,6 +123,8 @@ class ChannelScreenViewModel : ViewModel() { return } + _renderableMessages.clear() + viewModelScope.launch { fetchMessagesFromChannel(channel!!.id!!, limit = 50, false).let { it.messages!!.reversed().forEach { message -> @@ -122,6 +138,29 @@ class ChannelScreenViewModel : ViewModel() { } } + fun fetchOlderMessages() { + if (channel == null) { + return + } + + viewModelScope.launch { + fetchMessagesFromChannel( + channel!!.id!!, + limit = 20, + true, + before = renderableMessages.first().id + ).let { + it.messages!!.forEach { message -> + addUserIfUnknown(message.author!!) + if (!RevoltAPI.messageCache.containsKey(message.id)) { + RevoltAPI.messageCache[message.id!!] = message + } + _renderableMessages.add(0, message) + } + } + } + } + fun fetchChannel(id: String) { if (id in RevoltAPI.channelCache) { _channel = RevoltAPI.channelCache[id] @@ -158,6 +197,79 @@ class ChannelScreenViewModel : ViewModel() { } } +@Composable +fun ChannelInfoScreen( + channel: Channel, + viewModel: ChannelScreenViewModel, + onClosed: () -> Unit, +) { + val context = LocalContext.current + val clipboardManager: ClipboardManager = + LocalClipboardManager.current + val coroutineScope = rememberCoroutineScope() + + Column( + modifier = Modifier + .background(MaterialTheme.colorScheme.surface) + .padding(16.dp) + .fillMaxSize() + ) { + Row( + verticalAlignment = Alignment.CenterVertically + ) { + ChannelIcon( + channelType = channel.channelType!!, + modifier = Modifier.size(32.dp) + ) + PageHeader(text = channel.name ?: channel.id!!) + } + + Column(modifier = Modifier.weight(1f)) { + CollapsibleCard(title = "Advanced") { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(16.dp) + ) { + Text("Channel ID: ${channel.id}") + + Button(onClick = { + clipboardManager.setText(AnnotatedString(channel.id!!)) + Toast.makeText( + context, + "Copied", + Toast.LENGTH_SHORT + ).show() + }) { + Text("Copy ID") + } + + Button( + onClick = { + coroutineScope.launch { + viewModel.fetchMessages() + } + }, + modifier = Modifier + .fillMaxWidth() + ) { + Text("Refetch messages") + } + } + } + } + + Button( + onClick = onClosed, + modifier = Modifier + .fillMaxWidth() + ) { + Text("Close") + } + } +} + +@OptIn(ExperimentalComposeUiApi::class) @Composable fun ChannelScreen( navController: NavController, @@ -166,6 +278,8 @@ fun ChannelScreen( ) { val channel = viewModel.channel val scrollState = rememberScrollState() + val channelInfoOpen = remember { mutableStateOf(false) } + val coroutineScope = rememberCoroutineScope() LaunchedEffect(channelId) { viewModel.fetchChannel(channelId) @@ -184,20 +298,61 @@ fun ChannelScreen( return } + if (channelInfoOpen.value) { + Dialog( + onDismissRequest = { + channelInfoOpen.value = false + }, + properties = DialogProperties( + usePlatformDefaultWidth = false, + ) + ) { + ChannelInfoScreen(channel, viewModel) { + channelInfoOpen.value = false + } + } + } + Column { Row( modifier = Modifier + .clickable { + coroutineScope.launch { + channelInfoOpen.value = true + } + } .fillMaxWidth() .background(MaterialTheme.colorScheme.surface) + .padding(16.dp), + verticalAlignment = Alignment.CenterVertically ) { + ChannelIcon( + channelType = channel.channelType!!, + modifier = Modifier.padding(end = 8.dp) + ) Text( text = channel.name ?: channel.id!!, style = MaterialTheme.typography.labelLarge, - modifier = Modifier.padding(16.dp) + fontWeight = FontWeight.Bold, + modifier = Modifier.weight(1f), ) } LazyColumn(Modifier.weight(1f)) { + item { + Button( + onClick = { + coroutineScope.launch { + viewModel.fetchOlderMessages() + } + }, + modifier = Modifier + .fillMaxWidth() + .padding(vertical = 16.dp, horizontal = 8.dp) + ) { + Text("Load older") + } + } items(viewModel.renderableMessages) { message -> Message(message) } diff --git a/app/src/main/java/chat/revolt/screens/chat/views/HomeScreen.kt b/app/src/main/java/chat/revolt/screens/chat/views/HomeScreen.kt index 0edbfa62..aedda60b 100644 --- a/app/src/main/java/chat/revolt/screens/chat/views/HomeScreen.kt +++ b/app/src/main/java/chat/revolt/screens/chat/views/HomeScreen.kt @@ -3,14 +3,8 @@ package chat.revolt.screens.chat.views import androidx.compose.foundation.layout.* import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Close -import androidx.compose.material3.* import androidx.compose.runtime.* -import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.ViewModel import androidx.navigation.NavController @@ -19,6 +13,7 @@ import chat.revolt.components.screens.home.LinkOnHome import chat.revolt.persistence.KVStorage import dagger.hilt.android.lifecycle.HiltViewModel import chat.revolt.R +import chat.revolt.components.generic.PageHeader import kotlinx.coroutines.runBlocking import javax.inject.Inject @@ -36,19 +31,8 @@ class HomeScreenViewModel @Inject constructor( @Composable fun HomeScreen(navController: NavController, viewModel: HomeScreenViewModel = hiltViewModel()) { - Column() { - Text( - text = stringResource(id = R.string.home), - style = MaterialTheme.typography.displaySmall.copy( - fontWeight = FontWeight.Bold, - textAlign = TextAlign.Left, - fontSize = 24.sp - ), - modifier = Modifier - .padding(horizontal = 15.dp, vertical = 15.dp) - .fillMaxWidth(), - ) - + Column { + PageHeader(text = stringResource(id = R.string.home)) LinkOnHome( heading = stringResource(id = R.string.logout), icon = Icons.Default.Close, diff --git a/app/src/main/java/chat/revolt/ui/theme/Theme.kt b/app/src/main/java/chat/revolt/ui/theme/Theme.kt index e355e41a..502537bb 100644 --- a/app/src/main/java/chat/revolt/ui/theme/Theme.kt +++ b/app/src/main/java/chat/revolt/ui/theme/Theme.kt @@ -15,6 +15,8 @@ import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalView import androidx.core.view.ViewCompat +const val FORCE_ANDROID_DEFAULTS = false + const val FOREGROUND = 0xffffffff val DarkColorScheme = darkColorScheme( @@ -60,9 +62,15 @@ fun RevoltTheme( } } - MaterialTheme( - colorScheme = colorScheme, - typography = RevoltTypography, - content = content - ) + if (FORCE_ANDROID_DEFAULTS) { + MaterialTheme( + content = content + ) + } else { + MaterialTheme( + colorScheme = colorScheme, + typography = RevoltTypography, + content = content + ) + } } \ No newline at end of file