Updated on 2026-08-14
This commit is contained in:
parent
fd3d95097f
commit
f6fad0e6d1
24 changed files with 870 additions and 25 deletions
|
|
@ -235,6 +235,8 @@ dependencies {
|
|||
implementation(projects.features.createWalletSelection.impl)
|
||||
implementation(projects.features.home.api)
|
||||
implementation(projects.features.home.impl)
|
||||
implementation(projects.features.account.api)
|
||||
implementation(projects.features.account.impl)
|
||||
|
||||
/** AndroidX libraries */
|
||||
implementation(deps.androidx.core.ktx)
|
||||
|
|
|
|||
|
|
@ -120,6 +120,7 @@
|
|||
<string name="common_add_token">Token hinzufügen</string>
|
||||
<string name="common_all">Alle</string>
|
||||
<string name="common_allow">Erlauben</string>
|
||||
<string name="common_amount">Betrag</string>
|
||||
<string name="common_analytics">Analysen</string>
|
||||
<string name="common_apply">Anwenden</string>
|
||||
<string name="common_approval">Genehmigung</string>
|
||||
|
|
@ -165,6 +166,7 @@
|
|||
<string name="common_disabled">Deaktiviert</string>
|
||||
<string name="common_disconnect">Trennen</string>
|
||||
<string name="common_done">Erledigt</string>
|
||||
<string name="common_edit">Bearbeiten</string>
|
||||
<string name="common_enable">Aktivieren</string>
|
||||
<string name="common_enabled">Aktiviert</string>
|
||||
<string name="common_error">Fehler</string>
|
||||
|
|
|
|||
|
|
@ -109,6 +109,7 @@
|
|||
<string name="common_add_token">Agregar token</string>
|
||||
<string name="common_all">Todos</string>
|
||||
<string name="common_allow">Autorizar</string>
|
||||
<string name="common_amount">Montante</string>
|
||||
<string name="common_analytics">Analítica</string>
|
||||
<string name="common_apply">Aplicar</string>
|
||||
<string name="common_approval">Aprobación</string>
|
||||
|
|
@ -153,6 +154,7 @@
|
|||
<string name="common_disabled">Desactivado</string>
|
||||
<string name="common_disconnect">Desconectar</string>
|
||||
<string name="common_done">Listo</string>
|
||||
<string name="common_edit">Editar</string>
|
||||
<string name="common_enable">Activar</string>
|
||||
<string name="common_enabled">Activado</string>
|
||||
<string name="common_error">Error</string>
|
||||
|
|
|
|||
|
|
@ -99,6 +99,7 @@
|
|||
<string name="common_add_token">Ajouter un jeton</string>
|
||||
<string name="common_all">Tous</string>
|
||||
<string name="common_allow">Permettre</string>
|
||||
<string name="common_amount">Montant</string>
|
||||
<string name="common_analytics">Analytique</string>
|
||||
<string name="common_apply">Appliquer</string>
|
||||
<string name="common_approval">Approbation</string>
|
||||
|
|
@ -140,6 +141,7 @@
|
|||
<string name="common_disabled">Désactivé</string>
|
||||
<string name="common_disconnect">Se déconnecter</string>
|
||||
<string name="common_done">Exécuté</string>
|
||||
<string name="common_edit">Modifier</string>
|
||||
<string name="common_enable">Activer</string>
|
||||
<string name="common_enabled">Activé</string>
|
||||
<string name="common_error">Erreur</string>
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
<string name="alert_unsupported_card">Questa carta non è progettata per funzionare con Tangem</string>
|
||||
<string name="cardano_low_ada">L\'importo inviato e il cambio non può essere inferiore a 1 ADA</string>
|
||||
<string name="common_accept">Accetta</string>
|
||||
<string name="common_amount">Importo</string>
|
||||
<string name="common_balance">Saldo: %s</string>
|
||||
<string name="common_build_tx_error">Impossibile creare la transazione</string>
|
||||
<string name="common_camera_denied_alert_message">Non hai fornito l\'accesso alla tua videocamera, modifica le tue impostazioni sulla privacy</string>
|
||||
|
|
|
|||
|
|
@ -12,6 +12,18 @@
|
|||
<string name="access_code_create_description">ウォレットのロックを解除するには、 %s桁のアクセスコードを設定します。</string>
|
||||
<string name="access_code_create_title">アクセスコードの作成</string>
|
||||
<string name="access_code_navtitle">アクセスコード</string>
|
||||
<string name="account_form_create_button">アカウントを追加</string>
|
||||
<string name="account_form_edit_button">保存</string>
|
||||
<string name="account_form_name">アカウント名</string>
|
||||
<string name="account_form_placeholder_edit_account">アカウント</string>
|
||||
<string name="account_form_placeholder_new_account">新しいアカウント</string>
|
||||
<string name="account_form_title_create">アカウントを追加</string>
|
||||
<string name="account_form_title_edit">アカウントを編集</string>
|
||||
<string name="account_unsaved_dialog_action_first">編集を続ける</string>
|
||||
<string name="account_unsaved_dialog_action_second">破棄</string>
|
||||
<string name="account_unsaved_dialog_message_create">新しいアカウントを破棄してもよろしいですか?</string>
|
||||
<string name="account_unsaved_dialog_message_edit">編集内容を破棄してもよろしいですか?</string>
|
||||
<string name="account_unsaved_dialog_title">保存されていない変更</string>
|
||||
<string name="action_buttons_buy_empty_search_message">トークンが見つかりませんか?メインページのマーケットセクションに移動し、ポートフォリオに追加して買付できるようにします。</string>
|
||||
<string name="action_buttons_sell_empty_search_message">トークンが見つかりませんか?メインページのマーケットセクションに移動し、ポートフォリオに追加して売却できるようにします。</string>
|
||||
<string name="action_buttons_sell_navigation_bar_title">売却</string>
|
||||
|
|
@ -127,6 +139,7 @@
|
|||
<string name="common_add_token">トークンを追加</string>
|
||||
<string name="common_all">すべて</string>
|
||||
<string name="common_allow">許可する</string>
|
||||
<string name="common_amount">金額</string>
|
||||
<string name="common_analytics">アナリティクス</string>
|
||||
<string name="common_apply">適用する</string>
|
||||
<string name="common_approval">承認</string>
|
||||
|
|
@ -170,6 +183,7 @@
|
|||
<string name="common_disabled">無効</string>
|
||||
<string name="common_disconnect">切断</string>
|
||||
<string name="common_done">完了</string>
|
||||
<string name="common_edit">編集</string>
|
||||
<string name="common_enable">有効にする</string>
|
||||
<string name="common_enabled">有効</string>
|
||||
<string name="common_error">エラー</string>
|
||||
|
|
@ -1110,6 +1124,7 @@
|
|||
<string name="swapping_fee_estimation_error_text">手数料見積りエラーです。サポートにフィードバックをお送りください。</string>
|
||||
<string name="swapping_from_title">スワップする</string>
|
||||
<string name="swapping_high_price_impact_description">選択したトークンをこの量を交換すると、価格に大きな影響が生じ、結果が減少します。</string>
|
||||
<string name="swapping_high_price_impact_title">価格への影響が甚大です</string>
|
||||
<string name="swapping_insufficient_funds">残高不足</string>
|
||||
<string name="swapping_permission_header">許可を与える</string>
|
||||
<string name="swapping_swap_action">スワップ</string>
|
||||
|
|
@ -1285,6 +1300,7 @@
|
|||
<string name="wallet_settings_access_code_description">このウォレットを保護するためのシークレットコードです。ログインと署名に使用されます。</string>
|
||||
<string name="wallet_settings_access_code_title">アクセスコードの設定 / 変更</string>
|
||||
<string name="wallet_settings_push_notifications_description">ウォレットの受信取引とTangemの更新について通知を受け取る。</string>
|
||||
<string name="wallet_settings_push_notifications_huawei_warning">現在、Huaweiデバイスではプッシュ通知が機能しない可能性があります。現在、解決策の検討に取り組んでおり、今後のアップデートで修正をリリースする予定です。ご理解のほどよろしくお願いいたします。</string>
|
||||
<string name="wallet_settings_push_notifications_title">取引通知</string>
|
||||
<string name="wallet_settings_title">ウォレット設定</string>
|
||||
<string name="wallet_title">Tangem</string>
|
||||
|
|
@ -1426,15 +1442,19 @@
|
|||
<string name="wc_disconnect_all_alert_title">すべてのdAppを接続解除する</string>
|
||||
<string name="wc_estimated_wallet_changes">ウォレットの変更の予測</string>
|
||||
<string name="wc_estimated_wallet_changes_not_simulated">取引をシミュレーションできませんでした。注意して続行してください。</string>
|
||||
<string name="wc_estimation_is_not_supported">%sでは見積もりはサポートされていません</string>
|
||||
<string name="wc_fee_suggested">%sによる提案</string>
|
||||
<string name="wc_malicious_transaction">悪意のある取引</string>
|
||||
<string name="wc_missing_required_network_description">このウォレットのポートフォリオに%sネットワークを追加します</string>
|
||||
<string name="wc_missing_required_network_title">ウォレットに必要なネットワークはありません</string>
|
||||
<string name="wc_new_connection">新しい接続</string>
|
||||
<string name="wc_no_sessions_desc">ウォレットを別のdAppに接続する</string>
|
||||
<string name="wc_no_sessions_title">セッションなし</string>
|
||||
<string name="wc_no_wallet_changes_detected">ウォレットの変更は検出されませんでした</string>
|
||||
<string name="wc_notification_security_risk_subtitle">このドメインは複数のセキュリティプロバイダーから安全でないとの警告を受けています。あなたの資産を守るため、直ちにアクセスを中止してください。</string>
|
||||
<string name="wc_notification_security_risk_title">既知のセキュリティリスク</string>
|
||||
<string name="wc_request_from">リクエスト元</string>
|
||||
<string name="wc_send_anyway">とにかく送金</string>
|
||||
<string name="wc_signature_type">署名タイプ</string>
|
||||
<string name="wc_transaction_info_to_title">宛先</string>
|
||||
<string name="wc_transaction_request">取引リクエスト</string>
|
||||
|
|
@ -1443,6 +1463,7 @@
|
|||
<string name="wc_uri_already_used_description">各ペアリング試行で、新しくユニークなURIが使用されていることを確認します</string>
|
||||
<string name="wc_uri_already_used_title">URIはすでに使用されています</string>
|
||||
<string name="wc_wallet_connect">ウォレットコネクト</string>
|
||||
<string name="wc_warning_transaction">不審な取引</string>
|
||||
<string name="welcome_interrupted_backup_alert_discard">破棄</string>
|
||||
<string name="welcome_interrupted_backup_alert_message">バックアップが中断されました。再開しますか?</string>
|
||||
<string name="welcome_interrupted_backup_alert_resume">はい、再開します</string>
|
||||
|
|
|
|||
|
|
@ -96,6 +96,7 @@
|
|||
<string name="common_add_token">Добавить токен</string>
|
||||
<string name="common_all">Все</string>
|
||||
<string name="common_allow">Разрешить</string>
|
||||
<string name="common_amount">Сумма</string>
|
||||
<string name="common_analytics">Аналитика</string>
|
||||
<string name="common_apply">Применить</string>
|
||||
<string name="common_approval">Одобрение</string>
|
||||
|
|
@ -140,6 +141,7 @@
|
|||
<string name="common_disabled">Отключено</string>
|
||||
<string name="common_disconnect">Отключить</string>
|
||||
<string name="common_done">Готово</string>
|
||||
<string name="common_edit">Изменить</string>
|
||||
<string name="common_enable">Включить</string>
|
||||
<string name="common_enabled">Включено</string>
|
||||
<string name="common_error">Ошибка</string>
|
||||
|
|
|
|||
|
|
@ -96,6 +96,7 @@
|
|||
<string name="common_add_token">Додати токен</string>
|
||||
<string name="common_all">Усе</string>
|
||||
<string name="common_allow">Дозволити</string>
|
||||
<string name="common_amount">Сума</string>
|
||||
<string name="common_analytics">Аналітика</string>
|
||||
<string name="common_apply">Застосовувати</string>
|
||||
<string name="common_approval">Затвердження</string>
|
||||
|
|
@ -139,6 +140,7 @@
|
|||
<string name="common_disabled">Вимкнуто</string>
|
||||
<string name="common_disconnect">Від\'єднати</string>
|
||||
<string name="common_done">Готово</string>
|
||||
<string name="common_edit">Редагувати</string>
|
||||
<string name="common_enable">Увімкнути</string>
|
||||
<string name="common_enabled">Увімкнено</string>
|
||||
<string name="common_error">Помилка</string>
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@
|
|||
<string name="card_settings_title">卡片設置</string>
|
||||
<string name="cardano_low_ada">發送金額和找零不能少於1個ADA</string>
|
||||
<string name="common_accept">接受</string>
|
||||
<string name="common_amount">數量</string>
|
||||
<string name="common_approve">允許</string>
|
||||
<string name="common_attention">注意</string>
|
||||
<string name="common_balance">餘額: %s</string>
|
||||
|
|
|
|||
|
|
@ -12,7 +12,18 @@
|
|||
<string name="access_code_create_description">Set a %s-digit Access Code to unlock your wallet.</string>
|
||||
<string name="access_code_create_title">Create Access Code</string>
|
||||
<string name="access_code_navtitle">Access code</string>
|
||||
<string name="account_form_create_button">Add account</string>
|
||||
<string name="account_form_edit_button">Save</string>
|
||||
<string name="account_form_name">Account name</string>
|
||||
<string name="account_form_placeholder_edit_account">Account</string>
|
||||
<string name="account_form_placeholder_new_account">New account</string>
|
||||
<string name="account_form_title_create">Add account</string>
|
||||
<string name="account_form_title_edit">Edit account</string>
|
||||
<string name="account_unsaved_dialog_action_first">Keep Editing</string>
|
||||
<string name="account_unsaved_dialog_action_second">Discard</string>
|
||||
<string name="account_unsaved_dialog_message_create">Are you sure you want to discard new account?</string>
|
||||
<string name="account_unsaved_dialog_message_edit">Are you sure you want to discard edits?</string>
|
||||
<string name="account_unsaved_dialog_title">Unsaved Changes</string>
|
||||
<string name="action_buttons_buy_empty_search_message">Can’t find your token? Go to the Market section on the main page and add it to your portfolio for purchase</string>
|
||||
<string name="action_buttons_sell_empty_search_message">Can’t find your token? Go to the Market section on the main page and add it to your portfolio for selling.</string>
|
||||
<string name="action_buttons_sell_navigation_bar_title">Sell</string>
|
||||
|
|
@ -132,6 +143,7 @@
|
|||
<string name="common_add_token">Add token</string>
|
||||
<string name="common_all">All</string>
|
||||
<string name="common_allow">Allow</string>
|
||||
<string name="common_amount">Amount</string>
|
||||
<string name="common_analytics">Analytics</string>
|
||||
<string name="common_apply">Apply</string>
|
||||
<string name="common_approval">Approval</string>
|
||||
|
|
@ -177,6 +189,7 @@
|
|||
<string name="common_disabled">Disabled</string>
|
||||
<string name="common_disconnect">Disconnect</string>
|
||||
<string name="common_done">Done</string>
|
||||
<string name="common_edit">Edit</string>
|
||||
<string name="common_enable">Enable</string>
|
||||
<string name="common_enabled">Enabled</string>
|
||||
<string name="common_error">Error</string>
|
||||
|
|
@ -432,6 +445,8 @@
|
|||
<string name="hw_activation_need_finish">Finish Now</string>
|
||||
<string name="hw_activation_need_title">Finish Wallet Activation</string>
|
||||
<string name="hw_activation_need_warning_description">To complete setup, secure app access with Access Code.</string>
|
||||
<string name="hw_backup_alert_description">If you do, you\'ll need to start over.</string>
|
||||
<string name="hw_backup_alert_title">Are you sure you want to exit the activation process?</string>
|
||||
<string name="hw_backup_google_drive_description">Recover an existing wallet stored in your Google Drive backup</string>
|
||||
<string name="hw_backup_google_drive_title">Google Drive Backup</string>
|
||||
<string name="hw_backup_need_action">Go to backup</string>
|
||||
|
|
@ -1129,6 +1144,7 @@
|
|||
<string name="swapping_fee_estimation_error_text">Fee estimation error. Please send feedback to support.</string>
|
||||
<string name="swapping_from_title">You swap</string>
|
||||
<string name="swapping_high_price_impact_description">Swapping this amount of selected tokens will cause a significant price impact and reduce your outcome.</string>
|
||||
<string name="swapping_high_price_impact_title">High price impact</string>
|
||||
<string name="swapping_insufficient_funds">Insufficient funds</string>
|
||||
<string name="swapping_permission_header">Give Permission</string>
|
||||
<string name="swapping_swap_action">Swap</string>
|
||||
|
|
@ -1495,6 +1511,8 @@
|
|||
<string name="wc_disconnect_all_alert_title">Disconect All dApps</string>
|
||||
<string name="wc_estimated_wallet_changes">Estimated wallet changes</string>
|
||||
<string name="wc_estimated_wallet_changes_not_simulated">The transaction couldn\'t be simulated. Please proceed with caution.</string>
|
||||
<string name="wc_estimation_is_not_supported">Estimation is not supported for %s</string>
|
||||
<string name="wc_fee_suggested">Suggested by %s</string>
|
||||
<string name="wc_malicious_transaction">Malicious transaction</string>
|
||||
<string name="wc_missing_required_network_description">Add the %s network to your portfolio for this wallet</string>
|
||||
<string name="wc_missing_required_network_title">The wallet has no required networks</string>
|
||||
|
|
@ -1505,6 +1523,7 @@
|
|||
<string name="wc_notification_security_risk_subtitle">This domain is flagged as unsafe by multiple security providers. Leave immediately to protect your assets</string>
|
||||
<string name="wc_notification_security_risk_title">Known security risk</string>
|
||||
<string name="wc_request_from">Request from</string>
|
||||
<string name="wc_send_anyway">Send anyway</string>
|
||||
<string name="wc_signature_type">Signature Type</string>
|
||||
<string name="wc_transaction_info_to_title">To</string>
|
||||
<string name="wc_transaction_request">Transaction request</string>
|
||||
|
|
|
|||
|
|
@ -12,12 +12,7 @@ import androidx.compose.ui.Alignment.Companion.TopCenter
|
|||
import androidx.compose.ui.Alignment.Companion.TopStart
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.text.AnnotatedString
|
||||
import androidx.compose.ui.text.ParagraphIntrinsics
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.font.createFontFamilyResolver
|
||||
import androidx.compose.ui.text.input.KeyboardType
|
||||
import androidx.compose.ui.text.input.VisualTransformation
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
|
|
@ -77,24 +72,10 @@ fun AmountTextField(
|
|||
) {
|
||||
val decimalFormat = rememberDecimalFormat()
|
||||
BoxWithConstraints(modifier = modifier) {
|
||||
var fontSize = textStyle.fontSize
|
||||
if (isAutoResize) {
|
||||
val calculateIntrinsics = @Composable {
|
||||
val transformedText = visualTransformation.filter(AnnotatedString(value)).text.text
|
||||
ParagraphIntrinsics(
|
||||
text = transformedText,
|
||||
style = textStyle.copy(fontSize = fontSize),
|
||||
density = LocalDensity.current,
|
||||
fontFamilyResolver = createFontFamilyResolver(LocalContext.current),
|
||||
)
|
||||
}
|
||||
var intrinsics = calculateIntrinsics()
|
||||
with(LocalDensity.current) {
|
||||
while (intrinsics.maxIntrinsicWidth > maxWidth.toPx()) {
|
||||
fontSize *= reduceFactor
|
||||
intrinsics = calculateIntrinsics()
|
||||
}
|
||||
}
|
||||
val fontSize = if (isAutoResize) {
|
||||
resizeFont(visualTransformation, value, textStyle, reduceFactor)
|
||||
} else {
|
||||
textStyle.fontSize
|
||||
}
|
||||
val textColor = if (value.isBlank()) TangemTheme.colors.text.disabled else color
|
||||
SimpleTextField(
|
||||
|
|
|
|||
|
|
@ -0,0 +1,204 @@
|
|||
package com.tangem.core.ui.components.fields
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import androidx.annotation.FloatRange
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.layout.BoxWithConstraints
|
||||
import androidx.compose.foundation.layout.BoxWithConstraintsScope
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.text.KeyboardActions
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.text.AnnotatedString
|
||||
import androidx.compose.ui.text.ParagraphIntrinsics
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.font.createFontFamilyResolver
|
||||
import androidx.compose.ui.text.input.VisualTransformation
|
||||
import androidx.compose.ui.text.style.TextDirection
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||
import androidx.compose.ui.unit.TextUnit
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
|
||||
/**
|
||||
* Simple text field for auto size input.
|
||||
* Can display aligned placeholder.
|
||||
*
|
||||
* @param value initial text
|
||||
* @param onValueChange callback
|
||||
* @param isAutoResize is text font auto resize
|
||||
* @param reduceFactor font resize factor
|
||||
* @param textStyle text and placeholder styles
|
||||
* @param textFieldModifier modifier for [SimpleTextField]
|
||||
* @param boxModifier modifier for [BoxWithConstraints]
|
||||
* @see [SimpleTextField] for other text field params
|
||||
*/
|
||||
@SuppressLint("UnusedBoxWithConstraintsScope")
|
||||
@Composable
|
||||
fun AutoSizeTextField(
|
||||
value: String,
|
||||
onValueChange: (String) -> Unit,
|
||||
|
||||
// region AutoSize
|
||||
isAutoResize: Boolean = true,
|
||||
@FloatRange(from = 0.0, to = 1.0, fromInclusive = false, toInclusive = false)
|
||||
reduceFactor: Double = 0.9,
|
||||
|
||||
// region TextField
|
||||
textFieldModifier: Modifier = Modifier,
|
||||
boxModifier: Modifier = Modifier,
|
||||
placeholder: TextReference? = null,
|
||||
singleLine: Boolean = isAutoResize,
|
||||
centered: Boolean = false,
|
||||
visualTransformation: VisualTransformation = VisualTransformation.None,
|
||||
keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
|
||||
keyboardActions: KeyboardActions = KeyboardActions.Default,
|
||||
color: Color = TangemTheme.colors.text.primary1,
|
||||
textStyle: TextStyle = TangemTheme.typography.body2.copy(color = color),
|
||||
placeholderColor: Color = TangemTheme.colors.text.disabled,
|
||||
readOnly: Boolean = false,
|
||||
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
|
||||
isValuePasted: Boolean = false,
|
||||
onValuePastedTriggerDismiss: () -> Unit = {},
|
||||
decorationBox: (@Composable (innerTextField: @Composable () -> Unit) -> Unit)? = null,
|
||||
) {
|
||||
BoxWithConstraints(modifier = boxModifier) {
|
||||
val fontSize = if (isAutoResize) {
|
||||
resizeFont(visualTransformation, value, textStyle, reduceFactor)
|
||||
} else {
|
||||
textStyle.fontSize
|
||||
}
|
||||
val textColor = if (value.isBlank()) TangemTheme.colors.text.disabled else color
|
||||
SimpleTextField(
|
||||
value = value,
|
||||
onValueChange = onValueChange,
|
||||
textStyle = textStyle.copy(
|
||||
fontSize = fontSize,
|
||||
textDirection = TextDirection.ContentOrLtr,
|
||||
),
|
||||
isValuePasted = isValuePasted,
|
||||
onValuePastedTriggerDismiss = onValuePastedTriggerDismiss,
|
||||
color = textColor,
|
||||
keyboardOptions = keyboardOptions,
|
||||
keyboardActions = keyboardActions,
|
||||
placeholder = placeholder,
|
||||
placeholderColor = placeholderColor,
|
||||
singleLine = singleLine,
|
||||
interactionSource = interactionSource,
|
||||
readOnly = readOnly,
|
||||
centered = centered,
|
||||
visualTransformation = visualTransformation,
|
||||
decorationBox = decorationBox,
|
||||
modifier = textFieldModifier,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
internal fun BoxWithConstraintsScope.resizeFont(
|
||||
visualTransformation: VisualTransformation,
|
||||
value: String,
|
||||
textStyle: TextStyle,
|
||||
reduceFactor: Double,
|
||||
): TextUnit {
|
||||
var result = textStyle.fontSize
|
||||
val calculateIntrinsics = @Composable {
|
||||
val transformedText = visualTransformation.filter(AnnotatedString(value)).text.text
|
||||
ParagraphIntrinsics(
|
||||
text = transformedText,
|
||||
style = textStyle.copy(fontSize = result),
|
||||
density = LocalDensity.current,
|
||||
fontFamilyResolver = createFontFamilyResolver(LocalContext.current),
|
||||
)
|
||||
}
|
||||
var intrinsics = calculateIntrinsics()
|
||||
with(LocalDensity.current) {
|
||||
while (intrinsics.maxIntrinsicWidth > maxWidth.toPx()) {
|
||||
result *= reduceFactor
|
||||
intrinsics = calculateIntrinsics()
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// region preview
|
||||
@Preview(widthDp = 360, showBackground = true)
|
||||
@Composable
|
||||
private fun AmountTextFieldPreview(
|
||||
@PreviewParameter(AutoSizeTextFieldPreviewProvider::class) data: AutoSizeTextFieldPreviewData,
|
||||
) {
|
||||
var text by remember { mutableStateOf(data.value) }
|
||||
TangemThemePreview {
|
||||
AutoSizeTextField(
|
||||
textFieldModifier = Modifier.fillMaxWidth(),
|
||||
value = text,
|
||||
onValueChange = { text = it },
|
||||
centered = data.centered,
|
||||
isAutoResize = data.isAutoResize,
|
||||
placeholder = data.placeholder,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private class AutoSizeTextFieldPreviewProvider : PreviewParameterProvider<AutoSizeTextFieldPreviewData> {
|
||||
override val values = sequenceOf(
|
||||
AutoSizeTextFieldPreviewData(
|
||||
value = "AutoSizeTextField",
|
||||
placeholder = stringReference("placeholder"),
|
||||
isAutoResize = true,
|
||||
centered = false,
|
||||
),
|
||||
AutoSizeTextFieldPreviewData(
|
||||
value = "AutoSizeTextFieldAutoSizeTextFieldAutoSizeTextFieldAutoSizeTextField",
|
||||
placeholder = stringReference("placeholder"),
|
||||
isAutoResize = true,
|
||||
centered = false,
|
||||
),
|
||||
AutoSizeTextFieldPreviewData(
|
||||
value = "AutoSizeTextFieldAutoSizeTextFieldAutoSizeTextFieldAutoSizeTextField",
|
||||
placeholder = stringReference("Placeholder"),
|
||||
isAutoResize = true,
|
||||
centered = false,
|
||||
),
|
||||
AutoSizeTextFieldPreviewData(
|
||||
value = "",
|
||||
placeholder = stringReference("Placeholder"),
|
||||
isAutoResize = true,
|
||||
centered = false,
|
||||
),
|
||||
AutoSizeTextFieldPreviewData(
|
||||
value = "AutoSizeTextField",
|
||||
placeholder = stringReference("Placeholder"),
|
||||
isAutoResize = false,
|
||||
centered = true,
|
||||
),
|
||||
AutoSizeTextFieldPreviewData(
|
||||
value = "AutoSizeTextFieldAutoSizeTextFieldAutoSizeTextFieldAutoSizeTextField",
|
||||
placeholder = stringReference("Placeholder"),
|
||||
isAutoResize = false,
|
||||
centered = true,
|
||||
),
|
||||
AutoSizeTextFieldPreviewData(
|
||||
value = "",
|
||||
placeholder = stringReference("Placeholder"),
|
||||
isAutoResize = false,
|
||||
centered = true,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
private data class AutoSizeTextFieldPreviewData(
|
||||
val value: String,
|
||||
val placeholder: TextReference,
|
||||
val isAutoResize: Boolean,
|
||||
val centered: Boolean,
|
||||
)
|
||||
// endregion
|
||||
|
|
@ -8,6 +8,7 @@ import androidx.compose.foundation.text.KeyboardActions
|
|||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.focus.FocusRequester
|
||||
import androidx.compose.ui.focus.focusRequester
|
||||
|
|
@ -17,6 +18,7 @@ import androidx.compose.ui.text.TextRange
|
|||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.input.TextFieldValue
|
||||
import androidx.compose.ui.text.input.VisualTransformation
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.resolveReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
|
|
@ -39,6 +41,7 @@ fun SimpleTextField(
|
|||
textStyle: TextStyle = TangemTheme.typography.body2.copy(color = color),
|
||||
placeholderColor: Color = TangemTheme.colors.text.disabled,
|
||||
readOnly: Boolean = false,
|
||||
centered: Boolean = false,
|
||||
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
|
||||
isValuePasted: Boolean = false,
|
||||
onValuePastedTriggerDismiss: () -> Unit = {},
|
||||
|
|
@ -80,6 +83,8 @@ fun SimpleTextField(
|
|||
onValuePastedTriggerDismiss()
|
||||
}
|
||||
}
|
||||
var textStyle = textStyle.copy(color = color)
|
||||
if (centered) textStyle = textStyle.copy(textAlign = TextAlign.Center)
|
||||
|
||||
BasicTextField(
|
||||
value = textFieldValue,
|
||||
|
|
@ -91,7 +96,7 @@ fun SimpleTextField(
|
|||
|
||||
if (stringChangedSinceLastInvocation) onValueChange(newTextFieldValueState.text)
|
||||
},
|
||||
textStyle = textStyle.copy(color = color),
|
||||
textStyle = textStyle,
|
||||
cursorBrush = SolidColor(TangemTheme.colors.text.primary1),
|
||||
singleLine = singleLine,
|
||||
readOnly = readOnly,
|
||||
|
|
@ -105,6 +110,7 @@ fun SimpleTextField(
|
|||
value = value,
|
||||
textStyle = textStyle,
|
||||
textValue = textValue,
|
||||
centered = centered,
|
||||
color = placeholderColor,
|
||||
)
|
||||
},
|
||||
|
|
@ -118,10 +124,11 @@ private fun SimpleTextPlaceholder(
|
|||
placeholder: TextReference?,
|
||||
value: String,
|
||||
textStyle: TextStyle,
|
||||
centered: Boolean,
|
||||
textValue: @Composable () -> Unit,
|
||||
color: Color = TangemTheme.colors.text.disabled,
|
||||
) {
|
||||
Box {
|
||||
Box(contentAlignment = if (centered) Alignment.Center else Alignment.TopStart) {
|
||||
if (value.isBlank() && placeholder != null) {
|
||||
AnimatedContent(
|
||||
targetState = placeholder,
|
||||
|
|
|
|||
1
features/account/api/.gitignore
vendored
Normal file
1
features/account/api/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
/build
|
||||
16
features/account/api/build.gradle.kts
Normal file
16
features/account/api/build.gradle.kts
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
plugins {
|
||||
alias(deps.plugins.android.library)
|
||||
alias(deps.plugins.kotlin.android)
|
||||
id("configuration")
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "com.tangem.features.account.api"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
/* Project - Core */
|
||||
implementation(projects.core.decompose)
|
||||
implementation(projects.core.ui)
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
package com.tangem.features.account
|
||||
|
||||
import com.tangem.core.decompose.factory.ComponentFactory
|
||||
import com.tangem.core.ui.decompose.ComposableContentComponent
|
||||
|
||||
interface AccountCreateEditComponent : ComposableContentComponent {
|
||||
interface Factory : ComponentFactory<Params, AccountCreateEditComponent>
|
||||
|
||||
sealed interface Params {
|
||||
|
||||
data object Create : Params
|
||||
data object Edit : Params
|
||||
}
|
||||
}
|
||||
1
features/account/impl/.gitignore
vendored
Normal file
1
features/account/impl/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
/build
|
||||
59
features/account/impl/build.gradle.kts
Normal file
59
features/account/impl/build.gradle.kts
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
plugins {
|
||||
alias(deps.plugins.android.library)
|
||||
alias(deps.plugins.kotlin.android)
|
||||
alias(deps.plugins.kotlin.kapt)
|
||||
alias(deps.plugins.kotlin.serialization)
|
||||
alias(deps.plugins.hilt.android)
|
||||
id("configuration")
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "com.tangem.features.account.impl"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
/** Api */
|
||||
implementation(projects.features.account.api)
|
||||
|
||||
/** Core modules */
|
||||
implementation(projects.core.analytics)
|
||||
implementation(projects.core.analytics.models)
|
||||
implementation(projects.core.utils)
|
||||
implementation(projects.core.ui)
|
||||
implementation(projects.core.res)
|
||||
implementation(projects.core.decompose)
|
||||
implementation(projects.core.navigation)
|
||||
implementation(projects.core.datasource)
|
||||
|
||||
/** Domain */
|
||||
implementation(projects.domain.models)
|
||||
|
||||
/** Common */
|
||||
implementation(projects.common.ui)
|
||||
implementation(projects.common.routing)
|
||||
|
||||
/** AndroidX libraries */
|
||||
implementation(deps.androidx.core.ktx)
|
||||
implementation(deps.lifecycle.runtime.ktx)
|
||||
|
||||
/** Compose libraries */
|
||||
implementation(deps.compose.material3)
|
||||
implementation(deps.compose.animation)
|
||||
implementation(deps.compose.foundation)
|
||||
implementation(deps.compose.ui)
|
||||
implementation(deps.compose.ui.tooling)
|
||||
implementation(deps.compose.coil)
|
||||
implementation(deps.decompose.ext.compose)
|
||||
implementation(deps.androidx.activity.compose)
|
||||
|
||||
/** Other libraries */
|
||||
implementation(deps.arrow.core)
|
||||
implementation(deps.kotlin.immutable.collections)
|
||||
implementation(deps.kotlin.serialization)
|
||||
implementation(deps.timber)
|
||||
implementation(deps.firebase.crashlytics)
|
||||
|
||||
/** DI */
|
||||
implementation(deps.hilt.android)
|
||||
kapt(deps.hilt.kapt)
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
package com.tangem.features.account.createedit
|
||||
|
||||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.core.decompose.model.Model
|
||||
import com.tangem.core.decompose.model.ParamsContainer
|
||||
import com.tangem.core.decompose.navigation.Router
|
||||
import com.tangem.core.decompose.ui.UiMessageSender
|
||||
import com.tangem.core.res.R
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.message.DialogMessage
|
||||
import com.tangem.core.ui.message.EventMessageAction
|
||||
import com.tangem.features.account.AccountCreateEditComponent
|
||||
import com.tangem.features.account.createedit.entity.AccountCreateEditUM
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import javax.inject.Inject
|
||||
|
||||
@ModelScoped
|
||||
internal class AccountCreateEditModel @Inject constructor(
|
||||
paramsContainer: ParamsContainer,
|
||||
private val messageSender: UiMessageSender,
|
||||
private val router: Router,
|
||||
override val dispatchers: CoroutineDispatcherProvider,
|
||||
) : Model() {
|
||||
|
||||
private val params = paramsContainer.require<AccountCreateEditComponent.Params>()
|
||||
|
||||
val uiState: StateFlow<AccountCreateEditUM>
|
||||
field = MutableStateFlow(TODO())
|
||||
|
||||
init {
|
||||
params
|
||||
}
|
||||
|
||||
fun unsaveChangeDialog() {
|
||||
val firstAction = EventMessageAction(
|
||||
title = resourceReference(R.string.account_unsaved_dialog_action_first),
|
||||
onClick = {},
|
||||
)
|
||||
val secondAction = EventMessageAction(
|
||||
title = resourceReference(R.string.account_unsaved_dialog_action_second),
|
||||
onClick = { router.pop() },
|
||||
)
|
||||
messageSender.send(
|
||||
DialogMessage(
|
||||
title = resourceReference(R.string.account_unsaved_dialog_title),
|
||||
message = resourceReference(R.string.account_unsaved_dialog_message_create),
|
||||
firstActionBuilder = { firstAction },
|
||||
secondActionBuilder = { secondAction },
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
package com.tangem.features.account.createedit
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.tangem.core.decompose.context.AppComponentContext
|
||||
import com.tangem.core.decompose.model.getOrCreateModel
|
||||
import com.tangem.features.account.AccountCreateEditComponent
|
||||
import com.tangem.features.account.createedit.ui.AccountCreateEditContent
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
|
||||
internal class DefaultAccountCreateEditComponent @AssistedInject constructor(
|
||||
@Assisted appComponentContext: AppComponentContext,
|
||||
@Assisted params: AccountCreateEditComponent.Params,
|
||||
) : AppComponentContext by appComponentContext, AccountCreateEditComponent {
|
||||
|
||||
private val model: AccountCreateEditModel = getOrCreateModel(params)
|
||||
|
||||
@Composable
|
||||
override fun Content(modifier: Modifier) {
|
||||
val state by model.uiState.collectAsStateWithLifecycle()
|
||||
AccountCreateEditContent(
|
||||
modifier = modifier,
|
||||
state = state,
|
||||
)
|
||||
}
|
||||
|
||||
@AssistedFactory
|
||||
interface Factory : AccountCreateEditComponent.Factory {
|
||||
override fun create(
|
||||
context: AppComponentContext,
|
||||
params: AccountCreateEditComponent.Params,
|
||||
): DefaultAccountCreateEditComponent
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
package com.tangem.features.account.createedit.di
|
||||
|
||||
import com.tangem.core.decompose.model.Model
|
||||
import com.tangem.features.account.AccountCreateEditComponent
|
||||
import com.tangem.features.account.createedit.AccountCreateEditModel
|
||||
import com.tangem.features.account.createedit.DefaultAccountCreateEditComponent
|
||||
import dagger.Binds
|
||||
import dagger.Module
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
import dagger.multibindings.ClassKey
|
||||
import dagger.multibindings.IntoMap
|
||||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
internal interface AccountCreateEditModule {
|
||||
|
||||
@Binds
|
||||
fun bindAccountCreateEditComponentFactory(
|
||||
impl: DefaultAccountCreateEditComponent.Factory,
|
||||
): AccountCreateEditComponent.Factory
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@ClassKey(AccountCreateEditModel::class)
|
||||
fun bindAccountCreateEditModel(model: AccountCreateEditModel): Model
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
package com.tangem.features.account.createedit.entity
|
||||
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.domain.models.account.CryptoPortfolioIcon
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
||||
data class AccountCreateEditUM(
|
||||
val title: TextReference = TextReference.EMPTY,
|
||||
val account: Account = Account(),
|
||||
val colorsState: Colors,
|
||||
val iconsState: Icons,
|
||||
val buttonState: Button = Button(),
|
||||
val onCloseClick: () -> Unit = {},
|
||||
) {
|
||||
|
||||
data class Account(
|
||||
val name: TextReference = TextReference.EMPTY,
|
||||
val portfolioIcon: CryptoPortfolioIcon = CryptoPortfolioIcon.ofDefaultCustomAccount(),
|
||||
val derivationInfo: TextReference = TextReference.EMPTY,
|
||||
val inputPlaceholder: TextReference = TextReference.EMPTY,
|
||||
val onNameChange: (String) -> Unit = {},
|
||||
)
|
||||
|
||||
data class Colors(
|
||||
val selected: CryptoPortfolioIcon.Color,
|
||||
val list: ImmutableList<CryptoPortfolioIcon.Color> = persistentListOf(),
|
||||
val onColorSelect: (CryptoPortfolioIcon.Color) -> Unit = {},
|
||||
)
|
||||
|
||||
data class Icons(
|
||||
val selected: CryptoPortfolioIcon.Icon,
|
||||
val list: ImmutableList<CryptoPortfolioIcon.Icon> = persistentListOf(),
|
||||
val onIconSelect: (CryptoPortfolioIcon.Icon) -> Unit = {},
|
||||
)
|
||||
|
||||
data class Button(
|
||||
val isButtonEnabled: Boolean = false,
|
||||
val onConfirmClick: () -> Unit = {},
|
||||
val text: TextReference = TextReference.EMPTY,
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,344 @@
|
|||
package com.tangem.features.account.createedit.ui
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.border
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.grid.GridCells
|
||||
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
|
||||
import androidx.compose.foundation.lazy.grid.itemsIndexed
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material3.Icon
|
||||
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.clip
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.res.vectorResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameterProvider
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.common.ui.R
|
||||
import com.tangem.common.ui.account.getResId
|
||||
import com.tangem.common.ui.account.getUiColor
|
||||
import com.tangem.core.ui.components.PrimaryButton
|
||||
import com.tangem.core.ui.components.SpacerH
|
||||
import com.tangem.core.ui.components.SpacerH24
|
||||
import com.tangem.core.ui.components.SpacerH8
|
||||
import com.tangem.core.ui.components.appbar.AppBarWithBackButton
|
||||
import com.tangem.core.ui.components.fields.AutoSizeTextField
|
||||
import com.tangem.core.ui.extensions.resolveReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.extensions.stringResourceSafe
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.domain.models.account.CryptoPortfolioIcon
|
||||
import com.tangem.features.account.createedit.entity.AccountCreateEditUM
|
||||
import com.tangem.features.account.createedit.entity.AccountCreateEditUM.Account
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
|
||||
@Suppress("LongMethod", "MagicNumber")
|
||||
@Composable
|
||||
internal fun AccountCreateEditContent(state: AccountCreateEditUM, modifier: Modifier = Modifier) {
|
||||
Column(
|
||||
modifier = modifier
|
||||
.background(color = TangemTheme.colors.background.tertiary)
|
||||
.fillMaxSize()
|
||||
.imePadding()
|
||||
.systemBarsPadding(),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
) {
|
||||
AppBarWithBackButton(
|
||||
text = state.title.resolveReference(),
|
||||
onBackClick = state.onCloseClick,
|
||||
iconRes = R.drawable.ic_close_24,
|
||||
modifier = Modifier.height(TangemTheme.dimens.size56),
|
||||
)
|
||||
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.padding(horizontal = 16.dp)
|
||||
.weight(1f),
|
||||
|
||||
) {
|
||||
AccountSummary(state.account, state.account.onNameChange)
|
||||
SpacerH24()
|
||||
AccountColor(state.colorsState)
|
||||
SpacerH24()
|
||||
AccountIcon(state.iconsState)
|
||||
SpacerH8()
|
||||
Text(
|
||||
modifier = Modifier.padding(horizontal = 8.dp),
|
||||
text = state.account.derivationInfo.resolveReference(),
|
||||
style = TangemTheme.typography.caption2,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
)
|
||||
}
|
||||
PrimaryButton(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(16.dp),
|
||||
enabled = state.buttonState.isButtonEnabled,
|
||||
text = state.buttonState.text.resolveReference(),
|
||||
onClick = state.buttonState.onConfirmClick,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun AccountSummary(account: AccountCreateEditUM.Account, onNameChange: (String) -> Unit) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.clip(RoundedCornerShape(16.dp))
|
||||
.fillMaxWidth()
|
||||
.background(TangemTheme.colors.background.action),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
) {
|
||||
Spacer(modifier = Modifier.height(24.dp))
|
||||
|
||||
AccountIcon(account)
|
||||
Spacer(modifier = Modifier.height(24.dp))
|
||||
|
||||
Text(
|
||||
text = stringResourceSafe(R.string.account_form_name),
|
||||
style = TangemTheme.typography.caption2,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
)
|
||||
Spacer(modifier = Modifier.height(2.dp))
|
||||
|
||||
AutoSizeTextField(
|
||||
centered = true,
|
||||
textStyle = TangemTheme.typography.head,
|
||||
placeholder = account.inputPlaceholder,
|
||||
value = account.name.resolveReference(),
|
||||
singleLine = true,
|
||||
onValueChange = onNameChange,
|
||||
)
|
||||
SpacerH(20.dp)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun AccountIcon(account: AccountCreateEditUM.Account) {
|
||||
Box(
|
||||
contentAlignment = Alignment.Center,
|
||||
modifier = Modifier
|
||||
.size(88.dp)
|
||||
.clip(RoundedCornerShape(TangemTheme.dimens.radius24))
|
||||
.background(account.portfolioIcon.color.getUiColor()),
|
||||
) {
|
||||
val icon = account.portfolioIcon.value
|
||||
when {
|
||||
icon == CryptoPortfolioIcon.Icon.Letter -> Text(
|
||||
text = account.name.resolveReference().first().uppercase(),
|
||||
style = TangemTheme.typography.head,
|
||||
color = TangemTheme.colors.text.constantWhite,
|
||||
)
|
||||
else -> Icon(
|
||||
modifier = Modifier.size(44.dp),
|
||||
tint = TangemTheme.colors.text.constantWhite,
|
||||
imageVector = ImageVector.vectorResource(id = icon.getResId()),
|
||||
contentDescription = null,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("LongMethod", "MagicNumber")
|
||||
@Composable
|
||||
private fun AccountColor(colorsState: AccountCreateEditUM.Colors) {
|
||||
Box(
|
||||
Modifier
|
||||
.clip(RoundedCornerShape(16.dp))
|
||||
.fillMaxWidth()
|
||||
.background(TangemTheme.colors.background.action),
|
||||
) {
|
||||
val columns = GridCells.Fixed(6)
|
||||
val contentPadding = PaddingValues(horizontal = 8.dp, vertical = 12.dp)
|
||||
LazyVerticalGrid(
|
||||
columns = columns,
|
||||
contentPadding = contentPadding,
|
||||
horizontalArrangement = Arrangement.spacedBy(4.dp),
|
||||
) {
|
||||
itemsIndexed(colorsState.list) { index, color ->
|
||||
val isSelected = color == colorsState.selected
|
||||
Box(
|
||||
contentAlignment = Alignment.Center,
|
||||
modifier = Modifier
|
||||
.wrapContentSize()
|
||||
.clickable(onClick = { colorsState.onColorSelect(color) })
|
||||
.size(48.dp),
|
||||
) {
|
||||
if (isSelected) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.size(47.dp)
|
||||
.border(2.dp, color.getUiColor(), shape = CircleShape),
|
||||
)
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.size(36.dp)
|
||||
.background(color = color.getUiColor(), shape = CircleShape),
|
||||
)
|
||||
} else {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.size(40.dp)
|
||||
.background(color = color.getUiColor(), shape = CircleShape),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("LongMethod", "MagicNumber")
|
||||
@Composable
|
||||
private fun AccountIcon(iconsState: AccountCreateEditUM.Icons) {
|
||||
Box(
|
||||
Modifier
|
||||
.clip(RoundedCornerShape(16.dp))
|
||||
.fillMaxWidth()
|
||||
.background(TangemTheme.colors.background.action)
|
||||
.padding(8.dp),
|
||||
) {
|
||||
val columns = GridCells.Fixed(6)
|
||||
LazyVerticalGrid(
|
||||
columns = columns,
|
||||
) {
|
||||
itemsIndexed(iconsState.list) { index, icon ->
|
||||
val isSelected = icon == iconsState.selected
|
||||
Box(
|
||||
contentAlignment = Alignment.Center,
|
||||
modifier = Modifier
|
||||
.wrapContentSize()
|
||||
.clickable(onClick = { iconsState.onIconSelect(icon) })
|
||||
.size(52.dp),
|
||||
) {
|
||||
if (isSelected) {
|
||||
val borderColor: Color
|
||||
val iconTint: Color
|
||||
val backgroundTint: Color
|
||||
if (index == 0) {
|
||||
borderColor = TangemTheme.colors.icon.accent
|
||||
iconTint = TangemTheme.colors.icon.accent
|
||||
backgroundTint = TangemTheme.colors.icon.accent.copy(alpha = 0.1f)
|
||||
} else {
|
||||
borderColor = TangemTheme.colors.icon.informative
|
||||
iconTint = TangemTheme.colors.icon.secondary
|
||||
backgroundTint = TangemTheme.colors.field.focused
|
||||
}
|
||||
Box(
|
||||
contentAlignment = Alignment.Center,
|
||||
modifier = Modifier
|
||||
.size(44.dp)
|
||||
.border(2.dp, borderColor, shape = CircleShape),
|
||||
) {
|
||||
Box(
|
||||
contentAlignment = Alignment.Center,
|
||||
modifier = Modifier
|
||||
.size(36.dp)
|
||||
.background(color = backgroundTint, shape = CircleShape),
|
||||
) {
|
||||
Icon(
|
||||
imageVector = ImageVector.vectorResource(id = icon.getResId()),
|
||||
contentDescription = null,
|
||||
tint = iconTint,
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
val iconTint: Color
|
||||
val backgroundTint: Color
|
||||
if (index == 0) {
|
||||
iconTint = TangemTheme.colors.icon.accent
|
||||
backgroundTint = TangemTheme.colors.icon.accent.copy(alpha = 0.1f)
|
||||
} else {
|
||||
iconTint = TangemTheme.colors.text.tertiary
|
||||
backgroundTint = TangemTheme.colors.field.focused
|
||||
}
|
||||
Box(
|
||||
contentAlignment = Alignment.Center,
|
||||
modifier = Modifier
|
||||
.size(40.dp)
|
||||
.background(color = backgroundTint, shape = CircleShape),
|
||||
) {
|
||||
Icon(
|
||||
imageVector = ImageVector.vectorResource(id = icon.getResId()),
|
||||
contentDescription = null,
|
||||
tint = iconTint,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(showBackground = true, widthDp = 360)
|
||||
@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
private fun WcConnectionsContentPreview(@PreviewParameter(PreviewStateProvider::class) params: AccountCreateEditUM) {
|
||||
TangemThemePreview {
|
||||
AccountCreateEditContent(state = params)
|
||||
}
|
||||
}
|
||||
|
||||
private class PreviewStateProvider : CollectionPreviewParameterProvider<AccountCreateEditUM>(
|
||||
buildList {
|
||||
val colors = CryptoPortfolioIcon.Color.entries.toImmutableList()
|
||||
val icons = CryptoPortfolioIcon.Icon.entries.toImmutableList()
|
||||
var portfolioIcon = CryptoPortfolioIcon.ofDefaultCustomAccount()
|
||||
val first = AccountCreateEditUM(
|
||||
title = stringReference("Add account"),
|
||||
account = Account(
|
||||
portfolioIcon = portfolioIcon,
|
||||
derivationInfo = stringReference("Account #03 — used for address derivation."),
|
||||
),
|
||||
colorsState = AccountCreateEditUM.Colors(
|
||||
selected = portfolioIcon.color,
|
||||
list = colors.toImmutableList(),
|
||||
),
|
||||
iconsState = AccountCreateEditUM.Icons(
|
||||
selected = portfolioIcon.value,
|
||||
list = icons.toImmutableList(),
|
||||
),
|
||||
buttonState = AccountCreateEditUM.Button(
|
||||
text = stringReference("Add account"),
|
||||
),
|
||||
)
|
||||
add(first)
|
||||
|
||||
portfolioIcon = CryptoPortfolioIcon.ofCustomAccount(
|
||||
value = CryptoPortfolioIcon.Icon.Letter,
|
||||
color = CryptoPortfolioIcon.Color.entries.random(),
|
||||
)
|
||||
val second = AccountCreateEditUM(
|
||||
title = stringReference("Edit account"),
|
||||
account = Account(
|
||||
portfolioIcon = portfolioIcon,
|
||||
name = stringReference("Main account"),
|
||||
derivationInfo = stringReference("Account #03 — used for address derivation."),
|
||||
),
|
||||
colorsState = AccountCreateEditUM.Colors(
|
||||
selected = portfolioIcon.color,
|
||||
list = colors.toImmutableList(),
|
||||
),
|
||||
iconsState = AccountCreateEditUM.Icons(
|
||||
selected = portfolioIcon.value,
|
||||
list = icons.toImmutableList(),
|
||||
),
|
||||
buttonState = AccountCreateEditUM.Button(
|
||||
text = stringReference("Save"),
|
||||
),
|
||||
)
|
||||
add(second)
|
||||
},
|
||||
)
|
||||
|
|
@ -269,6 +269,9 @@ include(":features:create-wallet-selection:impl")
|
|||
|
||||
include(":features:welcome:api")
|
||||
include(":features:welcome:impl")
|
||||
|
||||
include(":features:account:api")
|
||||
include(":features:account:impl")
|
||||
// endregion Feature modules
|
||||
|
||||
// region Domain modules
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue