Skip to content

Commit

Permalink
Implement welcome/login screen animations;
Browse files Browse the repository at this point in the history
Fix default avatar colors on login screen;
  • Loading branch information
AleksandarIlic committed Mar 6, 2024
1 parent 7c5ab6c commit 53ecd1a
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 20 deletions.
32 changes: 30 additions & 2 deletions app/src/main/kotlin/net/primal/android/auth/login/LoginScreen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material3.CenterAlignedTopAppBar
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBarDefaults
Expand Down Expand Up @@ -62,6 +63,7 @@ import net.primal.android.core.compose.detectUiDensityModeFromMaxHeight
import net.primal.android.core.compose.foundation.keyboardVisibilityAsState
import net.primal.android.core.compose.icons.PrimalIcons
import net.primal.android.core.compose.icons.primaliconpack.ArrowBack
import net.primal.android.core.compose.icons.primaliconpack.AvatarDefault
import net.primal.android.core.compose.isCompactOrLower
import net.primal.android.core.utils.isValidNostrPrivateKey
import net.primal.android.core.utils.isValidNostrPublicKey
Expand All @@ -75,6 +77,7 @@ fun LoginScreen(
onClose: () -> Unit,
onLoginSuccess: (String) -> Unit,
) {
val keyboardController = LocalSoftwareKeyboardController.current
LaunchedEffect(viewModel, onLoginSuccess) {
viewModel.effect.collect {
when (it) {
Expand All @@ -89,7 +92,10 @@ fun LoginScreen(
LoginScreen(
state = uiState.value,
eventPublisher = { viewModel.setEvent(it) },
onClose = onClose,
onClose = {
keyboardController?.hide()
onClose()
},
)
}

Expand Down Expand Up @@ -202,8 +208,10 @@ fun LoginContent(
AvatarThumbnail(
avatarCdnImage = profileDetails.avatarCdnImage,
avatarSize = 100.dp,
hasBorder = true,
hasBorder = profileDetails.avatarCdnImage != null,
borderColor = Color.White,
backgroundColor = defaultAvatarBackground,
defaultAvatar = { DefaultAvatar() },
)

Spacer(modifier = Modifier.height(16.dp))
Expand Down Expand Up @@ -373,6 +381,26 @@ fun LoginContent(
}
}

private val defaultAvatarBackground = Color(0xFF7E382C)
private val defaultAvatarForeground = Color(0xFFFDB7AB)

@Composable
private fun DefaultAvatar() {
Box(
modifier = Modifier
.background(color = defaultAvatarBackground)
.fillMaxSize(),
contentAlignment = Alignment.Center,
) {
Icon(
imageVector = PrimalIcons.AvatarDefault,
contentDescription = null,
modifier = Modifier.fillMaxSize(),
tint = defaultAvatarForeground,
)
}
}

@Composable
fun LaunchedErrorHandler(viewModel: LoginViewModel) {
val genericMessage = stringResource(id = R.string.app_generic_error)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ fun AvatarThumbnail(
avatarSize: Dp = 48.dp,
hasBorder: Boolean = false,
borderColor: Color = AppTheme.colorScheme.primary,
backgroundColor: Color = AppTheme.extraColorScheme.surfaceVariantAlt1,
onClick: (() -> Unit)? = null,
defaultAvatar: @Composable () -> Unit = { DefaultAvatarThumbnailPlaceholderListItemImage() },
) {
val variant = avatarCdnImage?.variants?.minByOrNull { it.width }
val imageSource = variant?.mediaUrl ?: avatarCdnImage?.sourceUrl
Expand All @@ -42,7 +44,9 @@ fun AvatarThumbnail(
source = imageSource,
hasBorder = hasBorder,
borderColor = borderColor,
backgroundColor = backgroundColor,
onClick = onClick,
defaultAvatar = defaultAvatar,
)
}

Expand All @@ -53,7 +57,9 @@ private fun AvatarThumbnailListItemImage(
avatarSize: Dp = 48.dp,
hasBorder: Boolean = false,
borderColor: Color = AppTheme.colorScheme.primary,
backgroundColor: Color = AppTheme.extraColorScheme.surfaceVariantAlt1,
onClick: (() -> Unit)? = null,
defaultAvatar: @Composable () -> Unit,
) {
SubcomposeAsyncImage(
model = source,
Expand All @@ -70,10 +76,10 @@ private fun AvatarThumbnailListItemImage(
Box(
modifier = Modifier
.fillMaxSize()
.background(color = AppTheme.extraColorScheme.surfaceVariantAlt1),
.background(color = backgroundColor),
)
},
error = { DefaultAvatarThumbnailPlaceholderListItemImage() },
error = { defaultAvatar() },
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,6 @@ import net.primal.android.theme.PrimalTheme
import net.primal.android.theme.domain.PrimalTheme
import net.primal.android.thread.ThreadScreen
import net.primal.android.thread.ThreadViewModel
import timber.log.Timber

private fun NavController.navigateToWelcome() =
navigate(
Expand Down Expand Up @@ -428,14 +427,18 @@ private fun NavGraphBuilder.welcome(route: String, navController: NavController)
composable(
route = route,
enterTransition = {
Timber.e("Enter initialState = ${this.initialState.destination}")
Timber.e("Enter targetState = ${this.targetState.destination}")
slideInHorizontally(initialOffsetX = { -it })
if (initialState.destination.route in listOf("login", "create_account")) {
slideInHorizontally(initialOffsetX = { -it })
} else {
null
}
},
exitTransition = {
Timber.e("Exit initialState = ${this.initialState.destination}")
Timber.e("Exit targetState = ${this.targetState.destination}")
slideOutHorizontally(targetOffsetX = { -it })
if (targetState.destination.route in listOf("login", "create_account")) {
slideOutHorizontally(targetOffsetX = { -it })
} else {
null
}
},
) {
LockToOrientationPortrait()
Expand All @@ -453,14 +456,18 @@ private fun NavGraphBuilder.login(route: String, navController: NavController) =
composable(
route = route,
enterTransition = {
Timber.e("Enter initialState = ${this.initialState.destination}")
Timber.e("Enter targetState = ${this.targetState.destination}")
slideInHorizontally(initialOffsetX = { it })
if (initialState.destination.route == "welcome") {
slideInHorizontally(initialOffsetX = { it })
} else {
null
}
},
exitTransition = {
Timber.e("Exit initialState = ${this.initialState.destination}")
Timber.e("Exit targetState = ${this.targetState.destination}")
slideOutHorizontally(targetOffsetX = { it })
if (targetState.destination.route == "welcome") {
slideOutHorizontally(targetOffsetX = { it })
} else {
null
}
},
) {
val viewModel: LoginViewModel = hiltViewModel(it)
Expand All @@ -478,8 +485,20 @@ private fun NavGraphBuilder.login(route: String, navController: NavController) =
private fun NavGraphBuilder.createAccount(route: String, navController: NavController) =
composable(
route = route,
enterTransition = { slideInHorizontally(initialOffsetX = { it }) },
exitTransition = { slideOutHorizontally(targetOffsetX = { it }) },
enterTransition = {
if (initialState.destination.route == "welcome") {
slideInHorizontally(initialOffsetX = { it })
} else {
null
}
},
exitTransition = {
if (targetState.destination.route == "welcome") {
slideOutHorizontally(targetOffsetX = { it })
} else {
null
}
},
) {
val viewModel: CreateAccountViewModel = hiltViewModel(it)
PrimalTheme(PrimalTheme.Sunset) {
Expand All @@ -502,8 +521,8 @@ private fun NavGraphBuilder.feed(
arguments = arguments,
) { navBackEntry ->
val viewModel = hiltViewModel<FeedViewModel>(navBackEntry)
AdjustSystemColors(primalTheme = LocalPrimalTheme.current)
LockToOrientationPortrait()
AdjustSystemColors(primalTheme = LocalPrimalTheme.current)
FeedScreen(
viewModel = viewModel,
onFeedsClick = { navController.navigateToFeedList() },
Expand Down

0 comments on commit 53ecd1a

Please sign in to comment.