From 08163377f7c3305807b0df576b9c7401fe68e9cd Mon Sep 17 00:00:00 2001 From: Takanori Hoshi Date: Mon, 8 Mar 2021 13:43:12 -0800 Subject: [PATCH] Bump compose version to 1.0.0-beta01 --- app/build.gradle | 33 ++-- .../sudo/rizwan/twitterclone/MainActivity.kt | 34 ++-- .../com/sudo/rizwan/twitterclone/Themes.kt | 12 +- .../sudo/rizwan/twitterclone/models/Tweet.kt | 4 +- .../rizwan/twitterclone/state/AppState.kt | 20 +-- .../rizwan/twitterclone/ui/common/Divider.kt | 16 +- .../rizwan/twitterclone/ui/common/Text.kt | 27 ++- .../twitterclone/ui/common/TweetLayout.kt | 139 +++++++++------- .../rizwan/twitterclone/ui/common/UserInfo.kt | 28 ++-- .../twitterclone/ui/compose/ComposeTweet.kt | 114 ++++++++----- .../rizwan/twitterclone/ui/home/AppDrawer.kt | 152 ++++++++++------- .../rizwan/twitterclone/ui/home/BottomBar.kt | 35 ++-- .../rizwan/twitterclone/ui/home/Content.kt | 26 ++- .../sudo/rizwan/twitterclone/ui/home/Fab.kt | 33 ++-- .../sudo/rizwan/twitterclone/ui/home/Home.kt | 14 +- .../rizwan/twitterclone/ui/home/TopBar.kt | 70 +++++--- .../rizwan/twitterclone/ui/profile/Profile.kt | 156 +++++++++++------- build.gradle | 9 +- gradle/wrapper/gradle-wrapper.properties | 2 +- 19 files changed, 555 insertions(+), 369 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 9c40080..56c3bd5 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,16 +1,15 @@ plugins { id 'com.android.application' id 'kotlin-android' - id 'kotlin-android-extensions' } android { - compileSdkVersion 29 + compileSdkVersion 30 defaultConfig { applicationId "com.sudo.rizwan.twitterclone" minSdkVersion 23 - targetSdkVersion 29 + targetSdkVersion 30 versionCode 1 versionName "1.0" @@ -31,7 +30,8 @@ android { jvmTarget = '1.8' } composeOptions { - kotlinCompilerExtensionVersion "$compose_compiler_extension_version" + kotlinCompilerVersion kotlin_version + kotlinCompilerExtensionVersion compose_version } buildFeatures { compose true @@ -40,17 +40,22 @@ android { dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" - implementation 'androidx.core:core-ktx:1.3.0' - implementation 'androidx.appcompat:appcompat:1.1.0' - implementation 'androidx.constraintlayout:constraintlayout:1.1.3' + implementation 'androidx.core:core-ktx:1.3.2' + implementation 'androidx.appcompat:appcompat:1.2.0' - implementation "androidx.ui:ui-foundation:$compose_version" - implementation "androidx.ui:ui-tooling:$compose_version" + implementation 'androidx.activity:activity-compose:1.3.0-alpha03' + implementation "androidx.compose.ui:ui:$compose_version" + implementation "androidx.compose.ui:ui-tooling:$compose_version" + implementation "androidx.compose.foundation:foundation:$compose_version" + implementation "androidx.compose.material:material:$compose_version" + implementation "androidx.compose.material:material-icons-extended:$compose_version" - implementation "androidx.ui:ui-layout:$compose_version" - implementation "androidx.ui:ui-material:$compose_version" + implementation "androidx.compose.runtime:runtime-livedata:$compose_version" + implementation 'androidx.lifecycle:lifecycle-viewmodel-compose:1.0.0-alpha02' - testImplementation 'junit:junit:4.13' - androidTestImplementation 'androidx.test.ext:junit:1.1.1' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' + implementation 'androidx.constraintlayout:constraintlayout-compose:1.0.0-alpha03' + + testImplementation 'junit:junit:4.13.2' + androidTestImplementation 'androidx.test.ext:junit:1.1.2' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' } \ No newline at end of file diff --git a/app/src/main/java/com/sudo/rizwan/twitterclone/MainActivity.kt b/app/src/main/java/com/sudo/rizwan/twitterclone/MainActivity.kt index 8f5cbe8..1293101 100644 --- a/app/src/main/java/com/sudo/rizwan/twitterclone/MainActivity.kt +++ b/app/src/main/java/com/sudo/rizwan/twitterclone/MainActivity.kt @@ -1,32 +1,39 @@ package com.sudo.rizwan.twitterclone import android.os.Bundle +import androidx.activity.compose.setContent +import androidx.activity.viewModels import androidx.appcompat.app.AppCompatActivity -import androidx.compose.Composable -import androidx.ui.animation.Crossfade -import androidx.ui.core.setContent -import androidx.ui.material.MaterialTheme -import androidx.ui.material.Surface -import com.sudo.rizwan.twitterclone.ui.home.Home -import com.sudo.rizwan.twitterclone.ui.profile.Profile -import com.sudo.rizwan.twitterclone.state.AppState +import androidx.compose.animation.Crossfade +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Surface +import androidx.compose.runtime.Composable +import androidx.compose.runtime.livedata.observeAsState +import androidx.lifecycle.viewmodel.compose.viewModel +import com.sudo.rizwan.twitterclone.state.AppStateViewModel import com.sudo.rizwan.twitterclone.state.Screen import com.sudo.rizwan.twitterclone.ui.compose.ComposeTweet +import com.sudo.rizwan.twitterclone.ui.home.Home +import com.sudo.rizwan.twitterclone.ui.profile.Profile class MainActivity : AppCompatActivity() { + private val appState by viewModels() + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { - MaterialTheme(colors = AppState.theme) { + val theme = appState.theme.observeAsState(lightThemeColors) + + MaterialTheme(colors = theme.value) { AppContent() } } } override fun onBackPressed() { - if (AppState.currentScreen !is Screen.Home) { + if (appState.currentScreen.value !is Screen.Home) { // Temp handling of back navigation - AppState.currentScreen = Screen.Home + appState.currentScreen.value = Screen.Home return } super.onBackPressed() @@ -35,7 +42,10 @@ class MainActivity : AppCompatActivity() { @Composable fun AppContent() { - Crossfade(AppState.currentScreen) { screen -> + val appState = viewModel() + val currentScreen = appState.currentScreen.observeAsState(Screen.Home) + + Crossfade(currentScreen.value) { screen -> Surface(color = MaterialTheme.colors.background) { when (screen) { is Screen.Home -> Home() diff --git a/app/src/main/java/com/sudo/rizwan/twitterclone/Themes.kt b/app/src/main/java/com/sudo/rizwan/twitterclone/Themes.kt index a8fcac7..78e099d 100644 --- a/app/src/main/java/com/sudo/rizwan/twitterclone/Themes.kt +++ b/app/src/main/java/com/sudo/rizwan/twitterclone/Themes.kt @@ -1,27 +1,27 @@ package com.sudo.rizwan.twitterclone -import androidx.ui.graphics.Color -import androidx.ui.material.darkColorPalette -import androidx.ui.material.lightColorPalette +import androidx.compose.material.darkColors +import androidx.compose.material.lightColors +import androidx.compose.ui.graphics.Color private val lightBackgroundColor = Color.White private val darkBackgroundColor = Color(0xFF15202b) private val darkerBackgroundColor = Color(0xFF0a0a0a) private val primaryColor = Color(0xFF08a0e9) -val lightThemeColors = lightColorPalette( +val lightThemeColors = lightColors( primary = primaryColor, background = lightBackgroundColor, surface = lightBackgroundColor ) -val darkThemeColors = darkColorPalette( +val darkThemeColors = darkColors( primary = primaryColor, background = darkBackgroundColor, surface = darkBackgroundColor ) -val darkerThemeColors = darkColorPalette( +val darkerThemeColors = darkColors( primary = primaryColor, background = darkerBackgroundColor, surface = darkerBackgroundColor diff --git a/app/src/main/java/com/sudo/rizwan/twitterclone/models/Tweet.kt b/app/src/main/java/com/sudo/rizwan/twitterclone/models/Tweet.kt index 9ba5443..6813d46 100644 --- a/app/src/main/java/com/sudo/rizwan/twitterclone/models/Tweet.kt +++ b/app/src/main/java/com/sudo/rizwan/twitterclone/models/Tweet.kt @@ -1,9 +1,9 @@ package com.sudo.rizwan.twitterclone.models -import androidx.compose.Model +//import androidx.compose.Model import java.util.* -@Model +// TODO @Model data class Tweet( val user: User, val tweet: String, diff --git a/app/src/main/java/com/sudo/rizwan/twitterclone/state/AppState.kt b/app/src/main/java/com/sudo/rizwan/twitterclone/state/AppState.kt index ac92697..7536d45 100644 --- a/app/src/main/java/com/sudo/rizwan/twitterclone/state/AppState.kt +++ b/app/src/main/java/com/sudo/rizwan/twitterclone/state/AppState.kt @@ -1,6 +1,7 @@ package com.sudo.rizwan.twitterclone.state -import androidx.compose.Model +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel import com.sudo.rizwan.twitterclone.lightThemeColors import com.sudo.rizwan.twitterclone.models.User @@ -10,16 +11,11 @@ sealed class Screen { object Compose : Screen() } -@Model -object AppState { - var currentScreen: Screen = Screen.Home - var theme = lightThemeColors -} - -fun navigateTo(destination: Screen) { - AppState.currentScreen = destination -} +class AppStateViewModel : ViewModel() { + val currentScreen = MutableLiveData(Screen.Home) + val theme = MutableLiveData(lightThemeColors) -fun isLightTheme(): Boolean { - return AppState.theme.isLight + fun navigateTo(destination: Screen) { + currentScreen.value = destination + } } diff --git a/app/src/main/java/com/sudo/rizwan/twitterclone/ui/common/Divider.kt b/app/src/main/java/com/sudo/rizwan/twitterclone/ui/common/Divider.kt index 190fa28..a0af6a3 100644 --- a/app/src/main/java/com/sudo/rizwan/twitterclone/ui/common/Divider.kt +++ b/app/src/main/java/com/sudo/rizwan/twitterclone/ui/common/Divider.kt @@ -1,11 +1,17 @@ package com.sudo.rizwan.twitterclone.ui.common -import androidx.compose.Composable -import androidx.ui.graphics.Color -import androidx.ui.material.Divider -import com.sudo.rizwan.twitterclone.state.isLightTheme +import androidx.compose.material.Divider +import androidx.compose.runtime.Composable +import androidx.compose.runtime.livedata.observeAsState +import androidx.compose.ui.graphics.Color +import androidx.lifecycle.viewmodel.compose.viewModel +import com.sudo.rizwan.twitterclone.lightThemeColors +import com.sudo.rizwan.twitterclone.state.AppStateViewModel @Composable fun CustomDivider() { - Divider(color = if (isLightTheme()) Color(0xFFEEEEEE) else Color(0xFF333333)) + val appState = viewModel() + val theme = appState.theme.observeAsState(lightThemeColors) + + Divider(color = if (theme.value!!.isLight) Color(0xFFEEEEEE) else Color(0xFF333333)) } \ No newline at end of file diff --git a/app/src/main/java/com/sudo/rizwan/twitterclone/ui/common/Text.kt b/app/src/main/java/com/sudo/rizwan/twitterclone/ui/common/Text.kt index 35db513..1b8bdcb 100644 --- a/app/src/main/java/com/sudo/rizwan/twitterclone/ui/common/Text.kt +++ b/app/src/main/java/com/sudo/rizwan/twitterclone/ui/common/Text.kt @@ -1,30 +1,39 @@ package com.sudo.rizwan.twitterclone.ui.common -import androidx.compose.Composable -import androidx.ui.foundation.Text -import androidx.ui.graphics.Color -import androidx.ui.text.TextStyle -import androidx.ui.text.style.TextOverflow -import androidx.ui.unit.sp -import com.sudo.rizwan.twitterclone.state.AppState +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.livedata.observeAsState +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.sp +import androidx.lifecycle.viewmodel.compose.viewModel +import com.sudo.rizwan.twitterclone.lightThemeColors +import com.sudo.rizwan.twitterclone.state.AppStateViewModel @Composable fun ThemedText(text: String, style: TextStyle = TextStyle()) { + val appState = viewModel() + val theme = appState.theme.observeAsState(lightThemeColors) + Text( text = text, style = style, - color = if (AppState.theme.isLight) Color(0xFF111111) else Color(0xFFEEEEEE) + color = if (theme.value!!.isLight) Color(0xFF111111) else Color(0xFFEEEEEE) ) } @Composable fun GrayText(text: String) { + val appState = viewModel() + val theme = appState.theme.observeAsState(lightThemeColors) + Text( text = text, style = TextStyle( fontSize = 14.sp, - color = if (AppState.theme.isLight) Color(0xFF666666) else Color(0xFFDDDDDD) + color = if (theme.value!!.isLight) Color(0xFF666666) else Color(0xFFDDDDDD) ), maxLines = 1, overflow = TextOverflow.Ellipsis diff --git a/app/src/main/java/com/sudo/rizwan/twitterclone/ui/common/TweetLayout.kt b/app/src/main/java/com/sudo/rizwan/twitterclone/ui/common/TweetLayout.kt index cf279bb..47149fd 100644 --- a/app/src/main/java/com/sudo/rizwan/twitterclone/ui/common/TweetLayout.kt +++ b/app/src/main/java/com/sudo/rizwan/twitterclone/ui/common/TweetLayout.kt @@ -1,35 +1,43 @@ package com.sudo.rizwan.twitterclone.ui.common -import androidx.compose.Composable -import androidx.ui.core.Alignment -import androidx.ui.core.ContentScale -import androidx.ui.core.Modifier -import androidx.ui.core.clip -import androidx.ui.foundation.Clickable -import androidx.ui.foundation.Image -import androidx.ui.foundation.shape.corner.RoundedCornerShape -import androidx.ui.layout.* -import androidx.ui.material.ripple.ripple -import androidx.ui.res.imageResource -import androidx.ui.text.TextStyle -import androidx.ui.text.font.FontWeight -import androidx.ui.unit.dp -import androidx.ui.unit.sp +import androidx.compose.foundation.Image +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +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.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.lifecycle.viewmodel.compose.viewModel import com.sudo.rizwan.twitterclone.R import com.sudo.rizwan.twitterclone.models.Tweet +import com.sudo.rizwan.twitterclone.state.AppStateViewModel import com.sudo.rizwan.twitterclone.state.Screen -import com.sudo.rizwan.twitterclone.state.navigateTo @Composable fun TweetLayout(tweet: Tweet) { Row(modifier = Modifier.padding(all = 10.dp)) { UserAvatar(tweet) - Spacer(modifier = Modifier.preferredSize(12.dp)) + Spacer(modifier = Modifier.size(12.dp)) Column { NameAndUserName(tweet) - Spacer(modifier = Modifier.preferredSize(1.dp)) + Spacer(modifier = Modifier.size(1.dp)) TweetAndImage(tweet) - Spacer(modifier = Modifier.preferredSize(10.dp)) + Spacer(modifier = Modifier.size(10.dp)) TweetActions(tweet) } } @@ -38,49 +46,53 @@ fun TweetLayout(tweet: Tweet) { @Composable private fun TweetActions(tweet: Tweet) { Row( - modifier = Modifier.fillMaxWidth() + Modifier.padding(end = 40.dp), - verticalGravity = Alignment.CenterVertically, + modifier = Modifier.fillMaxWidth().padding(end = 40.dp), + verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.SpaceBetween ) { val imageSize = 18.dp Row { Image( - imageResource(R.drawable.ic_comment), - modifier = Modifier.preferredSize(imageSize) + painterResource(R.drawable.ic_comment), + contentDescription = null, + modifier = Modifier.size(imageSize) ) - Spacer(modifier = Modifier.preferredSize(4.dp)) + Spacer(modifier = Modifier.size(4.dp)) GrayText(text = tweet.comments.toString()) } - Clickable( - modifier = Modifier.ripple(enabled = true), - onClick = { tweet.retweet() }) { - Row { - Image( - imageResource(if (tweet.retweeted) R.drawable.ic_retweeted else R.drawable.ic_retweet), - modifier = Modifier.preferredSize(imageSize) - ) - Spacer(modifier = Modifier.preferredSize(4.dp)) - GrayText(text = tweet.retweets.toString()) - } + Row( + modifier = Modifier.clickable( + onClick = { tweet.retweet() } + ) + ) { + Image( + painterResource(if (tweet.retweeted) R.drawable.ic_retweeted else R.drawable.ic_retweet), + contentDescription = null, + modifier = Modifier.size(imageSize) + ) + Spacer(modifier = Modifier.size(4.dp)) + GrayText(text = tweet.retweets.toString()) } - Clickable( - modifier = Modifier.ripple(enabled = true), - onClick = { tweet.like() }) { - Row { - Image( - imageResource(if (tweet.liked) R.drawable.ic_liked else R.drawable.ic_like), - modifier = Modifier.preferredSize(imageSize) - ) - Spacer(modifier = Modifier.preferredSize(4.dp)) - GrayText(text = tweet.likes.toString()) - } + Row( + modifier = Modifier.clickable( + onClick = { tweet.like() } + ) + ) { + Image( + painterResource(if (tweet.liked) R.drawable.ic_liked else R.drawable.ic_like), + contentDescription = null, + modifier = Modifier.size(imageSize) + ) + Spacer(modifier = Modifier.size(4.dp)) + GrayText(text = tweet.likes.toString()) } Image( - imageResource(R.drawable.ic_share), - modifier = Modifier.preferredSize(imageSize) + painterResource(R.drawable.ic_share), + contentDescription = null, + modifier = Modifier.size(imageSize) ) } } @@ -92,11 +104,12 @@ private fun TweetAndImage(tweet: Tweet) { style = TextStyle(fontSize = 14.sp) ) if (tweet.image != null) { - Spacer(modifier = Modifier.preferredHeight(10.dp)) + Spacer(modifier = Modifier.height(10.dp)) Image( - imageResource(tweet.image), + painterResource(tweet.image), + contentDescription = null, modifier = Modifier - .preferredHeight(180.dp) + .height(180.dp) .fillMaxWidth() .clip(shape = RoundedCornerShape(2.dp)), contentScale = ContentScale.Crop @@ -106,29 +119,37 @@ private fun TweetAndImage(tweet: Tweet) { @Composable private fun NameAndUserName(tweet: Tweet) { - Row(verticalGravity = Alignment.CenterVertically) { + Row(verticalAlignment = Alignment.CenterVertically) { ThemedText( text = tweet.user.name, style = TextStyle(fontWeight = FontWeight.Bold, fontSize = 16.sp) ) if (tweet.user.verified) { - Spacer(modifier = Modifier.preferredSize(2.dp)) + Spacer(modifier = Modifier.size(2.dp)) Image( - imageResource(R.drawable.ic_verified), - modifier = Modifier.preferredSize(16.dp) + painterResource(R.drawable.ic_verified), + contentDescription = null, + modifier = Modifier.size(16.dp) ) } - Spacer(modifier = Modifier.preferredSize(5.dp)) + Spacer(modifier = Modifier.size(5.dp)) GrayText(text = "@${tweet.user.username} ยท ${tweet.timeAgo()}") } } @Composable private fun UserAvatar(tweet: Tweet) { - Clickable(onClick = { navigateTo(Screen.Profile(tweet.user)) }) { + val appState = viewModel() + + Box( + modifier = Modifier.clickable( + onClick = { appState.navigateTo(Screen.Profile(tweet.user)) } + ) + ) { Image( - imageResource(tweet.user.avatar), - modifier = Modifier.preferredSize(50.dp).clip(shape = RoundedCornerShape(25.dp)), + painterResource(tweet.user.avatar), + contentDescription = null, + modifier = Modifier.size(50.dp).clip(shape = RoundedCornerShape(25.dp)), contentScale = ContentScale.Crop ) } diff --git a/app/src/main/java/com/sudo/rizwan/twitterclone/ui/common/UserInfo.kt b/app/src/main/java/com/sudo/rizwan/twitterclone/ui/common/UserInfo.kt index cd38bc9..379fcbd 100644 --- a/app/src/main/java/com/sudo/rizwan/twitterclone/ui/common/UserInfo.kt +++ b/app/src/main/java/com/sudo/rizwan/twitterclone/ui/common/UserInfo.kt @@ -1,13 +1,17 @@ package com.sudo.rizwan.twitterclone.ui.common -import androidx.compose.Composable -import androidx.ui.core.Alignment -import androidx.ui.core.Modifier -import androidx.ui.layout.* -import androidx.ui.text.TextStyle -import androidx.ui.text.font.FontWeight -import androidx.ui.unit.dp -import androidx.ui.unit.sp +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.width +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp import com.sudo.rizwan.twitterclone.models.User @Composable @@ -18,16 +22,16 @@ fun UserInfo(user: User, showBio: Boolean = false) { ) ThemedText(text = "@${user.username}") if (showBio) { - Spacer(modifier = Modifier.preferredHeight(8.dp)) + Spacer(modifier = Modifier.height(8.dp)) ThemedText( text = user.bio, style = TextStyle(fontSize = 14.sp) ) } - Spacer(modifier = Modifier.preferredHeight(8.dp)) + Spacer(modifier = Modifier.height(8.dp)) Row( horizontalArrangement = Arrangement.SpaceBetween, - verticalGravity = Alignment.CenterVertically + verticalAlignment = Alignment.CenterVertically ) { ThemedText( text = "${user.following} ", @@ -37,7 +41,7 @@ fun UserInfo(user: User, showBio: Boolean = false) { text = "Following", style = TextStyle(fontSize = 14.sp) ) - Spacer(modifier = Modifier.preferredWidth(24.dp)) + Spacer(modifier = Modifier.width(24.dp)) ThemedText( text = "${user.followers} ", style = TextStyle(fontWeight = FontWeight.Bold) diff --git a/app/src/main/java/com/sudo/rizwan/twitterclone/ui/compose/ComposeTweet.kt b/app/src/main/java/com/sudo/rizwan/twitterclone/ui/compose/ComposeTweet.kt index 1c61880..0f29f87 100644 --- a/app/src/main/java/com/sudo/rizwan/twitterclone/ui/compose/ComposeTweet.kt +++ b/app/src/main/java/com/sudo/rizwan/twitterclone/ui/compose/ComposeTweet.kt @@ -1,40 +1,56 @@ package com.sudo.rizwan.twitterclone.ui.compose -import androidx.compose.Composable -import androidx.compose.MutableState -import androidx.compose.state -import androidx.ui.core.Alignment -import androidx.ui.core.ContentScale -import androidx.ui.core.Modifier -import androidx.ui.core.clip -import androidx.ui.foundation.* -import androidx.ui.foundation.shape.corner.RoundedCornerShape -import androidx.ui.graphics.Color -import androidx.ui.input.KeyboardType -import androidx.ui.layout.* -import androidx.ui.layout.ColumnScope.weight -import androidx.ui.material.Button -import androidx.ui.material.IconButton -import androidx.ui.material.icons.Icons -import androidx.ui.material.icons.filled.Clear -import androidx.ui.res.imageResource -import androidx.ui.text.TextStyle -import androidx.ui.unit.dp -import androidx.ui.unit.sp +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxHeight +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.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.material.Button +import androidx.compose.material.ButtonDefaults +import androidx.compose.material.Icon +import androidx.compose.material.IconButton +import androidx.compose.material.Text +import androidx.compose.material.TextField +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Clear +import androidx.compose.runtime.Composable +import androidx.compose.runtime.MutableState +import androidx.compose.runtime.livedata.observeAsState +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +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.layout.ContentScale +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.input.KeyboardType +import androidx.compose.ui.text.input.TextFieldValue +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.lifecycle.viewmodel.compose.viewModel import com.sudo.rizwan.twitterclone.R -import com.sudo.rizwan.twitterclone.state.AppState +import com.sudo.rizwan.twitterclone.lightThemeColors +import com.sudo.rizwan.twitterclone.state.AppStateViewModel import com.sudo.rizwan.twitterclone.state.Screen import com.sudo.rizwan.twitterclone.state.createNewTweet -import com.sudo.rizwan.twitterclone.state.navigateTo @Composable fun ComposeTweet() { - val tweetText = state { TextFieldValue(text = "") } + val tweetText = remember { mutableStateOf(TextFieldValue(text = "")) } Column(modifier = Modifier.fillMaxHeight()) { Row( modifier = Modifier.fillMaxWidth().padding(top = 10.dp, end = 16.dp), horizontalArrangement = Arrangement.SpaceBetween, - verticalGravity = Alignment.CenterVertically + verticalAlignment = Alignment.CenterVertically ) { CloseButton() TweetButton(tweetText) @@ -49,13 +65,14 @@ private fun AvatarWithTextField(tweetText: MutableState) { modifier = Modifier.padding(start = 16.dp, end = 16.dp, top = 10.dp, bottom = 10.dp) ) { Image( - imageResource(R.drawable.profile_image), + painterResource(R.drawable.profile_image), + contentDescription = null, modifier = Modifier - .preferredSize(34.dp) + .size(34.dp) .clip(shape = RoundedCornerShape(17.dp)), contentScale = ContentScale.Crop ) - Spacer(modifier = Modifier.preferredWidth(10.dp)) + Spacer(modifier = Modifier.width(10.dp)) TextFieldWithHint( modifier = Modifier.fillMaxWidth(), value = tweetText.value, @@ -67,24 +84,33 @@ private fun AvatarWithTextField(tweetText: MutableState) { @Composable private fun CloseButton() { - IconButton(onClick = { navigateTo(Screen.Home) }) { + val appState = viewModel() + val theme = appState.theme.observeAsState(lightThemeColors) + + IconButton(onClick = { appState.navigateTo(Screen.Home) }) { Icon( + Icons.Filled.Clear, + contentDescription = null, modifier = Modifier.size(50.dp), - asset = Icons.Filled.Clear, - tint = AppState.theme.primary + tint = theme.value!!.primary ) } } @Composable private fun TweetButton(tweetText: MutableState) { + val appState = viewModel() + val theme = appState.theme.observeAsState(lightThemeColors) + Button( onClick = { createNewTweet(tweetText.value.text) - navigateTo(Screen.Home) + appState.navigateTo(Screen.Home) }, shape = RoundedCornerShape(20.dp), - backgroundColor = if (tweetText.value.text.isEmpty()) Color(0xFFAAAAAA) else AppState.theme.primary + colors = ButtonDefaults.buttonColors( + backgroundColor = if (tweetText.value.text.isEmpty()) Color(0xFFAAAAAA) else theme.value!!.primary + ) ) { Text(text = "Tweet", color = Color.White) } @@ -97,16 +123,18 @@ private fun TextFieldWithHint( hint: String, onValueChange: (TextFieldValue) -> Unit ) { - Stack(Modifier.weight(1f)) { - TextField( - value = value, - modifier = modifier, - onValueChange = onValueChange, + TextField( + value = value, + modifier = modifier, + onValueChange = onValueChange, + placeholder = { + Text( + text = hint, + style = TextStyle(color = Color(0xFF666666), fontSize = 18.sp) + ) + }, + keyboardOptions = KeyboardOptions( keyboardType = KeyboardType.Text ) - if (value.text.isEmpty()) Text( - text = hint, - style = TextStyle(color = Color(0xFF666666), fontSize = 18.sp) - ) - } + ) } diff --git a/app/src/main/java/com/sudo/rizwan/twitterclone/ui/home/AppDrawer.kt b/app/src/main/java/com/sudo/rizwan/twitterclone/ui/home/AppDrawer.kt index 9feac06..9bdbd7e 100644 --- a/app/src/main/java/com/sudo/rizwan/twitterclone/ui/home/AppDrawer.kt +++ b/app/src/main/java/com/sudo/rizwan/twitterclone/ui/home/AppDrawer.kt @@ -1,28 +1,40 @@ package com.sudo.rizwan.twitterclone.ui.home -import androidx.compose.Composable -import androidx.compose.state -import androidx.ui.core.Alignment -import androidx.ui.core.ContentScale -import androidx.ui.core.Modifier -import androidx.ui.core.clip -import androidx.ui.foundation.Dialog -import androidx.ui.foundation.Image -import androidx.ui.foundation.shape.corner.RoundedCornerShape -import androidx.ui.graphics.Color -import androidx.ui.layout.* -import androidx.ui.material.Button -import androidx.ui.material.RadioButton -import androidx.ui.material.Surface -import androidx.ui.res.imageResource -import androidx.ui.text.TextStyle -import androidx.ui.unit.dp -import androidx.ui.unit.sp +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.Button +import androidx.compose.material.ButtonDefaults +import androidx.compose.material.RadioButton +import androidx.compose.material.Surface +import androidx.compose.runtime.Composable +import androidx.compose.runtime.livedata.observeAsState +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +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.layout.ContentScale +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.compose.ui.window.Dialog +import androidx.lifecycle.viewmodel.compose.viewModel import com.sudo.rizwan.twitterclone.R import com.sudo.rizwan.twitterclone.darkThemeColors import com.sudo.rizwan.twitterclone.darkerThemeColors import com.sudo.rizwan.twitterclone.lightThemeColors -import com.sudo.rizwan.twitterclone.state.AppState +import com.sudo.rizwan.twitterclone.state.AppStateViewModel import com.sudo.rizwan.twitterclone.state.sudorizwan import com.sudo.rizwan.twitterclone.ui.common.CustomDivider import com.sudo.rizwan.twitterclone.ui.common.ThemedText @@ -30,20 +42,24 @@ import com.sudo.rizwan.twitterclone.ui.common.UserInfo @Composable fun AppDrawer() { - val showThemeDialog = state { false } - Surface(color = AppState.theme.surface) { + val appState = viewModel() + val theme = appState.theme.observeAsState(lightThemeColors) + + val showThemeDialog = remember { mutableStateOf(false) } + Surface(color = theme.value!!.surface) { Column { Column(modifier = Modifier.padding(start = 16.dp, top = 16.dp, end = 16.dp)) { Image( - imageResource(R.drawable.profile_image), + painterResource(R.drawable.profile_image), + contentDescription = null, modifier = Modifier - .preferredSize(50.dp) + .size(50.dp) .clip(shape = RoundedCornerShape(25.dp)), contentScale = ContentScale.Crop ) - Spacer(modifier = Modifier.preferredHeight(2.dp)) + Spacer(modifier = Modifier.height(2.dp)) UserInfo(sudorizwan) - Spacer(modifier = Modifier.preferredHeight(16.dp)) + Spacer(modifier = Modifier.height(16.dp)) } CustomDivider() Column(modifier = Modifier.padding(start = 16.dp, end = 16.dp)) { @@ -81,53 +97,65 @@ fun AppDrawer() { CustomDivider() Row( modifier = Modifier.fillMaxWidth() - .preferredHeight(40.dp), + .height(40.dp), horizontalArrangement = Arrangement.SpaceBetween, - verticalGravity = Alignment.CenterVertically + verticalAlignment = Alignment.CenterVertically ) { Button( - padding = InnerPadding(all = 0.dp), - backgroundColor = Color.Transparent, - elevation = 0.dp, + modifier = Modifier.padding(all = 0.dp), + colors = ButtonDefaults.buttonColors( + backgroundColor = Color.Transparent + ), + elevation = ButtonDefaults.elevation( + defaultElevation = 0.dp, + pressedElevation = 0.dp + ), onClick = { showThemeDialog.value = true }) { Image( - imageResource(R.drawable.ic_theme), - modifier = Modifier.preferredSize(30.dp) + painterResource(R.drawable.ic_theme), + contentDescription = null, + modifier = Modifier.size(30.dp) ) } Button( - padding = InnerPadding(all = 0.dp), - backgroundColor = Color.Transparent, - elevation = 0.dp, + modifier = Modifier.padding(all = 0.dp), + colors = ButtonDefaults.buttonColors( + backgroundColor = Color.Transparent + ), + elevation = ButtonDefaults.elevation( + defaultElevation = 0.dp, + pressedElevation = 0.dp + ), onClick = {}) { Image( - imageResource(R.drawable.ic_qrcode), - modifier = Modifier.preferredSize(30.dp) + painterResource(R.drawable.ic_qrcode), + contentDescription = null, + modifier = Modifier.size(30.dp) ) } } } if (showThemeDialog.value) { - Dialog(onCloseRequest = { showThemeDialog.value = false }) { + Dialog(onDismissRequest = { showThemeDialog.value = false }) { Surface( - modifier = Modifier.preferredWidth(300.dp), + modifier = Modifier.width(300.dp), shape = RoundedCornerShape(10.dp), - color = AppState.theme.surface + color = theme.value!!.surface ) { Column(modifier = Modifier.padding(24.dp)) { ThemedText(text = "Pick a theme", style = TextStyle(fontSize = 22.sp)) - Spacer(modifier = Modifier.preferredHeight(16.dp)) - ThemeOption("Light", AppState.theme == lightThemeColors) { + Spacer(modifier = Modifier.height(16.dp)) + ThemeOption("Light", theme.value == lightThemeColors) { // on click - AppState.theme = lightThemeColors + appState.theme.value = lightThemeColors } - ThemeOption("Dark", AppState.theme == darkThemeColors) { + ThemeOption("Dark", theme.value == darkThemeColors) { // on click - AppState.theme = darkThemeColors + appState.theme.value = darkThemeColors } - ThemeOption("Darker", AppState.theme == darkerThemeColors) { + ThemeOption("Darker", theme.value == darkerThemeColors) { // on click - AppState.theme = darkerThemeColors + appState.theme.value = darkerThemeColors } } } @@ -138,12 +166,13 @@ fun AppDrawer() { @Composable fun SideBarListItem(text: String, icon: Int) { - Row(modifier = Modifier.preferredHeight(50.dp), verticalGravity = Alignment.CenterVertically) { + Row(modifier = Modifier.height(50.dp), verticalAlignment = Alignment.CenterVertically) { Image( - imageResource(icon), - modifier = Modifier.preferredSize(24.dp) + painterResource(icon), + contentDescription = null, + modifier = Modifier.size(24.dp) ) - Spacer(modifier = Modifier.preferredWidth(12.dp)) + Spacer(modifier = Modifier.width(12.dp)) ThemedText( text = text, style = TextStyle(fontSize = 18.sp) @@ -153,17 +182,26 @@ fun SideBarListItem(text: String, icon: Int) { @Composable private fun ThemeOption(text: String, selected: Boolean, onSelect: () -> Unit) { - Button(onClick = onSelect, backgroundColor = Color.Transparent, elevation = 0.dp) { + Button( + onClick = onSelect, + colors = ButtonDefaults.buttonColors( + backgroundColor = Color.Transparent + ), + elevation = ButtonDefaults.elevation( + defaultElevation = 0.dp, + pressedElevation = 0.dp + ) + ) { Row( - modifier = Modifier.preferredHeight(34.dp).fillMaxWidth(), - verticalGravity = Alignment.CenterVertically + modifier = Modifier.height(34.dp).fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically ) { RadioButton( selected = selected, - onSelect = onSelect, - color = AppState.theme.primary + onClick = onSelect, + // TODO colors = AppState.theme.primary ) - Spacer(modifier = Modifier.preferredWidth(16.dp)) + Spacer(modifier = Modifier.width(16.dp)) ThemedText(text = text) } } diff --git a/app/src/main/java/com/sudo/rizwan/twitterclone/ui/home/BottomBar.kt b/app/src/main/java/com/sudo/rizwan/twitterclone/ui/home/BottomBar.kt index f7a009f..091243a 100644 --- a/app/src/main/java/com/sudo/rizwan/twitterclone/ui/home/BottomBar.kt +++ b/app/src/main/java/com/sudo/rizwan/twitterclone/ui/home/BottomBar.kt @@ -1,21 +1,27 @@ package com.sudo.rizwan.twitterclone.ui.home -import androidx.compose.Composable -import androidx.ui.core.Modifier -import androidx.ui.foundation.Image -import androidx.ui.layout.Arrangement -import androidx.ui.layout.Row -import androidx.ui.layout.preferredSize -import androidx.ui.material.BottomAppBar -import androidx.ui.material.IconButton -import androidx.ui.res.imageResource -import androidx.ui.unit.dp +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.size +import androidx.compose.material.BottomAppBar +import androidx.compose.material.IconButton +import androidx.compose.runtime.Composable +import androidx.compose.runtime.livedata.observeAsState +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.unit.dp +import androidx.lifecycle.viewmodel.compose.viewModel import com.sudo.rizwan.twitterclone.R -import com.sudo.rizwan.twitterclone.state.AppState +import com.sudo.rizwan.twitterclone.lightThemeColors +import com.sudo.rizwan.twitterclone.state.AppStateViewModel @Composable fun BottomBar() { - BottomAppBar(backgroundColor = AppState.theme.surface) { + val appState = viewModel() + val theme = appState.theme.observeAsState(lightThemeColors) + + BottomAppBar(backgroundColor = theme.value!!.surface) { Row( modifier = Modifier.weight(1f), horizontalArrangement = Arrangement.SpaceAround @@ -32,8 +38,9 @@ fun BottomBar() { private fun BottomBarIcon(icon: Int) { IconButton(onClick = {}) { Image( - imageResource(icon), - modifier = Modifier.preferredSize(24.dp) + painterResource(icon), + contentDescription = null, + modifier = Modifier.size(24.dp) ) } } \ No newline at end of file diff --git a/app/src/main/java/com/sudo/rizwan/twitterclone/ui/home/Content.kt b/app/src/main/java/com/sudo/rizwan/twitterclone/ui/home/Content.kt index 99d140a..c243b53 100644 --- a/app/src/main/java/com/sudo/rizwan/twitterclone/ui/home/Content.kt +++ b/app/src/main/java/com/sudo/rizwan/twitterclone/ui/home/Content.kt @@ -1,12 +1,13 @@ package com.sudo.rizwan.twitterclone.ui.home -import androidx.compose.Composable -import androidx.ui.core.Modifier -import androidx.ui.foundation.VerticalScroller -import androidx.ui.layout.Column -import androidx.ui.layout.padding -import androidx.ui.material.ScaffoldState -import androidx.ui.unit.dp +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.material.ScaffoldState +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp import com.sudo.rizwan.twitterclone.state.tweets import com.sudo.rizwan.twitterclone.ui.common.CustomDivider import com.sudo.rizwan.twitterclone.ui.common.TweetLayout @@ -15,14 +16,11 @@ import com.sudo.rizwan.twitterclone.ui.common.TweetLayout fun Content(scaffoldState: ScaffoldState) { Column(modifier = Modifier.padding(bottom = 54.dp)) { TopBar(scaffoldState = scaffoldState) - VerticalScroller { - Column { - tweets.forEach { tweet -> - TweetLayout(tweet) - CustomDivider() - } + LazyColumn { + items(tweets) { tweet -> + TweetLayout(tweet) + CustomDivider() } } } } - diff --git a/app/src/main/java/com/sudo/rizwan/twitterclone/ui/home/Fab.kt b/app/src/main/java/com/sudo/rizwan/twitterclone/ui/home/Fab.kt index 6bb5b15..e29557c 100644 --- a/app/src/main/java/com/sudo/rizwan/twitterclone/ui/home/Fab.kt +++ b/app/src/main/java/com/sudo/rizwan/twitterclone/ui/home/Fab.kt @@ -1,27 +1,32 @@ package com.sudo.rizwan.twitterclone.ui.home -import androidx.compose.Composable -import androidx.ui.core.Modifier -import androidx.ui.foundation.Image -import androidx.ui.layout.preferredSize -import androidx.ui.material.FloatingActionButton -import androidx.ui.res.imageResource -import androidx.ui.unit.dp +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.size +import androidx.compose.material.FloatingActionButton +import androidx.compose.runtime.Composable +import androidx.compose.runtime.livedata.observeAsState +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.unit.dp +import androidx.lifecycle.viewmodel.compose.viewModel import com.sudo.rizwan.twitterclone.R -import com.sudo.rizwan.twitterclone.state.AppState +import com.sudo.rizwan.twitterclone.lightThemeColors +import com.sudo.rizwan.twitterclone.state.AppStateViewModel import com.sudo.rizwan.twitterclone.state.Screen -import com.sudo.rizwan.twitterclone.state.navigateTo @Composable fun Fab() { + val appState = viewModel() + val theme = appState.theme.observeAsState(lightThemeColors) + FloatingActionButton( - onClick = { navigateTo(Screen.Compose) }, - backgroundColor = AppState.theme.primary + onClick = { appState.navigateTo(Screen.Compose) }, + backgroundColor = theme.value!!.primary ) { Image( - imageResource(R.drawable.ic_compose), - modifier = Modifier - .preferredSize(25.dp) + painterResource(R.drawable.ic_compose), + contentDescription = null, + modifier = Modifier.size(25.dp) ) } } diff --git a/app/src/main/java/com/sudo/rizwan/twitterclone/ui/home/Home.kt b/app/src/main/java/com/sudo/rizwan/twitterclone/ui/home/Home.kt index 02f15ed..6815354 100644 --- a/app/src/main/java/com/sudo/rizwan/twitterclone/ui/home/Home.kt +++ b/app/src/main/java/com/sudo/rizwan/twitterclone/ui/home/Home.kt @@ -1,17 +1,17 @@ package com.sudo.rizwan.twitterclone.ui.home -import androidx.compose.Composable -import androidx.compose.remember -import androidx.ui.material.Scaffold -import androidx.ui.material.ScaffoldState +import androidx.compose.material.Scaffold +import androidx.compose.material.ScaffoldState +import androidx.compose.material.rememberScaffoldState +import androidx.compose.runtime.Composable @Composable -fun Home(scaffoldState: ScaffoldState = remember { ScaffoldState() }) { +fun Home(scaffoldState: ScaffoldState = rememberScaffoldState() ) { Scaffold( scaffoldState = scaffoldState, drawerContent = { AppDrawer() }, - bodyContent = { Content(scaffoldState = scaffoldState) }, + content = { Content(scaffoldState = scaffoldState) }, floatingActionButton = { Fab() }, - bottomAppBar = { BottomBar() } + bottomBar = { BottomBar() } ) } diff --git a/app/src/main/java/com/sudo/rizwan/twitterclone/ui/home/TopBar.kt b/app/src/main/java/com/sudo/rizwan/twitterclone/ui/home/TopBar.kt index 88c0acf..4d6b6f8 100644 --- a/app/src/main/java/com/sudo/rizwan/twitterclone/ui/home/TopBar.kt +++ b/app/src/main/java/com/sudo/rizwan/twitterclone/ui/home/TopBar.kt @@ -1,40 +1,62 @@ package com.sudo.rizwan.twitterclone.ui.home -import androidx.compose.Composable -import androidx.ui.core.Alignment -import androidx.ui.core.ContentScale -import androidx.ui.core.Modifier -import androidx.ui.core.clip -import androidx.ui.foundation.Clickable -import androidx.ui.foundation.Image -import androidx.ui.foundation.shape.corner.RoundedCornerShape -import androidx.ui.layout.* -import androidx.ui.material.DrawerState -import androidx.ui.material.ScaffoldState -import androidx.ui.material.Surface -import androidx.ui.res.imageResource -import androidx.ui.unit.dp +import androidx.compose.foundation.Image +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.ScaffoldState +import androidx.compose.material.Surface +import androidx.compose.runtime.Composable +import androidx.compose.runtime.livedata.observeAsState +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.unit.dp +import androidx.lifecycle.viewmodel.compose.viewModel import com.sudo.rizwan.twitterclone.R -import com.sudo.rizwan.twitterclone.state.AppState +import com.sudo.rizwan.twitterclone.lightThemeColors +import com.sudo.rizwan.twitterclone.state.AppStateViewModel +import kotlinx.coroutines.launch @Composable fun TopBar(scaffoldState: ScaffoldState) { - Surface(elevation = 2.dp, color = AppState.theme.surface) { + val appState = viewModel() + val theme = appState.theme.observeAsState(lightThemeColors) + val coroutineScope = rememberCoroutineScope() + + Surface(elevation = 2.dp, color = theme.value!!.surface) { Row( - modifier = Modifier.preferredHeight(50.dp).padding(start = 16.dp, end = 16.dp).fillMaxWidth(), + modifier = Modifier.height(50.dp).padding(start = 16.dp, end = 16.dp).fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween, - verticalGravity = Alignment.CenterVertically + verticalAlignment = Alignment.CenterVertically ) { - Clickable(onClick = { scaffoldState.drawerState = DrawerState.Opened }) { + Box( + modifier = Modifier.clickable( + onClick = { + coroutineScope.launch { + scaffoldState.drawerState.open() + } + } + ) + ) { Image( - imageResource(R.drawable.profile_image), - modifier = Modifier.preferredSize(34.dp).clip(shape = RoundedCornerShape(17.dp)), + painterResource(R.drawable.profile_image), + contentDescription = null, + modifier = Modifier.size(34.dp).clip(shape = RoundedCornerShape(17.dp)), contentScale = ContentScale.Crop ) } - Image(imageResource(R.drawable.ic_twitter), modifier = Modifier.preferredSize(22.dp)) - Image(imageResource(R.drawable.ic_trends), modifier = Modifier.preferredSize(24.dp)) + Image(painterResource(R.drawable.ic_twitter), contentDescription = null, modifier = Modifier.size(22.dp)) + Image(painterResource(R.drawable.ic_trends), contentDescription = null, modifier = Modifier.size(24.dp)) } } } - diff --git a/app/src/main/java/com/sudo/rizwan/twitterclone/ui/profile/Profile.kt b/app/src/main/java/com/sudo/rizwan/twitterclone/ui/profile/Profile.kt index fecd2bd..f484c55 100644 --- a/app/src/main/java/com/sudo/rizwan/twitterclone/ui/profile/Profile.kt +++ b/app/src/main/java/com/sudo/rizwan/twitterclone/ui/profile/Profile.kt @@ -1,25 +1,44 @@ package com.sudo.rizwan.twitterclone.ui.profile -import androidx.compose.Composable -import androidx.ui.core.ContentScale -import androidx.ui.core.Modifier -import androidx.ui.core.clip -import androidx.ui.core.tag -import androidx.ui.foundation.* -import androidx.ui.foundation.shape.corner.RoundedCornerShape -import androidx.ui.graphics.Color -import androidx.ui.layout.* -import androidx.ui.material.Button -import androidx.ui.material.IconButton -import androidx.ui.material.icons.Icons -import androidx.ui.material.icons.filled.ArrowBack -import androidx.ui.material.icons.filled.MoreVert -import androidx.ui.res.imageResource -import androidx.ui.unit.dp +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.Image +import androidx.compose.foundation.border +import androidx.compose.foundation.layout.Arrangement +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.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.verticalScroll +import androidx.compose.material.Button +import androidx.compose.material.ButtonDefaults +import androidx.compose.material.Icon +import androidx.compose.material.IconButton +import androidx.compose.material.Text +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.ArrowBack +import androidx.compose.material.icons.filled.MoreVert +import androidx.compose.runtime.Composable +import androidx.compose.runtime.livedata.observeAsState +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.layout.layoutId +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.unit.dp +import androidx.constraintlayout.compose.ConstraintLayout +import androidx.constraintlayout.compose.ConstraintSet +import androidx.lifecycle.viewmodel.compose.viewModel +import com.sudo.rizwan.twitterclone.lightThemeColors import com.sudo.rizwan.twitterclone.models.User -import com.sudo.rizwan.twitterclone.state.AppState +import com.sudo.rizwan.twitterclone.state.AppStateViewModel import com.sudo.rizwan.twitterclone.state.Screen -import com.sudo.rizwan.twitterclone.state.navigateTo import com.sudo.rizwan.twitterclone.state.tweets import com.sudo.rizwan.twitterclone.ui.common.CustomDivider import com.sudo.rizwan.twitterclone.ui.common.TweetLayout @@ -27,27 +46,36 @@ import com.sudo.rizwan.twitterclone.ui.common.UserInfo @Composable fun Profile(user: User) { - VerticalScroller { + Box( + modifier = Modifier.verticalScroll(state = rememberScrollState()) + ) { ConstraintLayout(constraintSet = ConstraintSet { - val banner = tag("banner") - val closeButton = tag("close") - val moreButton = tag("more") - val avatar = tag("avatar") - val content = tag("content") - val followButton = tag("follow") - avatar.top constrainTo banner.bottom - avatar.bottom constrainTo banner.bottom - avatar.left constrainTo parent.left - avatar.left.margin = 16.dp - followButton.top constrainTo banner.bottom - followButton.right constrainTo parent.right - followButton.right.margin = 16.dp - followButton.top.margin = 16.dp - closeButton.top constrainTo parent.top - closeButton.left constrainTo parent.left - moreButton.top constrainTo parent.top - moreButton.right constrainTo parent.right - content.top constrainTo banner.bottom + val banner = createRefFor("banner") + val closeButton = createRefFor("close") + val moreButton = createRefFor("more") + val avatar = createRefFor("avatar") + val content = createRefFor("content") + val followButton = createRefFor("follow") + constrain(avatar) { + top.linkTo(banner.bottom) + bottom.linkTo(banner.bottom) + start.linkTo(parent.start, 16.dp) + } + constrain(followButton) { + top.linkTo(banner.bottom, 16.dp) + end.linkTo(parent.end, 16.dp) + } + constrain(closeButton) { + top.linkTo(parent.top) + start.linkTo(parent.start) + } + constrain(moreButton) { + top.linkTo(parent.top) + end.linkTo(parent.end) + } + constrain(content) { + top.linkTo(banner.bottom) + } }) { Banner(user) FollowButton() @@ -60,14 +88,14 @@ fun Profile(user: User) { @Composable private fun ProfileContent(user: User) { - Column(modifier = Modifier.tag("content")) { + Column(modifier = Modifier.layoutId("content")) { Column(modifier = Modifier.padding(start = 16.dp, end = 16.dp)) { - Spacer(modifier = Modifier.preferredHeight(44.dp)) + Spacer(modifier = Modifier.height(44.dp)) UserInfo( user = user, showBio = true ) - Spacer(modifier = Modifier.preferredHeight(16.dp)) + Spacer(modifier = Modifier.height(16.dp)) } CustomDivider() tweets.filter { it.user == user }.forEach { tweet -> @@ -79,14 +107,18 @@ private fun ProfileContent(user: User) { @Composable private fun Avatar(user: User) { + val appState = viewModel() + val theme = appState.theme.observeAsState(lightThemeColors) + Image( - imageResource(user.avatar), + painterResource(user.avatar), + contentDescription = null, modifier = Modifier - .preferredSize(80.dp) + .size(80.dp) .clip(shape = RoundedCornerShape(40.dp)) - .tag("avatar") - .drawBorder( - border = Border(size = 3.dp, color = AppState.theme.surface), + .layoutId("avatar") + .border( + border = BorderStroke(3.dp, color = theme.value!!.surface), shape = RoundedCornerShape(40.dp) ), contentScale = ContentScale.Crop @@ -95,44 +127,52 @@ private fun Avatar(user: User) { @Composable private fun TopBar() { + val appState = viewModel() + Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween ) { IconButton( - modifier = Modifier.tag("close"), - onClick = { navigateTo(Screen.Home) }) { - Icon(asset = Icons.Filled.ArrowBack, tint = Color.White) + modifier = Modifier.layoutId("close"), + onClick = { appState.navigateTo(Screen.Home) }) { + Icon(Icons.Filled.ArrowBack, contentDescription = null, tint = Color.White) } - IconButton(modifier = Modifier.tag("more"), onClick = {}) { - Icon(asset = Icons.Filled.MoreVert, tint = Color.White) + IconButton(modifier = Modifier.layoutId("more"), onClick = {}) { + Icon(Icons.Filled.MoreVert, contentDescription = null, tint = Color.White) } } } @Composable private fun FollowButton() { + val appState = viewModel() + val theme = appState.theme.observeAsState(lightThemeColors) + Button( - modifier = Modifier.tag("follow"), + modifier = Modifier.layoutId("follow"), onClick = { }, shape = RoundedCornerShape(20.dp), - backgroundColor = AppState.theme.surface, - border = Border(1.dp, AppState.theme.primary) + colors = ButtonDefaults.buttonColors( + backgroundColor = theme.value!!.surface + ), + border = BorderStroke(1.dp, theme.value!!.primary) ) { - Text(text = "Follow", color = AppState.theme.primary) + Text(text = "Follow", color = theme.value!!.primary) } } @Composable private fun Banner(user: User) { Image( - imageResource(user.banner), + painterResource(user.banner), + contentDescription = null, modifier = Modifier - .preferredHeight(180.dp) + .height(180.dp) .fillMaxWidth() - .tag("banner"), + .layoutId("banner"), contentScale = ContentScale.Crop ) } diff --git a/build.gradle b/build.gradle index d1acb2a..fb8eaa2 100644 --- a/build.gradle +++ b/build.gradle @@ -1,17 +1,14 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { - ext.kotlin_version = '1.3.72' - - def compose_release_version = "dev13" - ext.compose_version = "0.1.0-$compose_release_version" - ext.compose_compiler_extension_version = "0.1.0-$compose_release_version" + ext.kotlin_version = '1.4.30' + ext.compose_version = '1.0.0-beta01' repositories { google() jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:4.2.0-alpha01' + classpath 'com.android.tools.build:gradle:7.0.0-alpha09' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" // NOTE: Do not place your application dependencies here; they belong diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 137a010..9ea9748 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-rc-1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.2-bin.zip