diff --git a/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt b/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt index deb8b82709..e2ce3a2b4a 100644 --- a/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt +++ b/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt @@ -2,6 +2,7 @@ package com.tangem.tap.routing.utils import com.tangem.common.routing.AppRoute import com.tangem.core.decompose.context.AppComponentContext +import com.tangem.domain.models.PortfolioId import com.tangem.domain.qrscanning.models.SourceType import com.tangem.feature.qrscanning.QrScanningComponent import com.tangem.feature.referral.api.ReferralComponent @@ -19,6 +20,7 @@ import com.tangem.features.hotwallet.* import com.tangem.features.kyc.KycComponent import com.tangem.features.managetokens.component.ChooseManagedTokensComponent import com.tangem.features.managetokens.component.ManageTokensComponent +import com.tangem.features.managetokens.component.ManageTokensMode import com.tangem.features.managetokens.component.ManageTokensSource import com.tangem.features.markets.details.MarketsTokenDetailsComponent import com.tangem.features.markets.tokenlist.MarketsTokenListComponent @@ -140,9 +142,15 @@ internal class ChildFactory @Inject constructor( AppRoute.ManageTokens.Source.STORIES -> ManageTokensSource.STORIES } + val mode = when (val portfolio = route.portfolioId) { + is PortfolioId.Account -> ManageTokensMode.Account(portfolio.accountId) + is PortfolioId.Wallet -> ManageTokensMode.Wallet(portfolio.userWalletId) + null -> ManageTokensMode.None + } + createComponentChild( context = context, - params = ManageTokensComponent.Params(route.userWalletId, source), + params = ManageTokensComponent.Params(mode, source), componentFactory = manageTokensComponentFactory, ) } diff --git a/common/routing/src/main/kotlin/com/tangem/common/routing/AppRoute.kt b/common/routing/src/main/kotlin/com/tangem/common/routing/AppRoute.kt index d051bdb21e..ce692050bc 100644 --- a/common/routing/src/main/kotlin/com/tangem/common/routing/AppRoute.kt +++ b/common/routing/src/main/kotlin/com/tangem/common/routing/AppRoute.kt @@ -121,8 +121,8 @@ sealed class AppRoute(val path: String) : Route { @Serializable data class ManageTokens( val source: Source, - val userWalletId: UserWalletId? = null, - ) : AppRoute(path = "${source.name.lowercase()}/manage_tokens/$userWalletId") { + val portfolioId: PortfolioId? = null, + ) : AppRoute(path = "${source.name.lowercase()}/manage_tokens/${portfolioId?.stringValue}") { enum class Source { STORIES, diff --git a/core/res/src/main/res/values-de/strings.xml b/core/res/src/main/res/values-de/strings.xml index 2817667d7e..645d4943f0 100644 --- a/core/res/src/main/res/values-de/strings.xml +++ b/core/res/src/main/res/values-de/strings.xml @@ -4,8 +4,8 @@ Trotzdem überspringen Zugangscode nicht festgelegt Zugangscode eingeben - Falscher Zugangscode. Deine Hot-Wallet wird nach %s weiteren Fehlversuchen gelöscht. - Falscher Zugangscode. App wird bei %s weiteren Eingabefehlern gesperrt + Falscher Zugangscode. Deine mobile Wallet wird nach %s weiteren Fehlversuchen gelöscht. + Falscher Zugangscode. Die App wird nach %s weiteren Fehlversuchen gesperrt. Falscher Zugangscode.\nBitte warte %s Sekunden und versuche es erneut. Bestätige Deinen zuvor eingegebenen Code, um fortzufahren Zugangscode erneut eingeben @@ -19,6 +19,7 @@ Wiederherstellen Du bist dabei, dich zu erholen \"%1$s”. Konto wiederherstellen + Du hast das Limit von 20 aktiven Konten bereits überschritten. Archiviere eines, um es wiederherzustellen. Archiviert Konto erstellt Archivkonto @@ -30,6 +31,7 @@ Konto hinzufügen Speichern Kontoname + Der Kontoname ist bereits vorhanden Konto Neues Konto Konto hinzufügen @@ -104,7 +106,7 @@ %s Karte %s Karten - Handy-Wallet + Mobile-Wallet Du hast Deine Wallet erfolgreich gesichert. Diese Wörter können bei Verlust nicht wiederhergestellt werden. Bewahre diese an einem sicheren Ort auf. Sicherung abgeschlossen @@ -174,6 +176,7 @@ Akzeptieren Zugang verweigert Konten + Aktivieren Hinzufügen Zum Portfolio hinzufügen Token hinzufügen @@ -182,6 +185,7 @@ Erlauben Betrag Analysen + und Anwenden Genehmigung Genehmigen @@ -198,6 +202,7 @@ D hast keinen Zugang zur Kamera erteilt, bitte passe deine Datenschutzeinstellungen an Abbrechen Ändern + Konto auswählen Aktion wählen Netzwerk auswählen Token auswählen @@ -246,7 +251,9 @@ Gebühren Beenden Kostenlos + Vom Adressen synchronisieren + Erste Schritte Zum Anbieter gehen Zum Token Verstanden @@ -255,6 +262,7 @@ Importieren In Arbeit Später + Mehr erfahren %1$s übrig Legacy Bitcoin Gesperrt @@ -505,6 +513,7 @@ Neues Wallet erstellen Karte oder Ring bestellen Karte oder Ring scannen + Möchtest Du „Tangem“ die biometrische Authentifizierung erlauben? Um Deine Identität zu bestätigen und die App zu öffnen An %s Im %s Netzwerk Willst Du den Vorgang zur Erstellung des Zugangscodes wirklich beenden? @@ -516,7 +525,7 @@ Wenn dies der Fall ist, musst Du von vorne beginnen. Bist Du sicher, dass Du den Aktivierungsprozess beenden willst? Wenn dies der Fall ist, musst Du von vorne beginnen. - Wiederherstellung einer bestehenden Wallet, die in Ihrem Google Drive-Backup gespeichert ist + Vorhandene Wallet über Google Drive-Backup wiederherstellen Google Drive-Backup Verbesser Deine Sicherheit sofort mit einer erstklassigen Hardware-Wallet von Tangem. Hardware-Wallet @@ -528,6 +537,7 @@ Schlüssel werden in der App gespeichert Sicherung der Seed-Phrase Mobile Wallet erstellen + Vorhandene Wallet importieren Diese Wiederherstellungsphrase wurde bereits importiert Mobile Wallet Dein Geld bleibt während des gesamten Prozesses sicher und vollständig zugänglich @@ -848,6 +858,7 @@ Zugangscode wiederherstellen Identische Karten oder Ring Zugangscode + Alle Angebote Verfügbar mit %s Anbieter erleichtern Transaktionen Suche nach Land @@ -855,13 +866,24 @@ Andere Währungen Beliebte Fiats Suche nach Währung + Sofort Durch die Nutzung der Onramp-Funktionalität stimmst Du den %1$s und %2$s des Anbieters zu. + Der Service wird von einem externen Anbieter bereitgestellt. \n Tangem übernimmt keine Verantwortung. Der Kaufbetrag sollte nicht höher sein als %s Der zu kaufende Betrag muss mindestens %s betragen Keine verfügbaren Anbieter für diese Währung + Schnellste Bezahlen mit + Zahlungsmethode Verfügbar bis zu %s Erhältlich bei %s + + Anbieter + Anbieter + + Anbieter + Kürzlich verwendet + Empfohlen Du kannst Deine Transaktion beim Drittanbieter %s abschließen. Umleitung auf %s… Unsere Dienstleistungen sind in diesem Land nicht verfügbar @@ -870,13 +892,18 @@ Bitte wähle das richtige Land aus, um korrekte Zahlungsoptionen und Dienstleistungen zu gewährleisten. Einstellungen Du kannst diesen Bildschirm schließen und den Transaktionsstatus auf dem Bildschirm mit den Token-Details überprüfen. + %s min + Du erhältst + Der Service wird von einem externen Anbieter bereitgestellt. \n Tangem übernimmt keine Verantwortung. Du kannst diesen Bildschirm schließen und den Transaktionsstatus auf dem Bildschirm mit den Token-Details überprüfen. + Bis zu Über Du zahlst Gruppe erstellen Nach Guthaben Token organisieren Gruppe löschen + %s Unterstützung Mehr Infos Du kannst Benachrichtigungen für Tangem in den Einstellungen aktivieren. Später aktivieren @@ -895,6 +922,7 @@ Sende nur %s an diese Adresse. Der Versand einer anderen Währung führt zu ihrem unwiderruflichen Verlust. Senden nur %1$s im Netzwerk %2$s Überweise Geld von einem anderen Wallet oder einer anderen Börse + Adresse für Prämien Teilnehmen Die Informationen zum Empfehlungsprogramm konnten nicht geladen werden. Bitte versuche es später noch einmal. Die Informationen über das Empfehlungsprogramm konnten nicht geladen werden. Fehlercode: %s. Bitte versuche es später noch einmal. @@ -1071,6 +1099,9 @@ Hiermit wird die Wallet aus der Anwendung entfernt. Die Wallet selbst kann wieder hinzugefügt werden. Name Lass deinen Token für dich arbeiten + Eine Netzwerkgebühr ist eine kleine Zahlung, die erforderlich ist, um Deine Transaktion auf der Blockchain zu verarbeiten und zu bestätigen. + Um mit dem Staking zu beginnen, muss Dein TON-Konto mit einer Selbsttransaktion von 1 TON aktiviert werden. Das Guthaben verbleibt in Deiner Wallet – dieser Schritt aktiviert Dein Konto lediglich für das Staking. + Kontoaktivierung Die Anzahl der zu stakenden Krypros muss mindesten %s betragen Der Stakingbetrag wird aufgrund der Netzwerkregeln auf %1$s TRX aufgerundet. Der Betrag der unstaked wird, wird aufgrund der Netzwerkregeln auf %1$s TRX gerundet. @@ -1079,6 +1110,7 @@ Ein Staking-Konto ist ein spezielles Konto, auf dem eingesetzte SOL-Token gespeichert werden. Es wird erstellt, indem Sie Ihre Token an einen Validator delegieren, um an der Transaktionsvalidierung teilzunehmen und Belohnungen zu erhalten. Für die Einrichtung des Staking-Kontos wird eine geringe Gebühr erhoben, die nach Abschluss des Stakings zurückerstattet wird. Jährliche prozentuale Rendite Die jährliche prozentuale Rendite, die du durch die Teilnahme am Staking erzielen kannst. + APY zeigt den jährlichen prozentualen Ertrag des Validators basierend auf seiner Leistung Effektiver Jahreszins Belohnungen sammeln sich täglich automatisch in deinem Staking-Konto an. Verfügbar @@ -1134,6 +1166,8 @@ Reinvestiert Deine verdienten Prämien in Deinen Einsatzbetrag und erhöht so den potenziellen Gewinn. Mit Restake kannst Du Dein Guthaben von einem Validator zu einem anderen verschieben, ohne dass Du den Stake aufheben musst. Du bist dabei, Dein gesamtes Guthaben zu staken. Wir empfehlen, einen kleinen Betrag übrig zu lassen, um die Netzwerkgebühren für die Aufhebung des Stakes oder das Einfordern von Prämien abzudecken. + Um mit dem Staking zu beginnen, muss Dein TON-Konto mit einer Selbsttransaktion von 1 TON aktiviert werden. Das Guthaben verbleibt in Deiner Wallet – dieser Schritt aktiviert Dein Konto lediglich für das Staking. + Kontoaktivierung Um mit dem Staking bei TON zu beginnen, führe zunächst eine ausgehende Transaktion in beliebiger Höhe durch – dadurch wird Deine Wallet aktiviert. Für den Abschluss der Transaktion können zusätzlich zur Netzwerkgebühr bis zu 0,2 TON erforderlich sein. Nicht genutzte Beträge werden zurückerstattet. Für diesen Vorgang sind zusätzlich zur Netzwerkgebühr 0,2 TON erforderlich. Bitte lade Dein Guthaben auf. @@ -1166,6 +1200,7 @@ Monatlich Wöchentlich Belohnungen + Belohnungen auf Solana werden automatisch Deinem Staking-Guthaben hinzugefügt und können nicht separat angezeigt werden. Stake gesperrt Mehr staken Beim Staking %1$s wird Dein gesamtes %2$s -Guthaben eingesetzt. Alle weiteren %2$s due Du in Deine Tangem-Wallet einzahlst, werden ebenfalls automatisch eingesetzt. @@ -1205,6 +1240,7 @@ Web 3.0-kompatibel Zum Fortfahren ist eine eingehende Transaktion von mindestens %1$s erforderlich Unzureichende Mittel + Durch die Genehmigung erlaubst Du dem Smart Contract, Deine Token in zukünftigen Transaktionen zu verwenden. Fester Zinssatz Das Netzwerk erhebt eine Token-Genehmigungsgebühr, um zu überprüfen, ob Sie die Verwendung Ihres Tokens für den Swap genehmigen. Tausche mehr Token zu besseren Kursen direkt in deiner Brieftasche. @@ -1237,6 +1273,19 @@ Du erhältst Token auswählen Nicht verfügbar + Daten konnten nicht geladen werden. Versuche es später noch einmal. + Verstecken + Aufdecken + Kartendetails + Karte erhalten + Füge es Deiner Wallet hinzu und bezahle überall mit Deinem Smartphone. + Apple Pay & Google Pay + Verwende Dein USDC-Guthaben, um alltägliche Einkäufe problemlos zu bezahlen. + Einkäufe im Alltag + Deine Kartendaten sind geschützt – volle Kontrolle in der App. + Integrierte Sicherheit + Hol Dir Deine kostenlose Crypto Card \n in wenigen Minuten + Tangem Pay Das ist meine Wallet Guthaben versteckt Angezeigte Salden @@ -1264,6 +1313,7 @@ Token in %%image%% %1$s Netzwerk Der %1$s (%2$s) Token ist die Hauptwährung im %3$s Netzwerk und kann nicht versteckt werden, solange du andere Token dieses Netzwerks in der Liste aktiv hast. %s kann nicht ausgeblendet werden + QR-Code anzeigen Tausche diesen Token gegen einen anderen zu %1$s Servicegebühren von Februar %2$s-%3$s. Tausche mit Changelly, %s Gebühren Jetzt tauschen @@ -1312,6 +1362,8 @@ Frühzeitiger Zugriff auf neue Funktionen und exklusive Angebote. Updates zu Funktionen und Neuigkeiten Möchtest du Push-Benachrichtigungen verwenden? + Aktiviere Push-Benachrichtigungen und wir benachrichtigen Dich sofort, wenn Gelder eintreffen \n + Verpasse keine Transaktion Neues Wallet hinzufügen Möchtest Du diese Wallet wirklich entfernen? Es ist ein Fehler aufgetreten, bitte scanne deine Karte oder Ring, um sich anzumelden @@ -1548,6 +1600,7 @@ Wir haben eine Art Problem Alle dApps getrennt Erlaubnis auszugeben + Durch die Genehmigung erlaubst Du dApps oder Smart Contracts, Token in zukünftigen Transaktionen zu verwenden. Vertragsadresse Verbinden Laden @@ -1622,4 +1675,31 @@ Nein, alles senden Um %s XTZ reduziert Damit Sie beim nächsten Aufladen Ihrer Brieftasche keine erhöhte Provision zahlen, soll der Betrag um %s XTZ reduziert werden + Chart konnte nicht geladen werden... + Der erhaltene Betrag %1$s %2$s wurde nicht auf Aave eingezahlt. + Aktuelle Gebühr + Maximale Gebühr + Gebührenpolitik + Die Netzwerkgebühr ist derzeit zu hoch. Warte, bis sie unter Dein Limit fällt. + Historische Renditen + Sofortige Auszahlung + Wie funktioniert das? + Verdiene %s%% jährlich + Aave • Variabler Zinssatz + Aave + Durchschnitt %s + Renditen des letzten Jahres + Unterstützt durch + Der Zinssatz ist variabel + Beginn des Verdienstes + Siehe Gebührenrichtlinie + Aktiv + Pausiert + Effektiver Jahreszins für Versorgung + Lass Dein Geld arbeiten – verdiene Zinsen auf Dein Guthaben. + Verdienst auf Dein Guthaben + Verdienen %1$s%% pro Jahr + Der Stakingservice ist derzeit nicht verfügbar. Bitte versuche es später erneut. + Einnahmen nicht verfügbar + Chart konnte nicht geladen werden... diff --git a/core/res/src/main/res/values-ja/strings.xml b/core/res/src/main/res/values-ja/strings.xml index d76ede5115..f252579b6e 100644 --- a/core/res/src/main/res/values-ja/strings.xml +++ b/core/res/src/main/res/values-ja/strings.xml @@ -19,7 +19,7 @@ 回復する 「 %1$s 」を回復しようとしています。 アカウントを回復する - すでにアクティブアカウント数の上限(20件)を超えています。復元するには1件アーカイブしてください。 + すでにアクティブアカウントの上限(20件)に達しています。復元するには、1つをアーカイブしてください。 アカウントを復元できません アーカイブ済み アカウントを作成できませんでした。しばらくしてからもう一度お試しください。 @@ -176,6 +176,7 @@ 受け入れる アクセスが拒否されました アカウント + 有効化 追加 ポートフォリオに追加 トークンを追加 @@ -248,6 +249,7 @@ 速度と料金 終了 無料 + 送信元 アドレスを同期する はじめる プロバイダーへ移動 @@ -532,6 +534,7 @@ 鍵はアプリに保存されます シードフレーズのバックアップ モバイルウォレットを作成する + 既存のウォレットをインポートする このリカバリーフレーズはすでにインポートされています。 モバイルウォレット アップグレードできません。このデバイスにはすでにウォレットが存在します。 @@ -896,6 +899,7 @@ 残高順 トークンを整理する グループ解除 + %sサポート 詳細はこちら Tangemの通知は設定で有効にできます。 後で有効にする @@ -1089,6 +1093,9 @@ これにより、ウォレットがアプリから削除されます。ウォレットは再度追加できます。 名前 トークンを活用しよう + ネットワーク手数料とは、ブロックチェーン上で取引を処理し、承認するために支払う少額の料金です。 + ステーキングを始めるには、1 TONの自己取引によってTONアカウントを有効化する必要があります。資金はウォレット内にそのまま残ります。これは、ステーキング有効化のためのステップにすぎません。 + アカウントの有効化 ステーキング金額は %s 以上である必要があります ネットワークルールにより、ステーキング金額は%1$s TRX に切り上げられます。 ネットワークルールにより、ステーキング解除の量は%1$s TRX に切り上げられます。 @@ -1154,6 +1161,8 @@ 獲得した報酬をステーキングに再投資し、潜在的な収益を増やします。 再ステーキングを使うと、ステーキングを解除することなく、あるバリデータから別のバリデータに資金を移動できます。 残高のすべてをステーキングしようとしています。ステーキング解除や報酬請求にかかるネットワーク手数料をカバーするために、少額を残しておくことをお勧めします。 + ステーキングを始めるには、TONアカウントを1 TONの自己取引で有効化する必要があります。資金はウォレット内にそのまま残り、この手順でステーキング用にアカウントを有効化できます。 + アカウントの有効化 TONのステーキングを開始するには、まず自分のアドレスに少額の取引を送信します。これによりウォレットが有効になります。 取引を完了するには、ネットワーク手数料に加えて最大0.2TONが必要になる場合があります。未使用分は返金されます。 この操作を続行するには、ネットワーク手数料に加えて0.2 TONが必要です。残高を補充してください。 @@ -1186,6 +1195,7 @@ 毎月 毎週 報酬 + Solanaの報酬は自動的にステーキング残高に追加され、個別に表示することはできません。 ステーキングはロックされています もっとステーキングする %1$sをステーキングすると、 %2$s残高全体がステーキングされます。Tangemウォレットに入金した追加の%2$sも、自動的にステーキングされます。 @@ -1647,6 +1657,13 @@ URIはすでに使用されています WalletConnect 不審な取引 + 業界最高水準のハードウェアウォレット + 迅速な配送 + シンプルな操作 + Tangemでハードウェアウォレットを作成しましょう。銀行のカードのようにスリムで、金庫のように安全です。 + ソフトウェアウォレットを作成またはインポート + モバイルウォレットから始める + その他の方法 破棄 バックアップが中断されました。再開しますか? はい、再開します diff --git a/core/res/src/main/res/values-ru/strings.xml b/core/res/src/main/res/values-ru/strings.xml index d3729cd4c9..cf16e56da7 100644 --- a/core/res/src/main/res/values-ru/strings.xml +++ b/core/res/src/main/res/values-ru/strings.xml @@ -1,8 +1,11 @@ Ваш кошелёк не защищён без кода доступа. + Лимит в 20 активных аккаунтов достигнут. Пожалуйста, зархивируйте один аккаунт, чтобы продолжить. + Невозможно восстановить аккаунт Архив Вы архивируете свой аккаунт, но в любое время можете вернуть его обратно + Имя аккаунта уже существует Аккаунт Новый аккаунт Основной аккаунт @@ -118,6 +121,7 @@ Недостаточно ADA Принять Доступ запрещен + Активировать Добавить Добавить в портфель Добавить токен @@ -188,6 +192,7 @@ Медленно Скорость и комиссия Завершить + Из Синхронизировать адреса К провайдеру Перейти в токен @@ -859,6 +864,7 @@ Отправляйте только %s на этот адрес. Использование другой сети может привести к утрате средств. Отправляйте только %1$s в сети %2$s Переводите средства с любого кошелька или биржи + Адрес для начислений Участвовать Не удалось загрузить информацию по реферальной программе. Пожалуйста, попробуйте позже. Не удалось загрузить информацию по реферальной программе. Код ошибки: %s. Пожалуйста, попробуйте позже. @@ -1035,6 +1041,9 @@ Это приведет к удалению кошелька из приложения. Сам кошелек можно добавить снова. Имя Заставьте ваш токен работать + Сетевая комиссия — это небольшая плата за обработку и подтверждение вашей транзакции в блокчейне. + Чтобы начать стейкинг, ваш TON-аккаунт должен быть активирован транзакцией самому себе на 1 TON. Средства остаются в вашем кошельке — этот шаг лишь активирует ваш аккаунт для участия в стейкинге. + Активация аккаунта Сумма для стейкинга должна быть не менее %s Согласно правилам сети, сумма стейкинга будет округлена до %1$sTRX. Сумма для вывода из стейкинга будет округлена до %1$s TRX ввиду особенностей сети. @@ -1098,6 +1107,8 @@ Реинвестируйте свои заработанные награды в вашу застейканную сумму, увеличивая потенциальный доход Рестейк позволяет вам переместить средства из одного валидатора в другого без необходимости выхода из стейкинга. Вы собираетесь застейкать весь баланс, рекомендуем оставить небольшую сумму для оплаты комиссии сети при выходе из стейкинга или получении награды. + Чтобы начать стейкинг, ваш TON-аккаунт должен быть активирован транзакцией самому себе на 1 TON. Средства остаются в вашем кошельке — этот шаг лишь активирует ваш аккаунт для участия в стейкинге. + Активация аккаунта Чтобы начать стейкинг в TON, сначала отправьте небольшую транзакцию на свой же адрес — это активирует ваш кошелёк. До 0.2 TON может потребоваться сверх сетевой комиссии для завершения транзакции. Неиспользованная часть будет возвращена. Для выполнения операции требуется дополнительно 0.2 TON, помимо сетевой комиссии. Пожалуйста, пополните баланс. @@ -1130,6 +1141,7 @@ Месяц Еженедельно Вознаграждения + Вознаграждения в сети Solana автоматически добавляются к вашему стейкинг-балансу и не могут отображаться отдельно. Стейкинг закрыт Застейкать еще При стейкинге %1$s используется весь ваш баланс в %2$s. Любой дополнительный %2$s депозит будет автоматически застейкан. @@ -1169,6 +1181,7 @@ Поддержка Web 3.0 Для отправки требуется входящая транзакция на сумму не менее %1$s Недостаточно средств + Подтверждая, вы разрешаете смарт-контракту использовать ваши токены в будущих транзакциях. Комиссия сети за одобрение токена будет взиматься за подтверждение того, что именно вы разрешаете использовать ваш токен для обмена. Обменивайте больше токенов по лучшим курсам прямо в вашем кошельке. Новый провайдер обмена! @@ -1227,6 +1240,7 @@ Токен в сети %%image%% %1$s Токен %1$s (%2$s) является основной валютой в сети %3$s и не может быть скрыт до тех пор, пока у вас в списке есть другие токены этой сети Невозможно скрыть %s + Показать QR код Обменивайте этот токен на другие с %1$s комиссии за обслуживание с %2$s по %3$s февраля. Обмен с Changelly, %s комиссии Обменять @@ -1516,6 +1530,7 @@ Изменения в кошельке не обнаружены. Обнаружены потенциальные риски или вредоносное поведение. Подключение или подписание транзакций может привести к потере средств. Известный риск безопасности + Откройте Web3-приложение и выберите опцию WalletConnect. Запрос от Подписать всё равно Тип подписи @@ -1544,4 +1559,13 @@ Нет, отправить все Уменьшить на %s XTZ Чтобы не платить повышенную комиссию при следующем пополнении кошелька, уменьшите сумму на %s XTZ + Невозможно загрузить график + Полученная сумма, %1$s %2$s, не была зачислена на Aave. + Сетевая комиссия сейчас слишком высокая. Ожидаем, пока она упадёт ниже вашего лимита. + Историческая доходность + Проверьте ваше интернет соединение + Годовая доходность + Сервис начисления процентов в данный момент недоступен. Пожалуйста, попробуйте позже. + Данные о доходе недоступны + Невозможно загрузить график diff --git a/core/res/src/main/res/values-uk-rUA/strings.xml b/core/res/src/main/res/values-uk-rUA/strings.xml index e832ab378e..ddc9e58212 100644 --- a/core/res/src/main/res/values-uk-rUA/strings.xml +++ b/core/res/src/main/res/values-uk-rUA/strings.xml @@ -1183,8 +1183,12 @@ Використовуйте %s або відскануйте картку/кільце, щоб отримати доступ до свого гаманця Не вдалося встановити з\'єднання: Цей dApp використовує Wallet Connect версії 1.0, яка не підтримується. Будь ласка, переконайтеся, що dApp підтримує Wallet Connect версії 2.0 для успішного підключення. Будьте в курсі останніх функцій та новин + Миттєві сповіщення про транзакції, обміни та важливі оновлення. + Сповіщення про транзакції Отримуйте сповіщення про вхідні транзакції Дізнавайтеся першими про нові акції + Ранній доступ до нових функцій та ексклюзивних пропозицій. + Нові функції та важливі новини Бажаєте використовувати Push-повідомлення? Додати новий гаманець Ви впевнені, що хочете видалити цей гаманець? diff --git a/core/res/src/main/res/values/strings.xml b/core/res/src/main/res/values/strings.xml index 9987d7f342..6479a28a3f 100644 --- a/core/res/src/main/res/values/strings.xml +++ b/core/res/src/main/res/values/strings.xml @@ -19,7 +19,7 @@ Recover You’re about to recover “%1$s”. Recover account - You have already exceeded the limit of 20 active accounts. Archive one to recover + You have already exceeded the limit of 20 active accounts. Archive one to recover. Can\'t recover account Archived We couldn’t create account. Please try again later. @@ -355,6 +355,8 @@ Yes Contract address copied! Available networks + Derivation of your token matches the derivation of %1$s. Your token will be added to this account. + Derivation belongs to another account. Contract address Contract address is invalid Please select the network @@ -1713,7 +1715,7 @@ No wallet changes detected Potential risks or malicious behavior have been detected. Connecting or signing transactions may lead to loss of funds. Known security risk - Open Web3 app and chose WalletConnect option + Open the Web3 app and choose the WalletConnect option. Request from Sign anyway Signature Type @@ -1729,6 +1731,13 @@ URI already used WalletConnect Suspicious transaction + Best in class hardware wallet + Fast delivery + Simple to use + Create a hardware wallet with Tangem. Slim as a bank card, secure as a bank vault. + Create or import a software wallet + Start with Mobile Wallet + Other method Discard You have an interrupted backup. Do you want to resume? Yes, resume diff --git a/domain/account/status/src/main/java/com/tangem/domain/account/status/supplier/SingleAccountStatusListSupplier.kt b/domain/account/status/src/main/java/com/tangem/domain/account/status/supplier/SingleAccountStatusListSupplier.kt index 5e5ef8f506..6177e2cde5 100644 --- a/domain/account/status/src/main/java/com/tangem/domain/account/status/supplier/SingleAccountStatusListSupplier.kt +++ b/domain/account/status/src/main/java/com/tangem/domain/account/status/supplier/SingleAccountStatusListSupplier.kt @@ -3,6 +3,8 @@ package com.tangem.domain.account.status.supplier import com.tangem.domain.account.models.AccountStatusList import com.tangem.domain.account.status.producer.SingleAccountStatusListProducer import com.tangem.domain.core.flow.FlowCachingSupplier +import com.tangem.domain.models.wallet.UserWalletId +import kotlinx.coroutines.flow.Flow /** * Supplier that provides a single [AccountStatusList] for a specific user wallet. @@ -12,4 +14,10 @@ import com.tangem.domain.core.flow.FlowCachingSupplier abstract class SingleAccountStatusListSupplier( override val factory: SingleAccountStatusListProducer.Factory, override val keyCreator: (SingleAccountStatusListProducer.Params) -> String, -) : FlowCachingSupplier() \ No newline at end of file +) : FlowCachingSupplier() { + + operator fun invoke(userWalletId: UserWalletId): Flow { + val params = SingleAccountStatusListProducer.Params(userWalletId) + return this.invoke(params) + } +} \ No newline at end of file diff --git a/domain/legacy/src/main/java/com/tangem/domain/tokens/TokensAction.kt b/domain/legacy/src/main/java/com/tangem/domain/tokens/TokensAction.kt deleted file mode 100644 index 90378e19c2..0000000000 --- a/domain/legacy/src/main/java/com/tangem/domain/tokens/TokensAction.kt +++ /dev/null @@ -1,16 +0,0 @@ -package com.tangem.domain.tokens - -import com.tangem.blockchain.common.Blockchain -import com.tangem.blockchain.common.Token -import org.rekotlin.Action - -sealed interface TokensAction : Action { - - /** Single way to pass data to the screen */ - sealed interface SetArgs : TokensAction { - object ManageAccess : SetArgs - object ReadAccess : SetArgs - } -} - -data class TokenWithBlockchain(val token: Token, val blockchain: Blockchain) \ No newline at end of file diff --git a/features/account/impl/src/main/java/com/tangem/features/account/details/AccountDetailsModel.kt b/features/account/impl/src/main/java/com/tangem/features/account/details/AccountDetailsModel.kt index 2c0a24413a..2cf339e309 100644 --- a/features/account/impl/src/main/java/com/tangem/features/account/details/AccountDetailsModel.kt +++ b/features/account/impl/src/main/java/com/tangem/features/account/details/AccountDetailsModel.kt @@ -13,7 +13,10 @@ import com.tangem.core.ui.message.DialogMessage import com.tangem.core.ui.message.EventMessageAction import com.tangem.core.ui.message.ToastMessage import com.tangem.domain.account.usecase.ArchiveCryptoPortfolioUseCase +import com.tangem.domain.models.PortfolioId import com.tangem.domain.models.account.Account +import com.tangem.domain.models.wallet.isMultiCurrency +import com.tangem.domain.wallets.usecase.GetUserWalletUseCase import com.tangem.features.account.AccountDetailsComponent import com.tangem.features.account.createedit.entity.AccountCreateEditUMBuilder.Companion.portfolioIcon import com.tangem.features.account.details.entity.AccountDetailsUM @@ -30,6 +33,7 @@ internal class AccountDetailsModel @Inject constructor( private val router: Router, override val dispatchers: CoroutineDispatcherProvider, private val archiveCryptoPortfolioUseCase: ArchiveCryptoPortfolioUseCase, + private val getUserWalletUseCase: GetUserWalletUseCase, ) : Model() { private val params = paramsContainer.require() @@ -42,8 +46,11 @@ internal class AccountDetailsModel @Inject constructor( } private fun onManageTokensClick() { - // todo account add account param - router.push(AppRoute.ManageTokens(source = AppRoute.ManageTokens.Source.SETTINGS)) + val route = AppRoute.ManageTokens( + source = AppRoute.ManageTokens.Source.SETTINGS, + portfolioId = PortfolioId(params.account.accountId), + ) + router.push(route) } private fun onArchiveAccountClick() { @@ -89,6 +96,8 @@ internal class AccountDetailsModel @Inject constructor( ) } } + val isMultiCurrency = getUserWalletUseCase(params.account.accountId.userWalletId) + .getOrNull()?.isMultiCurrency ?: false return AccountDetailsUM( accountName = params.account.accountName.toUM().value, accountIcon = params.account.portfolioIcon.toUM(), @@ -96,6 +105,7 @@ internal class AccountDetailsModel @Inject constructor( onAccountEditClick = ::onEditAccountClick, onManageTokensClick = ::onManageTokensClick, archiveMode = archiveMode, + isManageTokensAvailable = isMultiCurrency, ) } } \ No newline at end of file diff --git a/features/account/impl/src/main/java/com/tangem/features/account/details/entity/AccountDetailsUM.kt b/features/account/impl/src/main/java/com/tangem/features/account/details/entity/AccountDetailsUM.kt index 3938e757fb..27ad494553 100644 --- a/features/account/impl/src/main/java/com/tangem/features/account/details/entity/AccountDetailsUM.kt +++ b/features/account/impl/src/main/java/com/tangem/features/account/details/entity/AccountDetailsUM.kt @@ -7,6 +7,7 @@ internal data class AccountDetailsUM( val accountName: TextReference, val accountIcon: CryptoPortfolioIconUM, val archiveMode: ArchiveMode, + val isManageTokensAvailable: Boolean, val onCloseClick: () -> Unit, val onAccountEditClick: () -> Unit, val onManageTokensClick: () -> Unit, diff --git a/features/account/impl/src/main/java/com/tangem/features/account/details/ui/AccountDetailsContent.kt b/features/account/impl/src/main/java/com/tangem/features/account/details/ui/AccountDetailsContent.kt index bd4a0e319f..e3708f495f 100644 --- a/features/account/impl/src/main/java/com/tangem/features/account/details/ui/AccountDetailsContent.kt +++ b/features/account/impl/src/main/java/com/tangem/features/account/details/ui/AccountDetailsContent.kt @@ -22,7 +22,6 @@ import com.tangem.common.ui.R import com.tangem.common.ui.account.AccountIconPreviewData import com.tangem.common.ui.account.AccountRow import com.tangem.core.ui.components.SpacerH -import com.tangem.core.ui.components.SpacerH16 import com.tangem.core.ui.components.appbar.AppBarWithBackButton import com.tangem.core.ui.components.buttons.SecondarySmallButton import com.tangem.core.ui.components.buttons.SmallButtonConfig @@ -49,6 +48,7 @@ internal fun AccountDetailsContent(state: AccountDetailsUM, modifier: Modifier = ) Column( + verticalArrangement = Arrangement.spacedBy(16.dp), modifier = Modifier .fillMaxSize() .padding(horizontal = TangemTheme.dimens.spacing16) @@ -61,21 +61,22 @@ internal fun AccountDetailsContent(state: AccountDetailsUM, modifier: Modifier = style = TangemTheme.typography.h1, color = TangemTheme.colors.text.primary1, ) - SpacerH16() AccountRow(state) - SpacerH16() - ManageTokensRow(state) + if (state.isManageTokensAvailable) { + ManageTokensRow(state) + } when (state.archiveMode) { is AccountDetailsUM.ArchiveMode.Available -> { - SpacerH16() - ArchiveAccountRow(state.archiveMode) - SpacerH(8.dp) - Text( - modifier = Modifier.padding(horizontal = 12.dp), - text = stringResourceSafe(R.string.account_details_archive_description), - style = TangemTheme.typography.caption2, - color = TangemTheme.colors.text.tertiary, - ) + Column { + ArchiveAccountRow(state.archiveMode) + SpacerH(8.dp) + Text( + modifier = Modifier.padding(horizontal = 12.dp), + text = stringResourceSafe(R.string.account_details_archive_description), + style = TangemTheme.typography.caption2, + color = TangemTheme.colors.text.tertiary, + ) + } } AccountDetailsUM.ArchiveMode.None -> Unit } @@ -186,10 +187,12 @@ private class PreviewStateProvider : CollectionPreviewParameterProvider } \ No newline at end of file diff --git a/features/manage-tokens/api/src/main/kotlin/com/tangem/features/managetokens/component/ManageTokensSource.kt b/features/manage-tokens/api/src/main/kotlin/com/tangem/features/managetokens/component/ManageTokensSource.kt index 3c34dd0f34..bdd3cdbc10 100644 --- a/features/manage-tokens/api/src/main/kotlin/com/tangem/features/managetokens/component/ManageTokensSource.kt +++ b/features/manage-tokens/api/src/main/kotlin/com/tangem/features/managetokens/component/ManageTokensSource.kt @@ -17,6 +17,13 @@ sealed interface ManageTokensMode { } sealed interface AddCustomTokenMode { - data class Wallet(val userWalletId: UserWalletId) : AddCustomTokenMode + + val userWalletId: UserWalletId + get() = when (this) { + is Account -> accountId.userWalletId + is Wallet -> userWalletId + } + + data class Wallet(override val userWalletId: UserWalletId) : AddCustomTokenMode data class Account(val accountId: AccountId) : AddCustomTokenMode } \ No newline at end of file diff --git a/features/manage-tokens/impl/build.gradle.kts b/features/manage-tokens/impl/build.gradle.kts index 0506848d40..58cffdfd57 100644 --- a/features/manage-tokens/impl/build.gradle.kts +++ b/features/manage-tokens/impl/build.gradle.kts @@ -25,6 +25,8 @@ dependencies { implementation(projects.common.ui) /* Project - Domain */ + implementation(projects.domain.account.status) + implementation(projects.domain.account) implementation(projects.domain.card) implementation(projects.domain.legacy) implementation(projects.domain.manageTokens) @@ -35,6 +37,14 @@ dependencies { implementation(projects.domain.swap.models) implementation(projects.domain.notifications) + // region Project - Libs + implementation(projects.libs.crypto) + // endregion + + // region Tangem SDKs + implementation(tangemDeps.blockchain) + // endregion + /* AndroidX */ implementation(deps.androidx.activity.compose) implementation(deps.lifecycle.compose) diff --git a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/entity/managetokens/ManageTokensUM.kt b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/entity/managetokens/ManageTokensUM.kt index 56323dcd9a..13fca6567a 100644 --- a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/entity/managetokens/ManageTokensUM.kt +++ b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/entity/managetokens/ManageTokensUM.kt @@ -54,6 +54,7 @@ internal sealed class ManageTokensUM { isSavingInProgress: Boolean = this is ManageContent && this.isSavingInProgress, scrollToTop: StateEvent = this.scrollToTop, needToInteractWithColdWallet: Boolean = this is ManageContent && this.needToInteractWithColdWallet, + topBar: ManageTokensTopBarUM? = this.topBar, ): ManageTokensUM { return when (this) { is ManageContent -> copy( @@ -65,6 +66,7 @@ internal sealed class ManageTokensUM { isSavingInProgress = isSavingInProgress, scrollToTop = scrollToTop, needToInteractWithColdWallet = needToInteractWithColdWallet, + topBar = topBar, ) is ReadContent -> copy( search = search, @@ -72,6 +74,7 @@ internal sealed class ManageTokensUM { isInitialBatchLoading = isInitialBatchLoading, isNextBatchLoading = isNextBatchLoading, scrollToTop = scrollToTop, + topBar = topBar, ) } } diff --git a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/model/CustomTokenSelectorModel.kt b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/model/CustomTokenSelectorModel.kt index 3bb119e580..cadcf9f356 100644 --- a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/model/CustomTokenSelectorModel.kt +++ b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/model/CustomTokenSelectorModel.kt @@ -3,13 +3,22 @@ package com.tangem.features.managetokens.model import arrow.core.getOrElse import com.arkivanov.decompose.router.slot.SlotNavigation import com.arkivanov.decompose.router.slot.activate +import com.tangem.blockchain.common.Blockchain +import com.tangem.common.ui.account.toUM 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.ui.UiMessageSender +import com.tangem.core.ui.extensions.TextReference import com.tangem.core.ui.extensions.resourceReference +import com.tangem.core.ui.extensions.wrappedList +import com.tangem.core.ui.message.DialogMessage +import com.tangem.core.ui.message.EventMessageAction import com.tangem.core.ui.message.SnackbarMessage +import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles +import com.tangem.domain.account.status.supplier.SingleAccountStatusListSupplier import com.tangem.domain.managetokens.GetSupportedNetworksUseCase +import com.tangem.domain.models.account.AccountStatus import com.tangem.domain.models.network.Network import com.tangem.features.managetokens.component.AddCustomTokenMode import com.tangem.features.managetokens.component.CustomTokenSelectorComponent @@ -25,10 +34,12 @@ import com.tangem.features.managetokens.entity.item.SelectableItemUM import com.tangem.features.managetokens.impl.R import com.tangem.features.managetokens.utils.mapper.toCurrencyNetworkModel import com.tangem.features.managetokens.utils.mapper.toDerivationPathModel +import com.tangem.lib.crypto.derivation.AccountNodeRecognizer import com.tangem.utils.coroutines.CoroutineDispatcherProvider import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import javax.inject.Inject @@ -38,6 +49,8 @@ internal class CustomTokenSelectorModel @Inject constructor( override val dispatchers: CoroutineDispatcherProvider, private val getSupportedNetworksUseCase: GetSupportedNetworksUseCase, private val messageSender: UiMessageSender, + private val singleAccountStatusListSupplier: SingleAccountStatusListSupplier, + private val accountsFeatureToggles: AccountsFeatureToggles, paramsContainer: ParamsContainer, ) : Model() { @@ -146,9 +159,8 @@ internal class CustomTokenSelectorModel @Inject constructor( return derivationPaths } - private suspend fun getSupportedNetworks(mode: AddCustomTokenMode): List = when (mode) { - is AddCustomTokenMode.Account -> TODO("Account") - is AddCustomTokenMode.Wallet -> getSupportedNetworksUseCase(mode.userWalletId).getOrElse { e -> + private suspend fun getSupportedNetworks(mode: AddCustomTokenMode): List { + return getSupportedNetworksUseCase(mode.userWalletId).getOrElse { e -> val message = SnackbarMessage(message = resourceReference(R.string.common_unknown_error)) messageSender.send(message) @@ -168,7 +180,60 @@ internal class CustomTokenSelectorModel @Inject constructor( fun selectCustomDerivationPath(value: SelectedDerivationPath) { when (params) { is NetworkSelector -> return - is DerivationPathSelector -> params.onDerivationPathSelected(value) + is DerivationPathSelector -> if (accountsFeatureToggles.isFeatureEnabled) { + params.checkAccountDerivation(value) + } else { + params.onDerivationPathSelected(value) + } } } + + private fun DerivationPathSelector.checkAccountDerivation(derivationPath: SelectedDerivationPath) = + modelScope.launch { + val accountName = derivationPath.id + ?.let { Blockchain.fromId(it.rawId.value) }?.let(::AccountNodeRecognizer) + ?.let { recognizer -> derivationPath.value.value?.let { recognizer.recognize(it) } } + ?.let { accountNode -> + fun AccountStatus.CryptoPortfolio.sameNodeAndNotMain() = !this.account.isMainAccount && + this.account.derivationIndex.value.toLong() == accountNode + + val accounts = singleAccountStatusListSupplier(mode.userWalletId) + .first().accountStatuses + val account = accounts.find { + when (it) { + is AccountStatus.CryptoPortfolio -> it.sameNodeAndNotMain() + } + } + val accountName = when (account) { + is AccountStatus.CryptoPortfolio -> account.account.accountName.toUM() + null -> null + } + accountName + } + + if (accountName == null) { + onDerivationPathSelected(derivationPath) + } else { + showAccountNameExist( + accountName = accountName.value, + onClick = { onDerivationPathSelected(derivationPath) }, + ) + } + } + + private fun showAccountNameExist(accountName: TextReference, onClick: () -> Unit) { + val firstAction = EventMessageAction( + title = resourceReference(R.string.common_got_it), + onClick = onClick, + ) + val dialogMessage = DialogMessage( + title = resourceReference(R.string.custom_token_another_account_dialog_title), + message = resourceReference( + R.string.custom_token_another_account_dialog_description, + wrappedList(accountName), + ), + firstActionBuilder = { firstAction }, + ) + messageSender.send(dialogMessage) + } } \ No newline at end of file diff --git a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/model/ManageTokensModel.kt b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/model/ManageTokensModel.kt index c34a6ba32d..74ee2da6c5 100644 --- a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/model/ManageTokensModel.kt +++ b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/model/ManageTokensModel.kt @@ -17,6 +17,7 @@ import com.tangem.core.ui.event.triggeredEvent import com.tangem.core.ui.extensions.resourceReference import com.tangem.core.ui.extensions.stringReference import com.tangem.core.ui.message.SnackbarMessage +import com.tangem.domain.account.status.supplier.SingleAccountStatusListSupplier import com.tangem.features.managetokens.analytics.CustomTokenAnalyticsEvent import com.tangem.features.managetokens.analytics.ManageTokensAnalyticEvent import com.tangem.features.managetokens.component.ManageTokensComponent @@ -40,13 +41,14 @@ import kotlinx.coroutines.launch import timber.log.Timber import javax.inject.Inject -@Suppress("LongParameterList") +@Suppress("LongParameterList", "LargeClass") @ModelScoped internal class ManageTokensModel @Inject constructor( override val dispatchers: CoroutineDispatcherProvider, private val router: Router, private val messageSender: UiMessageSender, private val analyticsEventHandler: AnalyticsEventHandler, + private val singleAccountStatusListSupplier: SingleAccountStatusListSupplier, manageTokensListManagerFactory: ManageTokensListManager.Factory, manageTokensUseCasesFacadeFactory: ManageTokensUseCasesFacade.Factory, paramsContainer: ParamsContainer, @@ -86,6 +88,7 @@ internal class ManageTokensModel @Inject constructor( modelScope.launch { manageTokensListManager.launchPagination(isCollapsed = true) } + checkIsSupportAddCustomTokens() } fun reloadList() { @@ -105,16 +108,34 @@ internal class ManageTokensModel @Inject constructor( } } + private fun getTopBarInitialState(): ManageTokensTopBarUM = when (params.mode) { + is ManageTokensMode.Wallet -> manageContentTopBar() + is ManageTokensMode.Account -> ManageTokensTopBarUM.ReadContent( + title = resourceReference(id = R.string.main_manage_tokens), + onBackButtonClick = router::pop, + ) + ManageTokensMode.None -> ManageTokensTopBarUM.ReadContent( + title = resourceReference(R.string.common_search_tokens), + onBackButtonClick = router::pop, + ) + } + + private fun manageContentTopBar() = ManageTokensTopBarUM.ManageContent( + title = resourceReference(id = R.string.main_manage_tokens), + onBackButtonClick = router::pop, + endButton = TopAppBarButtonUM.Icon( + iconRes = R.drawable.ic_plus_24, + onClicked = ::navigateToAddCustomToken, + ), + ) + private fun createReadContentModel(): ManageTokensUM.ReadContent { return ManageTokensUM.ReadContent( popBack = router::pop, isInitialBatchLoading = true, isNextBatchLoading = false, items = getLoadingItems(), - topBar = ManageTokensTopBarUM.ReadContent( - title = resourceReference(R.string.common_search_tokens), - onBackButtonClick = router::pop, - ), + topBar = getTopBarInitialState(), search = SearchBarUM( placeholderText = resourceReference(R.string.common_search), query = "", @@ -132,14 +153,7 @@ internal class ManageTokensModel @Inject constructor( isInitialBatchLoading = true, isNextBatchLoading = false, items = getLoadingItems(), - topBar = ManageTokensTopBarUM.ManageContent( - title = resourceReference(id = R.string.main_manage_tokens), - onBackButtonClick = router::pop, - endButton = TopAppBarButtonUM.Icon( - iconRes = R.drawable.ic_plus_24, - onClicked = ::navigateToAddCustomToken, - ), - ), + topBar = getTopBarInitialState(), search = SearchBarUM( placeholderText = resourceReference(R.string.common_search), query = "", @@ -174,6 +188,20 @@ internal class ManageTokensModel @Inject constructor( .launchIn(modelScope) } + private fun checkIsSupportAddCustomTokens() { + when (val mode = params.mode) { + is ManageTokensMode.Account -> modelScope.launch { + val mainAccount = singleAccountStatusListSupplier(mode.accountId.userWalletId).first().mainAccount + if (mode.accountId == mainAccount.account.accountId) { + state.update { it.copySealed(topBar = manageContentTopBar()) } + } + } + ManageTokensMode.None, + is ManageTokensMode.Wallet, + -> Unit // use init state + } + } + private fun updateItems(items: ImmutableList) { val updatedState = state.updateAndGet { state -> state.copySealed( diff --git a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/ui/ManageTokensScreen.kt b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/ui/ManageTokensScreen.kt index e7426ae87c..2b20edf084 100644 --- a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/ui/ManageTokensScreen.kt +++ b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/ui/ManageTokensScreen.kt @@ -57,6 +57,7 @@ import com.tangem.core.ui.utils.WindowInsetsZero import com.tangem.core.ui.utils.rememberHideKeyboardNestedScrollConnection import com.tangem.domain.models.wallet.UserWalletId import com.tangem.features.managetokens.component.ManageTokensComponent +import com.tangem.features.managetokens.component.ManageTokensMode import com.tangem.features.managetokens.component.ManageTokensSource import com.tangem.features.managetokens.component.preview.PreviewManageTokensComponent import com.tangem.features.managetokens.entity.item.CurrencyItemUM @@ -442,20 +443,23 @@ private class PreviewManageTokensComponentProvider : PreviewParameterProvider, ): PersistentList { + val accountsFeatureEnabled = accountsFeatureToggles.isFeatureEnabled val isMultiCurrency = when (userWallet) { is UserWallet.Cold -> userWallet.isMultiCurrency is UserWallet.Hot -> true @@ -188,7 +191,7 @@ internal class WalletSettingsModel @Inject constructor( is UserWallet.Cold -> userWallet.scanResponse.card.backupStatus == CardDTO.BackupStatus.NoBackup is UserWallet.Hot -> false }, - isManageTokensAvailable = isMultiCurrency, + isManageTokensAvailable = !accountsFeatureEnabled && isMultiCurrency, isNFTFeatureEnabled = isMultiCurrency, isNFTEnabled = isNFTEnabled, onCheckedNFTChange = ::onCheckedNFTChange, diff --git a/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/utils/ItemsBuilder.kt b/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/utils/ItemsBuilder.kt index 6d2bf36754..e3caaf89d5 100644 --- a/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/utils/ItemsBuilder.kt +++ b/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/utils/ItemsBuilder.kt @@ -9,6 +9,7 @@ import com.tangem.core.ui.components.block.model.BlockUM import com.tangem.core.ui.components.label.entity.LabelStyle import com.tangem.core.ui.components.label.entity.LabelUM import com.tangem.core.ui.extensions.resourceReference +import com.tangem.domain.models.PortfolioId import com.tangem.domain.models.wallet.UserWallet import com.tangem.feature.walletsettings.analytics.Settings import com.tangem.feature.walletsettings.entity.WalletSettingsAccountsUM @@ -207,7 +208,7 @@ internal class ItemsBuilder @Inject constructor( iconRes = R.drawable.ic_tether_24, onClick = { analyticsEventHandler.send(Settings.ButtonManageTokens) - router.push(AppRoute.ManageTokens(Source.SETTINGS, userWalletId)) + router.push(AppRoute.ManageTokens(Source.SETTINGS, PortfolioId(userWalletId))) }, ).let(::add) } diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/intents/WalletContentClickIntents.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/intents/WalletContentClickIntents.kt index a9e2270a44..39e5b37251 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/intents/WalletContentClickIntents.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/intents/WalletContentClickIntents.kt @@ -10,11 +10,9 @@ import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.models.wallet.UserWalletId import com.tangem.domain.models.wallet.isLocked import com.tangem.domain.nft.analytics.NFTAnalyticsEvent -import com.tangem.domain.redux.ReduxStateHolder import com.tangem.domain.settings.ShouldShowMarketsTooltipUseCase import com.tangem.domain.tokens.GetCryptoCurrencyActionsUseCase import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase -import com.tangem.domain.tokens.TokensAction import com.tangem.domain.tokens.model.TokenActionsState import com.tangem.domain.txhistory.usecase.GetExplorerTransactionUrlUseCase import com.tangem.domain.wallets.usecase.GetUserWalletUseCase @@ -39,8 +37,6 @@ internal interface WalletContentClickIntents { fun onDetailsClick() - fun onManageTokensClick() - fun onOrganizeTokensClick() fun onDismissMarketsOnboarding() @@ -81,7 +77,6 @@ internal class WalletContentClickIntentsImplementor @Inject constructor( private val getExplorerTransactionUrlUseCase: GetExplorerTransactionUrlUseCase, private val shouldShowMarketsTooltipUseCase: ShouldShowMarketsTooltipUseCase, private val dispatchers: CoroutineDispatcherProvider, - private val reduxStateHolder: ReduxStateHolder, private val walletEventSender: WalletEventSender, private val analyticsEventHandler: AnalyticsEventHandler, private val hotWalletFeatureToggles: HotWalletFeatureToggles, @@ -122,11 +117,6 @@ internal class WalletContentClickIntentsImplementor @Inject constructor( } } - override fun onManageTokensClick() { - reduxStateHolder.dispatch(action = TokensAction.SetArgs.ManageAccess) - router.openManageTokensScreen(userWalletId = stateHolder.getSelectedWalletId()) - } - override fun onOrganizeTokensClick() { router.openOrganizeTokensScreen(userWalletId = stateHolder.getSelectedWalletId()) } diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/router/DefaultWalletRouter.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/router/DefaultWalletRouter.kt index 1bab1f8a28..f2f41882cc 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/router/DefaultWalletRouter.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/router/DefaultWalletRouter.kt @@ -3,7 +3,6 @@ package com.tangem.feature.wallet.presentation.router import com.arkivanov.decompose.router.slot.SlotNavigation import com.arkivanov.decompose.router.slot.activate import com.tangem.common.routing.AppRoute -import com.tangem.common.routing.AppRoute.ManageTokens.Source import com.tangem.common.routing.AppRouter import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.navigation.url.UrlOpener @@ -86,10 +85,6 @@ internal class DefaultWalletRouter @Inject constructor( return router.stack.lastOrNull() is AppRoute.Wallet } - override fun openManageTokensScreen(userWalletId: UserWalletId) { - router.push(AppRoute.ManageTokens(Source.SETTINGS, userWalletId)) - } - override fun openScanFailedDialog(onTryAgain: () -> Unit) { reduxStateHolder.dispatchDialogShow(StateDialog.ScanFailsDialog(StateDialog.ScanFailsSource.MAIN, onTryAgain)) } diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/router/InnerWalletRouter.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/router/InnerWalletRouter.kt index 106cafa945..4c6c7ba002 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/router/InnerWalletRouter.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/router/InnerWalletRouter.kt @@ -49,9 +49,6 @@ internal interface InnerWalletRouter { /** Is wallet last screen */ fun isWalletLastScreen(): Boolean - /** Open manage tokens screen */ - fun openManageTokensScreen(userWalletId: UserWalletId) - /** Open scan failed dialog */ fun openScanFailedDialog(onTryAgain: () -> Unit)