diff --git a/.gitignore b/.gitignore index d3006f4a..3efc0675 100644 --- a/.gitignore +++ b/.gitignore @@ -16,7 +16,6 @@ .cxx local.properties revoltbuild.properties -stoatbuild.properties sentry.properties /.kotlin/sessions app/src/main/assets/embedded diff --git a/app/.gitignore b/app/.gitignore index 77f70dc7..956c004d 100644 --- a/app/.gitignore +++ b/app/.gitignore @@ -1,3 +1,2 @@ /build -/release -google-services.json \ No newline at end of file +/release \ No newline at end of file diff --git a/app/google-services.json b/app/google-services.json new file mode 100644 index 00000000..997e884c --- /dev/null +++ b/app/google-services.json @@ -0,0 +1,68 @@ +{ + "project_info": { + "project_number": "123456789012", + "project_id": "revolt-android-dev", + "storage_bucket": "revolt-chat.appspot.com" + }, + "client": [ + { + "client_info": { + "mobilesdk_app_id": "1:123456789012:android:abcdef1234567890", + "android_client_info": { + "package_name": "chat.revolt" + } + }, + "oauth_client": [ + { + "client_id": "123456789012-abcdefghijklmnopqrstuvwxyz123456.apps.googleusercontent.com", + "client_type": 3 + } + ], + "api_key": [ + { + "current_key": "AIzaSyDummyKeyForDevelopmentOnly1234567890" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [ + { + "client_id": "123456789012-abcdefghijklmnopqrstuvwxyz123456.apps.googleusercontent.com", + "client_type": 3 + } + ] + } + } + }, + { + "client_info": { + "mobilesdk_app_id": "1:123456789012:android:abcdef1234567891", + "android_client_info": { + "package_name": "chat.revolt.debug" + } + }, + "oauth_client": [ + { + "client_id": "123456789012-abcdefghijklmnopqrstuvwxyz123456.apps.googleusercontent.com", + "client_type": 3 + } + ], + "api_key": [ + { + "current_key": "AIzaSyDummyKeyForDevelopmentOnly1234567890" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [ + { + "client_id": "123456789012-abcdefghijklmnopqrstuvwxyz123456.apps.googleusercontent.com", + "client_type": 3 + } + ] + } + } + } + ], + "configuration_version": "1" +} \ No newline at end of file diff --git a/app/src/main/java/chat/stoat/composables/chat/Message.kt b/app/src/main/java/chat/stoat/composables/chat/Message.kt index ee93be87..54246c89 100644 --- a/app/src/main/java/chat/stoat/composables/chat/Message.kt +++ b/app/src/main/java/chat/stoat/composables/chat/Message.kt @@ -254,7 +254,9 @@ fun Message( Column(modifier.animateContentSize()) { if (message.tail == false) { - Spacer(modifier = Modifier.height(10.dp)) + Spacer(modifier = Modifier.height(12.dp)) + } else { + Spacer(modifier = Modifier.height(2.dp)) } if (authorIsBlocked) { diff --git a/app/src/main/java/chat/stoat/composables/chat/MessageField.kt b/app/src/main/java/chat/stoat/composables/chat/MessageField.kt index a223b0c9..818bff79 100644 --- a/app/src/main/java/chat/stoat/composables/chat/MessageField.kt +++ b/app/src/main/java/chat/stoat/composables/chat/MessageField.kt @@ -54,6 +54,7 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.focusRequester import androidx.compose.ui.focus.onFocusChanged @@ -260,7 +261,7 @@ fun MessageField( } Column( - modifier = modifier.background(MaterialTheme.colorScheme.surfaceContainer) + modifier = modifier.background(Color.Transparent) ) { AnimatedVisibility( visible = autocompleteSuggestions.isNotEmpty(), @@ -491,7 +492,9 @@ fun MessageField( } Row( modifier = modifier - .background(MaterialTheme.colorScheme.surfaceContainer), + .padding(horizontal = 8.dp, vertical = 4.dp) + .clip(MaterialTheme.shapes.extraLarge) + .background(MaterialTheme.colorScheme.surfaceContainerHigh), verticalAlignment = Alignment.CenterVertically ) { Spacer(modifier = Modifier.width(8.dp)) diff --git a/app/src/main/java/chat/stoat/screens/chat/views/OverviewScreen.kt b/app/src/main/java/chat/stoat/screens/chat/views/OverviewScreen.kt index b9ad7c99..7a5368aa 100644 --- a/app/src/main/java/chat/stoat/screens/chat/views/OverviewScreen.kt +++ b/app/src/main/java/chat/stoat/screens/chat/views/OverviewScreen.kt @@ -413,8 +413,8 @@ fun OverviewScreenLink( modifier = Modifier .clip(MaterialTheme.shapes.extraLarge) .then(if (clickable) Modifier.clickable(onClick = onClick) else Modifier) - .background(backgroundColour) - .padding(vertical = 32.dp) + .background(backgroundColour.copy(alpha = 0.8f)) + .padding(vertical = 24.dp) .fillMaxWidth() ) { CompositionLocalProvider(LocalContentColor provides foregroundColour) { diff --git a/app/src/main/java/chat/stoat/screens/chat/views/channel/ChannelScreen.kt b/app/src/main/java/chat/stoat/screens/chat/views/channel/ChannelScreen.kt index a92e896d..7ddc81c7 100644 --- a/app/src/main/java/chat/stoat/screens/chat/views/channel/ChannelScreen.kt +++ b/app/src/main/java/chat/stoat/screens/chat/views/channel/ChannelScreen.kt @@ -86,6 +86,7 @@ import androidx.compose.runtime.snapshotFlow import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.alpha +import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.ColorFilter import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.platform.LocalContext @@ -147,6 +148,10 @@ import chat.stoat.screens.chat.LocalIsConnected import chat.stoat.sheets.ChannelInfoSheet import chat.stoat.sheets.MessageContextSheet import chat.stoat.sheets.ReactSheet +import dev.chrisbanes.haze.HazeState +import dev.chrisbanes.haze.hazeEffect +import dev.chrisbanes.haze.hazeSource +import dev.chrisbanes.haze.materials.HazeMaterials import com.valentinilk.shimmer.ShimmerBounds import com.valentinilk.shimmer.rememberShimmer import com.valentinilk.shimmer.shimmer @@ -203,6 +208,7 @@ fun ChannelScreen( // val scope = rememberCoroutineScope() val context = LocalContext.current + val hazeState = remember { HazeState() } val config = LocalConfiguration.current LaunchedEffect(Unit) { @@ -524,7 +530,8 @@ fun ChannelScreen( TopAppBar( modifier = Modifier.clickable { channelInfoSheetShown = true - }, + }.hazeEffect(state = hazeState, style = HazeMaterials.thin(MaterialTheme.colorScheme.surface)), + colors = androidx.compose.material3.TopAppBarDefaults.topAppBarColors(containerColor = Color.Transparent), title = { Row( verticalAlignment = Alignment.CenterVertically, @@ -675,7 +682,7 @@ fun ChannelScreen( .padding(pv) ) { Box( - modifier = Modifier.weight(1f), + modifier = Modifier.weight(1f).hazeSource(state = hazeState), contentAlignment = Alignment.BottomCenter ) { LazyColumn( @@ -963,7 +970,8 @@ fun ChannelScreen( Column( modifier = Modifier - .background(MaterialTheme.colorScheme.surfaceContainer) + .hazeEffect(state = hazeState, style = HazeMaterials.thin(MaterialTheme.colorScheme.surfaceContainer)) + .background(Color.Transparent) .fillMaxWidth(), verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally diff --git a/app/src/main/java/chat/stoat/screens/main/ConversationsScreen.kt b/app/src/main/java/chat/stoat/screens/main/ConversationsScreen.kt index 2a82ce3d..f1d64944 100644 --- a/app/src/main/java/chat/stoat/screens/main/ConversationsScreen.kt +++ b/app/src/main/java/chat/stoat/screens/main/ConversationsScreen.kt @@ -1,20 +1,25 @@ package chat.stoat.screens.main +import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.exclude import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.ui.draw.clip import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Badge import androidx.compose.material3.CenterAlignedTopAppBar import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.Icon -import androidx.compose.material3.ListItem +import androidx.compose.material3.MaterialTheme import androidx.compose.material3.NavigationBarDefaults import androidx.compose.material3.Scaffold import androidx.compose.material3.ScaffoldDefaults @@ -26,6 +31,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.navigation.NavController @@ -78,52 +84,95 @@ fun ConversationsScreen(navController: NavController) { } if (notesChannel != null) { - ListItem( - headlineContent = { - Text(stringResource(R.string.channel_notes)) - }, - supportingContent = { + Row( + modifier = Modifier + .fillMaxWidth() + .clickable { + navController.navigate("main/conversation/${notesChannel.id}") + } + .padding(16.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Box(contentAlignment = Alignment.TopEnd) { + StoatAPI.userCache[StoatAPI.selfId]?.let { + UserAvatar( + username = it.username.toString(), + avatar = it.avatar, + userId = it.id.toString(), + shape = RoundedCornerShape(LoadedSettings.avatarRadius) + ) + } + Badge { + Icon( + painter = painterResource(R.drawable.ic_keep_24dp), + contentDescription = null, + modifier = Modifier.size(12.dp) + ) + } + } + + Spacer(modifier = Modifier.width(16.dp)) + + Column(modifier = Modifier.weight(1f)) { + Text( + stringResource(R.string.channel_notes), + style = MaterialTheme.typography.titleMedium, + fontWeight = FontWeight.SemiBold + ) if (preview.isNotBlank()) { Text( preview, maxLines = 1, overflow = TextOverflow.Ellipsis, + style = MaterialTheme.typography.bodyMedium, + color = MaterialTheme.colorScheme.onSurfaceVariant ) } - }, - leadingContent = { - Box(contentAlignment = Alignment.TopEnd) { - StoatAPI.userCache[StoatAPI.selfId]?.let { - UserAvatar( - username = it.username.toString(), - avatar = it.avatar, - userId = it.id.toString(), - shape = RoundedCornerShape(LoadedSettings.avatarRadius) - ) - } - Badge { - Icon( - painter = painterResource(R.drawable.ic_keep_24dp), - contentDescription = null, - modifier = Modifier.size(12.dp) - ) - } - } - }, - modifier = Modifier.clickable { - navController.navigate("main/conversation/${notesChannel.id}") } - ) - HorizontalDivider() + } } } - items(1000) { - Text( - "Conversation $it", modifier = Modifier + items(100) { + Row( + modifier = Modifier + .fillMaxWidth() .clickable { navController.navigate("main/conversation/${it}") } - .fillMaxWidth()) + .padding(16.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Box( + modifier = Modifier + .size(LoadedSettings.avatarRadius.dp * 2) + .clip(RoundedCornerShape(LoadedSettings.avatarRadius)) + .background(MaterialTheme.colorScheme.primaryContainer), + contentAlignment = Alignment.Center + ) { + Text( + text = it.toString().take(1), + style = MaterialTheme.typography.titleMedium, + color = MaterialTheme.colorScheme.onPrimaryContainer + ) + } + + Spacer(modifier = Modifier.width(16.dp)) + + Column(modifier = Modifier.weight(1f)) { + Text( + "Conversation $it", + style = MaterialTheme.typography.titleMedium, + fontWeight = FontWeight.SemiBold + ) + Text( + "Last message preview $it", + maxLines = 1, + overflow = TextOverflow.Ellipsis, + style = MaterialTheme.typography.bodyMedium, + color = MaterialTheme.colorScheme.onSurfaceVariant + ) + } + } } } } diff --git a/app/src/main/java/chat/stoat/screens/main/MainScreen.kt b/app/src/main/java/chat/stoat/screens/main/MainScreen.kt index 93919ec5..45b99e29 100644 --- a/app/src/main/java/chat/stoat/screens/main/MainScreen.kt +++ b/app/src/main/java/chat/stoat/screens/main/MainScreen.kt @@ -1,23 +1,31 @@ package chat.stoat.screens.main import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme import androidx.compose.material3.NavigationBar import androidx.compose.material3.NavigationBarItem import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.navigation.NavController import chat.stoat.R import chat.stoat.screens.chat.views.OverviewScreen +import dev.chrisbanes.haze.HazeState +import dev.chrisbanes.haze.hazeEffect +import dev.chrisbanes.haze.hazeSource +import dev.chrisbanes.haze.materials.HazeMaterials enum class MainScreenTab { Communities, @@ -28,10 +36,14 @@ enum class MainScreenTab { @Composable fun MainScreen(navController: NavController) { var currentTab by rememberSaveable { mutableStateOf(MainScreenTab.Communities) } + val hazeState = remember { HazeState() } Scaffold( bottomBar = { - NavigationBar { + NavigationBar( + containerColor = Color.Transparent, + modifier = Modifier.hazeEffect(state = hazeState, style = HazeMaterials.thin(MaterialTheme.colorScheme.surfaceContainer)) + ) { NavigationBarItem( selected = currentTab == MainScreenTab.Communities, onClick = { currentTab = MainScreenTab.Communities }, @@ -88,22 +100,28 @@ fun MainScreen(navController: NavController) { } }, ) { pv -> - Box(Modifier.padding(pv)) { - when (currentTab) { - MainScreenTab.Communities -> {} - MainScreenTab.Conversations -> { - ConversationsScreen( - navController - ) - } + Box( + Modifier + .fillMaxSize() + .hazeSource(state = hazeState) + ) { + Box(Modifier.padding(pv)) { + when (currentTab) { + MainScreenTab.Communities -> {} + MainScreenTab.Conversations -> { + ConversationsScreen( + navController + ) + } - MainScreenTab.Overview -> { - OverviewScreen( - navController, - useDrawer = false, - onDrawerClicked = {}, - includePadding = false - ) + MainScreenTab.Overview -> { + OverviewScreen( + navController, + useDrawer = false, + onDrawerClicked = {}, + includePadding = false + ) + } } } } diff --git a/app/src/main/java/chat/stoat/ui/theme/Colour.kt b/app/src/main/java/chat/stoat/ui/theme/Colour.kt index 4f23807b..00d88861 100644 --- a/app/src/main/java/chat/stoat/ui/theme/Colour.kt +++ b/app/src/main/java/chat/stoat/ui/theme/Colour.kt @@ -3,9 +3,9 @@ package chat.stoat.ui.theme import androidx.compose.ui.graphics.Color object Colour { - val RevoltUltraPink = Color(0xFFFF005C) + val RevoltUltraPink = Color(0xFFFF3377) - val PrimaryLight = Color(0xFFBD0042) + val PrimaryLight = Color(0xFFB90041) val OnPrimaryLight = Color(0xFFFFFFFF) val PrimaryContainerLight = Color(0xFFFFD9DC) val OnPrimaryContainerLight = Color(0xFF910031) @@ -41,10 +41,10 @@ object Colour { val SurfaceContainerHighLight = Color(0xFFE4E8F8) val SurfaceContainerHighestLight = Color(0xFFDEE2F2) - val PrimaryDark = Color(0xFFFFB2BA) - val OnPrimaryDark = Color(0xFF670020) - val PrimaryContainerDark = Color(0xFF910031) - val OnPrimaryContainerDark = Color(0xFFFFD9DC) + val PrimaryDark = Color(0xFFFFB2BB) + val OnPrimaryDark = Color(0xFF67001F) + val PrimaryContainerDark = Color(0xFF910030) + val OnPrimaryContainerDark = Color(0xFFFFD9DD) val SecondaryDark = Color(0xFFFFB3AE) val OnSecondaryDark = Color(0xFF68000C) val SecondaryContainerDark = Color(0xFF930015) diff --git a/app/src/main/java/chat/stoat/ui/theme/Theme.kt b/app/src/main/java/chat/stoat/ui/theme/Theme.kt index 249415ac..f27b7f4b 100644 --- a/app/src/main/java/chat/stoat/ui/theme/Theme.kt +++ b/app/src/main/java/chat/stoat/ui/theme/Theme.kt @@ -129,11 +129,11 @@ fun getColorScheme( val m3Supported = systemSupportsDynamicColors() val colorScheme = when { - m3Supported && requestedTheme == Theme.M3Dynamic && systemInDarkTheme -> dynamicDarkColorScheme( + m3Supported && (requestedTheme == Theme.M3Dynamic || requestedTheme == Theme.None) && systemInDarkTheme -> dynamicDarkColorScheme( context ) - m3Supported && requestedTheme == Theme.M3Dynamic && !systemInDarkTheme -> dynamicLightColorScheme( + m3Supported && (requestedTheme == Theme.M3Dynamic || requestedTheme == Theme.None) && !systemInDarkTheme -> dynamicLightColorScheme( context ) diff --git a/stoatbuild.properties b/stoatbuild.properties new file mode 100644 index 00000000..ea6a101c --- /dev/null +++ b/stoatbuild.properties @@ -0,0 +1,4 @@ +sentry.dsn= +sentry.upload_mappings=true +build.debug.app_name= +build.flavour_id=ZZUU \ No newline at end of file