diff --git a/app/detekt-baseline.xml b/app/detekt-baseline.xml
index c01f3c83..c9e279dc 100644
--- a/app/detekt-baseline.xml
+++ b/app/detekt-baseline.xml
@@ -21,8 +21,7 @@
CyclomaticComplexMethod:ProfileDetailsScreen.kt$@Composable private fun ErrorHandler(error: ProfileError?, snackbarHostState: SnackbarHostState)
CyclomaticComplexMethod:ProfileDetailsScreen.kt$@Suppress("MagicNumber") @OptIn(ExperimentalFoundationApi::class, ExperimentalMaterial3Api::class) @Composable fun ProfileDetailsScreen( state: ProfileDetailsContract.UiState, onClose: () -> Unit, onPostClick: (String) -> Unit, onPostReplyClick: (String) -> Unit, onPostQuoteClick: (String) -> Unit, onProfileClick: (String) -> Unit, onEditProfileClick: () -> Unit, onMessageClick: (String) -> Unit, onZapProfileClick: (DraftTx) -> Unit, onHashtagClick: (String) -> Unit, onMediaClick: (String, String) -> Unit, onGoToWallet: () -> Unit, onFollowsClick: (String, ProfileFollowsType) -> Unit, eventPublisher: (ProfileDetailsContract.UiEvent) -> Unit, )
CyclomaticComplexMethod:ThreadScreen.kt$@OptIn(ExperimentalMaterial3Api::class) @Composable fun ThreadScreen( state: ThreadContract.UiState, onClose: () -> Unit, onPostClick: (String) -> Unit, onPostReplyClick: (String) -> Unit, onPostQuoteClick: (String) -> Unit, onProfileClick: (String) -> Unit, onHashtagClick: (String) -> Unit, onMediaClick: (String, String) -> Unit, onGoToWallet: () -> Unit, onReplyInNoteEditor: (String, Uri?, String) -> Unit, eventPublisher: (ThreadContract.UiEvent) -> Unit, )
- CyclomaticComplexMethod:TransactionEditor.kt$@Composable private fun TransactionHeaderColumn( modifier: Modifier, uiMode: UiMode, state: CreateTransactionContract.UiState, keyboardVisible: Boolean, onAmountClick: () -> Unit, )
- CyclomaticComplexMethod:TransactionEditor.kt$@ExperimentalMaterial3Api @ExperimentalComposeUiApi @Composable fun TransactionEditor( modifier: Modifier, state: CreateTransactionContract.UiState, paddingValues: PaddingValues, eventPublisher: (CreateTransactionContract.UiEvent) -> Unit, onCancelClick: () -> Unit, )
+ CyclomaticComplexMethod:TransactionEditor.kt$@Composable private fun TransactionHeaderColumn( modifier: Modifier, uiMode: UiDensityMode, state: CreateTransactionContract.UiState, keyboardVisible: Boolean, onAmountClick: () -> Unit, )
CyclomaticComplexMethod:WalletDashboardScreen.kt$@OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class) @Composable fun WalletDashboardScreen( state: WalletDashboardContract.UiState, onPrimaryDestinationChanged: (PrimalTopLevelDestination) -> Unit, onDrawerDestinationClick: (DrawerScreenDestination) -> Unit, onWalletActivateClick: () -> Unit, onProfileClick: (String) -> Unit, onTransactionClick: (String) -> Unit, onSendClick: () -> Unit, onScanClick: () -> Unit, onReceiveClick: () -> Unit, eventPublisher: (UiEvent) -> Unit, )
CyclomaticComplexMethod:WalletTransactionsMediator.kt$WalletTransactionsMediator$override suspend fun load(loadType: LoadType, state: PagingState<Int, WalletTransaction>): MediatorResult
DestructuringDeclarationWithTooManyEntries:PrimalDrawer.kt$val (avatarRef, usernameRef, iconRef, identifierRef, statsRef) = createRefs()
@@ -63,7 +62,7 @@
LongMethod:SendPaymentScreen.kt$@OptIn(ExperimentalMaterial3Api::class) @Composable fun SendPaymentScreen( state: SendPaymentContract.UiState, eventPublisher: (SendPaymentContract.UiEvent) -> Unit, onClose: () -> Unit, )
LongMethod:ThreadScreen.kt$@OptIn(ExperimentalComposeUiApi::class) @Composable fun ReplyToBottomBar( modifier: Modifier, publishingReply: Boolean, replyToAuthorName: String, replyToAuthorHandle: String, replyTextProvider: () -> String, onPublishReplyClick: () -> Unit, onReplyUpdated: (String) -> Unit, onPhotoImported: (Uri) -> Unit, onExpand: () -> Unit, )
LongMethod:ThreadScreen.kt$@OptIn(ExperimentalMaterial3Api::class) @Composable fun ThreadScreen( state: ThreadContract.UiState, onClose: () -> Unit, onPostClick: (String) -> Unit, onPostReplyClick: (String) -> Unit, onPostQuoteClick: (String) -> Unit, onProfileClick: (String) -> Unit, onHashtagClick: (String) -> Unit, onMediaClick: (String, String) -> Unit, onGoToWallet: () -> Unit, onReplyInNoteEditor: (String, Uri?, String) -> Unit, eventPublisher: (ThreadContract.UiEvent) -> Unit, )
- LongMethod:TransactionEditor.kt$@Composable private fun TransactionHeaderColumn( modifier: Modifier, uiMode: UiMode, state: CreateTransactionContract.UiState, keyboardVisible: Boolean, onAmountClick: () -> Unit, )
+ LongMethod:TransactionEditor.kt$@Composable private fun TransactionHeaderColumn( modifier: Modifier, uiMode: UiDensityMode, state: CreateTransactionContract.UiState, keyboardVisible: Boolean, onAmountClick: () -> Unit, )
LongMethod:TransactionEditor.kt$@ExperimentalMaterial3Api @ExperimentalComposeUiApi @Composable fun TransactionEditor( modifier: Modifier, state: CreateTransactionContract.UiState, paddingValues: PaddingValues, eventPublisher: (CreateTransactionContract.UiEvent) -> Unit, onCancelClick: () -> Unit, )
LongMethod:WalletActivationScreen.kt$@ExperimentalComposeUiApi @Composable private fun WalletCodeActivationInput( working: Boolean, error: Throwable?, email: String, onCodeChanged: () -> Unit, onCodeConfirmation: (String) -> Unit, isKeyboardVisible: Boolean, )
LongMethod:WalletActivationScreen.kt$@Suppress("MagicNumber") @OptIn(ExperimentalMaterial3Api::class) @ExperimentalComposeUiApi @Composable private fun WalletActivationDataInput( data: WalletActivationData, working: Boolean, error: Throwable?, onErrorDismiss: () -> Unit, onDataChanged: (WalletActivationData) -> Unit, onActivationCodeRequest: (WalletActivationData) -> Unit, )
@@ -132,8 +131,6 @@
MagicNumber:Timestamps.kt$7
MagicNumber:ValidationUtils.kt$32
MagicNumber:WalletDashboardScreen.kt$0.42f
- MagicNumber:WelcomeScreen.kt$0.4f
- MagicNumber:WelcomeScreen.kt$0.6f
MagicNumber:ZapBottomSheet.kt$3
MatchingDeclarationName:__PrimalIcons.kt$PrimalIcons
NestedBlockDepth:FeedRemoteMediator.kt$FeedRemoteMediator$override suspend fun load(loadType: LoadType, state: PagingState<Int, FeedPost>): MediatorResult
@@ -151,7 +148,6 @@
ThrowingExceptionsWithoutMessageOrCause:ThreadViewModel.kt$ThreadViewModel$IllegalStateException()
ThrowsCount:FileUploader.kt$FileUploader$@Throws(UnsuccessfulFileUpload::class) suspend fun uploadFile(userId: String, uri: Uri): String
ThrowsCount:LnInvoiceUtils.kt$LnInvoiceUtils$private fun decodeUnlimitedLength(invoice: String): Boolean
- ThrowsCount:PrimalApiClient.kt$PrimalApiClient$@Throws(WssException::class) suspend fun query(message: PrimalCacheFilter): PrimalQueryResult
TooGenericExceptionCaught:NostrIncomingMessageParser.kt$error: Exception
TooManyFunctions:ConversionUtils.kt$net.primal.android.crypto.ConversionUtils.kt
TooManyFunctions:NostrNotary.kt$NostrNotary
diff --git a/app/src/main/kotlin/net/primal/android/attachments/gallery/MediaGalleryScreen.kt b/app/src/main/kotlin/net/primal/android/attachments/gallery/MediaGalleryScreen.kt
index 41fc379a..25929f3e 100644
--- a/app/src/main/kotlin/net/primal/android/attachments/gallery/MediaGalleryScreen.kt
+++ b/app/src/main/kotlin/net/primal/android/attachments/gallery/MediaGalleryScreen.kt
@@ -118,12 +118,8 @@ fun MediaGalleryScreen(
}
},
actionLabel = stringResource(id = R.string.media_gallery_retry_save),
- onErrorDismiss = {
- eventPublisher(MediaGalleryContract.UiEvent.DismissError)
- },
- onActionPerformed = {
- currentImage()?.let { eventPublisher(MediaGalleryContract.UiEvent.SaveMedia(it.url)) }
- },
+ onErrorDismiss = { eventPublisher(MediaGalleryContract.UiEvent.DismissError) },
+ onActionPerformed = { currentImage()?.let { eventPublisher(MediaGalleryContract.UiEvent.SaveMedia(it.url)) } },
)
Scaffold(
diff --git a/app/src/main/kotlin/net/primal/android/auth/welcome/WelcomeScreen.kt b/app/src/main/kotlin/net/primal/android/auth/welcome/WelcomeScreen.kt
index 5c718e3e..50888d1d 100644
--- a/app/src/main/kotlin/net/primal/android/auth/welcome/WelcomeScreen.kt
+++ b/app/src/main/kotlin/net/primal/android/auth/welcome/WelcomeScreen.kt
@@ -8,128 +8,163 @@ import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
-import androidx.compose.foundation.layout.navigationBarsPadding
+import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.systemBarsPadding
+import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.widthIn
-import androidx.compose.foundation.layout.wrapContentWidth
-import androidx.compose.foundation.shape.CircleShape
-import androidx.compose.material3.Surface
+import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
-import androidx.compose.ui.draw.shadow
-import androidx.compose.ui.platform.LocalDensity
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.IntOffset
+import androidx.compose.ui.unit.IntSize
+import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
+import kotlin.math.roundToInt
import net.primal.android.R
+import net.primal.android.core.compose.ApplySystemBarColors
import net.primal.android.core.compose.ToSAndPrivacyPolicyText
-import net.primal.android.core.compose.button.PrimalCallToActionButton
-import net.primal.android.core.compose.fadingBottomEdge
+import net.primal.android.core.compose.UiDensityMode
+import net.primal.android.core.compose.button.PrimalFilledButton
+import net.primal.android.core.compose.detectUiDensityModeFromMaxHeight
import net.primal.android.theme.AppTheme
import net.primal.android.theme.PrimalTheme
import net.primal.android.theme.domain.PrimalTheme
@Composable
fun WelcomeScreen(onSignInClick: () -> Unit, onCreateAccountClick: () -> Unit) {
- Surface(
- modifier = Modifier
- .systemBarsPadding()
- .navigationBarsPadding()
- .fillMaxSize(),
- ) {
- Column(
+ ApplySystemBarColors(
+ statusBarColor = Color.Transparent,
+ navigationBarColor = Color.Transparent,
+ )
+ BoxWithConstraints {
+ val uiMode = this.maxHeight.detectUiDensityModeFromMaxHeight()
+
+ Image(
modifier = Modifier.fillMaxSize(),
+ imageVector = ImageVector.vectorResource(id = R.drawable.onboarding_bg_full),
+ contentScale = ContentScale.FillHeight,
+ alignment = OnboardingAlignment(fullXOffset = 0.0f),
+ contentDescription = null,
+ )
+
+ Column(
+ modifier = Modifier
+ .fillMaxSize()
+ .systemBarsPadding(),
) {
Column(
- modifier = Modifier
- .padding(top = 32.dp)
- .weight(0.6f)
- .fillMaxSize(),
+ modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally,
) {
Image(
- painter = painterResource(id = R.drawable.primal_logo),
+ modifier = Modifier
+ .widthIn(240.dp, MAX_COMPONENT_WIDTH.dp)
+ .heightIn(
+ 0.dp,
+ this@BoxWithConstraints.maxHeight * when (uiMode) {
+ UiDensityMode.Normal, UiDensityMode.Comfortable -> ONE_HALF
+ else -> TWO_FIFTHS
+ },
+ )
+ .fillMaxWidth(),
+ painter = painterResource(id = R.drawable.welcome),
contentDescription = null,
+ alignment = Alignment.BottomCenter,
)
Image(
- modifier = Modifier
- .wrapContentWidth()
- .padding(bottom = 40.dp)
- .fadingBottomEdge()
- .shadow(
- elevation = 128.dp,
- shape = CircleShape,
- clip = false,
- ambientColor = AppTheme.colorScheme.primary,
- spotColor = AppTheme.colorScheme.primary,
- ),
- painter = painterResource(id = R.drawable.welcome),
+ modifier = Modifier.width(200.dp),
+ painter = painterResource(id = R.drawable.primal_logo),
contentDescription = null,
- alignment = Alignment.BottomCenter,
)
- }
- BoxWithConstraints(
- modifier = Modifier.weight(0.4f),
- contentAlignment = Alignment.TopCenter,
- ) {
- val maxHeight = with(LocalDensity.current) { maxHeight.roundToPx() }
- Column(
- modifier = Modifier.fillMaxSize(),
- verticalArrangement = Arrangement.Top,
- horizontalAlignment = Alignment.CenterHorizontally,
- ) {
- PrimalCallToActionButton(
- modifier = Modifier
- .widthIn(0.dp, 420.dp)
- .fillMaxWidth()
- .padding(horizontal = 32.dp),
- title = stringResource(id = R.string.welcome_create_account_button_title),
- subtitle = if (maxHeight > MIN_HEIGHT_FOR_SUBTITLE) {
- stringResource(id = R.string.welcome_create_account_button_subtitle)
- } else {
- null
+ Text(
+ modifier = Modifier.padding(vertical = 8.dp),
+ text = "The Social Bitcoin Wallet",
+ style = AppTheme.typography.bodyMedium.copy(
+ color = Color.White,
+ fontSize = 18.sp,
+ lineHeight = 24.sp,
+ ),
+ )
+
+ Spacer(
+ modifier = Modifier.height(
+ when (uiMode) {
+ UiDensityMode.Normal -> 24.dp
+ UiDensityMode.Comfortable -> 20.dp
+ else -> 16.dp
},
- onClick = onCreateAccountClick,
- )
+ ),
+ )
- Spacer(modifier = Modifier.height(16.dp))
+ WelcomeButton(
+ text = stringResource(id = R.string.welcome_sign_in_button_title),
+ onClick = onSignInClick,
+ )
- PrimalCallToActionButton(
- modifier = Modifier
- .widthIn(0.dp, 420.dp)
- .fillMaxWidth()
- .padding(horizontal = 32.dp),
- title = stringResource(id = R.string.welcome_sign_in_button_title),
- subtitle = if (maxHeight > MIN_HEIGHT_FOR_SUBTITLE) {
- stringResource(id = R.string.welcome_sign_in_button_subtitle)
- } else {
- null
- },
- onClick = onSignInClick,
- )
+ Spacer(modifier = Modifier.height(8.dp))
- Spacer(modifier = Modifier.height(16.dp))
+ WelcomeButton(
+ text = stringResource(id = R.string.welcome_create_account_button_title),
+ onClick = onCreateAccountClick,
+ )
- ToSAndPrivacyPolicyText(
- modifier = Modifier
- .widthIn(0.dp, 360.dp)
- .fillMaxWidth()
- .padding(horizontal = 32.dp),
- tosPrefix = stringResource(id = R.string.welcome_tos_prefix),
- )
- }
+ ToSAndPrivacyPolicyText(
+ modifier = Modifier
+ .widthIn(0.dp, MAX_COMPONENT_WIDTH.dp)
+ .fillMaxWidth()
+ .padding(top = 16.dp),
+ color = Color.White,
+ fontSize = 16.sp,
+ linksColor = Color.White,
+ tosPrefix = stringResource(id = R.string.welcome_tos_prefix),
+ )
}
}
}
}
-private const val MIN_HEIGHT_FOR_SUBTITLE = 500
+class OnboardingAlignment(var fullXOffset: Float = 0.0f) : Alignment {
+ override fun align(
+ size: IntSize,
+ space: IntSize,
+ layoutDirection: LayoutDirection,
+ ): IntOffset {
+ val shiftedX = (fullXOffset * (size.width - space.width)) * -1f
+ val centerY = (space.height - size.height).toFloat()
+ return IntOffset(shiftedX.roundToInt(), centerY.roundToInt())
+ }
+}
+
+@Composable
+private fun WelcomeButton(text: String, onClick: () -> Unit) {
+ PrimalFilledButton(
+ modifier = Modifier
+ .widthIn(240.dp, MAX_COMPONENT_WIDTH.dp)
+ .fillMaxWidth(),
+ containerColor = Color.Black,
+ contentColor = Color.White,
+ onClick = onClick,
+ ) {
+ Text(text = text)
+ }
+}
+
+private const val MAX_COMPONENT_WIDTH = 320
+private const val ONE_HALF = 0.5f
+private const val TWO_FIFTHS = 0.4f
@Preview
@Composable
diff --git a/app/src/main/kotlin/net/primal/android/core/compose/ToS.kt b/app/src/main/kotlin/net/primal/android/core/compose/ToS.kt
index 69a9aa6d..b65992a4 100644
--- a/app/src/main/kotlin/net/primal/android/core/compose/ToS.kt
+++ b/app/src/main/kotlin/net/primal/android/core/compose/ToS.kt
@@ -2,12 +2,16 @@ package net.primal.android.core.compose
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalUriHandler
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.style.TextAlign
+import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.text.withStyle
+import androidx.compose.ui.unit.TextUnit
+import androidx.compose.ui.unit.sp
import net.primal.android.R
import net.primal.android.core.ext.openUriSafely
import net.primal.android.theme.AppTheme
@@ -19,8 +23,14 @@ private const val PRIMAL_TOS_URL = "https://www.primal.net/terms"
private const val PRIMAL_PRIVACY_POLICY_URL = "https://www.primal.net/privacy"
@Composable
-fun ToSAndPrivacyPolicyText(modifier: Modifier = Modifier, tosPrefix: String) {
- val linkSpanStyle = SpanStyle(color = AppTheme.colorScheme.primary)
+fun ToSAndPrivacyPolicyText(
+ tosPrefix: String,
+ modifier: Modifier = Modifier,
+ fontSize: TextUnit = 14.sp,
+ color: Color = AppTheme.extraColorScheme.onSurfaceVariantAlt3,
+ linksColor: Color = AppTheme.colorScheme.primary,
+) {
+ val linkSpanStyle = SpanStyle(color = linksColor, textDecoration = TextDecoration.Underline)
val annotatedString = buildAnnotatedString {
append(tosPrefix)
append("\n")
@@ -36,7 +46,6 @@ fun ToSAndPrivacyPolicyText(modifier: Modifier = Modifier, tosPrefix: String) {
withStyle(style = linkSpanStyle) {
append(stringResource(id = R.string.legal_privacy_policy_hint_highlighted_word))
}
- append(".")
pop()
}
@@ -45,7 +54,8 @@ fun ToSAndPrivacyPolicyText(modifier: Modifier = Modifier, tosPrefix: String) {
modifier = modifier,
text = annotatedString,
style = AppTheme.typography.bodySmall.copy(
- color = AppTheme.extraColorScheme.onSurfaceVariantAlt3,
+ color = color,
+ fontSize = fontSize,
textAlign = TextAlign.Center,
),
onClick = { position, offset ->
diff --git a/app/src/main/kotlin/net/primal/android/core/compose/UiDensityMode.kt b/app/src/main/kotlin/net/primal/android/core/compose/UiDensityMode.kt
new file mode 100644
index 00000000..97ae28d7
--- /dev/null
+++ b/app/src/main/kotlin/net/primal/android/core/compose/UiDensityMode.kt
@@ -0,0 +1,22 @@
+package net.primal.android.core.compose
+
+import androidx.compose.ui.unit.Dp
+import androidx.compose.ui.unit.dp
+
+enum class UiDensityMode {
+ Normal,
+ Comfortable,
+ Compact,
+ Unsupported,
+}
+
+fun Dp.detectUiDensityModeFromMaxHeight(): UiDensityMode {
+ return when {
+ this > 730.dp -> UiDensityMode.Normal
+ this < 730.dp && this > 680.dp -> UiDensityMode.Comfortable
+ this < 680.dp && this > 580.dp -> UiDensityMode.Compact
+ else -> UiDensityMode.Unsupported
+ }
+}
+
+fun UiDensityMode?.isCompactOrLower() = this == UiDensityMode.Compact || this == UiDensityMode.Unsupported
diff --git a/app/src/main/kotlin/net/primal/android/messages/chat/ChatScreen.kt b/app/src/main/kotlin/net/primal/android/messages/chat/ChatScreen.kt
index 540caada..d7eee78d 100644
--- a/app/src/main/kotlin/net/primal/android/messages/chat/ChatScreen.kt
+++ b/app/src/main/kotlin/net/primal/android/messages/chat/ChatScreen.kt
@@ -185,12 +185,8 @@ fun ChatScreen(
sendEnabled = state.newMessageText.isNotBlank() && !state.sending,
sending = state.sending,
participantUsername = participantUsername,
- onSend = {
- eventPublisher(ChatContract.UiEvent.SendMessage)
- },
- onValueChange = {
- eventPublisher(ChatContract.UiEvent.UpdateNewMessage(text = it))
- },
+ onSend = { eventPublisher(ChatContract.UiEvent.SendMessage) },
+ onValueChange = { eventPublisher(ChatContract.UiEvent.UpdateNewMessage(text = it)) },
)
}
},
diff --git a/app/src/main/kotlin/net/primal/android/navigation/PrimalAppNavigation.kt b/app/src/main/kotlin/net/primal/android/navigation/PrimalAppNavigation.kt
index 105254fc..a8d58064 100644
--- a/app/src/main/kotlin/net/primal/android/navigation/PrimalAppNavigation.kt
+++ b/app/src/main/kotlin/net/primal/android/navigation/PrimalAppNavigation.kt
@@ -1,6 +1,8 @@
package net.primal.android.navigation
import android.net.Uri
+import androidx.compose.animation.slideInHorizontally
+import androidx.compose.animation.slideOutHorizontally
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.platform.LocalContext
@@ -414,7 +416,11 @@ private fun NavGraphBuilder.splash(route: String) =
}
private fun NavGraphBuilder.welcome(route: String, navController: NavController) =
- composable(route = route) {
+ composable(
+ route = route,
+ enterTransition = { slideInHorizontally(initialOffsetX = { -it }) },
+ exitTransition = { slideOutHorizontally(targetOffsetX = { -it }) },
+ ) {
LockToOrientationPortrait()
PrimalTheme(PrimalTheme.Sunset) {
WelcomeScreen(
@@ -425,7 +431,11 @@ private fun NavGraphBuilder.welcome(route: String, navController: NavController)
}
private fun NavGraphBuilder.login(route: String, navController: NavController) =
- composable(route = route) {
+ composable(
+ route = route,
+ enterTransition = { slideInHorizontally(initialOffsetX = { it }) },
+ exitTransition = { slideOutHorizontally(targetOffsetX = { it }) },
+ ) {
val viewModel: LoginViewModel = hiltViewModel(it)
PrimalTheme(PrimalTheme.Sunset) {
LoginScreen(
@@ -437,7 +447,11 @@ private fun NavGraphBuilder.login(route: String, navController: NavController) =
}
private fun NavGraphBuilder.createAccount(route: String, navController: NavController) =
- composable(route = route) {
+ composable(
+ route = route,
+ enterTransition = { slideInHorizontally(initialOffsetX = { it }) },
+ exitTransition = { slideOutHorizontally(targetOffsetX = { it }) },
+ ) {
val viewModel: CreateAccountViewModel = hiltViewModel(it)
PrimalTheme(PrimalTheme.Sunset) {
CreateAccountScreen(
diff --git a/app/src/main/kotlin/net/primal/android/wallet/transactions/send/create/ui/TransactionEditor.kt b/app/src/main/kotlin/net/primal/android/wallet/transactions/send/create/ui/TransactionEditor.kt
index 4995f631..35f50287 100644
--- a/app/src/main/kotlin/net/primal/android/wallet/transactions/send/create/ui/TransactionEditor.kt
+++ b/app/src/main/kotlin/net/primal/android/wallet/transactions/send/create/ui/TransactionEditor.kt
@@ -47,7 +47,6 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.style.TextAlign
-import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import java.math.BigDecimal
@@ -56,10 +55,13 @@ import net.primal.android.R
import net.primal.android.core.compose.AvatarThumbnail
import net.primal.android.core.compose.PrimalDefaults
import net.primal.android.core.compose.PrimalLoadingSpinner
+import net.primal.android.core.compose.UiDensityMode
import net.primal.android.core.compose.button.PrimalLoadingButton
+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.WalletBitcoinPayment
+import net.primal.android.core.compose.isCompactOrLower
import net.primal.android.core.compose.numericpad.PrimalNumericPad
import net.primal.android.theme.AppTheme
import net.primal.android.wallet.dashboard.ui.BtcAmountText
@@ -98,7 +100,7 @@ fun TransactionEditor(
}
val density = LocalDensity.current
- var uiMode by remember { mutableStateOf(null) }
+ var uiMode by remember { mutableStateOf(null) }
val layoutDirection = LocalLayoutDirection.current
Column(
@@ -114,7 +116,7 @@ fun TransactionEditor(
if (uiMode == null) {
uiMode = it.height
.toDp()
- .toUiMode()
+ .detectUiDensityModeFromMaxHeight()
}
}
},
@@ -124,7 +126,7 @@ fun TransactionEditor(
Column(horizontalAlignment = Alignment.CenterHorizontally) {
TransactionHeaderColumn(
modifier = Modifier.fillMaxWidth(),
- uiMode = uiMode ?: UiMode.Normal,
+ uiMode = uiMode ?: UiDensityMode.Normal,
state = state,
keyboardVisible = keyboardVisible,
onAmountClick = {
@@ -159,11 +161,11 @@ fun TransactionEditor(
}
var minAmountAlertVisible by remember { mutableStateOf(false) }
- val actionsRowHidden = (uiMode == UiMode.Compact || uiMode == UiMode.Unsupported) && keyboardVisible
+ val actionsRowHidden = uiMode.isCompactOrLower() && keyboardVisible
if (!actionsRowHidden) {
TransactionActionsRow(
state = state,
- uiMode = uiMode ?: UiMode.Normal,
+ uiMode = uiMode ?: UiDensityMode.Normal,
keyboardVisible = keyboardVisible,
isNumericPadOn = isNumericPadOn,
onCancelClick = onCancelClick,
@@ -188,22 +190,6 @@ fun TransactionEditor(
}
}
-private enum class UiMode {
- Normal,
- Comfortable,
- Compact,
- Unsupported,
-}
-
-private fun Dp.toUiMode(): UiMode {
- return when {
- this > 730.dp -> UiMode.Normal
- this < 730.dp && this > 680.dp -> UiMode.Comfortable
- this < 680.dp && this > 580.dp -> UiMode.Compact
- else -> UiMode.Unsupported
- }
-}
-
@ExperimentalMaterial3Api
@ExperimentalComposeUiApi
@Composable
@@ -269,7 +255,7 @@ private fun TransactionMainContent(
@Composable
private fun TransactionActionsRow(
state: CreateTransactionContract.UiState,
- uiMode: UiMode,
+ uiMode: UiDensityMode,
keyboardVisible: Boolean,
isNumericPadOn: Boolean,
onCancelClick: () -> Unit,
@@ -283,8 +269,8 @@ private fun TransactionActionsRow(
0.dp
} else {
when (uiMode) {
- UiMode.Normal -> 32.dp
- UiMode.Comfortable -> 8.dp
+ UiDensityMode.Normal -> 32.dp
+ UiDensityMode.Comfortable -> 8.dp
else -> 4.dp
}
},
@@ -325,7 +311,7 @@ private fun TransactionActionsRow(
@Composable
private fun TransactionHeaderColumn(
modifier: Modifier,
- uiMode: UiMode,
+ uiMode: UiDensityMode,
state: CreateTransactionContract.UiState,
keyboardVisible: Boolean,
onAmountClick: () -> Unit,
@@ -335,7 +321,7 @@ private fun TransactionHeaderColumn(
4.dp
} else {
when (uiMode) {
- UiMode.Normal, UiMode.Comfortable -> 16.dp
+ UiDensityMode.Normal, UiDensityMode.Comfortable -> 16.dp
else -> 4.dp
}
},
@@ -344,9 +330,9 @@ private fun TransactionHeaderColumn(
val avatarSize = animateDpAsState(
targetValue = if (keyboardVisible) {
when (uiMode) {
- UiMode.Normal -> 64.dp
- UiMode.Comfortable -> 48.dp
- UiMode.Compact -> 40.dp
+ UiDensityMode.Normal -> 64.dp
+ UiDensityMode.Comfortable -> 48.dp
+ UiDensityMode.Compact -> 40.dp
else -> 0.dp
}
} else {
@@ -360,8 +346,8 @@ private fun TransactionHeaderColumn(
0.dp
} else {
when (uiMode) {
- UiMode.Normal -> 32.dp
- UiMode.Comfortable -> 24.dp
+ UiDensityMode.Normal -> 32.dp
+ UiDensityMode.Comfortable -> 24.dp
else -> 8.dp
}
},
@@ -372,8 +358,8 @@ private fun TransactionHeaderColumn(
16.dp
} else {
when (uiMode) {
- UiMode.Normal -> 48.dp
- UiMode.Comfortable -> 32.dp
+ UiDensityMode.Normal -> 48.dp
+ UiDensityMode.Comfortable -> 32.dp
else -> 24.dp
}
},
@@ -439,15 +425,15 @@ private fun TransactionHeaderColumn(
modifier = Modifier
.padding(
start = when (uiMode) {
- UiMode.Normal -> 32.dp
- UiMode.Comfortable -> 26.dp
+ UiDensityMode.Normal -> 32.dp
+ UiDensityMode.Comfortable -> 26.dp
else -> 18.dp
},
)
.height(
when (uiMode) {
- UiMode.Normal -> 72.dp
- UiMode.Comfortable -> 64.dp
+ UiDensityMode.Normal -> 72.dp
+ UiDensityMode.Comfortable -> 64.dp
else -> 56.dp
},
)
diff --git a/app/src/main/res/drawable-nodpi/welcome.png b/app/src/main/res/drawable-nodpi/welcome.png
index 02263913..8809563f 100644
Binary files a/app/src/main/res/drawable-nodpi/welcome.png and b/app/src/main/res/drawable-nodpi/welcome.png differ
diff --git a/app/src/main/res/drawable/onboarding_bg_full.xml b/app/src/main/res/drawable/onboarding_bg_full.xml
new file mode 100644
index 00000000..a045b831
--- /dev/null
+++ b/app/src/main/res/drawable/onboarding_bg_full.xml
@@ -0,0 +1,266 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/primal_logo.xml b/app/src/main/res/drawable/primal_logo.xml
index 2cb953eb..7ab763ad 100644
--- a/app/src/main/res/drawable/primal_logo.xml
+++ b/app/src/main/res/drawable/primal_logo.xml
@@ -1,67 +1,37 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ android:width="188dp"
+ android:height="45dp"
+ android:viewportWidth="188"
+ android:viewportHeight="45">
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 02174fce..ff0a4ffd 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -17,10 +17,8 @@
Unable to mute user. Please try again.
Unable to unmute user. Please try again.
- Sign in
- Already have a Nostr account? Sign with your Nostr key.
- Create account
- Your new Nostr account will be up and running in a minute.
+ Sign In
+ Create Account
By proceeding you accept our
Terms of Service