Dart modernization & various updates/fixes/enhancements

- Updated entire codebase to modern "null safe" dart.

- Updated all dependencies to newer/null safe versions.

- fixed a serious bug in PIN setup that didn't properly check the two
  pins were the same (and always used the second one).

- Various translation fixes and wording updates.

- Use more appropriate locale-specific date displays

- Fixes several small memory leaks

- Stylized the "receive" QR code

- Added QR code scanning to the New Stake page (to allow scanning QR
  code pubkeys from awaiting contribution nodes on
  https://oxen.observer)

- Made the multi-option settings on the Settings page default to current
  value instead of resetting to the first value when tapped.

- Removed character restrictions from wallet, account, subaccount, and
  address book names.

- Service Nodes stakes now properly lists only the wallet's actual
  stakes for staked service node rather than everyone's stakes in the
  service node.

- Label staking transactions as "Stake" rather than "Sent"

- Don't show fiat on send page if fiat lookups not enabled
This commit is contained in:
Jason Rhinelander 2022-04-18 13:31:22 -03:00
parent ba55cd3b76
commit 78fca4ba28
No known key found for this signature in database
GPG Key ID: C4992CE7A88D4262
222 changed files with 3120 additions and 7827 deletions

View File

@ -11,47 +11,48 @@ analyzer:
linter:
rules:
- always_declare_return_types
- annotate_overrides
- avoid_empty_else
- avoid_init_to_null
- avoid_return_types_on_setters
- await_only_futures
- camel_case_types
- cancel_subscriptions
- close_sinks
- comment_references
- constant_identifier_names
- control_flow_in_finally
- empty_catches
- empty_constructor_bodies
- empty_statements
- hash_and_equals
- implementation_imports
- invariant_booleans
- iterable_contains_unrelated_type
- library_names
- library_prefixes
- list_remove_unrelated_type
- literal_only_boolean_expressions
- non_constant_identifier_names
- one_member_abstracts
- only_throw_errors
- overridden_fields
- package_api_docs
- package_names
- package_prefixed_library_names
- parameter_assignments
- prefer_final_fields
- prefer_final_locals
- prefer_is_not_empty
- slash_for_doc_comments
- sort_constructors_first
- sort_unnamed_constructors_first
- test_types_in_equals
- throw_in_finally
- type_init_formals
- unawaited_futures
- unnecessary_getters_setters
- unrelated_type_equality_checks
- valid_regexps
always_declare_return_types: true
annotate_overrides: true
avoid_empty_else: true
avoid_init_to_null: true
avoid_return_types_on_setters: true
await_only_futures: true
camel_case_types: true
cancel_subscriptions: true
close_sinks: true
comment_references: true
constant_identifier_names: true
control_flow_in_finally: true
curly_braces_in_flow_control_structures: false
empty_catches: true
empty_constructor_bodies: true
empty_statements: true
hash_and_equals: true
implementation_imports: true
invariant_booleans: true
iterable_contains_unrelated_type: true
library_names: true
library_prefixes: true
list_remove_unrelated_type: true
literal_only_boolean_expressions: true
non_constant_identifier_names: true
one_member_abstracts: true
only_throw_errors: true
overridden_fields: true
package_api_docs: true
package_names: true
package_prefixed_library_names: true
parameter_assignments: true
prefer_final_fields: true
prefer_final_locals: true
prefer_is_not_empty: true
slash_for_doc_comments: true
sort_constructors_first: true
sort_unnamed_constructors_first: true
test_types_in_equals: true
throw_in_finally: true
type_init_formals: true
unawaited_futures: true
unnecessary_getters_setters: true
unrelated_type_equality_checks: true
valid_regexps: true

View File

@ -32,7 +32,7 @@ apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
android {
compileSdkVersion 29
compileSdkVersion 31
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
@ -51,11 +51,25 @@ android {
externalNativeBuild {
cmake {
cppFlags "-std=c++11"
arguments '-DANDROID_STL=c++_shared', '-DBUILD_TESTING=OFF'
version "3.10.2"
cppFlags "-std=c++17"
arguments '-DANDROID_STL=c++_shared'
version "3.18.0+"
}
}
ndk {
abiFilters.clear()
// abiFilters 'x86_64', 'armeabi-v7a', 'arm64-v8a'
}
}
splits {
abi {
enable true //enables the ABIs split mechanism
reset() //reset the list of ABIs to be included to an empty string
include 'arm64-v8a', 'armeabi-v7a', 'x86_64'
universalApk true
}
}
signingConfigs {
@ -73,9 +87,6 @@ android {
signingConfig signingConfigs.release
minifyEnabled true
useProguard true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}

View File

@ -1,12 +1,12 @@
buildscript {
ext.kotlin_version = '1.4.10'
ext.kotlin_version = '1.6.20'
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.5.0'
classpath 'com.android.tools.build:gradle:7.1.3'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}

View File

@ -1,4 +1,5 @@
org.gradle.jvmargs=-Xmx1536M
android.enableR8=true
android.useAndroidX=true
android.enableJetifier=true
android.native.buildOutput=verbose
android.bundle.enableUncompressedNativeLibs = false

View File

@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-all.zip

View File

@ -1,50 +1,50 @@
[
{
"question" : "Was ist der Unterschied zwischen verfügbarem Guthaben und vollständigem Guthaben?",
"answer" : "Nachdem Sie eine Transaktion getätigt oder Oxen erhalten haben, muss die Transaktion noch bestätigt werden. In ungefähr 20 Minuten sollte Ihr \"verfügbares Guthaben\" aktualisiert werden!\nWenn Sie Oxen senden, verringert sich manchmal Ihr verfügbares Guthaben um mehr als den Betrag, den Sie gesendet haben. Dies ist normal und zum Schutz Ihrer Privatsphäre erforderlich. Ihr \"vollständiges Gleichgewicht\" sollte in 20 Minuten wieder normal sein.\n"
"answer" : "Nachdem Sie eine Transaktion getätigt oder Oxen erhalten haben, muss die Transaktion noch bestätigt werden. In ungefähr 20 Minuten sollte Ihr \"verfügbares Guthaben\" aktualisiert werden!\n\nWenn Sie Oxen senden, verringert sich manchmal Ihr verfügbares Guthaben um mehr als den Betrag, den Sie gesendet haben. Dies ist normal und zum Schutz Ihrer Privatsphäre erforderlich. Ihr \"vollständiges Gleichgewicht\" sollte in 20 Minuten wieder normal sein."
},
{
"question" : "Was bedeuten \"Seed\" und \"Schlüssel\"?",
"answer" : "Ihre Schlüssel verschlüsseln die privaten Informationen in Ihres Wallets und ermöglichen es Ihnen, Coins auszugeben und eingehende Transaktionen anzuzeigen.\nIhr Seed ist nur eine Version Ihres privaten Schlüssels, die so geschrieben wurde, dass Sie sie leichter notieren können. Ihr Seed und Schlüssel sind tatsächlich dasselbe, nur in verschiedenen Formen!\nGeben Sie niemals Ihren Seed oder Schlüssel an jemanden weiter. Ihr Geld wird gestohlen, wenn Sie Ihren Seed oder Schlüssel herausgeben. Bitte notieren Sie sich jedoch Ihren Seed und bewahren Sie ihn an einem sicheren Ort auf (so können Sie Ihr Wallet wiederherstellen, wenn Sie Ihr Telefon verlieren.)\n"
"answer" : "Ihre Schlüssel verschlüsseln die privaten Informationen in Ihres Wallets und ermöglichen es Ihnen, Coins auszugeben und eingehende Transaktionen anzuzeigen.\n\nIhr Seed ist nur eine Version Ihres privaten Schlüssels, die so geschrieben wurde, dass Sie sie leichter notieren können. Ihr Seed und Schlüssel sind tatsächlich dasselbe, nur in verschiedenen Formen!\n\nGeben Sie niemals Ihren Seed oder Schlüssel an jemanden weiter. Ihr Geld wird gestohlen, wenn Sie Ihren Seed oder Schlüssel herausgeben. Bitte notieren Sie sich jedoch Ihren Seed und bewahren Sie ihn an einem sicheren Ort auf (so können Sie Ihr Wallet wiederherstellen, wenn Sie Ihr Telefon verlieren.)"
},
{
"question" : "Wie viele Wallets kann ich erstellen?",
"answer" : "Es gibt keine Grenzen! Sie können so viele Wallets erstellen, wie Sie möchten.\n"
"answer" : "Es gibt keine Grenzen! Sie können so viele Wallets erstellen, wie Sie möchten."
},
{
"question" : "Wie kann ich mein Wallet wiederherstellen?",
"answer" : "Tippen Sie auf das Profil Icon auf ihrem Dashboard (oben rechts), wählen Sie „Wallets“ und dann „Wallet wiederherstellen“. Geben Sie dann Ihren Seed (oder Ihre Schlüssel) und optional ein Datum vor der ersten Transaktion in Ihrer Brieftasche ein (dies beschleunigt den Synchronisierungsvorgang) .) Möglicherweise müssen Sie die App 15 bis 30 Minuten geöffnet lassen, um Ihr Wallet vollständig wiederherzustellen.\n"
"answer" : "Tippen Sie auf das Profil Icon auf ihrem Dashboard (oben rechts), wählen Sie „Wallets“ und dann „Wallet wiederherstellen“. Geben Sie dann Ihren Seed (oder Ihre Schlüssel) und optional ein Datum vor der ersten Transaktion in Ihrer Brieftasche ein (dies beschleunigt den Synchronisierungsvorgang) .) Möglicherweise müssen Sie die App 15 bis 30 Minuten geöffnet lassen, um Ihr Wallet vollständig wiederherzustellen."
},
{
"question" : "Was kann ich tun, wenn ich meinen Seed verliere?",
"answer" : "Wenn Sie Ihren Seed vergessen haben, haben Sie ihn wahrscheinlich irgendwo aufgeschrieben. Bitte überprüfen Sie Ihre Notizen und schauen Sie sich auf Ihrem Computer um. Wenn Sie es nirgendwo finden, haben Sie möglicherweise Oxen Wallet gesichert (in diesem Fall können Sie es aus diesem Backup wiederherstellen.) Wenn keines von beidem der Fall ist, können wir leider nichts tun.\n"
"answer" : "Wenn Sie Ihren Seed vergessen haben, haben Sie ihn wahrscheinlich irgendwo aufgeschrieben. Bitte überprüfen Sie Ihre Notizen und schauen Sie sich auf Ihrem Computer um. Wenn Sie es nirgendwo finden, haben Sie möglicherweise Oxen Wallet gesichert (in diesem Fall können Sie es aus diesem Backup wiederherstellen.) Wenn keines von beidem der Fall ist, können wir leider nichts tun."
},
{
"question" : "Sammeln Sie Informationen zu mir oder meinem Wallet?",
"answer" : "Oxen Wallet sammelt oder zeichnet keine Informationen über Sie oder Ihr Wallet auf. Ihre Privatsphäre ist uns wichtig.\nIhre Privatsphäre kann aber duch die Verbindung zu einem bösarigem Knoten kompromitiert werden. Deshalb empfehlen wir, die Standart Knoten oder ihren eigenen zu verwenden. "
"answer" : "Oxen Wallet sammelt oder zeichnet keine Informationen über Sie oder Ihr Wallet auf. Ihre Privatsphäre ist uns wichtig.\n\nIhre Privatsphäre kann aber duch die Verbindung zu einem bösarigem Knoten kompromitiert werden. Deshalb empfehlen wir, die Standart Knoten oder ihren eigenen zu verwenden. "
},
{
"question" : "Woher die Fiat-Daten?",
"answer" : "Die Fiat-Daten werden durch ein Gateway von CoinGecko geladen.\nDer code des Gateways ist open-source und sammelt oder zeichnet keine Informationen auf, durch das Anfragen der Daten durch das Gateway enthüllen sie Ihre IP und Fiat-Währung.\nDie Fiat Umrechnung ist standartmäßig deaktiviert."
"answer" : "Die Fiat-Daten werden durch ein Gateway von CoinGecko geladen.\n\nDer code des Gateways ist open-source und sammelt oder zeichnet keine Informationen auf, durch das Anfragen der Daten durch das Gateway enthüllen sie Ihre IP und Fiat-Währung.\n\nDie Fiat Umrechnung ist standartmäßig deaktiviert."
},
{
"question" : "Kann ich eine Transaktion stornieren?",
"answer" : "Sobald eine Transaktion an die Blockchain gesendet wurde, kann sie leider nicht mehr rückgängig gemacht werden. Sie können die Transaktion jederzeit abbrechen, bevor sie gesendet wird. Überprüfen Sie die Adresse daher immer, bevor Sie eine Transaktion senden.\n"
"answer" : "Sobald eine Transaktion an die Blockchain gesendet wurde, kann sie leider nicht mehr rückgängig gemacht werden. Sie können die Transaktion jederzeit abbrechen, bevor sie gesendet wird. Überprüfen Sie die Adresse daher immer, bevor Sie eine Transaktion senden."
},
{
"question" : "Was sind Subadressen und wie verwende ich sie?",
"answer" : "Eine Unteradresse ist im Grunde eine eindeutige Adresse, die Sie jederzeit generieren können. An sie gesendete Coins landen weiterhin in Ihrem Wallet, aber die Person, die die Coins sendet, kann Ihre Hauptadresse nicht ermitteln.\nSie können eine neue Unteradresse im Empfangsbildschirm erstellen, indem Sie auf das „+“ neben der Schaltfläche Unteradressen tippen. Geben Sie einen Namen für die Unteradresse ein und tippen Sie auf \"Hinzufügen\". Dann tippen Sie einfach auf den Namen der Subadresse, wenn Sie ihn verwenden möchten!\nWenn Sie paranoid sind, sollten Sie wahrscheinlich jedes Mal, wenn Sie Oxen erhalten, eine neue Unteradresse erstellen.\n"
"answer" : "Eine Unteradresse ist im Grunde eine eindeutige Adresse, die Sie jederzeit generieren können. An sie gesendete Coins landen weiterhin in Ihrem Wallet, aber die Person, die die Coins sendet, kann Ihre Hauptadresse nicht ermitteln.\n\nSie können eine neue Unteradresse im Empfangsbildschirm erstellen, indem Sie auf das „+“ neben der Schaltfläche Unteradressen tippen. Geben Sie einen Namen für die Unteradresse ein und tippen Sie auf \"Hinzufügen\". Dann tippen Sie einfach auf den Namen der Subadresse, wenn Sie ihn verwenden möchten!\n\nWenn Sie paranoid sind, sollten Sie wahrscheinlich jedes Mal, wenn Sie Oxen erhalten, eine neue Unteradresse erstellen."
},
{
"question" : "Ich habe meine OXEN nicht erhalten! Was kann ich tun?",
"answer" : "Wenn Sie Ihr Oxen nicht erhalten haben, möchten Sie möglicherweise auf das Synchonisations Icon auf auf ihrem Dashboard (oben links) tippen und auf Reconnect (Neu verbinden) klicken. Wenn dies nicht funktioniert, gehen Sie in das Einstellungsmenü, tippen Sie auf das Feld \"Aktueller Knoten\" und wählen Sie einen Knoten mit einem grünen Punkt daneben aus.\n"
"answer" : "Wenn Sie Ihr Oxen nicht erhalten haben, möchten Sie möglicherweise auf das Synchonisations Icon auf auf ihrem Dashboard (oben links) tippen und auf Reconnect (Neu verbinden) klicken. Wenn dies nicht funktioniert, gehen Sie in das Einstellungsmenü, tippen Sie auf das Feld \"Aktueller Knoten\" und wählen Sie einen Knoten mit einem grünen Punkt daneben aus."
},
{
"question" : "Wie kontaktiere ich den Oxen Wallet-Support?",
"answer" : "Senden Sie eine E-Mail an team@oxen.io, schließen Sie sich dem Telegram unter @LokiCommunity an oder twittern Sie @Oxen_io!\n"
"answer" : "Senden Sie eine E-Mail an team@oxen.io, schließen Sie sich dem Telegram unter @LokiCommunity an oder twittern Sie @Oxen_io!"
},
{
"question" : "Macht mich der Besitz von Oxen zu einem Investor?",
"answer" : "Nein, macht es nicht. Es macht sie zu einer coolen Person mit Oxen.\n"
"answer" : "Nein, macht es nicht. Es macht sie zu einer coolen Person mit Oxen."
}
]
]

View File

@ -1,50 +1,50 @@
[
{
"question" : "Whats the difference between Available Balance and Full Balance?",
"answer" : "After you make a transaction or receive some Oxen, the transaction still needs to be confirmed. In about 20 minutes your available balance should update!\nSometimes, when you send Oxen, your available balance will decrease by more than the amount youve sent. This is normal, and its necessary in order to protect your privacy. Your full balance should be back to normal in 20 minutes.\n"
"answer" : "After you make a transaction or receive some Oxen, the transaction still needs to be confirmed. In about 20 minutes your available balance should update!\n\nSometimes, when you send Oxen, your available balance will decrease by more than the amount youve sent. This is normal, and its necessary in order to protect your privacy. Your full balance should be back to normal in 20 minutes.\n\nYour Oxen is also locked by the contributed amount when you contribute to a Service Node for the duration of the stake."
},
{
"question" : "What do \"seed\" and \"keys\" mean?",
"answer" : "Your keys encode the private information in your wallet, and are what allow you to spend coins and see incoming transactions.\nYour seed is just a version of your private key written in a way thats easier for you to write down. Your seed and keys are actually the same thing, just in different forms!\nDO NOT ever give your seed or keys to anyone. Your funds will be stolen if you give out your seed or keys. Please write down your seed, however, and store it in a safe place (this will allow you to restore your wallet if you lose your phone.)\n"
"answer" : "Your keys encode the private information in your wallet, and are what allow you to spend coins and see incoming transactions.\n\nYour seed is just a version of your private key written in a way thats easier for you to write down. Your seed and keys are actually the same thing, just in different forms!\n\nDO NOT ever give your seed or keys to anyone. Your funds will be stolen if you give out your seed or keys. Please write down your seed, however, and store it in a safe place (this will allow you to restore your wallet if you lose your phone)."
},
{
"question" : "How many wallets can I create?",
"answer" : "There is no limit! You can create as many wallets as you want.\n"
"answer" : "There is no limit! You can create as many wallets as you want."
},
{
"question" : "How can I restore my wallet?",
"answer" : "Tap the profile icon on your dashboard (upper right), select Wallets, and then choose Restore Wallet. Then enter your seed (or your keys), and optionally enter a date before the first transaction in your wallet (this will speed up the syncing process.) You may need to keep the app open for 15-30 minutes in order to completely restore your wallet.\n"
"answer" : "Tap the profile icon on your dashboard (upper right), select Wallets, and then choose Restore Wallet. Then enter your seed (or your keys), and optionally enter a date before the first transaction in your wallet (this will speed up the syncing process.) You may need to keep the app open for 15-30 minutes in order to completely restore your wallet."
},
{
"question" : "What can I do if I lose my seed?",
"answer" : "If you forgot your seed, you likely wrote it down somewhere. Please check your notes and look around on your computer. If you cant find it anywhere, you may have backed up Oxen Wallet (in which case you would be able to restore from that backup.) If none of these work, there is unfortunately nothing that we can do.\n"
"answer" : "If you forgot your seed, you likely wrote it down somewhere. Please check your notes and look around on your computer. If you cant find it anywhere, you may have backed up Oxen Wallet (in which case you would be able to restore from that backup.) If none of these work, there is unfortunately nothing that we can do."
},
{
"question" : "Do you collect any information about me or my wallet?",
"answer" : "Oxen Wallet DOES NOT collect or record any information about you or your wallet. We care about your privacy.\nYour privacy can be compromised by connecting to a malicious node, so we recommend to use either the default nodes or your own.\n"
"answer" : "Oxen Wallet DOES NOT collect or record any information about you or your wallet. We care about your privacy.\n\nYour privacy can be compromised by connecting to a malicious node, so we recommend to use either the default nodes or your own."
},
{
"question" : "Where do you get the fiat data from?",
"answer" : "The fiat data is pulled trough a gateway from CoinGecko.\nThe code of the gateway is open-source and does not collect or record any data, but by requesting data from the gateway you are exposing your IP and Fiat.\nThe Fiat conversation is disabled by default.\n"
"answer" : "The fiat data is pulled trough a gateway from CoinGecko.\n\nThe code of the gateway is open-source and does not collect or record any data, but by requesting data from the gateway you are exposing your IP and fiat currency selection.\n\nThe fiat conversation is disabled by default."
},
{
"question" : "Is it possible to reverse a transaction?",
"answer" : "Unfortunately, as soon as a transaction has been submitted to the blockchain, there is no way to undo it. You can always cancel the transaction before its sent though, so always double-check the address before you send a transaction.\n"
"answer" : "Unfortunately, as soon as a transaction has been submitted to the blockchain, there is no way to undo it. You can always cancel the transaction before its sent though, so always double-check the address before you send a transaction."
},
{
"question" : "What are subaddresses, and how do I use them?",
"answer" : "A subaddress is basically a unique address that you can generate at any time. Coins sent to it will still arrive in your main wallet, but the person sending the coins cant tell what your main address is.\nYou can make a new subaddress in the Receive screen by tapping the + next to the Subaddresses button. Enter a name for the subaddress and tap Add. Then just tap on the subaddress name when you want to use it!\nIf youre paranoid, you should probably create a new subaddress every time you receive Oxen.\n"
"answer" : "A subaddress is basically a unique address that you can generate at any time. Coins sent to it will still arrive in your main wallet, but the person sending the coins cant tell what your main address is.\n\nYou can make a new subaddress in the Receive screen by tapping the + next to the Subaddresses button. Enter a name for the subaddress and tap Add. Then just tap on the subaddress name when you want to use it!\n\nIf youre paranoid, you should probably create a new subaddress every time you receive Oxen."
},
{
"question" : "I didn't receive my OXEN! What can I do?",
"answer" : "If you didn't receive your Oxen, you might want to tap the Synchronize Icon on your dashboard (upper left) and hit Reconnect. If that doesn't work, go into the settings menu, tap the 'Current Node' box, and select a node with a green dot next to it.\n"
"answer" : "If you didn't receive your Oxen, you might want to tap the Synchronize Icon on your dashboard (upper left) and hit Reconnect. If that doesn't work, go into the settings menu, tap the 'Current Node' box, and select a node with a green dot next to it."
},
{
"question" : "How do I contact Oxen Wallet support?",
"answer" : "Email team@oxen.io, join the Telegram at @LokiCommunity, or tweet @Oxen_io!\n"
"answer" : "Email team@oxen.io, join the Telegram at @LokiCommunity, or tweet @Oxen_io!"
},
{
"question" : "Does owning Oxen make me an Investor?",
"answer" : "No, it does not. It makes you a cool person, but with Oxen.\n"
"answer" : "No, it does not. It makes you a cool person, but with Oxen."
}
]
]

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

BIN
assets/images/Session.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -1,12 +1,8 @@
-
uri: public.loki.foundation:22023
is_default: true
-
uri: nodes.hashvault.pro:22023
is_default: false
-
uri: node.loki-pool.com:18081
is_default: false
-
uri: freyr.imaginary.stream:22023
is_default: false
-
uri: nodes.hashvault.pro:22023
-
uri: node.loki-pool.com:18081

View File

@ -1,3 +1,2 @@
-
uri: public.loki.foundation:38157
is_default: true

View File

@ -604,4 +604,4 @@
/* End XCConfigurationList section */
};
rootObject = 97C146E61CF9000F007C117D /* Project object */;
}
}

4
l10n.yaml Normal file
View File

@ -0,0 +1,4 @@
arb-dir: lib/l10n
template-arb-file: app_en.arb
output-localization-file: app_localizations.dart
#output-dir: lib/generated

View File

@ -1,71 +0,0 @@
// DO NOT EDIT. This is code generated via package:intl/generate_localized.dart
// This is a library that looks up messages for specific locales by
// delegating to the appropriate library.
// Ignore issues from commonly used lints in this file.
// ignore_for_file:implementation_imports, file_names, unnecessary_new
// ignore_for_file:unnecessary_brace_in_string_interps, directives_ordering
// ignore_for_file:argument_type_not_assignable, invalid_assignment
// ignore_for_file:prefer_single_quotes, prefer_generic_function_type_aliases
// ignore_for_file:comment_references
import 'dart:async';
import 'package:intl/intl.dart';
import 'package:intl/message_lookup_by_library.dart';
import 'package:intl/src/intl_helpers.dart';
import 'messages_de.dart' as messages_de;
import 'messages_en.dart' as messages_en;
import 'messages_fr.dart' as messages_fr;
typedef Future<dynamic> LibraryLoader();
Map<String, LibraryLoader> _deferredLibraries = {
'de': () => new Future.value(null),
'en': () => new Future.value(null),
'fr': () => new Future.value(null),
};
MessageLookupByLibrary _findExact(String localeName) {
switch (localeName) {
case 'de':
return messages_de.messages;
case 'en':
return messages_en.messages;
case 'fr':
return messages_fr.messages;
default:
return null;
}
}
/// User programs should call this before using [localeName] for messages.
Future<bool> initializeMessages(String localeName) async {
var availableLocale = Intl.verifiedLocale(
localeName,
(locale) => _deferredLibraries[locale] != null,
onFailure: (_) => null);
if (availableLocale == null) {
return new Future.value(false);
}
var lib = _deferredLibraries[availableLocale];
await (lib == null ? new Future.value(false) : lib());
initializeInternalMessageLookup(() => new CompositeMessageLookup());
messageLookup.addLocale(availableLocale, _findGeneratedMessagesFor);
return new Future.value(true);
}
bool _messagesExistFor(String locale) {
try {
return _findExact(locale) != null;
} catch (e) {
return false;
}
}
MessageLookupByLibrary _findGeneratedMessagesFor(String locale) {
var actualLocale = Intl.verifiedLocale(locale, _messagesExistFor,
onFailure: (_) => null);
if (actualLocale == null) return null;
return _findExact(actualLocale);
}

View File

@ -1,305 +0,0 @@
// DO NOT EDIT. This is code generated via package:intl/generate_localized.dart
// This is a library that provides messages for a de locale. All the
// messages from the main program should be duplicated here with the same
// function name.
// Ignore issues from commonly used lints in this file.
// ignore_for_file:unnecessary_brace_in_string_interps, unnecessary_new
// ignore_for_file:prefer_single_quotes,comment_references, directives_ordering
// ignore_for_file:annotate_overrides,prefer_generic_function_type_aliases
// ignore_for_file:unused_import, file_names
import 'package:intl/intl.dart';
import 'package:intl/message_lookup_by_library.dart';
final messages = new MessageLookup();
typedef String MessageIfAbsent(String messageStr, List<dynamic> args);
class MessageLookup extends MessageLookupByLibrary {
String get localeName => 'de';
static m0(status) => "${status} verbleibende Blöcke";
static m1(serviceNodeKey) => "Möchtest du wirkklich dein Stake von ${serviceNodeKey} entsperren?";
static m2(node) => "Möchten Sie den aktuellen Knoten wirklich auf ändern? ${node}?";
static m3(language) => "Ändern Sie die Sprache zu ${language}?";
static m4(amount, fee) => "Transaktion festschreiben\nMenge: ${amount}\nGebühr: ${fee}";
static m5(key) => "Kopiert ${key} in die Zwischenablage";
static m6(item, app_store) => "Geben sie NIEMALS ihren Oxen wallet ${item} in einer andere software oder website außer den OFFIZIELLEN Oxen wallets aus dem ${app_store}, der Oxen website, der dem Oxen GitHub.\nMöchtest du wirklich fortfahren?";
static m7(state_error) => "Authentifizierung fehlgeschlagen. ${state_error}";
static m8(item) => "Geben sie NIEMALS ihren Oxen wallet ${item} weiter!";
static m9(recipient_name) => "Sie senden Geld an\n${recipient_name}";
static m10(name) => "Keine Route definiert für ${name}";
static m11(transactionPriority) => "Derzeit ist die Priorität auf ${transactionPriority} festgelegt.\nDie Transaktionspriorität kann in den Einstellungen angepasst werden";
static m12(title) => "${title} in die Zwischenablage kopiert";
static m13(currentVersion) => "Ausführung ${currentVersion}";
static m14(wallet_name, error) => "Laden fehlgeschlagen ${wallet_name} Wallet. ${error}";
static m15(wallet_name, error) => "Fehler beim Entfernen ${wallet_name} Wallet. ${error}";
static m16(wallet_name) => "Wallet ${wallet_name} wird geladen";
static m17(wallet_name) => "Wallet ${wallet_name} entfernen";
final messages = _notInlinedMessages(_notInlinedMessages);
static _notInlinedMessages(_) => <String, Function> {
"Blocks_remaining" : m0,
"account" : MessageLookupByLibrary.simpleMessage("Konto"),
"accounts" : MessageLookupByLibrary.simpleMessage("Konten"),
"add" : MessageLookupByLibrary.simpleMessage("Hinzufügen"),
"add_new_word" : MessageLookupByLibrary.simpleMessage("Neues Wort hinzufügen"),
"address_book" : MessageLookupByLibrary.simpleMessage("Adressbuch"),
"address_book_menu" : MessageLookupByLibrary.simpleMessage("Adressbuch"),
"all" : MessageLookupByLibrary.simpleMessage("ALLE"),
"amount" : MessageLookupByLibrary.simpleMessage("Menge: "),
"amount_detail_detailed" : MessageLookupByLibrary.simpleMessage("4 - Detailliert"),
"amount_detail_none" : MessageLookupByLibrary.simpleMessage("0 - Keine"),
"amount_detail_normal" : MessageLookupByLibrary.simpleMessage("2 - Normal"),
"amount_detail_ultra" : MessageLookupByLibrary.simpleMessage("9 - Ultra"),
"auth_store_ban_timeout" : MessageLookupByLibrary.simpleMessage("Auszeit verbieten"),
"auth_store_banned_for" : MessageLookupByLibrary.simpleMessage("Gebannt für "),
"auth_store_banned_minutes" : MessageLookupByLibrary.simpleMessage(" Protokoll"),
"auth_store_incorrect_password" : MessageLookupByLibrary.simpleMessage("Falsches PIN"),
"authenticated" : MessageLookupByLibrary.simpleMessage("Authentifiziert"),
"authentication" : MessageLookupByLibrary.simpleMessage("Authentifizierung"),
"available_balance" : MessageLookupByLibrary.simpleMessage("Verfügbares Guthaben"),
"biometric_auth_reason" : MessageLookupByLibrary.simpleMessage("Scannen Sie Ihren Fingerabdruck zur Authentifizierung"),
"body_confirm_unlock_stake" : m1,
"cancel" : MessageLookupByLibrary.simpleMessage("Abbrechen"),
"change" : MessageLookupByLibrary.simpleMessage("Veränderung"),
"change_current_node" : m2,
"change_language" : MessageLookupByLibrary.simpleMessage("Sprache ändern"),
"change_language_to" : m3,
"changelog" : MessageLookupByLibrary.simpleMessage("Änderungsprotokoll"),
"clear" : MessageLookupByLibrary.simpleMessage("Löschen"),
"commit_transaction_amount_fee" : m4,
"confirm" : MessageLookupByLibrary.simpleMessage("Bestätigen"),
"confirm_sending" : MessageLookupByLibrary.simpleMessage("Bestätigen Sie das Senden"),
"contact" : MessageLookupByLibrary.simpleMessage("Kontakt"),
"contact_name" : MessageLookupByLibrary.simpleMessage("Name des Ansprechpartners"),
"continue_text" : MessageLookupByLibrary.simpleMessage("Fortsetzen"),
"copied_key_to_clipboard" : m5,
"copied_to_clipboard" : MessageLookupByLibrary.simpleMessage("In die Zwischenablage kopiert"),
"copy" : MessageLookupByLibrary.simpleMessage("Kopieren"),
"create_new" : MessageLookupByLibrary.simpleMessage("Neu erstellen"),
"dangerzone" : MessageLookupByLibrary.simpleMessage("Gefahrenzone"),
"dangerzone_warning" : m6,
"delete" : MessageLookupByLibrary.simpleMessage("Löschen"),
"digit_pin" : MessageLookupByLibrary.simpleMessage("-stelliger PIN"),
"edit" : MessageLookupByLibrary.simpleMessage("Bearbeiten"),
"enter_your_pin" : MessageLookupByLibrary.simpleMessage("PIN eingeben"),
"enter_your_pin_again" : MessageLookupByLibrary.simpleMessage("Geben Sie Ihre PIN erneut ein"),
"error" : MessageLookupByLibrary.simpleMessage("Error"),
"error_text_account_name" : MessageLookupByLibrary.simpleMessage("Der Kontoname darf nur Buchstaben und Zahlen enthalten\nund muss zwischen 1 und 15 Zeichen lang sein"),
"error_text_address" : MessageLookupByLibrary.simpleMessage("Die Walletadresse muss dem Typ der Kryptowährung\nentsprechen"),
"error_text_amount" : MessageLookupByLibrary.simpleMessage("Betrag kann nur Zahlen enthalten"),
"error_text_contact_name" : MessageLookupByLibrary.simpleMessage("Im Kontaktname könne die Symbole ` , \' \" nicht enthalten sein\nund muss zwischen 1 und 32 Zeichen lang sein"),
"error_text_crypto_currency" : MessageLookupByLibrary.simpleMessage("Die Anzahl der Nachkommastellen\nmuss kleiner oder gleich 12 sein."),
"error_text_fiat" : MessageLookupByLibrary.simpleMessage("Der Wert des Betrags darf den verfügbaren Kontostand nicht überschreiten.\nDie Anzahl der Nachkommastellen muss kleiner oder gleich 2 sein"),
"error_text_keys" : MessageLookupByLibrary.simpleMessage("Walletschlüssel können nur 64 hexadezimale Zeichen enthalten"),
"error_text_node_address" : MessageLookupByLibrary.simpleMessage("Bitte geben Sie eine iPv4-Adresse ein"),
"error_text_node_port" : MessageLookupByLibrary.simpleMessage("Der Knotenport kann nur Nummern zwischen 0 und 65535 enthalten"),
"error_text_oxen" : MessageLookupByLibrary.simpleMessage("Der OXEN-Wert kann das verfügbare Guthaben nicht überschreiten.\nDie Anzahl der Nachkommastellen muss kleiner oder gleich 12 sein"),
"error_text_payment_id" : MessageLookupByLibrary.simpleMessage("Die Zahlungs-ID kann nur 16 bis 64 hexadezimale Zeichen enthalten"),
"error_text_service_node" : MessageLookupByLibrary.simpleMessage("Service Node Schlüssel können nur 64 hexadezimale Zeichen enthalten"),
"error_text_subaddress_name" : MessageLookupByLibrary.simpleMessage("Im Namen der Unteradresse könne die Symbole ` , \' \" nicht enthalten sein\nund muss zwischen 1 und 20 Zeichen lang sein"),
"error_text_wallet_name" : MessageLookupByLibrary.simpleMessage("Der Walletname darf nur Buchstaben und Zahlen enthalten\nund muss zwischen 1 und 15 Zeichen lang sein"),
"failed_authentication" : m7,
"faq" : MessageLookupByLibrary.simpleMessage("FAQ"),
"fetching" : MessageLookupByLibrary.simpleMessage("aktualisieren"),
"filters" : MessageLookupByLibrary.simpleMessage("Filter"),
"first_wallet_text" : MessageLookupByLibrary.simpleMessage("Das tolle Wallet\nfür Oxen"),
"full_balance" : MessageLookupByLibrary.simpleMessage("Volles Guthaben"),
"hidden_balance" : MessageLookupByLibrary.simpleMessage("Verstecktes Guthaben"),
"id" : MessageLookupByLibrary.simpleMessage("ID: "),
"incoming" : MessageLookupByLibrary.simpleMessage("Eingehend"),
"incorrect_seed" : MessageLookupByLibrary.simpleMessage("Der eingegebene Text ist ungültig."),
"keys_title" : MessageLookupByLibrary.simpleMessage("Schlüssel"),
"loading_your_wallet" : MessageLookupByLibrary.simpleMessage("Wallet wird geladen"),
"login" : MessageLookupByLibrary.simpleMessage("Einloggen"),
"never_give_your" : m8,
"new_subaddress_create" : MessageLookupByLibrary.simpleMessage("Erstellen"),
"new_subaddress_label_name" : MessageLookupByLibrary.simpleMessage("Name"),
"new_subaddress_title" : MessageLookupByLibrary.simpleMessage("Neue Unteradresse"),
"new_wallet" : MessageLookupByLibrary.simpleMessage("Neues Wallet"),
"node_address" : MessageLookupByLibrary.simpleMessage("Knotenadresse"),
"node_new" : MessageLookupByLibrary.simpleMessage("Neuer Knoten"),
"node_port" : MessageLookupByLibrary.simpleMessage("Knotenport"),
"node_reset_settings_title" : MessageLookupByLibrary.simpleMessage("Einstellungen zurücksetzen"),
"nodes" : MessageLookupByLibrary.simpleMessage("Knoten"),
"nodes_list_reset_to_default_message" : MessageLookupByLibrary.simpleMessage("Möchten Sie die Einstellungen wirklich auf die Standardeinstellungen zurücksetzen?"),
"nothing_staked" : MessageLookupByLibrary.simpleMessage("Noch nichts gestaked"),
"ok" : MessageLookupByLibrary.simpleMessage("OK"),
"openalias_alert_content" : m9,
"openalias_alert_title" : MessageLookupByLibrary.simpleMessage("OXEN-Empfänger erkannt"),
"outgoing" : MessageLookupByLibrary.simpleMessage("Ausgehend"),
"oxen_available_balance" : MessageLookupByLibrary.simpleMessage("OXEN verfügbares Guthaben"),
"oxen_full_balance" : MessageLookupByLibrary.simpleMessage("OXEN volles Guthaben"),
"oxen_hidden" : MessageLookupByLibrary.simpleMessage("OXEN versteckt"),
"password" : MessageLookupByLibrary.simpleMessage("Passwort"),
"paste" : MessageLookupByLibrary.simpleMessage("Einfügen"),
"pending" : MessageLookupByLibrary.simpleMessage(" (steht aus)"),
"pin_is_incorrect" : MessageLookupByLibrary.simpleMessage("PIN ist falsch"),
"please_make_selection" : MessageLookupByLibrary.simpleMessage("Bitte treffen Sie unten eine Auswahl zu\nErstellen oder Wiederherstellen Ihres Wallets."),
"please_select" : MessageLookupByLibrary.simpleMessage("Bitte auswählen:"),
"please_try_to_connect_to_another_node" : MessageLookupByLibrary.simpleMessage("Bitte versuchen Sie, eine Verbindung zu einem anderen Knoten herzustellen"),
"receive" : MessageLookupByLibrary.simpleMessage("Erhalten"),
"receive_amount" : MessageLookupByLibrary.simpleMessage("Menge"),
"received" : MessageLookupByLibrary.simpleMessage("Empfangen"),
"reconnect" : MessageLookupByLibrary.simpleMessage("Erneut verbinden"),
"reconnect_alert_text" : MessageLookupByLibrary.simpleMessage("Sind Sie sicher, dass Sie die Verbindung wiederherstellen möchten?"),
"reconnection" : MessageLookupByLibrary.simpleMessage("Wiederverbindung"),
"reload_fiat" : MessageLookupByLibrary.simpleMessage("Fiat-Kurs neuladen"),
"remove" : MessageLookupByLibrary.simpleMessage("Löschen"),
"remove_node" : MessageLookupByLibrary.simpleMessage("Knoten entfernen"),
"remove_node_message" : MessageLookupByLibrary.simpleMessage("Möchten Sie den ausgewählten Knoten wirklich entfernen?"),
"rescan" : MessageLookupByLibrary.simpleMessage("Erneut scannen"),
"reset" : MessageLookupByLibrary.simpleMessage("Zurücksetzen"),
"restore_address" : MessageLookupByLibrary.simpleMessage("Adresse"),
"restore_description_from_backup" : MessageLookupByLibrary.simpleMessage("Sie können die gesamte Oxen Wallet-App aus ihrer Sicherungsdatei wiederherstellen."),
"restore_description_from_keys" : MessageLookupByLibrary.simpleMessage("Stellen Sie Ihr Wallet von generiert wieder her Tastenanschläge, die von Ihren privaten Schlüsseln gespeichert wurden"),
"restore_description_from_seed" : MessageLookupByLibrary.simpleMessage("Stellen Sie Ihr Wallet aus den 25 Wörtern wieder her oder 13-Wort-Kombinationscode"),
"restore_description_from_seed_keys" : MessageLookupByLibrary.simpleMessage("Stellen sie Ihr Wallet mit Seed / Schlüsseln, welche Sie an einem sicheren Ort aufbewahrt haben, wieder her"),
"restore_from_seed_placeholder" : MessageLookupByLibrary.simpleMessage("Bitte geben Sie hier Ihren Code ein"),
"restore_next" : MessageLookupByLibrary.simpleMessage("Weiter"),
"restore_recover" : MessageLookupByLibrary.simpleMessage("Wiederherstellen"),
"restore_restore_wallet" : MessageLookupByLibrary.simpleMessage("Wallet wiederherstellen"),
"restore_seed_keys_restore" : MessageLookupByLibrary.simpleMessage("Seed / Schlüssel wiederherstellen"),
"restore_spend_key_private" : MessageLookupByLibrary.simpleMessage("Ausgabe-Schlüssel (geheim)"),
"restore_title_from_backup" : MessageLookupByLibrary.simpleMessage("Aus einer Sicherungsdatei wiederherstellen"),
"restore_title_from_keys" : MessageLookupByLibrary.simpleMessage("Wiederherstellen von Schlüsseln"),
"restore_title_from_seed" : MessageLookupByLibrary.simpleMessage("Aus Seed wiederherstellen"),
"restore_title_from_seed_keys" : MessageLookupByLibrary.simpleMessage("Vom Seed / Schlüssel wiederherstellen"),
"restore_view_key_private" : MessageLookupByLibrary.simpleMessage("Anzeige-Schlüssel (geheim)"),
"restore_wallet" : MessageLookupByLibrary.simpleMessage("Wallet wiederherstellen"),
"restore_wallet_name" : MessageLookupByLibrary.simpleMessage("Walletname"),
"restore_wallet_restore_description" : MessageLookupByLibrary.simpleMessage("Beschreibung zur Wiederherstellung des Wallets"),
"router_no_route" : m10,
"save" : MessageLookupByLibrary.simpleMessage("Speichern"),
"seed_language_chinese" : MessageLookupByLibrary.simpleMessage("Chinesisch"),
"seed_language_choose" : MessageLookupByLibrary.simpleMessage("Bitte wählen Sie die Ausgangssprache"),
"seed_language_dutch" : MessageLookupByLibrary.simpleMessage("Niederländisch"),
"seed_language_english" : MessageLookupByLibrary.simpleMessage("Englisch"),
"seed_language_french" : MessageLookupByLibrary.simpleMessage("Französisch"),
"seed_language_german" : MessageLookupByLibrary.simpleMessage("Deutsch"),
"seed_language_italian" : MessageLookupByLibrary.simpleMessage("Italienisch"),
"seed_language_japanese" : MessageLookupByLibrary.simpleMessage("Japanisch"),
"seed_language_next" : MessageLookupByLibrary.simpleMessage("Weiter"),
"seed_language_portuguese" : MessageLookupByLibrary.simpleMessage("Portugiesisch"),
"seed_language_russian" : MessageLookupByLibrary.simpleMessage("Russisch"),
"seed_language_spanish" : MessageLookupByLibrary.simpleMessage("Spanisch"),
"seed_share" : MessageLookupByLibrary.simpleMessage("Teilen Sie Seed"),
"seed_title" : MessageLookupByLibrary.simpleMessage("Seed"),
"send" : MessageLookupByLibrary.simpleMessage("Senden"),
"send_creating_transaction" : MessageLookupByLibrary.simpleMessage("Transaktion erstellen"),
"send_error_currency" : MessageLookupByLibrary.simpleMessage("Die Währung kann nur Zahlen enthalten"),
"send_estimated_fee" : MessageLookupByLibrary.simpleMessage("Geschätzte Gebühr:"),
"send_oxen" : MessageLookupByLibrary.simpleMessage("OXEN Senden"),
"send_oxen_address" : MessageLookupByLibrary.simpleMessage("Oxen-Adresse"),
"send_priority" : m11,
"send_title" : MessageLookupByLibrary.simpleMessage("Senden Sie Oxen"),
"send_your_wallet" : MessageLookupByLibrary.simpleMessage("Dein Wallet"),
"sending" : MessageLookupByLibrary.simpleMessage("Senden"),
"sent" : MessageLookupByLibrary.simpleMessage("Geschickt"),
"service_node_key" : MessageLookupByLibrary.simpleMessage("Service Node Schlüssel"),
"settings_all" : MessageLookupByLibrary.simpleMessage("ALLE"),
"settings_allow_biometric_authentication" : MessageLookupByLibrary.simpleMessage("Biometrische Authentifizierung"),
"settings_balance_detail" : MessageLookupByLibrary.simpleMessage("Dezimalstellen"),
"settings_change_language" : MessageLookupByLibrary.simpleMessage("Sprache ändern"),
"settings_change_pin" : MessageLookupByLibrary.simpleMessage("PIN ändern"),
"settings_currency" : MessageLookupByLibrary.simpleMessage("Währung"),
"settings_current_node" : MessageLookupByLibrary.simpleMessage("Aktueller Knoten"),
"settings_dark_mode" : MessageLookupByLibrary.simpleMessage("Dunkler Modus"),
"settings_display_balance_as" : MessageLookupByLibrary.simpleMessage("Kontostand anzeigen als"),
"settings_display_on_dashboard_list" : MessageLookupByLibrary.simpleMessage("Anzeige in der Dashboard-Liste"),
"settings_enable_fiat_currency" : MessageLookupByLibrary.simpleMessage("In Fiat Währung umrechnen"),
"settings_fee_priority" : MessageLookupByLibrary.simpleMessage("Gebührenpriorität"),
"settings_nodes" : MessageLookupByLibrary.simpleMessage("Knoten"),
"settings_none" : MessageLookupByLibrary.simpleMessage("Keiner"),
"settings_personal" : MessageLookupByLibrary.simpleMessage("Persönlich"),
"settings_save_recipient_address" : MessageLookupByLibrary.simpleMessage("Empfängeradresse speichern"),
"settings_support" : MessageLookupByLibrary.simpleMessage("Unterstützung"),
"settings_terms_and_conditions" : MessageLookupByLibrary.simpleMessage("Geschäftsbedingungen"),
"settings_title" : MessageLookupByLibrary.simpleMessage("Einstellungen"),
"settings_transactions" : MessageLookupByLibrary.simpleMessage("Transaktionen"),
"settings_wallets" : MessageLookupByLibrary.simpleMessage("Wallets"),
"setup_pin" : MessageLookupByLibrary.simpleMessage("PIN einrichten"),
"setup_successful" : MessageLookupByLibrary.simpleMessage("Ihre PIN wurde erfolgreich eingerichtet!"),
"share_address" : MessageLookupByLibrary.simpleMessage("Adresse teilen "),
"show_keys" : MessageLookupByLibrary.simpleMessage("Schlüssel anzeigen"),
"show_seed" : MessageLookupByLibrary.simpleMessage("Seed zeigen"),
"spend_key_private" : MessageLookupByLibrary.simpleMessage("Ausgabe-Schlüssel (geheim)"),
"spend_key_public" : MessageLookupByLibrary.simpleMessage("Ausgabe-Schlüssel (öffentlich)"),
"stake_more" : MessageLookupByLibrary.simpleMessage("Mehr staken"),
"stake_oxen" : MessageLookupByLibrary.simpleMessage("Oxen staken"),
"start_staking" : MessageLookupByLibrary.simpleMessage("Starte zu staken"),
"status" : MessageLookupByLibrary.simpleMessage("Status: "),
"subaddress_title" : MessageLookupByLibrary.simpleMessage("Unteradressenliste"),
"subaddresses" : MessageLookupByLibrary.simpleMessage("Unteradressen"),
"sync_status_connected" : MessageLookupByLibrary.simpleMessage("IN VERBINDUNG GEBRACHT"),
"sync_status_connecting" : MessageLookupByLibrary.simpleMessage("ANSCHLUSS"),
"sync_status_failed_connect" : MessageLookupByLibrary.simpleMessage("Verbindung zum Knoten fehlgeschlagen"),
"sync_status_not_connected" : MessageLookupByLibrary.simpleMessage("NICHT VERBUNDEN"),
"sync_status_starting_sync" : MessageLookupByLibrary.simpleMessage("STARTEN DER SYNCHRONISIERUNG"),
"sync_status_synchronized" : MessageLookupByLibrary.simpleMessage("SYNCHRONISIERT"),
"sync_status_synchronizing" : MessageLookupByLibrary.simpleMessage("SYNCHRONISIERUNG"),
"title_confirm_unlock_stake" : MessageLookupByLibrary.simpleMessage("Stake entsperren"),
"title_new_stake" : MessageLookupByLibrary.simpleMessage("Neuer Stake"),
"title_stakes" : MessageLookupByLibrary.simpleMessage("Stakes"),
"today" : MessageLookupByLibrary.simpleMessage("Heute"),
"transaction_details_amount" : MessageLookupByLibrary.simpleMessage("Betrag"),
"transaction_details_copied" : m12,
"transaction_details_date" : MessageLookupByLibrary.simpleMessage("Datum"),
"transaction_details_height" : MessageLookupByLibrary.simpleMessage("Höhe"),
"transaction_details_recipient_address" : MessageLookupByLibrary.simpleMessage("Empfängeradresse"),
"transaction_details_title" : MessageLookupByLibrary.simpleMessage("Transaktionsdetails"),
"transaction_details_transaction_id" : MessageLookupByLibrary.simpleMessage("Transaktions-ID"),
"transaction_priority_blink" : MessageLookupByLibrary.simpleMessage("Blink"),
"transaction_priority_slow" : MessageLookupByLibrary.simpleMessage("Langsam"),
"transaction_sent" : MessageLookupByLibrary.simpleMessage("Transaktion gesendet!"),
"transactions" : MessageLookupByLibrary.simpleMessage("Transaktionen"),
"transactions_by_date" : MessageLookupByLibrary.simpleMessage("Transaktionen nach Datum"),
"unable_unlock_stake" : MessageLookupByLibrary.simpleMessage("Stake Entsperrung nicht möglich"),
"unlock_stake_requested" : MessageLookupByLibrary.simpleMessage("Stake Entsperrung angefragt"),
"use" : MessageLookupByLibrary.simpleMessage("Wechseln zu "),
"version" : m13,
"view_key_private" : MessageLookupByLibrary.simpleMessage("Anzeige-Schlüssel (geheim)"),
"view_key_public" : MessageLookupByLibrary.simpleMessage("Anzeige-Schlüssel (öffentlich)"),
"wallet_keys" : MessageLookupByLibrary.simpleMessage("Wallet Schlüssel"),
"wallet_list_create_new_wallet" : MessageLookupByLibrary.simpleMessage("Neues Wallet erstellen"),
"wallet_list_failed_to_load" : m14,
"wallet_list_failed_to_remove" : m15,
"wallet_list_load_wallet" : MessageLookupByLibrary.simpleMessage("Wallet laden"),
"wallet_list_loading_wallet" : m16,
"wallet_list_removing_wallet" : m17,
"wallet_list_restore_wallet" : MessageLookupByLibrary.simpleMessage("Wallet wiederherstellen"),
"wallet_list_title" : MessageLookupByLibrary.simpleMessage("Oxen Wallet"),
"wallet_menu" : MessageLookupByLibrary.simpleMessage("Wallet-Menü"),
"wallet_name" : MessageLookupByLibrary.simpleMessage("Walletname"),
"wallet_restoration_store_incorrect_seed_length" : MessageLookupByLibrary.simpleMessage("Falsche Seed-länge"),
"wallets" : MessageLookupByLibrary.simpleMessage("Wallets"),
"welcome" : MessageLookupByLibrary.simpleMessage("Willkommen\nim OXEN WALLET"),
"widgets_address" : MessageLookupByLibrary.simpleMessage("Adresse"),
"widgets_or" : MessageLookupByLibrary.simpleMessage("oder"),
"widgets_restore_from_blockheight" : MessageLookupByLibrary.simpleMessage("Aus Blockhöhe wiederherstellen"),
"widgets_restore_from_date" : MessageLookupByLibrary.simpleMessage("Vom Datum wiederherstellen"),
"widgets_seed" : MessageLookupByLibrary.simpleMessage("Seed"),
"yes_im_sure" : MessageLookupByLibrary.simpleMessage("Ja, Ich bin mir sicher!"),
"yesterday" : MessageLookupByLibrary.simpleMessage("Gestern"),
"your_contributions" : MessageLookupByLibrary.simpleMessage("Deine Anteile")
};
}

View File

@ -1,305 +0,0 @@
// DO NOT EDIT. This is code generated via package:intl/generate_localized.dart
// This is a library that provides messages for a en locale. All the
// messages from the main program should be duplicated here with the same
// function name.
// Ignore issues from commonly used lints in this file.
// ignore_for_file:unnecessary_brace_in_string_interps, unnecessary_new
// ignore_for_file:prefer_single_quotes,comment_references, directives_ordering
// ignore_for_file:annotate_overrides,prefer_generic_function_type_aliases
// ignore_for_file:unused_import, file_names
import 'package:intl/intl.dart';
import 'package:intl/message_lookup_by_library.dart';
final messages = new MessageLookup();
typedef String MessageIfAbsent(String messageStr, List<dynamic> args);
class MessageLookup extends MessageLookupByLibrary {
String get localeName => 'en';
static m0(status) => "${status} Blocks Remaining";
static m1(serviceNodeKey) => "Do you really want to unlock your stake from ${serviceNodeKey}?";
static m2(node) => "Are you sure to change current node to ${node}?";
static m3(language) => "Change language to ${language}?";
static m4(amount, fee) => "Commit transaction\nAmount: ${amount}\nFee: ${fee}";
static m5(key) => "Copied ${key} to Clipboard";
static m6(item, app_store) => "NEVER input your Oxen wallet ${item} into any software or website other than the OFFICIAL Oxen wallets downloaded directly from the ${app_store}, the Oxen website, or the Oxen GitHub.\nAre you sure you want to access your wallet ${item}?";
static m7(state_error) => "Failed authentication. ${state_error}";
static m8(item) => "NEVER give your Oxen wallet ${item} to ANYONE!";
static m9(recipient_name) => "You will be sending funds to\n${recipient_name}";
static m10(name) => "No route defined for ${name}";
static m11(transactionPriority) => "Currently the fee is set at ${transactionPriority} priority.\nTransaction priority can be adjusted in the settings";
static m12(title) => "${title} copied to Clipboard";
static m13(currentVersion) => "Version ${currentVersion}";
static m14(wallet_name, error) => "Failed to load ${wallet_name} wallet. ${error}";
static m15(wallet_name, error) => "Failed to remove ${wallet_name} wallet. ${error}";
static m16(wallet_name) => "Loading ${wallet_name} wallet";
static m17(wallet_name) => "Removing ${wallet_name} wallet";
final messages = _notInlinedMessages(_notInlinedMessages);
static _notInlinedMessages(_) => <String, Function> {
"Blocks_remaining" : m0,
"account" : MessageLookupByLibrary.simpleMessage("Account"),
"accounts" : MessageLookupByLibrary.simpleMessage("Accounts"),
"add" : MessageLookupByLibrary.simpleMessage("Add"),
"add_new_word" : MessageLookupByLibrary.simpleMessage("Add new word"),
"address_book" : MessageLookupByLibrary.simpleMessage("Address Book"),
"address_book_menu" : MessageLookupByLibrary.simpleMessage("Address book"),
"all" : MessageLookupByLibrary.simpleMessage("ALL"),
"amount" : MessageLookupByLibrary.simpleMessage("Amount: "),
"amount_detail_detailed" : MessageLookupByLibrary.simpleMessage("4 - Detailed"),
"amount_detail_none" : MessageLookupByLibrary.simpleMessage("0 - None"),
"amount_detail_normal" : MessageLookupByLibrary.simpleMessage("2 - Normal"),
"amount_detail_ultra" : MessageLookupByLibrary.simpleMessage("9 - Ultra"),
"auth_store_ban_timeout" : MessageLookupByLibrary.simpleMessage("ban_timeout"),
"auth_store_banned_for" : MessageLookupByLibrary.simpleMessage("Banned for "),
"auth_store_banned_minutes" : MessageLookupByLibrary.simpleMessage(" minutes"),
"auth_store_incorrect_password" : MessageLookupByLibrary.simpleMessage("Wrong PIN"),
"authenticated" : MessageLookupByLibrary.simpleMessage("Authenticated"),
"authentication" : MessageLookupByLibrary.simpleMessage("Authentication"),
"available_balance" : MessageLookupByLibrary.simpleMessage("Available Balance"),
"biometric_auth_reason" : MessageLookupByLibrary.simpleMessage("Scan your fingerprint to authenticate"),
"body_confirm_unlock_stake" : m1,
"cancel" : MessageLookupByLibrary.simpleMessage("Cancel"),
"change" : MessageLookupByLibrary.simpleMessage("Change"),
"change_current_node" : m2,
"change_language" : MessageLookupByLibrary.simpleMessage("Change language"),
"change_language_to" : m3,
"changelog" : MessageLookupByLibrary.simpleMessage("Changelog"),
"clear" : MessageLookupByLibrary.simpleMessage("Clear"),
"commit_transaction_amount_fee" : m4,
"confirm" : MessageLookupByLibrary.simpleMessage("Confirm"),
"confirm_sending" : MessageLookupByLibrary.simpleMessage("Confirm sending"),
"contact" : MessageLookupByLibrary.simpleMessage("Contact"),
"contact_name" : MessageLookupByLibrary.simpleMessage("Contact Name"),
"continue_text" : MessageLookupByLibrary.simpleMessage("Continue"),
"copied_key_to_clipboard" : m5,
"copied_to_clipboard" : MessageLookupByLibrary.simpleMessage("Copied to Clipboard"),
"copy" : MessageLookupByLibrary.simpleMessage("Copy"),
"create_new" : MessageLookupByLibrary.simpleMessage("Create new"),
"dangerzone" : MessageLookupByLibrary.simpleMessage("Dangerzone"),
"dangerzone_warning" : m6,
"delete" : MessageLookupByLibrary.simpleMessage("Delete"),
"digit_pin" : MessageLookupByLibrary.simpleMessage("-digit PIN"),
"edit" : MessageLookupByLibrary.simpleMessage("Edit"),
"enter_your_pin" : MessageLookupByLibrary.simpleMessage("Enter your PIN"),
"enter_your_pin_again" : MessageLookupByLibrary.simpleMessage("Enter your pin again"),
"error" : MessageLookupByLibrary.simpleMessage("Error"),
"error_text_account_name" : MessageLookupByLibrary.simpleMessage("Account name can only contain letters, numbers\nand must be between 1 and 15 characters long"),
"error_text_address" : MessageLookupByLibrary.simpleMessage("Wallet address must correspond to the type\nof cryptocurrency"),
"error_text_amount" : MessageLookupByLibrary.simpleMessage("Amount can only contain numbers"),
"error_text_contact_name" : MessageLookupByLibrary.simpleMessage("Contact name can\'t contain ` , \' \" symbols\nand must be between 1 and 32 characters long"),
"error_text_crypto_currency" : MessageLookupByLibrary.simpleMessage("The number of fraction digits\nmust be less or equal to 12"),
"error_text_fiat" : MessageLookupByLibrary.simpleMessage("Value of amount can\'t exceed available balance.\nThe number of fraction digits must be less or equal to 2"),
"error_text_keys" : MessageLookupByLibrary.simpleMessage("Wallet keys can only contain 64 chars in hex"),
"error_text_node_address" : MessageLookupByLibrary.simpleMessage("Please enter a iPv4 address"),
"error_text_node_port" : MessageLookupByLibrary.simpleMessage("Node port can only contain numbers between 0 and 65535"),
"error_text_oxen" : MessageLookupByLibrary.simpleMessage("OXEN value can\'t exceed available balance.\nThe number of fraction digits must be less or equal to 12"),
"error_text_payment_id" : MessageLookupByLibrary.simpleMessage("Payment ID can only contain from 16 to 64 chars in hex"),
"error_text_service_node" : MessageLookupByLibrary.simpleMessage("A Service Node key can only contain 64 chars in hex"),
"error_text_subaddress_name" : MessageLookupByLibrary.simpleMessage("Subaddress name can\'t contain ` , \' \" symbols\nand must be between 1 and 20 characters long"),
"error_text_wallet_name" : MessageLookupByLibrary.simpleMessage("Wallet name can only contain letters, numbers\nand must be between 1 and 15 characters long"),
"failed_authentication" : m7,
"faq" : MessageLookupByLibrary.simpleMessage("FAQ"),
"fetching" : MessageLookupByLibrary.simpleMessage("Fetching"),
"filters" : MessageLookupByLibrary.simpleMessage("Filters"),
"first_wallet_text" : MessageLookupByLibrary.simpleMessage("Awesome wallet\nfor Oxen"),
"full_balance" : MessageLookupByLibrary.simpleMessage("Full Balance"),
"hidden_balance" : MessageLookupByLibrary.simpleMessage("Hidden Balance"),
"id" : MessageLookupByLibrary.simpleMessage("ID: "),
"incoming" : MessageLookupByLibrary.simpleMessage("Incoming"),
"incorrect_seed" : MessageLookupByLibrary.simpleMessage("The text entered is not valid."),
"keys_title" : MessageLookupByLibrary.simpleMessage("Keys"),
"loading_your_wallet" : MessageLookupByLibrary.simpleMessage("Loading your wallet"),
"login" : MessageLookupByLibrary.simpleMessage("Login"),
"never_give_your" : m8,
"new_subaddress_create" : MessageLookupByLibrary.simpleMessage("Create"),
"new_subaddress_label_name" : MessageLookupByLibrary.simpleMessage("Label name"),
"new_subaddress_title" : MessageLookupByLibrary.simpleMessage("New subaddress"),
"new_wallet" : MessageLookupByLibrary.simpleMessage("New Wallet"),
"node_address" : MessageLookupByLibrary.simpleMessage("Node Address"),
"node_new" : MessageLookupByLibrary.simpleMessage("New Node"),
"node_port" : MessageLookupByLibrary.simpleMessage("Node port"),
"node_reset_settings_title" : MessageLookupByLibrary.simpleMessage("Reset settings"),
"nodes" : MessageLookupByLibrary.simpleMessage("Nodes"),
"nodes_list_reset_to_default_message" : MessageLookupByLibrary.simpleMessage("Are you sure that you want to reset settings to default?"),
"nothing_staked" : MessageLookupByLibrary.simpleMessage("Nothing staked yet"),
"ok" : MessageLookupByLibrary.simpleMessage("OK"),
"openalias_alert_content" : m9,
"openalias_alert_title" : MessageLookupByLibrary.simpleMessage("OXEN Recipient Detected"),
"outgoing" : MessageLookupByLibrary.simpleMessage("Outgoing"),
"oxen_available_balance" : MessageLookupByLibrary.simpleMessage("OXEN Available Balance"),
"oxen_full_balance" : MessageLookupByLibrary.simpleMessage("OXEN Full Balance"),
"oxen_hidden" : MessageLookupByLibrary.simpleMessage("OXEN Hidden"),
"password" : MessageLookupByLibrary.simpleMessage("Password"),
"paste" : MessageLookupByLibrary.simpleMessage("Paste"),
"pending" : MessageLookupByLibrary.simpleMessage(" (pending)"),
"pin_is_incorrect" : MessageLookupByLibrary.simpleMessage("PIN is incorrect"),
"please_make_selection" : MessageLookupByLibrary.simpleMessage("Please make selection below to\ncreate or recover your wallet."),
"please_select" : MessageLookupByLibrary.simpleMessage("Please select:"),
"please_try_to_connect_to_another_node" : MessageLookupByLibrary.simpleMessage("Please try to connect to another node"),
"receive" : MessageLookupByLibrary.simpleMessage("Receive"),
"receive_amount" : MessageLookupByLibrary.simpleMessage("Amount"),
"received" : MessageLookupByLibrary.simpleMessage("Received"),
"reconnect" : MessageLookupByLibrary.simpleMessage("Reconnect"),
"reconnect_alert_text" : MessageLookupByLibrary.simpleMessage("Are you sure to reconnect?"),
"reconnection" : MessageLookupByLibrary.simpleMessage("Reconnection"),
"reload_fiat" : MessageLookupByLibrary.simpleMessage("Reload Fiat data"),
"remove" : MessageLookupByLibrary.simpleMessage("Remove"),
"remove_node" : MessageLookupByLibrary.simpleMessage("Remove node"),
"remove_node_message" : MessageLookupByLibrary.simpleMessage("Are you sure that you want to remove selected node?"),
"rescan" : MessageLookupByLibrary.simpleMessage("Rescan"),
"reset" : MessageLookupByLibrary.simpleMessage("Reset"),
"restore_address" : MessageLookupByLibrary.simpleMessage("Address"),
"restore_description_from_backup" : MessageLookupByLibrary.simpleMessage("You can restore the whole Oxen Wallet app from your back-up file"),
"restore_description_from_keys" : MessageLookupByLibrary.simpleMessage("Restore your wallet from generated keystrokes saved from your private keys"),
"restore_description_from_seed" : MessageLookupByLibrary.simpleMessage("Restore your wallet from either the 25 word or 13 word combination code"),
"restore_description_from_seed_keys" : MessageLookupByLibrary.simpleMessage("Get back your wallet from seed/keys that you\'ve saved to secure place"),
"restore_from_seed_placeholder" : MessageLookupByLibrary.simpleMessage("Please enter or paste your seed here"),
"restore_next" : MessageLookupByLibrary.simpleMessage("Next"),
"restore_recover" : MessageLookupByLibrary.simpleMessage("Restore"),
"restore_restore_wallet" : MessageLookupByLibrary.simpleMessage("Restore Wallet"),
"restore_seed_keys_restore" : MessageLookupByLibrary.simpleMessage("Seed/Keys Restore"),
"restore_spend_key_private" : MessageLookupByLibrary.simpleMessage("Spend key (private)"),
"restore_title_from_backup" : MessageLookupByLibrary.simpleMessage("Restore from a back-up file"),
"restore_title_from_keys" : MessageLookupByLibrary.simpleMessage("Restore from keys"),
"restore_title_from_seed" : MessageLookupByLibrary.simpleMessage("Restore from seed"),
"restore_title_from_seed_keys" : MessageLookupByLibrary.simpleMessage("Restore from seed/keys"),
"restore_view_key_private" : MessageLookupByLibrary.simpleMessage("View key (private)"),
"restore_wallet" : MessageLookupByLibrary.simpleMessage("Restore wallet"),
"restore_wallet_name" : MessageLookupByLibrary.simpleMessage("Wallet name"),
"restore_wallet_restore_description" : MessageLookupByLibrary.simpleMessage("Wallet restore description"),
"router_no_route" : m10,
"save" : MessageLookupByLibrary.simpleMessage("Save"),
"seed_language_chinese" : MessageLookupByLibrary.simpleMessage("Chinese"),
"seed_language_choose" : MessageLookupByLibrary.simpleMessage("Please choose seed language"),
"seed_language_dutch" : MessageLookupByLibrary.simpleMessage("Dutch"),
"seed_language_english" : MessageLookupByLibrary.simpleMessage("English"),
"seed_language_french" : MessageLookupByLibrary.simpleMessage("French"),
"seed_language_german" : MessageLookupByLibrary.simpleMessage("German"),
"seed_language_italian" : MessageLookupByLibrary.simpleMessage("Italian"),
"seed_language_japanese" : MessageLookupByLibrary.simpleMessage("Japanese"),
"seed_language_next" : MessageLookupByLibrary.simpleMessage("Next"),
"seed_language_portuguese" : MessageLookupByLibrary.simpleMessage("Portuguese"),
"seed_language_russian" : MessageLookupByLibrary.simpleMessage("Russian"),
"seed_language_spanish" : MessageLookupByLibrary.simpleMessage("Spanish"),
"seed_share" : MessageLookupByLibrary.simpleMessage("Share seed"),
"seed_title" : MessageLookupByLibrary.simpleMessage("Seed"),
"send" : MessageLookupByLibrary.simpleMessage("Send"),
"send_creating_transaction" : MessageLookupByLibrary.simpleMessage("Creating transaction"),
"send_error_currency" : MessageLookupByLibrary.simpleMessage("Currency can only contain numbers"),
"send_estimated_fee" : MessageLookupByLibrary.simpleMessage("Estimated fee:"),
"send_oxen" : MessageLookupByLibrary.simpleMessage("Send OXEN"),
"send_oxen_address" : MessageLookupByLibrary.simpleMessage("Oxen address"),
"send_priority" : m11,
"send_title" : MessageLookupByLibrary.simpleMessage("Send Oxen"),
"send_your_wallet" : MessageLookupByLibrary.simpleMessage("Your wallet"),
"sending" : MessageLookupByLibrary.simpleMessage("Sending"),
"sent" : MessageLookupByLibrary.simpleMessage("Sent"),
"service_node_key" : MessageLookupByLibrary.simpleMessage("Service Node Key"),
"settings_all" : MessageLookupByLibrary.simpleMessage("ALL"),
"settings_allow_biometric_authentication" : MessageLookupByLibrary.simpleMessage("Allow biometric authentication"),
"settings_balance_detail" : MessageLookupByLibrary.simpleMessage("Decimals"),
"settings_change_language" : MessageLookupByLibrary.simpleMessage("Change language"),
"settings_change_pin" : MessageLookupByLibrary.simpleMessage("Change PIN"),
"settings_currency" : MessageLookupByLibrary.simpleMessage("Currency"),
"settings_current_node" : MessageLookupByLibrary.simpleMessage("Current node"),
"settings_dark_mode" : MessageLookupByLibrary.simpleMessage("Dark mode"),
"settings_display_balance_as" : MessageLookupByLibrary.simpleMessage("Display balance as"),
"settings_display_on_dashboard_list" : MessageLookupByLibrary.simpleMessage("Display on dashboard list"),
"settings_enable_fiat_currency" : MessageLookupByLibrary.simpleMessage("Enable Fiat Currency conversion"),
"settings_fee_priority" : MessageLookupByLibrary.simpleMessage("Fee priority"),
"settings_nodes" : MessageLookupByLibrary.simpleMessage("Nodes"),
"settings_none" : MessageLookupByLibrary.simpleMessage("None"),
"settings_personal" : MessageLookupByLibrary.simpleMessage("Personal"),
"settings_save_recipient_address" : MessageLookupByLibrary.simpleMessage("Save recipient address"),
"settings_support" : MessageLookupByLibrary.simpleMessage("Support"),
"settings_terms_and_conditions" : MessageLookupByLibrary.simpleMessage("Terms and conditions"),
"settings_title" : MessageLookupByLibrary.simpleMessage("Settings"),
"settings_transactions" : MessageLookupByLibrary.simpleMessage("Transactions"),
"settings_wallets" : MessageLookupByLibrary.simpleMessage("Wallets"),
"setup_pin" : MessageLookupByLibrary.simpleMessage("Setup PIN"),
"setup_successful" : MessageLookupByLibrary.simpleMessage("Your PIN has been set up successfully!"),
"share_address" : MessageLookupByLibrary.simpleMessage("Share address"),
"show_keys" : MessageLookupByLibrary.simpleMessage("Show keys"),
"show_seed" : MessageLookupByLibrary.simpleMessage("Show seed"),
"spend_key_private" : MessageLookupByLibrary.simpleMessage("Spend key (private)"),
"spend_key_public" : MessageLookupByLibrary.simpleMessage("Spend key (public)"),
"stake_more" : MessageLookupByLibrary.simpleMessage("Stake more"),
"stake_oxen" : MessageLookupByLibrary.simpleMessage("Stake Oxen"),
"start_staking" : MessageLookupByLibrary.simpleMessage("Start staking"),
"status" : MessageLookupByLibrary.simpleMessage("Status: "),
"subaddress_title" : MessageLookupByLibrary.simpleMessage("Subaddress list"),
"subaddresses" : MessageLookupByLibrary.simpleMessage("Subaddresses"),
"sync_status_connected" : MessageLookupByLibrary.simpleMessage("CONNECTED"),
"sync_status_connecting" : MessageLookupByLibrary.simpleMessage("CONNECTING"),
"sync_status_failed_connect" : MessageLookupByLibrary.simpleMessage("FAILED CONNECT TO THE NODE"),
"sync_status_not_connected" : MessageLookupByLibrary.simpleMessage("NOT CONNECTED"),
"sync_status_starting_sync" : MessageLookupByLibrary.simpleMessage("STARTING SYNC"),
"sync_status_synchronized" : MessageLookupByLibrary.simpleMessage("SYNCHRONIZED"),
"sync_status_synchronizing" : MessageLookupByLibrary.simpleMessage("SYNCHRONIZING"),
"title_confirm_unlock_stake" : MessageLookupByLibrary.simpleMessage("Unlock Stake"),
"title_new_stake" : MessageLookupByLibrary.simpleMessage("New Stake"),
"title_stakes" : MessageLookupByLibrary.simpleMessage("Stakes"),
"today" : MessageLookupByLibrary.simpleMessage("Today"),
"transaction_details_amount" : MessageLookupByLibrary.simpleMessage("Amount"),
"transaction_details_copied" : m12,
"transaction_details_date" : MessageLookupByLibrary.simpleMessage("Date"),
"transaction_details_height" : MessageLookupByLibrary.simpleMessage("Height"),
"transaction_details_recipient_address" : MessageLookupByLibrary.simpleMessage("Recipient address"),
"transaction_details_title" : MessageLookupByLibrary.simpleMessage("Transaction Details"),
"transaction_details_transaction_id" : MessageLookupByLibrary.simpleMessage("Transaction ID"),
"transaction_priority_blink" : MessageLookupByLibrary.simpleMessage("Blink"),
"transaction_priority_slow" : MessageLookupByLibrary.simpleMessage("Slow"),
"transaction_sent" : MessageLookupByLibrary.simpleMessage("Transaction sent!"),
"transactions" : MessageLookupByLibrary.simpleMessage("Transactions"),
"transactions_by_date" : MessageLookupByLibrary.simpleMessage("Transactions by date"),
"unable_unlock_stake" : MessageLookupByLibrary.simpleMessage("Unable to unlock stake"),
"unlock_stake_requested" : MessageLookupByLibrary.simpleMessage("Stake unlock requested"),
"use" : MessageLookupByLibrary.simpleMessage("Switch to "),
"version" : m13,
"view_key_private" : MessageLookupByLibrary.simpleMessage("View key (private)"),
"view_key_public" : MessageLookupByLibrary.simpleMessage("View key (public)"),
"wallet_keys" : MessageLookupByLibrary.simpleMessage("Wallet keys"),
"wallet_list_create_new_wallet" : MessageLookupByLibrary.simpleMessage("Create New Wallet"),
"wallet_list_failed_to_load" : m14,
"wallet_list_failed_to_remove" : m15,
"wallet_list_load_wallet" : MessageLookupByLibrary.simpleMessage("Load wallet"),
"wallet_list_loading_wallet" : m16,
"wallet_list_removing_wallet" : m17,
"wallet_list_restore_wallet" : MessageLookupByLibrary.simpleMessage("Restore Wallet"),
"wallet_list_title" : MessageLookupByLibrary.simpleMessage("Oxen Wallet"),
"wallet_menu" : MessageLookupByLibrary.simpleMessage("Menu"),
"wallet_name" : MessageLookupByLibrary.simpleMessage("Wallet name"),
"wallet_restoration_store_incorrect_seed_length" : MessageLookupByLibrary.simpleMessage("Incorrect seed length"),
"wallets" : MessageLookupByLibrary.simpleMessage("Wallets"),
"welcome" : MessageLookupByLibrary.simpleMessage("WELCOME\nTO OXEN WALLET"),
"widgets_address" : MessageLookupByLibrary.simpleMessage("Address"),
"widgets_or" : MessageLookupByLibrary.simpleMessage("or"),
"widgets_restore_from_blockheight" : MessageLookupByLibrary.simpleMessage("Restore from blockheight"),
"widgets_restore_from_date" : MessageLookupByLibrary.simpleMessage("Restore from date"),
"widgets_seed" : MessageLookupByLibrary.simpleMessage("Seed"),
"yes_im_sure" : MessageLookupByLibrary.simpleMessage("Yes, I\'m sure!"),
"yesterday" : MessageLookupByLibrary.simpleMessage("Yesterday"),
"your_contributions" : MessageLookupByLibrary.simpleMessage("Your Contributions")
};
}

View File

@ -1,305 +0,0 @@
// DO NOT EDIT. This is code generated via package:intl/generate_localized.dart
// This is a library that provides messages for a fr locale. All the
// messages from the main program should be duplicated here with the same
// function name.
// Ignore issues from commonly used lints in this file.
// ignore_for_file:unnecessary_brace_in_string_interps, unnecessary_new
// ignore_for_file:prefer_single_quotes,comment_references, directives_ordering
// ignore_for_file:annotate_overrides,prefer_generic_function_type_aliases
// ignore_for_file:unused_import, file_names
import 'package:intl/intl.dart';
import 'package:intl/message_lookup_by_library.dart';
final messages = new MessageLookup();
typedef String MessageIfAbsent(String messageStr, List<dynamic> args);
class MessageLookup extends MessageLookupByLibrary {
String get localeName => 'fr';
static m0(status) => "${status} blocs restants";
static m1(serviceNodeKey) => "Voulez-vous vraiment débloquer votre mise de${serviceNodeKey}?";
static m2(node) => "Voulez-vous vraiment changer le Node actuel vers ${node}?";
static m3(language) => "Changez la langue en ${language}?";
static m4(amount, fee) => "Valider la transaction\nMontant: ${amount}\nFee: ${fee}";
static m5(key) => "Clé ${key} dans le presse-papiers";
static m6(item, app_store) => "Ne JAMAIS saisir vos identifiants de votre Wallet Oxen ${item} dans tout logiciel ou site Web autre que les portefeuilles OFFICIELS Oxen téléchargés directement à partir du ${app_store}, le site internet Oxen, ou Oxen sur GitHub.\nÊtes-vous sûr de vouloir accéder à votre portefeuille ${item}?";
static m7(state_error) => "Échec de l\'authentification. ${state_error}";
static m8(item) => "Ne donnez JAMAIS votre Wallet Oxen à qui que ce soit! ${item} à qui que ce soit!";
static m9(recipient_name) => "Vous envoyez de l\'argent à\n${recipient_name}";
static m10(name) => "Aucun itinéraire défini pour ${name}";
static m11(transactionPriority) => "Actuellement, la priorité est définie sur ${transactionPriority}.\nLa priorité de transaction peut être ajustée dans les paramètres";
static m12(title) => "${title} copié dans le presse-papiers";
static m13(currentVersion) => "Version ${currentVersion}";
static m14(wallet_name, error) => "Échec du chargement du portefeuille ${wallet_name}. ${error}";
static m15(wallet_name, error) => "Erreur lors de la suppression ${wallet_name} Wallet. ${error}";
static m16(wallet_name) => "chargement du ${wallet_name} wallet";
static m17(wallet_name) => "Wallet ${wallet_name}";
final messages = _notInlinedMessages(_notInlinedMessages);
static _notInlinedMessages(_) => <String, Function> {
"Blocks_remaining" : m0,
"account" : MessageLookupByLibrary.simpleMessage("Compte"),
"accounts" : MessageLookupByLibrary.simpleMessage("Comptes"),
"add" : MessageLookupByLibrary.simpleMessage("Ajouter"),
"add_new_word" : MessageLookupByLibrary.simpleMessage("Ajouter un nouveau mot"),
"address_book" : MessageLookupByLibrary.simpleMessage("Carnet d\'adresses"),
"address_book_menu" : MessageLookupByLibrary.simpleMessage("Carnet d\'adresses"),
"all" : MessageLookupByLibrary.simpleMessage("TOUT"),
"amount" : MessageLookupByLibrary.simpleMessage("Montant: "),
"amount_detail_detailed" : MessageLookupByLibrary.simpleMessage("4 - Détaillé"),
"amount_detail_none" : MessageLookupByLibrary.simpleMessage("0 - Aucun"),
"amount_detail_normal" : MessageLookupByLibrary.simpleMessage("2 - Normal"),
"amount_detail_ultra" : MessageLookupByLibrary.simpleMessage("9 - Ultra"),
"auth_store_ban_timeout" : MessageLookupByLibrary.simpleMessage("Interdire le délai d\'expiration"),
"auth_store_banned_for" : MessageLookupByLibrary.simpleMessage("Interdit pour "),
"auth_store_banned_minutes" : MessageLookupByLibrary.simpleMessage(" Protocole"),
"auth_store_incorrect_password" : MessageLookupByLibrary.simpleMessage("mauvais code PIN"),
"authenticated" : MessageLookupByLibrary.simpleMessage("Authentifié"),
"authentication" : MessageLookupByLibrary.simpleMessage("Authentification"),
"available_balance" : MessageLookupByLibrary.simpleMessage("Solde disponible"),
"biometric_auth_reason" : MessageLookupByLibrary.simpleMessage("Scannez votre empreinte digitale pour l\'authentification"),
"body_confirm_unlock_stake" : m1,
"cancel" : MessageLookupByLibrary.simpleMessage("Annuler"),
"change" : MessageLookupByLibrary.simpleMessage("Changement"),
"change_current_node" : m2,
"change_language" : MessageLookupByLibrary.simpleMessage("changer la langue"),
"change_language_to" : m3,
"changelog" : MessageLookupByLibrary.simpleMessage("Journal des modifications"),
"clear" : MessageLookupByLibrary.simpleMessage("clair"),
"commit_transaction_amount_fee" : m4,
"confirm" : MessageLookupByLibrary.simpleMessage("confirmer"),
"confirm_sending" : MessageLookupByLibrary.simpleMessage("confirmer l\'envoi"),
"contact" : MessageLookupByLibrary.simpleMessage("Contact"),
"contact_name" : MessageLookupByLibrary.simpleMessage("Nom du contact"),
"continue_text" : MessageLookupByLibrary.simpleMessage("Continuez"),
"copied_key_to_clipboard" : m5,
"copied_to_clipboard" : MessageLookupByLibrary.simpleMessage("Copié dans le presse-papiers"),
"copy" : MessageLookupByLibrary.simpleMessage("copier"),
"create_new" : MessageLookupByLibrary.simpleMessage("Créer un nouveau portefeuille"),
"dangerzone" : MessageLookupByLibrary.simpleMessage("zone de danger"),
"dangerzone_warning" : m6,
"delete" : MessageLookupByLibrary.simpleMessage("effacer"),
"digit_pin" : MessageLookupByLibrary.simpleMessage("-chiffre PIN"),
"edit" : MessageLookupByLibrary.simpleMessage("Éditer"),
"enter_your_pin" : MessageLookupByLibrary.simpleMessage("entrez le code PIN"),
"enter_your_pin_again" : MessageLookupByLibrary.simpleMessage("Saisissez à nouveau votre code PIN"),
"error" : MessageLookupByLibrary.simpleMessage("erreur"),
"error_text_account_name" : MessageLookupByLibrary.simpleMessage("Le nom du compte ne peut contenir que des lettres et des chiffres\net doit comporter entre 1 et 15 caractères"),
"error_text_address" : MessageLookupByLibrary.simpleMessage("L\'adresse du portefeuille doit correspondre au type de crypto-monnaie"),
"error_text_amount" : MessageLookupByLibrary.simpleMessage("Le montant ne peut contenir que des nombres"),
"error_text_contact_name" : MessageLookupByLibrary.simpleMessage("Dans le nom du contact, les symboles ` , \' \" ne doivent pas être inclus\net doit comporter entre 1 et 32 caractères"),
"error_text_crypto_currency" : MessageLookupByLibrary.simpleMessage("Le nombre de décimales\nm doit être inférieur ou égal à 12."),
"error_text_fiat" : MessageLookupByLibrary.simpleMessage("La valeur du montant ne peut pas dépasser le solde disponible du compte.\nLe nombre de décimales doit être inférieur ou égal à 2"),
"error_text_keys" : MessageLookupByLibrary.simpleMessage("Les clés de portefeuille ne peuvent contenir que 64 caractères hexadécimaux"),
"error_text_node_address" : MessageLookupByLibrary.simpleMessage("Veuillez saisir une adresse iPv4"),
"error_text_node_port" : MessageLookupByLibrary.simpleMessage("Le port du Node ne peut contenir que des nombres compris entre 0 et 65535"),
"error_text_oxen" : MessageLookupByLibrary.simpleMessage("La valeur OXEN ne peut pas dépasser le solde disponible.\nLe nombre de décimales doit être inférieur ou égal à 12"),
"error_text_payment_id" : MessageLookupByLibrary.simpleMessage("L\'ID de paiement ne peut contenir que 16 à 64 caractères hexadécimaux"),
"error_text_service_node" : MessageLookupByLibrary.simpleMessage("Une clé de nœud de service ne peut contenir que 64 caractères maximum"),
"error_text_subaddress_name" : MessageLookupByLibrary.simpleMessage("Au nom de la sous-adresse, les symboles ` , \' \" ne pas être inclus\net doit comporter entre 1 et 20 caractères"),
"error_text_wallet_name" : MessageLookupByLibrary.simpleMessage("Le nom du portefeuille ne peut contenir que des lettres et des chiffres\net doit comporter entre 1 et 15 caractères"),
"failed_authentication" : m7,
"faq" : MessageLookupByLibrary.simpleMessage("FAQ"),
"fetching" : MessageLookupByLibrary.simpleMessage("Récupération"),
"filters" : MessageLookupByLibrary.simpleMessage("filtres"),
"first_wallet_text" : MessageLookupByLibrary.simpleMessage("Super Wallet\npour Oxen"),
"full_balance" : MessageLookupByLibrary.simpleMessage("Solde complet"),
"hidden_balance" : MessageLookupByLibrary.simpleMessage("solde caché"),
"id" : MessageLookupByLibrary.simpleMessage("ID: "),
"incoming" : MessageLookupByLibrary.simpleMessage("entrant"),
"incorrect_seed" : MessageLookupByLibrary.simpleMessage("Le texte saisi n\'est pas valide."),
"keys_title" : MessageLookupByLibrary.simpleMessage("Clés"),
"loading_your_wallet" : MessageLookupByLibrary.simpleMessage("chargement du portefeuille"),
"login" : MessageLookupByLibrary.simpleMessage("Login"),
"never_give_your" : m8,
"new_subaddress_create" : MessageLookupByLibrary.simpleMessage("Créer"),
"new_subaddress_label_name" : MessageLookupByLibrary.simpleMessage("Nom"),
"new_subaddress_title" : MessageLookupByLibrary.simpleMessage("Nouvelle sous-adresse"),
"new_wallet" : MessageLookupByLibrary.simpleMessage("Nouveau portefeuille"),
"node_address" : MessageLookupByLibrary.simpleMessage("L\'adresse du Node"),
"node_new" : MessageLookupByLibrary.simpleMessage("Nouveau Node"),
"node_port" : MessageLookupByLibrary.simpleMessage("Port du Node"),
"node_reset_settings_title" : MessageLookupByLibrary.simpleMessage("Réinitialiser les paramètres"),
"nodes" : MessageLookupByLibrary.simpleMessage("Nodes"),
"nodes_list_reset_to_default_message" : MessageLookupByLibrary.simpleMessage("Êtes-vous sûr de vouloir réinitialiser les paramètres par défaut?"),
"nothing_staked" : MessageLookupByLibrary.simpleMessage("Aucune contribution pour le moment"),
"ok" : MessageLookupByLibrary.simpleMessage("OK"),
"openalias_alert_content" : m9,
"openalias_alert_title" : MessageLookupByLibrary.simpleMessage("OXEN-destinataire reconnu"),
"outgoing" : MessageLookupByLibrary.simpleMessage("sortant"),
"oxen_available_balance" : MessageLookupByLibrary.simpleMessage("OXEN solde disponible"),
"oxen_full_balance" : MessageLookupByLibrary.simpleMessage("OXEN solde complet"),
"oxen_hidden" : MessageLookupByLibrary.simpleMessage("OXEN caché"),
"password" : MessageLookupByLibrary.simpleMessage("Mot de Passe"),
"paste" : MessageLookupByLibrary.simpleMessage("Coller"),
"pending" : MessageLookupByLibrary.simpleMessage(" (en attente)"),
"pin_is_incorrect" : MessageLookupByLibrary.simpleMessage("Le code PIN est faux"),
"please_make_selection" : MessageLookupByLibrary.simpleMessage("Veuillez faire un choix ci-dessous\nCréez ou restaurez votre portefeuille."),
"please_select" : MessageLookupByLibrary.simpleMessage("Veuillez sélectionner:"),
"please_try_to_connect_to_another_node" : MessageLookupByLibrary.simpleMessage("veuillez essayer de vous connecter à un autre node"),
"receive" : MessageLookupByLibrary.simpleMessage("recevoir"),
"receive_amount" : MessageLookupByLibrary.simpleMessage("Montant"),
"received" : MessageLookupByLibrary.simpleMessage("a reçu"),
"reconnect" : MessageLookupByLibrary.simpleMessage("se reconnecter"),
"reconnect_alert_text" : MessageLookupByLibrary.simpleMessage("Voulez-vous vraiment vous reconnecter?"),
"reconnection" : MessageLookupByLibrary.simpleMessage("reconnexion"),
"reload_fiat" : MessageLookupByLibrary.simpleMessage("Actualiser le taux fiat"),
"remove" : MessageLookupByLibrary.simpleMessage("supprimer"),
"remove_node" : MessageLookupByLibrary.simpleMessage("supprimer le Node"),
"remove_node_message" : MessageLookupByLibrary.simpleMessage("Vous voulez vraiment supprimer le Node sélectionné?"),
"rescan" : MessageLookupByLibrary.simpleMessage("réanalyser"),
"reset" : MessageLookupByLibrary.simpleMessage("Réinitialiser"),
"restore_address" : MessageLookupByLibrary.simpleMessage("Adresse"),
"restore_description_from_backup" : MessageLookupByLibrary.simpleMessage("Vous pouvez restaurer l\'intégralité de l\'application Oxen Wallet à partir de son fichier de sauvegarde."),
"restore_description_from_keys" : MessageLookupByLibrary.simpleMessage("Restaurez votre portefeuille à partir du mnemonic généré à partir de vos clés privées"),
"restore_description_from_seed" : MessageLookupByLibrary.simpleMessage("Récupérez votre portefeuille à partir du code de combinaison de 25 ou 13 mots"),
"restore_description_from_seed_keys" : MessageLookupByLibrary.simpleMessage("Restaurez votre portefeuille avec le Seed ou les clées que vous avez conservées dans un endroit sûr"),
"restore_from_seed_placeholder" : MessageLookupByLibrary.simpleMessage("Veuillez entrer votre code ici"),
"restore_next" : MessageLookupByLibrary.simpleMessage("Continuer"),
"restore_recover" : MessageLookupByLibrary.simpleMessage("Restaurer"),
"restore_restore_wallet" : MessageLookupByLibrary.simpleMessage("Restauration du portefeuille"),
"restore_seed_keys_restore" : MessageLookupByLibrary.simpleMessage("Restaurer depuis le Seed ou les clés"),
"restore_spend_key_private" : MessageLookupByLibrary.simpleMessage("Clé de dépense (secret)"),
"restore_title_from_backup" : MessageLookupByLibrary.simpleMessage("Restaurer à partir d\'un fichier de sauvegarde"),
"restore_title_from_keys" : MessageLookupByLibrary.simpleMessage("Récupération des clés"),
"restore_title_from_seed" : MessageLookupByLibrary.simpleMessage("Restaurer à partir du Seed"),
"restore_title_from_seed_keys" : MessageLookupByLibrary.simpleMessage("Restaurer à partir du seed ou des clés"),
"restore_view_key_private" : MessageLookupByLibrary.simpleMessage("Clé d\'observation (secret)"),
"restore_wallet" : MessageLookupByLibrary.simpleMessage("Restaurer un portefeuille"),
"restore_wallet_name" : MessageLookupByLibrary.simpleMessage("Nom du portefeuille"),
"restore_wallet_restore_description" : MessageLookupByLibrary.simpleMessage("Description de la restauration du portefeuille"),
"router_no_route" : m10,
"save" : MessageLookupByLibrary.simpleMessage("Sauvegarder"),
"seed_language_chinese" : MessageLookupByLibrary.simpleMessage("Chinois"),
"seed_language_choose" : MessageLookupByLibrary.simpleMessage("Veuillez sélectionner la langue source"),
"seed_language_dutch" : MessageLookupByLibrary.simpleMessage("Néerlandais"),
"seed_language_english" : MessageLookupByLibrary.simpleMessage("Anglais"),
"seed_language_french" : MessageLookupByLibrary.simpleMessage("Français"),
"seed_language_german" : MessageLookupByLibrary.simpleMessage("Allemand"),
"seed_language_italian" : MessageLookupByLibrary.simpleMessage("Italien"),
"seed_language_japanese" : MessageLookupByLibrary.simpleMessage("Japonais"),
"seed_language_next" : MessageLookupByLibrary.simpleMessage("Continuer"),
"seed_language_portuguese" : MessageLookupByLibrary.simpleMessage("Portugais"),
"seed_language_russian" : MessageLookupByLibrary.simpleMessage("Russe"),
"seed_language_spanish" : MessageLookupByLibrary.simpleMessage("Espagnol"),
"seed_share" : MessageLookupByLibrary.simpleMessage("Partager Seed"),
"seed_title" : MessageLookupByLibrary.simpleMessage("Seed"),
"send" : MessageLookupByLibrary.simpleMessage("envoyer"),
"send_creating_transaction" : MessageLookupByLibrary.simpleMessage("Créer une transaction"),
"send_error_currency" : MessageLookupByLibrary.simpleMessage("La devise ne peut contenir que des nombres"),
"send_estimated_fee" : MessageLookupByLibrary.simpleMessage("Frais estimés:"),
"send_oxen" : MessageLookupByLibrary.simpleMessage("Envoyer OXEN"),
"send_oxen_address" : MessageLookupByLibrary.simpleMessage("Adresse Oxen"),
"send_priority" : m11,
"send_title" : MessageLookupByLibrary.simpleMessage("Envoyer des OXEN"),
"send_your_wallet" : MessageLookupByLibrary.simpleMessage("Votre portefeuille"),
"sending" : MessageLookupByLibrary.simpleMessage("Envoyer"),
"sent" : MessageLookupByLibrary.simpleMessage("expédié"),
"service_node_key" : MessageLookupByLibrary.simpleMessage("Clé de nœud de service"),
"settings_all" : MessageLookupByLibrary.simpleMessage("TOUT"),
"settings_allow_biometric_authentication" : MessageLookupByLibrary.simpleMessage("Authentification biométrique"),
"settings_balance_detail" : MessageLookupByLibrary.simpleMessage("Décimales"),
"settings_change_language" : MessageLookupByLibrary.simpleMessage("changer de langue"),
"settings_change_pin" : MessageLookupByLibrary.simpleMessage("changer le code PIN"),
"settings_currency" : MessageLookupByLibrary.simpleMessage("Devise"),
"settings_current_node" : MessageLookupByLibrary.simpleMessage("Node actuel"),
"settings_dark_mode" : MessageLookupByLibrary.simpleMessage("Mode Sombre"),
"settings_display_balance_as" : MessageLookupByLibrary.simpleMessage("Afficher la balance comme"),
"settings_display_on_dashboard_list" : MessageLookupByLibrary.simpleMessage("Afficher dans la liste du tableau de bord"),
"settings_enable_fiat_currency" : MessageLookupByLibrary.simpleMessage("Convertir la devise en fiat"),
"settings_fee_priority" : MessageLookupByLibrary.simpleMessage("Priorité des frais"),
"settings_nodes" : MessageLookupByLibrary.simpleMessage("Node"),
"settings_none" : MessageLookupByLibrary.simpleMessage("Rien"),
"settings_personal" : MessageLookupByLibrary.simpleMessage("personnel"),
"settings_save_recipient_address" : MessageLookupByLibrary.simpleMessage("Enregistrer l\'adresse du destinataire"),
"settings_support" : MessageLookupByLibrary.simpleMessage("Soutien"),
"settings_terms_and_conditions" : MessageLookupByLibrary.simpleMessage("Termes et conditions"),
"settings_title" : MessageLookupByLibrary.simpleMessage("Paramètres"),
"settings_transactions" : MessageLookupByLibrary.simpleMessage("Transactions"),
"settings_wallets" : MessageLookupByLibrary.simpleMessage("Portefeuilles"),
"setup_pin" : MessageLookupByLibrary.simpleMessage("Configurer le code PIN"),
"setup_successful" : MessageLookupByLibrary.simpleMessage("Votre code PIN a été configuré avec succès!"),
"share_address" : MessageLookupByLibrary.simpleMessage("Partager l\'adresse "),
"show_keys" : MessageLookupByLibrary.simpleMessage("Afficher les clés"),
"show_seed" : MessageLookupByLibrary.simpleMessage("Afficher le seed"),
"spend_key_private" : MessageLookupByLibrary.simpleMessage("Clé de dépense (secret)"),
"spend_key_public" : MessageLookupByLibrary.simpleMessage("Clé de dépense (publique)"),
"stake_more" : MessageLookupByLibrary.simpleMessage("Staker plus"),
"stake_oxen" : MessageLookupByLibrary.simpleMessage("Stake Oxen"),
"start_staking" : MessageLookupByLibrary.simpleMessage("Commencer le staking"),
"status" : MessageLookupByLibrary.simpleMessage("Statut: "),
"subaddress_title" : MessageLookupByLibrary.simpleMessage("Liste des sous-adresses"),
"subaddresses" : MessageLookupByLibrary.simpleMessage("Sous-adresses"),
"sync_status_connected" : MessageLookupByLibrary.simpleMessage("CONNECTÉ"),
"sync_status_connecting" : MessageLookupByLibrary.simpleMessage("CONNEXION"),
"sync_status_failed_connect" : MessageLookupByLibrary.simpleMessage("ÉCHEC DE LA CONNEXION AU NODE"),
"sync_status_not_connected" : MessageLookupByLibrary.simpleMessage("PAS CONNECTÉ"),
"sync_status_starting_sync" : MessageLookupByLibrary.simpleMessage("DÉBUT DE LA SYNCHRONISATION"),
"sync_status_synchronized" : MessageLookupByLibrary.simpleMessage("SYNCHRONISÉ"),
"sync_status_synchronizing" : MessageLookupByLibrary.simpleMessage("SYNCHRONISATION"),
"title_confirm_unlock_stake" : MessageLookupByLibrary.simpleMessage("Déverrouiller Stake"),
"title_new_stake" : MessageLookupByLibrary.simpleMessage("Nouveau Stake"),
"title_stakes" : MessageLookupByLibrary.simpleMessage("Stakes"),
"today" : MessageLookupByLibrary.simpleMessage("aujourd\'hui"),
"transaction_details_amount" : MessageLookupByLibrary.simpleMessage("Montant"),
"transaction_details_copied" : m12,
"transaction_details_date" : MessageLookupByLibrary.simpleMessage("Date"),
"transaction_details_height" : MessageLookupByLibrary.simpleMessage("Taille"),
"transaction_details_recipient_address" : MessageLookupByLibrary.simpleMessage("Adresse du destinataire"),
"transaction_details_title" : MessageLookupByLibrary.simpleMessage("détails de la transaction"),
"transaction_details_transaction_id" : MessageLookupByLibrary.simpleMessage("ID Transaction"),
"transaction_priority_blink" : MessageLookupByLibrary.simpleMessage("Blink"),
"transaction_priority_slow" : MessageLookupByLibrary.simpleMessage("Lente"),
"transaction_sent" : MessageLookupByLibrary.simpleMessage("Transaction envoyé!"),
"transactions" : MessageLookupByLibrary.simpleMessage("transactions"),
"transactions_by_date" : MessageLookupByLibrary.simpleMessage("transactions par date"),
"unable_unlock_stake" : MessageLookupByLibrary.simpleMessage("Impossible de déverrouiller le Stake"),
"unlock_stake_requested" : MessageLookupByLibrary.simpleMessage("Déverrouillage du Stake demandé"),
"use" : MessageLookupByLibrary.simpleMessage("Basculer vers "),
"version" : m13,
"view_key_private" : MessageLookupByLibrary.simpleMessage("Clé d\'observation (secret)"),
"view_key_public" : MessageLookupByLibrary.simpleMessage("Clé d\'observation (publique)"),
"wallet_keys" : MessageLookupByLibrary.simpleMessage("Clés du portefeuille"),
"wallet_list_create_new_wallet" : MessageLookupByLibrary.simpleMessage("Créer un nouveau portefeuille"),
"wallet_list_failed_to_load" : m14,
"wallet_list_failed_to_remove" : m15,
"wallet_list_load_wallet" : MessageLookupByLibrary.simpleMessage("Charger le portefeuille"),
"wallet_list_loading_wallet" : m16,
"wallet_list_removing_wallet" : m17,
"wallet_list_restore_wallet" : MessageLookupByLibrary.simpleMessage("Restaurer le portefeuille"),
"wallet_list_title" : MessageLookupByLibrary.simpleMessage("Oxen Wallet"),
"wallet_menu" : MessageLookupByLibrary.simpleMessage("Menu du portefeuille"),
"wallet_name" : MessageLookupByLibrary.simpleMessage("Nom du portefeuille"),
"wallet_restoration_store_incorrect_seed_length" : MessageLookupByLibrary.simpleMessage("mauvaise longueur du Seed"),
"wallets" : MessageLookupByLibrary.simpleMessage("Wallets"),
"welcome" : MessageLookupByLibrary.simpleMessage("Bienvenu sur\nOXEN WALLET"),
"widgets_address" : MessageLookupByLibrary.simpleMessage("Adresse"),
"widgets_or" : MessageLookupByLibrary.simpleMessage("ou"),
"widgets_restore_from_blockheight" : MessageLookupByLibrary.simpleMessage("restaurer à partir du blockheight"),
"widgets_restore_from_date" : MessageLookupByLibrary.simpleMessage("Restaurer à partir de la date"),
"widgets_seed" : MessageLookupByLibrary.simpleMessage("Seed"),
"yes_im_sure" : MessageLookupByLibrary.simpleMessage("Oui, je suis sûr!"),
"yesterday" : MessageLookupByLibrary.simpleMessage("hier"),
"your_contributions" : MessageLookupByLibrary.simpleMessage("Vos contributions")
};
}

File diff suppressed because it is too large Load Diff

8
lib/l10n.dart Normal file
View File

@ -0,0 +1,8 @@
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:flutter/material.dart';
export 'package:flutter_gen/gen_l10n/app_localizations.dart' show AppLocalizations;
AppLocalizations tr(BuildContext ctx) {
return AppLocalizations.of(ctx) ?? lookupAppLocalizations(Locale('en', ''));
}

View File

@ -20,6 +20,12 @@
"contact_name" : "Name des Ansprechpartners",
"reset" : "Zurücksetzen",
"save" : "Speichern",
"remove_contact" : "Kontakt entfernen",
"remove_contact_confirm" : "Bist du sicher dass du den ausgewählten Kontakt entfernen möchtest?",
"remove_wallet_confirmation": "Bist du sicher dass du dieses Wallet löschen möchtest?",
"dangerzone_remove_wallet_warning": "Wenn du deine Seed-Phrase nicht gespeichert hast, wird alles Kapital dass zu diesem Wallet gesendet wurde für immer verloren sein.",
"authenticated" : "Authentifiziert",
@ -28,7 +34,7 @@
"wallet_menu" : "Wallet-Menü",
"Blocks_remaining" : "{status} verbleibende Blöcke",
"blocks_remaining" : "{status} verbleibende Blöcke",
"please_try_to_connect_to_another_node" : "Bitte versuchen Sie, eine Verbindung zu einem anderen Knoten herzustellen",
"oxen_hidden" : "OXEN versteckt",
"oxen_available_balance" : "OXEN verfügbares Guthaben",
@ -44,6 +50,7 @@
"yesterday" : "Gestern",
"received" : "Empfangen",
"sent" : "Geschickt",
"stake" : "Stake",
"pending" : " (steht aus)",
"rescan" : "Erneut scannen",
"reconnect" : "Erneut verbinden",
@ -67,7 +74,8 @@
"status" : "Status: ",
"confirm" : "Bestätigen",
"confirm_sending" : "Bestätigen Sie das Senden",
"commit_transaction_amount_fee" : "Transaktion festschreiben\nMenge: {amount}\nGebühr: {fee}",
"confirm_stake" : "Bestätigen Sie der Stake",
"confirm_transaction_amount_fee" : "Menge: {amount} OXEN\nGebühr: {fee} OXEN",
"sending" : "Senden",
"transaction_sent" : "Transaktion gesendet!",
"send_oxen" : "OXEN Senden",
@ -101,8 +109,7 @@
"delete" : "Löschen",
"use" : "Wechseln zu ",
"digit_pin" : "-stelliger PIN",
"use_n_digit_pin" : "Wechseln zu {n}-stelliger PIN",
"share_address" : "Adresse teilen ",
@ -118,7 +125,7 @@
"restore_description_from_backup" : "Sie können die gesamte Oxen Wallet-App aus ihrer Sicherungsdatei wiederherstellen.",
"restore_seed_keys_restore" : "Seed / Schlüssel wiederherstellen",
"restore_title_from_seed" : "Aus Seed wiederherstellen",
"restore_description_from_seed" : "Stellen Sie Ihr Wallet aus den 25 Wörtern wieder her oder 13-Wort-Kombinationscode",
"restore_description_from_seed" : "Stellen Sie Ihr Wallet aus dem 25-Wörter-Kombinationscode",
"restore_title_from_keys" : "Wiederherstellen von Schlüsseln",
"restore_description_from_keys" : "Stellen Sie Ihr Wallet von generiert wieder her Tastenanschläge, die von Ihren privaten Schlüsseln gespeichert wurden",
"restore_wallet_name" : "Walletname",
@ -251,25 +258,20 @@
"router_no_route" : "Keine Route definiert für {name}",
"error_text_account_name" : "Der Kontoname darf nur Buchstaben und Zahlen enthalten\nund muss zwischen 1 und 15 Zeichen lang sein",
"error_text_contact_name" : "Im Kontaktname könne die Symbole ` , ' \" nicht enthalten sein\nund muss zwischen 1 und 32 Zeichen lang sein",
"error_text_empty": "Kann nicht leer sein",
"error_text_address" : "Die Walletadresse muss dem Typ der Kryptowährung\nentsprechen",
"error_text_node_address" : "Bitte geben Sie eine iPv4-Adresse ein",
"error_text_node_address" : "Bitte geben Sie eine IP-Adresse ein",
"error_text_node_port" : "Der Knotenport kann nur Nummern zwischen 0 und 65535 enthalten",
"error_text_payment_id" : "Die Zahlungs-ID kann nur 16 bis 64 hexadezimale Zeichen enthalten",
"error_text_oxen" : "Der OXEN-Wert kann das verfügbare Guthaben nicht überschreiten.\nDie Anzahl der Nachkommastellen muss kleiner oder gleich 12 sein",
"error_text_oxen" : "Der OXEN-Wert kann das verfügbare Guthaben nicht überschreiten.\nDie Anzahl der Nachkommastellen muss kleiner oder gleich 9 sein",
"error_text_fiat" : "Der Wert des Betrags darf den verfügbaren Kontostand nicht überschreiten.\nDie Anzahl der Nachkommastellen muss kleiner oder gleich 2 sein",
"error_text_subaddress_name" : "Im Namen der Unteradresse könne die Symbole ` , ' \" nicht enthalten sein\nund muss zwischen 1 und 20 Zeichen lang sein",
"error_text_amount" : "Betrag kann nur Zahlen enthalten",
"error_text_wallet_name" : "Der Walletname darf nur Buchstaben und Zahlen enthalten\nund muss zwischen 1 und 15 Zeichen lang sein",
"error_text_keys" : "Walletschlüssel können nur 64 hexadezimale Zeichen enthalten",
"error_text_crypto_currency" : "Die Anzahl der Nachkommastellen\nmuss kleiner oder gleich 12 sein.",
"error_text_crypto_currency" : "Die Anzahl der Nachkommastellen\nmuss kleiner oder gleich 9 sein.",
"error_text_service_node": "Service Node Schlüssel können nur 64 hexadezimale Zeichen enthalten",
"auth_store_ban_timeout" : "Auszeit verbieten",
"auth_store_banned_for" : "Gebannt für ",
"auth_store_banned_minutes" : " Protokoll",
"auth_store_banned_for" : "{mins} Minuten gebannt.",
"auth_store_incorrect_password" : "Falsches PIN",
"wallet_restoration_store_incorrect_seed_length" : "Falsche Seed-länge",

View File

@ -20,15 +20,19 @@
"contact_name" : "Contact Name",
"reset" : "Reset",
"save" : "Save",
"remove_contact" : "Remove Contact",
"remove_contact_confirm" : "Are you sure that you want to remove the selected contact?",
"authenticated" : "Authenticated",
"authentication" : "Authentication",
"failed_authentication" : "Failed authentication. {state_error}",
"@failed_authentication" : { "placeholders": { "state_error": {} } },
"wallet_menu" : "Menu",
"Blocks_remaining" : "{status} Blocks Remaining",
"blocks_remaining" : "{status} Blocks Remaining",
"@blocks_remaining" : { "placeholders": { "status": {} } },
"please_try_to_connect_to_another_node" : "Please try to connect to another node",
"oxen_hidden" : "OXEN Hidden",
"oxen_available_balance" : "OXEN Available Balance",
@ -44,6 +48,7 @@
"yesterday" : "Yesterday",
"received" : "Received",
"sent" : "Sent",
"stake" : "Stake",
"pending" : " (pending)",
"rescan" : "Rescan",
"reconnect" : "Reconnect",
@ -67,7 +72,9 @@
"status" : "Status: ",
"confirm" : "Confirm",
"confirm_sending" : "Confirm sending",
"commit_transaction_amount_fee" : "Commit transaction\nAmount: {amount}\nFee: {fee}",
"confirm_stake" : "Confirm stake",
"confirm_transaction_amount_fee" : "Amount: {amount}\nFee: {fee}",
"@confirm_transaction_amount_fee" : { "placeholders": { "amount": {}, "fee": {} } },
"sending" : "Sending",
"transaction_sent" : "Transaction sent!",
"send_oxen" : "Send OXEN",
@ -85,6 +92,10 @@
"continue_text" : "Continue",
"remove_wallet_confirmation": "Are you sure you want to delete this wallet?",
"dangerzone_remove_wallet_warning": "If you have not saved your seed phrase then any funds sent to this wallet will be lost forever!",
"node_new" : "New Node",
"node_address" : "Node Address",
"node_port" : "Node port",
@ -94,6 +105,7 @@
"node_reset_settings_title" : "Reset settings",
"nodes_list_reset_to_default_message" : "Are you sure that you want to reset settings to default?",
"change_current_node" : "Are you sure to change current node to {node}?",
"@change_current_node" : { "placeholders": { "node": {} }},
"change" : "Change",
"remove_node" : "Remove node",
"remove_node_message" : "Are you sure that you want to remove selected node?",
@ -101,8 +113,8 @@
"delete" : "Delete",
"use" : "Switch to ",
"digit_pin" : "-digit PIN",
"use_n_digit_pin" : "Switch to {n}-digit PIN",
"@use_n_digit_pin" : { "placeholders": { "n": {} }},
"share_address" : "Share address",
@ -118,7 +130,7 @@
"restore_description_from_backup" : "You can restore the whole Oxen Wallet app from your back-up file",
"restore_seed_keys_restore" : "Seed/Keys Restore",
"restore_title_from_seed" : "Restore from seed",
"restore_description_from_seed" : "Restore your wallet from either the 25 word or 13 word combination code",
"restore_description_from_seed" : "Restore your wallet from the 25 word combination code",
"restore_title_from_keys" : "Restore from keys",
"restore_description_from_keys" : "Restore your wallet from generated keystrokes saved from your private keys",
"restore_wallet_name" : "Wallet name",
@ -155,6 +167,7 @@
"send_error_currency" : "Currency can only contain numbers",
"send_estimated_fee" : "Estimated fee:",
"send_priority" : "Currently the fee is set at {transactionPriority} priority.\nTransaction priority can be adjusted in the settings",
"@send_priority" : { "placeholders": { "transactionPriority": {} }},
"send_creating_transaction" : "Creating transaction",
@ -168,6 +181,7 @@
"stake_oxen": "Stake Oxen",
"title_confirm_unlock_stake": "Unlock Stake",
"body_confirm_unlock_stake": "Do you really want to unlock your stake from {serviceNodeKey}?",
"@body_confirm_unlock_stake" : { "placeholders": { "serviceNodeKey": {} }},
"unlock_stake_requested": "Stake unlock requested",
"unable_unlock_stake": "Unable to unlock stake",
@ -202,7 +216,7 @@
"setup_pin" : "Setup PIN",
"enter_your_pin_again" : "Enter your pin again",
"enter_your_pin_again" : "Enter your PIN again",
"setup_successful" : "Your PIN has been set up successfully!",
@ -212,6 +226,7 @@
"spend_key_private" : "Spend key (private)",
"spend_key_public" : "Spend key (public)",
"copied_key_to_clipboard" : "Copied {key} to Clipboard",
"@copied_key_to_clipboard" : { "placeholders": { "key": {} }},
"new_subaddress_title" : "New subaddress",
@ -228,6 +243,7 @@
"transaction_details_height" : "Height",
"transaction_details_amount" : "Amount",
"transaction_details_copied" : "{title} copied to Clipboard",
"@transaction_details_copied" : { "placeholders": { "title": {} }},
"transaction_details_recipient_address" : "Recipient address",
@ -236,9 +252,13 @@
"wallet_list_restore_wallet" : "Restore Wallet",
"wallet_list_load_wallet" : "Load wallet",
"wallet_list_loading_wallet" : "Loading {wallet_name} wallet",
"@wallet_list_loading_wallet" : { "placeholders": { "wallet_name": {} }},
"wallet_list_failed_to_load" : "Failed to load {wallet_name} wallet. {error}",
"@wallet_list_failed_to_load" : { "placeholders": { "wallet_name": {}, "error": {} }},
"wallet_list_removing_wallet" : "Removing {wallet_name} wallet",
"wallet_list_failed_to_remove" : "Failed to remove {wallet_name} wallet. {error}",
"@wallet_list_removing_wallet" : { "placeholders": { "wallet_name": {} }},
"wallet_list_failed_to_remove" : "Failed to remove {wallet_name} wallet: {error}",
"@wallet_list_failed_to_remove" : { "placeholders": { "wallet_name": {}, "error": {} }},
"widgets_address" : "Address",
@ -249,27 +269,24 @@
"router_no_route" : "No route defined for {name}",
"@router_no_route" : { "placeholders": { "name": {} }},
"error_text_account_name" : "Account name can only contain letters, numbers\nand must be between 1 and 15 characters long",
"error_text_contact_name" : "Contact name can't contain ` , ' \" symbols\nand must be between 1 and 32 characters long",
"error_text_address" : "Wallet address must correspond to the type\nof cryptocurrency",
"error_text_node_address" : "Please enter a iPv4 address",
"error_text_node_port" : "Node port can only contain numbers between 0 and 65535",
"error_text_empty": "Cannot be empty",
"error_text_address" : "Invalid OXEN wallet address!",
"error_text_node_address" : "Please enter a valid hostname or IP address",
"error_text_node_port" : "Node port can only contain numbers between 1 and 65535",
"error_text_payment_id" : "Payment ID can only contain from 16 to 64 chars in hex",
"error_text_oxen" : "OXEN value can't exceed available balance.\nThe number of fraction digits must be less or equal to 12",
"error_text_oxen" : "OXEN value can't exceed available balance.\nThe number of fraction digits must be less or equal to 9",
"error_text_fiat" : "Value of amount can't exceed available balance.\nThe number of fraction digits must be less or equal to 2",
"error_text_subaddress_name" : "Subaddress name can't contain ` , ' \" symbols\nand must be between 1 and 20 characters long",
"error_text_amount" : "Amount can only contain numbers",
"error_text_wallet_name" : "Wallet name can only contain letters, numbers\nand must be between 1 and 15 characters long",
"error_text_keys" : "Wallet keys can only contain 64 chars in hex",
"error_text_crypto_currency" : "The number of fraction digits\nmust be less or equal to 12",
"error_text_crypto_currency" : "The number of fraction digits\nmust be less or equal to 9",
"error_text_service_node" : "A Service Node key can only contain 64 chars in hex",
"auth_store_ban_timeout" : "ban_timeout",
"auth_store_banned_for" : "Banned for ",
"auth_store_banned_minutes" : " minutes",
"auth_store_banned_for" : "Banned for {mins} minutes",
"@auth_store_banned_for": { "placeholders": {"mins": {}}},
"auth_store_incorrect_password" : "Wrong PIN",
"wallet_restoration_store_incorrect_seed_length" : "Incorrect seed length",
@ -294,6 +311,7 @@
"change_language" : "Change language",
"change_language_to" : "Change language to {language}?",
"@change_language_to" : { "placeholders": { "language": {} }},
"paste" : "Paste",
"restore_from_seed_placeholder" : "Please enter or paste your seed here",
@ -302,13 +320,17 @@
"biometric_auth_reason" : "Scan your fingerprint to authenticate",
"version" : "Version {currentVersion}",
"@version" : { "placeholders": { "currentVersion": {} }},
"openalias_alert_title" : "OXEN Recipient Detected",
"openalias_alert_content" : "You will be sending funds to\n{recipient_name}",
"@openalias_alert_content" : { "placeholders": { "recipient_name": {} }},
"dangerzone": "Dangerzone",
"yes_im_sure": "Yes, I'm sure!",
"never_give_your": "NEVER give your Oxen wallet {item} to ANYONE!",
"@never_give_your" : { "placeholders": { "item": {} }},
"dangerzone_warning": "NEVER input your Oxen wallet {item} into any software or website other than the OFFICIAL Oxen wallets downloaded directly from the {app_store}, the Oxen website, or the Oxen GitHub.\nAre you sure you want to access your wallet {item}?",
"@dangerzone_warning" : { "placeholders": { "item": {}, "app_store": {} }},
"keys_title": "Keys"
}

View File

@ -20,6 +20,8 @@
"contact_name" : "Nom du contact",
"reset" : "Réinitialiser",
"save" : "Sauvegarder",
"remove_contact" : "Supprimer le Contact",
"remove_contact_confirm" : "Êtes vous sûr de vouloir supprimer le contact sélectionné?",
"authenticated" : "Authentifié",
@ -28,7 +30,7 @@
"wallet_menu" : "Menu du portefeuille",
"Blocks_remaining" : "{status} blocs restants",
"blocks_remaining" : "{status} blocs restants",
"please_try_to_connect_to_another_node" : "veuillez essayer de vous connecter à un autre node",
"oxen_hidden" : "OXEN caché",
"oxen_available_balance" : "OXEN solde disponible",
@ -44,6 +46,7 @@
"yesterday" : "hier",
"received" : "a reçu",
"sent" : "expédié",
"stake" : "Stake",
"pending" : " (en attente)",
"rescan" : "réanalyser",
"reconnect" : "se reconnecter",
@ -66,8 +69,9 @@
"amount" : "Montant: ",
"status" : "Statut: ",
"confirm" : "confirmer",
"confirm_sending" : "confirmer l'envoi",
"commit_transaction_amount_fee" : "Valider la transaction\nMontant: {amount}\nFee: {fee}",
"confirm_sending" : "Confirmer l'envoi",
"confirm_stake" : "Confirmer le Stake",
"confirm_transaction_amount_fee" : "Montant: {amount} OXEN\nFee: {fee} OXEN",
"sending" : "Envoyer",
"transaction_sent" : "Transaction envoyé!",
"send_oxen" : "Envoyer OXEN",
@ -85,6 +89,10 @@
"continue_text" : "Continuez",
"remove_wallet_confirmation": "Êtes vous sûr de vouloir supprimer ce wallet?",
"dangerzone_remove_wallet_warning": "Si vous n'avez pas sauvegardé votre phrase de récupération tous les fonds envoyés sur ce wallet seront perdus pour toujours!",
"node_new" : "Nouveau Node",
"node_address" : "L'adresse du Node",
"node_port" : "Port du Node",
@ -101,8 +109,7 @@
"delete" : "effacer",
"use" : "Basculer vers ",
"digit_pin" : "-chiffre PIN",
"use_n_digit_pin" : "Basculer vers {n}-chiffre PIN",
"share_address" : "Partager l'adresse ",
@ -118,7 +125,7 @@
"restore_description_from_backup" : "Vous pouvez restaurer l'intégralité de l'application Oxen Wallet à partir de son fichier de sauvegarde.",
"restore_seed_keys_restore" : "Restaurer depuis le Seed ou les clés",
"restore_title_from_seed" : "Restaurer à partir du Seed",
"restore_description_from_seed" : "Récupérez votre portefeuille à partir du code de combinaison de 25 ou 13 mots",
"restore_description_from_seed" : "Récupérez votre portefeuille à partir du code de combinaison de 25 mots",
"restore_title_from_keys" : "Récupération des clés",
"restore_description_from_keys" : "Restaurez votre portefeuille à partir du mnemonic généré à partir de vos clés privées",
"restore_wallet_name" : "Nom du portefeuille",
@ -251,25 +258,20 @@
"router_no_route" : "Aucun itinéraire défini pour {name}",
"error_text_account_name" : "Le nom du compte ne peut contenir que des lettres et des chiffres\net doit comporter entre 1 et 15 caractères",
"error_text_contact_name" : "Dans le nom du contact, les symboles ` , ' \" ne doivent pas être inclus\net doit comporter entre 1 et 32 caractères",
"error_text_address" : "L'adresse du portefeuille doit correspondre au type de crypto-monnaie",
"error_text_node_address" : "Veuillez saisir une adresse iPv4",
"error_text_empty": "Ne peux pas être vide",
"error_text_address" : "Adresse de portefeuille OXEN invalide!",
"error_text_node_address" : "Veuillez saisir une adresse IP",
"error_text_node_port" : "Le port du Node ne peut contenir que des nombres compris entre 0 et 65535",
"error_text_payment_id" : "L'ID de paiement ne peut contenir que 16 à 64 caractères hexadécimaux",
"error_text_oxen" : "La valeur OXEN ne peut pas dépasser le solde disponible.\nLe nombre de décimales doit être inférieur ou égal à 12",
"error_text_oxen" : "La valeur OXEN ne peut pas dépasser le solde disponible.\nLe nombre de décimales doit être inférieur ou égal à 9",
"error_text_fiat" : "La valeur du montant ne peut pas dépasser le solde disponible du compte.\nLe nombre de décimales doit être inférieur ou égal à 2",
"error_text_subaddress_name" : "Au nom de la sous-adresse, les symboles ` , ' \" ne pas être inclus\net doit comporter entre 1 et 20 caractères",
"error_text_amount" : "Le montant ne peut contenir que des nombres",
"error_text_wallet_name" : "Le nom du portefeuille ne peut contenir que des lettres et des chiffres\net doit comporter entre 1 et 15 caractères",
"error_text_keys" : "Les clés de portefeuille ne peuvent contenir que 64 caractères hexadécimaux",
"error_text_crypto_currency" : "Le nombre de décimales\nm doit être inférieur ou égal à 12.",
"error_text_crypto_currency" : "Le nombre de décimales\nm doit être inférieur ou égal à 9.",
"error_text_service_node" : "Une clé de nœud de service ne peut contenir que 64 caractères maximum",
"auth_store_ban_timeout" : "Interdire le délai d'expiration",
"auth_store_banned_for" : "Interdit pour ",
"auth_store_banned_minutes" : " Protocole",
"auth_store_banned_for" : "Interdit pendant {mins} minutes",
"auth_store_incorrect_password" : "mauvais code PIN",
"wallet_restoration_store_incorrect_seed_length" : "mauvaise longueur du Seed",

View File

@ -1,4 +1,3 @@
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:oxen_wallet/src/wallet/oxen/transaction/transaction_priority.dart';
import 'package:path_provider/path_provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
@ -32,8 +31,7 @@ import 'package:oxen_wallet/src/domain/common/default_settings_migration.dart';
import 'package:oxen_wallet/src/domain/common/fiat_currency.dart';
import 'package:oxen_wallet/src/wallet/wallet_type.dart';
import 'package:oxen_wallet/src/domain/services/wallet_service.dart';
import 'package:oxen_wallet/generated/l10n.dart';
import 'package:oxen_wallet/src/domain/common/language.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:oxen_wallet/src/stores/seed_language/seed_language_store.dart';
void main() async {
@ -57,7 +55,7 @@ void main() async {
final nodes = await Hive.openBox<Node>(Node.boxName);
final transactionDescriptions = await Hive.openBox<TransactionDescription>(
TransactionDescription.boxName,
encryptionKey: transactionDescriptionsBoxKey);
encryptionCipher: HiveAesCipher(transactionDescriptionsBoxKey));
final walletInfoSource = await Hive.openBox<WalletInfo>(WalletInfo.boxName);
final sharedPreferences = await SharedPreferences.getInstance();
@ -121,7 +119,7 @@ void main() async {
Provider(create: (_) => transactionDescriptions),
Provider(create: (_) => seedLanguageStore)
], child: OxenWalletApp()));
} catch (e) {
} catch (e, trace) {
runApp(MaterialApp(
debugShowCheckedModeBanner: true,
home: Scaffold(
@ -129,7 +127,7 @@ void main() async {
margin:
EdgeInsets.only(top: 50, left: 20, right: 20, bottom: 20),
child: Text(
'Error:\n${e.toString()}',
'Error:\n${e.toString()}\n${trace.toString()}',
style: TextStyle(fontSize: 22),
)
)
@ -139,13 +137,11 @@ void main() async {
}
Future<void> initialSetup(
{WalletListService walletListService,
SharedPreferences sharedPreferences,
Box<Node> nodes,
AuthenticationStore authStore,
int initialMigrationVersion = 1,
WalletType initialWalletType = WalletType.oxen}) async {
await walletListService.changeWalletManger(walletType: initialWalletType);
{required WalletListService walletListService,
required SharedPreferences sharedPreferences,
required Box<Node> nodes,
required AuthenticationStore authStore,
required int initialMigrationVersion}) async {
await defaultSettingsMigration(
version: initialMigrationVersion,
sharedPreferences: sharedPreferences,
@ -167,9 +163,7 @@ class OxenWalletApp extends StatelessWidget {
return ChangeNotifierProvider<ThemeChanger>(
create: (_) => ThemeChanger(
settingsStore.isDarkTheme ? Themes.darkTheme : Themes.lightTheme),
child: ChangeNotifierProvider<Language>(
create: (_) => Language(settingsStore.languageCode),
child: MaterialAppWithTheme()));
child: MaterialAppWithTheme());
}
}
@ -188,7 +182,6 @@ class MaterialAppWithTheme extends StatelessWidget {
final theme = Provider.of<ThemeChanger>(context);
final statusBarColor =
settingsStore.isDarkTheme ? Colors.black : Colors.white;
final currentLanguage = Provider.of<Language>(context);
final contacts = Provider.of<Box<Contact>>(context);
final nodes = Provider.of<Box<Node>>(context);
final transactionDescriptions =
@ -200,14 +193,8 @@ class MaterialAppWithTheme extends StatelessWidget {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: theme.getTheme(),
localizationsDelegates: [
S.delegate,
GlobalCupertinoLocalizations.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
],
supportedLocales: S.delegate.supportedLocales,
locale: Locale(currentLanguage.getCurrentLanguage()),
localizationsDelegates: AppLocalizations.localizationsDelegates,
supportedLocales: AppLocalizations.supportedLocales,
onGenerateRoute: (settings) => oxenroute.Router.generateRoute(
sharedPreferences: sharedPreferences,
walletListService: walletListService,

View File

@ -83,6 +83,7 @@ class OxenPalette {
static const Color black = Color.fromRGBO(0, 0, 0, 1.0); // #000000
// Opacity
static const Color navyWithOpacity = Color.fromRGBO(31, 28, 71, 0.8);
static const Color tealWithOpacity = Color.fromRGBO(18, 199, 186, 0.2);
static const Color lightRedWithOpacity = Color.fromRGBO(255, 122, 135, 0.5);
static const Color limeWithOpacity = Color.fromRGBO(195, 245, 58, 0.5);

View File

@ -1,9 +1,8 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:hive/hive.dart';
import 'package:oxen_wallet/generated/l10n.dart';
import 'package:oxen_wallet/routes.dart';
import 'package:oxen_wallet/l10n.dart';
// MARK: Import domains
import 'package:oxen_wallet/src/domain/common/contact.dart';
@ -40,7 +39,6 @@ import 'package:oxen_wallet/src/screens/restore/restore_wallet_options_page.dart
import 'package:oxen_wallet/src/screens/seed/create_seed_page.dart';
import 'package:oxen_wallet/src/screens/seed_language/seed_language_page.dart';
import 'package:oxen_wallet/src/screens/send/send_page.dart';
import 'package:oxen_wallet/src/screens/settings/change_language.dart';
import 'package:oxen_wallet/src/screens/settings/settings.dart';
import 'package:oxen_wallet/src/screens/setup_pin_code/setup_pin_code.dart';
import 'package:oxen_wallet/src/screens/show_keys/show_keys_page.dart';
@ -72,7 +70,7 @@ import 'package:oxen_wallet/src/stores/wallet/wallet_store.dart';
import 'package:oxen_wallet/src/stores/wallet_creation/wallet_creation_store.dart';
import 'package:oxen_wallet/src/stores/wallet_list/wallet_list_store.dart';
import 'package:oxen_wallet/src/stores/wallet_restoration/wallet_restoration_store.dart';
import 'package:oxen_wallet/src/wallet/mnemotic_item.dart';
import 'package:oxen_wallet/src/wallet/mnemonic_item.dart';
import 'package:oxen_wallet/src/wallet/oxen/account.dart';
import 'package:oxen_wallet/src/wallet/oxen/subaddress.dart';
import 'package:oxen_wallet/src/wallet/oxen/transaction/transaction_description.dart';
@ -82,19 +80,19 @@ import 'package:shared_preferences/shared_preferences.dart';
class Router {
static Route<dynamic> generateRoute(
{SharedPreferences sharedPreferences,
WalletListService walletListService,
WalletService walletService,
UserService userService,
RouteSettings settings,
PriceStore priceStore,
WalletStore walletStore,
SyncStore syncStore,
BalanceStore balanceStore,
SettingsStore settingsStore,
Box<Contact> contacts,
Box<Node> nodes,
Box<TransactionDescription> transactionDescriptions}) {
{required SharedPreferences sharedPreferences,
required WalletListService walletListService,
required WalletService walletService,
required UserService userService,
required RouteSettings settings,
required PriceStore priceStore,
required WalletStore walletStore,
required SyncStore syncStore,
required BalanceStore balanceStore,
required SettingsStore settingsStore,
required Box<Contact> contacts,
required Box<Node> nodes,
required Box<TransactionDescription> transactionDescriptions}) {
switch (settings.name) {
case Routes.welcome:
return MaterialPageRoute<void>(builder: (_) => WelcomePage());
@ -125,7 +123,7 @@ class Router {
sharedPreferences: sharedPreferences)));
case Routes.setupPin:
Function(BuildContext, String) callback;
Function(BuildContext, String)? callback;
if (settings.arguments is Function(BuildContext, String)) {
callback = settings.arguments as Function(BuildContext, String);
@ -164,7 +162,7 @@ class Router {
builder: (_) => createSeedPage(
settingsStore: settingsStore,
walletService: walletService,
callback: settings.arguments as void Function()));
callback: settings.arguments as void Function()?));
case Routes.restoreWalletFromSeed:
return MaterialPageRoute<void>(
@ -218,6 +216,7 @@ class Router {
create: (_) => SendStore(
walletService: walletService,
priceStore: priceStore,
settingsStore: settingsStore,
transactionDescriptions: transactionDescriptions)),
], child: SendPage()));
@ -324,7 +323,7 @@ class Router {
return MaterialPageRoute<String>(builder: (context) {
return Provider(
create: (_) => AccountListStore(walletService: walletService),
child: AccountPage(account: settings.arguments as Account));
child: AccountPage(account: settings.arguments as Account?));
});
case Routes.addressBook:
@ -357,12 +356,10 @@ class Router {
return MaterialPageRoute<void>(builder: (context) {
return MultiProvider(
providers: [
Provider(
create: (_) =>
AccountListStore(walletService: walletService)),
Provider(create: (_) => AccountListStore(walletService: walletService)),
Provider(create: (_) => AddressBookStore(contacts: contacts))
],
child: ContactPage(contact: settings.arguments as Contact),
child: ContactPage(contact: settings.arguments as Contact?),
);
});
@ -413,7 +410,7 @@ class Router {
authStore: authStore,
sharedPreferences: sharedPreferences,
walletListService: walletListService,
seed: settings.arguments as List<MnemoticItem>),
seed: settings.arguments as List<MnemonicItem>),
child: RestoreWalletFromSeedDetailsPage()));
case Routes.settings:
@ -434,9 +431,6 @@ class Router {
case Routes.changelog:
return MaterialPageRoute<void>(builder: (_) => ChangelogPage());
case Routes.changeLanguage:
return MaterialPageRoute<void>(builder: (_) => ChangeLanguage());
case Routes.profile:
return MaterialPageRoute<void>(builder: (_) => ProfilePage());
@ -459,15 +453,16 @@ class Router {
Provider(
create: (_) => SendStore(
walletService: walletService,
settingsStore: settingsStore,
priceStore: priceStore,
transactionDescriptions: transactionDescriptions)),
], child: NewStakePage()));
default:
return MaterialPageRoute<void>(
builder: (_) => Scaffold(
builder: (context) => Scaffold(
body: Center(
child: Text(S.current.router_no_route(settings.name))),
child: Text(tr(context).router_no_route(settings.name ?? 'null'))),
));
}
}

View File

@ -1,46 +1,41 @@
import 'package:flutter/foundation.dart';
import 'package:oxen_wallet/generated/l10n.dart';
import 'package:oxen_wallet/l10n.dart';
import 'package:oxen_wallet/src/domain/common/enumerable_item.dart';
class BalanceDisplayMode extends EnumerableItem<int> with Serializable<int> {
const BalanceDisplayMode({@required String title, @required int raw})
: super(title: title, raw: raw);
const BalanceDisplayMode({required int raw})
: super(raw: raw);
static const all = [
BalanceDisplayMode.fullBalance,
BalanceDisplayMode.availableBalance,
BalanceDisplayMode.hiddenBalance
];
static const fullBalance = BalanceDisplayMode(raw: 0, title: 'Full Balance');
static const availableBalance =
BalanceDisplayMode(raw: 1, title: 'Available Balance');
static const hiddenBalance =
BalanceDisplayMode(raw: 2, title: 'Hidden Balance');
static const fullBalance = BalanceDisplayMode(raw: 0);
static const availableBalance = BalanceDisplayMode(raw: 1);
static const hiddenBalance = BalanceDisplayMode(raw: 2);
static BalanceDisplayMode deserialize({int raw}) {
static BalanceDisplayMode deserialize({required int? raw}) {
switch (raw) {
case 0:
return fullBalance;
case 1:
return availableBalance;
case 2:
return hiddenBalance;
case 1:
default:
return null;
return availableBalance;
}
}
@override
String toString() {
String getTitle(AppLocalizations l10n) {
switch (this) {
case BalanceDisplayMode.fullBalance:
return S.current.oxen_full_balance;
case BalanceDisplayMode.availableBalance:
return S.current.oxen_available_balance;
return l10n.oxen_full_balance;
case BalanceDisplayMode.hiddenBalance:
return S.current.oxen_hidden;
return l10n.oxen_hidden;
case BalanceDisplayMode.availableBalance:
default:
return '';
return l10n.oxen_available_balance;
}
}
}

View File

@ -1,14 +1,15 @@
import 'package:flutter/services.dart';
import 'package:local_auth/local_auth.dart';
import 'package:oxen_wallet/generated/l10n.dart';
import 'package:oxen_wallet/l10n.dart';
class BiometricAuth {
Future<bool> isAuthenticated() async {
Future<bool> isAuthenticated(AppLocalizations t) async {
final _localAuth = LocalAuthentication();
try {
return await _localAuth.authenticateWithBiometrics(
localizedReason: S.current.biometric_auth_reason,
return await _localAuth.authenticate(
biometricOnly: true,
localizedReason: t.biometric_auth_reason,
useErrorDialogs: true,
stickyAuth: false);
} on PlatformException catch (e) {

View File

@ -1,9 +1,8 @@
import 'package:oxen_wallet/src/wallet/oxen/oxen_amount_format.dart';
String calculateFiatAmount({double price, int cryptoAmount}) {
if (price == null || cryptoAmount == null) {
String calculateFiatAmount({required double price, required int cryptoAmount}) {
if (price.isNaN || price <= 0.0 || cryptoAmount <= 0)
return '0.00';
}
final result = price * oxenAmountToDouble(cryptoAmount);
if (result == 0.0) {
@ -11,4 +10,4 @@ String calculateFiatAmount({double price, int cryptoAmount}) {
}
return result > 0.01 ? result.toStringAsFixed(2) : '< 0.01';
}
}

View File

@ -1,13 +1,9 @@
String calculateFiatAmountRaw({double price, double cryptoAmount}) {
if (price == null) {
return '0.00';
}
final result = price * cryptoAmount;
String calculateFiatAmountRaw({required double? price, required double cryptoAmount}) {
final result = (price ?? 0.0) * cryptoAmount;
if (result == 0.0) {
return '0.00';
}
return result > 0.01 ? result.toStringAsFixed(2) : '< 0.01';
}
}

View File

@ -1,13 +1,10 @@
import 'package:flutter/foundation.dart';
import 'package:hive/hive.dart';
import 'package:oxen_wallet/src/domain/common/crypto_currency.dart';
part 'contact.g.dart';
@HiveType(typeId: 0)
class Contact extends HiveObject {
Contact({@required this.name, @required this.address, CryptoCurrency type})
: raw = type?.raw;
Contact({required this.name, required this.address, this.raw = 0});
static const boxName = 'Contacts';
@ -17,11 +14,7 @@ class Contact extends HiveObject {
@HiveField(1)
String address;
// unused
@HiveField(2)
int raw;
CryptoCurrency get type => CryptoCurrency.deserialize(raw: raw);
void updateCryptoCurrency({@required CryptoCurrency currency}) =>
raw = currency.raw;
}

View File

@ -1,122 +0,0 @@
import 'package:oxen_wallet/src/domain/common/enumerable_item.dart';
import 'package:hive/hive.dart';
part 'crypto_currency.g.dart';
@HiveType(typeId: 0)
class CryptoCurrency extends EnumerableItem<int> with Serializable<int> {
const CryptoCurrency({final String title, final int raw})
: super(title: title, raw: raw);
static const all = [
CryptoCurrency.oxen,
CryptoCurrency.ada,
CryptoCurrency.bch,
CryptoCurrency.bnb,
CryptoCurrency.btc,
CryptoCurrency.dash,
CryptoCurrency.eos,
CryptoCurrency.eth,
CryptoCurrency.ltc,
CryptoCurrency.nano,
CryptoCurrency.trx,
CryptoCurrency.usdt,
CryptoCurrency.xlm,
CryptoCurrency.xrp,
CryptoCurrency.xmr
];
static const oxen = CryptoCurrency(title: 'OXEN', raw: 0);
static const ada = CryptoCurrency(title: 'ADA', raw: 1);
static const bch = CryptoCurrency(title: 'BCH', raw: 2);
static const bnb = CryptoCurrency(title: 'BNB', raw: 3);
static const btc = CryptoCurrency(title: 'BTC', raw: 4);
static const dash = CryptoCurrency(title: 'DASH', raw: 5);
static const eos = CryptoCurrency(title: 'EOS', raw: 6);
static const eth = CryptoCurrency(title: 'ETH', raw: 7);
static const ltc = CryptoCurrency(title: 'LTC', raw: 8);
static const nano = CryptoCurrency(title: 'NANO', raw: 9);
static const trx = CryptoCurrency(title: 'TRX', raw: 10);
static const usdt = CryptoCurrency(title: 'USDT', raw: 11);
static const xlm = CryptoCurrency(title: 'XLM', raw: 12);
static const xrp = CryptoCurrency(title: 'XRP', raw: 13);
static const xmr = CryptoCurrency(title: 'XMR', raw: 14);
static CryptoCurrency deserialize({int raw}) {
switch (raw) {
case 0:
return CryptoCurrency.oxen;
case 1:
return CryptoCurrency.ada;
case 2:
return CryptoCurrency.bch;
case 3:
return CryptoCurrency.bnb;
case 4:
return CryptoCurrency.btc;
case 5:
return CryptoCurrency.dash;
case 6:
return CryptoCurrency.eos;
case 7:
return CryptoCurrency.eth;
case 8:
return CryptoCurrency.ltc;
case 9:
return CryptoCurrency.nano;
case 10:
return CryptoCurrency.trx;
case 11:
return CryptoCurrency.usdt;
case 12:
return CryptoCurrency.xlm;
case 13:
return CryptoCurrency.xrp;
case 14:
return CryptoCurrency.xmr;
default:
return null;
}
}
static CryptoCurrency fromString(String raw) {
switch (raw.toLowerCase()) {
case 'oxen':
return CryptoCurrency.oxen;
case 'xmr':
return CryptoCurrency.xmr;
case 'ada':
return CryptoCurrency.ada;
case 'bch':
return CryptoCurrency.bch;
case 'bnb':
return CryptoCurrency.bnb;
case 'btc':
return CryptoCurrency.btc;
case 'dash':
return CryptoCurrency.dash;
case 'eos':
return CryptoCurrency.eos;
case 'eth':
return CryptoCurrency.eth;
case 'ltc':
return CryptoCurrency.ltc;
case 'nano':
return CryptoCurrency.nano;
case 'trx':
return CryptoCurrency.trx;
case 'usdt':
return CryptoCurrency.usdt;
case 'xlm':
return CryptoCurrency.xlm;
case 'xrp':
return CryptoCurrency.xrp;
default:
return null;
}
}
@override
String toString() => title;
}

View File

@ -1,4 +1,3 @@
import 'package:flutter/foundation.dart';
import 'package:hive/hive.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:oxen_wallet/src/node/node.dart';
@ -8,9 +7,9 @@ import 'package:oxen_wallet/src/node/node_list.dart';
import 'package:oxen_wallet/src/wallet/oxen/transaction/transaction_priority.dart';
Future defaultSettingsMigration(
{@required int version,
@required SharedPreferences sharedPreferences,
@required Box<Node> nodes}) async {
{required int version,
required SharedPreferences sharedPreferences,
required Box<Node> nodes}) async {
final currentVersion =
sharedPreferences.getInt('current_default_settings_migration_version') ??
0;
@ -60,13 +59,12 @@ Future defaultSettingsMigration(
'current_default_settings_migration_version', version);
}
Future<void> replaceNodesMigration({@required Box<Node> nodes}) async {
Future<void> replaceNodesMigration({required Box<Node> nodes}) async {
final replaceNodes = <String, Node>{
'public.loki.foundation:22023':
Node(uri: 'public.loki.foundation:22023'),
'nodes.hashvault.pro:22023':
Node(uri: 'nodes.hashvault.pro:22023'),
'node.loki-pool.com:18081': Node(uri: 'node.loki-pool.com:18081')
/*
'OLD-public.loki.foundation:22023':
Node(uri: 'NEW-public.loki.foundation:22023'),
*/
};
nodes.values.forEach((Node node) async {
@ -82,42 +80,39 @@ Future<void> replaceNodesMigration({@required Box<Node> nodes}) async {
}
Future<void> changeCurrentNodeToDefault(
{@required SharedPreferences sharedPreferences,
@required Box<Node> nodes}) async {
final timeZone = DateTime.now().timeZoneOffset.inHours;
var nodeUri = '';
{required SharedPreferences sharedPreferences,
required Box<Node> nodes}) async {
late String nodeUri;
if (timeZone >= 1) { // Eurasia
final timeZone = DateTime.now().timeZoneOffset.inHours;
if (timeZone >= -1) { // Europe, Africa, Asia, Australia -- prefer OPTF EU public server
nodeUri = 'public.loki.foundation:22023';
} else if (timeZone <= -4) { // America
} else { // Americas -- prefer OPTF NA public server
nodeUri = 'freyr.imaginary.stream:22023';
}
final node = nodes.values.firstWhere((Node node) => node.uri == nodeUri) ??
nodes.values.first;
final nodeId = node != null ? node.key as int : 0; // 0 - England
final node = nodes.values.firstWhere((Node node) => node.uri == nodeUri,
orElse: () => nodes.values.first);
await sharedPreferences.setInt('current_node_id', nodeId);
await sharedPreferences.setInt('current_node_id', node.key as int);
}
Future<void> replaceDefaultNode(
{@required SharedPreferences sharedPreferences,
@required Box<Node> nodes}) async {
{required SharedPreferences sharedPreferences,
required Box<Node> nodes}) async {
const nodesForReplace = <String>[
/*
'public.loki.foundation:22023',
'nodes.hashvault.pro:22023',
'node.loki-pool.com:18081'
*/
];
final currentNodeId = sharedPreferences.getInt('current_node_id');
final currentNode =
nodes.values.firstWhere((Node node) => node.key == currentNodeId);
final needToReplace =
currentNode == null ? true : nodesForReplace.contains(currentNode.uri);
if (!needToReplace) {
return;
Node? currentNode;
try {
currentNode =
nodes.values.firstWhere((Node node) => node.key == currentNodeId);
} catch (_) {}
if (currentNode == null || nodesForReplace.contains(currentNode.uri)) {
await changeCurrentNodeToDefault(
sharedPreferences: sharedPreferences, nodes: nodes);
}
await changeCurrentNodeToDefault(
sharedPreferences: sharedPreferences, nodes: nodes);
}

View File

@ -1,7 +1,7 @@
import 'package:encrypt/encrypt.dart';
import 'package:oxen_wallet/.secrets.g.dart' as secrets;
String encrypt({String source, String key, int keyLength = 16}) {
String encrypt({required String source, required String key, int keyLength = 16}) {
final _key = Key.fromUtf8(key);
final iv = IV.fromLength(keyLength);
final encrypter = Encrypter(AES(_key));
@ -10,7 +10,7 @@ String encrypt({String source, String key, int keyLength = 16}) {
return encrypted.base64;
}
String decrypt({String source, String key, int keyLength = 16}) {
String decrypt({required String source, required String key, int keyLength = 16}) {
final _key = Key.fromUtf8(key);
final iv = IV.fromLength(keyLength);
final encrypter = Encrypter(AES(_key));
@ -19,26 +19,26 @@ String decrypt({String source, String key, int keyLength = 16}) {
return decrypted;
}
String encodedPinCode({String pin}) {
String encodedPinCode({required String pin}) {
final source = '${secrets.salt}$pin';
return encrypt(source: source, key: secrets.key);
}
String decodedPinCode({String pin}) {
String decodedPinCode({required String pin}) {
final decrypted = decrypt(source: pin, key: secrets.key);
return decrypted.substring(secrets.key.length, decrypted.length);
}
String encodeWalletPassword({String password}) {
String encodeWalletPassword({required String password}) {
final source = password;
final _key = secrets.shortKey + secrets.walletSalt;
return encrypt(source: source, key: _key);
}
String decodeWalletPassword({String password}) {
String decodeWalletPassword({required String password}) {
final source = password;
final _key = secrets.shortKey + secrets.walletSalt;

View File

@ -1,17 +1,15 @@
import 'package:flutter/foundation.dart';
import 'package:oxen_wallet/l10n.dart';
abstract class EnumerableItem<T> {
const EnumerableItem({@required this.title, @required this.raw});
const EnumerableItem({required this.raw});
final T raw;
final String title;
@override
String toString() => title;
String getTitle(AppLocalizations t);
}
mixin Serializable<T> on EnumerableItem<T> {
static Serializable deserialize<T>({T raw}) => null;
static Serializable? deserialize<T>({required T raw}) => null;
T serialize() => raw;
}

View File

@ -1,12 +1,11 @@
import 'dart:convert';
import 'package:oxen_wallet/src/domain/common/crypto_currency.dart';
import 'package:oxen_wallet/src/domain/common/fiat_currency.dart';
import 'package:http/http.dart';
const fiatApiAuthority = 'oxen.observer';
Future<double> fetchPriceFor({CryptoCurrency crypto, FiatCurrency fiat}) async {
Future<double> fetchPriceFor({required FiatCurrency fiat}) async {
var price = 0.0;
try {

View File

@ -1,11 +1,18 @@
import 'package:oxen_wallet/src/domain/common/enumerable_item.dart';
import 'package:oxen_wallet/l10n.dart';
class FiatCurrency extends EnumerableItem<String> with Serializable<String> {
const FiatCurrency({String symbol}) : super(title: symbol, raw: symbol);
const FiatCurrency({required String? symbol}) : super(raw: symbol ?? 'USD');
@override
bool operator ==(Object other) => other is FiatCurrency && other.raw == raw;
@override
String toString() => raw;
@override
String getTitle(AppLocalizations l10n) => raw;
static const all = [
FiatCurrency.aud,
FiatCurrency.bgn,
@ -77,5 +84,5 @@ class FiatCurrency extends EnumerableItem<String> with Serializable<String> {
static const vef = FiatCurrency(symbol: 'VEF');
@override
int get hashCode => raw.hashCode ^ title.hashCode;
int get hashCode => raw.hashCode;
}

View File

@ -2,7 +2,7 @@ import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:hive/hive.dart';
Future<List<int>> getEncryptionKey(
{String forKey, FlutterSecureStorage secureStorage}) async {
{required String forKey, required FlutterSecureStorage secureStorage}) async {
final keyFromStorage = await secureStorage.read(key: forKey);
List<int> key;

View File

@ -1,39 +0,0 @@
import 'package:flutter/material.dart';
import 'package:devicelocale/devicelocale.dart';
import 'package:intl/intl.dart';
const Map<String, String> languages = {
'en': 'English',
'de': 'Deutsch (German)',
'fr': 'Français (French)',
// 'es': 'Español (Spanish)',
// 'hi': 'हिंदी (Hindi)',
// 'ja': '日本 (Japanese)',
// 'ko': '한국어 (Korean)',
// 'nl': 'Nederlands (Dutch)',
// 'pl': 'Polski (Polish)',
// 'pt': 'Português (Portuguese)',
// 'ru': 'Русский (Russian)',
// 'uk': 'Українська (Ukrainian)',
// 'zh': '中文 (Chinese)'
};
class Language with ChangeNotifier {
Language(this._currentLanguage);
String _currentLanguage;
String getCurrentLanguage() => _currentLanguage;
void setCurrentLanguage(String language) {
_currentLanguage = language;
notifyListeners();
}
static Future<String> localeDetection() async {
var locale = await Devicelocale.currentLocale;
locale = Intl.shortLocale(locale);
return languages.keys.contains(locale) ? locale : 'en';
}
}

View File

@ -2,7 +2,7 @@ import 'package:basic_utils/basic_utils.dart';
class OpenaliasRecord {
OpenaliasRecord({this.address, this.name});
OpenaliasRecord({required this.address, required this.name});
final String name;
final String address;

View File

@ -1,15 +1,31 @@
import 'package:barcode_scan/barcode_scan.dart';
import 'package:barcode_scan2/barcode_scan2.dart';
var isQrScannerShown = false;
Future<String> presentQRScanner() async {
class QRScanException implements Exception {
QRScanException(this.message);
String message;
@override
String toString() => message;
}
/// Shows the QR scanner to the user; this sets the future once the user either scans a QR code (we
/// return the string value), cancels (we return null), or an error occurs (we throw a
/// QRScanException).
Future<String?> presentQRScanner() async {
isQrScannerShown = true;
try {
final result = await BarcodeScanner.scan();
isQrScannerShown = false;
return result;
if (result.type == ResultType.Error)
throw QRScanException(result.rawContent);
if (result.type == ResultType.Cancelled)
return null;
return result.rawContent;
} catch (e) {
isQrScannerShown = false;
rethrow;
throw QRScanException(e.toString());
}
}

View File

@ -3,7 +3,7 @@ enum SecretStoreKey { moneroWalletPassword, pinCodePassword }
const moneroWalletPassword = 'MONERO_WALLET_PASSWORD';
const pinCodePassword = 'PIN_CODE_PASSWORD';
String generateStoreKeyFor({SecretStoreKey key, String walletName = '',}) {
String generateStoreKeyFor({required SecretStoreKey key, String walletName = '',}) {
var _key = '';
switch (key) {
@ -19,4 +19,4 @@ String generateStoreKeyFor({SecretStoreKey key, String walletName = '',}) {
}
return _key;
}
}

View File

@ -4,7 +4,7 @@ import 'package:oxen_wallet/src/domain/common/secret_store_key.dart';
import 'package:oxen_wallet/src/domain/common/encrypt.dart';
class UserService {
UserService({this.sharedPreferences, this.secureStorage});
UserService({required this.sharedPreferences, required this.secureStorage});
final FlutterSecureStorage secureStorage;
final SharedPreferences sharedPreferences;
@ -24,21 +24,24 @@ class UserService {
Future<bool> canAuthenticate() async {
final key = generateStoreKeyFor(key: SecretStoreKey.pinCodePassword);
final sharedPreferences = await SharedPreferences.getInstance();
final walletName = sharedPreferences.getString('current_wallet_name') ?? '';
var password = '';
final walletName = sharedPreferences.getString('current_wallet_name');
if (!(walletName?.isNotEmpty ?? false))
return false;
String? password;
try {
password = await secureStorage.read(key: key);
} catch (e) {
print(e);
}
return walletName.isNotEmpty && password.isNotEmpty;
return password?.isNotEmpty ?? false;
}
Future<bool> authenticate(String pin) async {
final key = generateStoreKeyFor(key: SecretStoreKey.pinCodePassword);
final encodedPin = await secureStorage.read(key: key);
if (encodedPin == null)
return false;
final decodedPin = decodedPinCode(pin: encodedPin);
return decodedPin == pin;

View File

@ -1,6 +1,5 @@
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:hive/hive.dart';
import 'package:oxen_wallet/src/domain/common/encrypt.dart';
@ -10,7 +9,6 @@ import 'package:oxen_wallet/src/wallet/oxen/oxen_wallets_manager.dart';
import 'package:oxen_wallet/src/wallet/wallet.dart';
import 'package:oxen_wallet/src/wallet/wallet_description.dart';
import 'package:oxen_wallet/src/wallet/wallet_info.dart';
import 'package:oxen_wallet/src/wallet/wallet_type.dart';
import 'package:oxen_wallet/src/wallet/wallets_manager.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:uuid/uuid.dart';
@ -26,11 +24,12 @@ class WalletIsExistException implements Exception {
class WalletListService {
WalletListService(
{this.secureStorage,
this.walletInfoSource,
this.walletsManager,
@required this.walletService,
@required this.sharedPreferences});
{required this.secureStorage,
required this.walletInfoSource,
WalletsManager? walletsManager,
required this.walletService,
required this.sharedPreferences})
: walletsManager = walletsManager ?? OxenWalletsManager(walletInfoSource: walletInfoSource);
final FlutterSecureStorage secureStorage;
final WalletService walletService;
@ -107,18 +106,6 @@ class WalletListService {
await onWalletChange(wallet);
}
Future changeWalletManger({WalletType walletType}) async {
switch (walletType) {
case WalletType.oxen:
walletsManager = OxenWalletsManager(walletInfoSource: walletInfoSource);
break;
case WalletType.monero:
case WalletType.none:
walletsManager = null;
break;
}
}
Future onWalletChange(Wallet wallet) async {
walletService.currentWallet = wallet;
final walletName = await wallet.getName();
@ -128,15 +115,15 @@ class WalletListService {
Future remove(WalletDescription wallet) async =>
await walletsManager.remove(wallet);
Future<String> getWalletPassword({String walletName}) async {
Future<String> getWalletPassword({required String walletName}) async {
final key = generateStoreKeyFor(
key: SecretStoreKey.moneroWalletPassword, walletName: walletName);
final encodedPassword = await secureStorage.read(key: key);
return decodeWalletPassword(password: encodedPassword);
return decodeWalletPassword(password: encodedPassword!);
}
Future saveWalletPassword({String walletName, String password}) async {
Future saveWalletPassword({required String walletName, required String password}) async {
final key = generateStoreKeyFor(
key: SecretStoreKey.moneroWalletPassword, walletName: walletName);
final encodedPassword = encodeWalletPassword(password: password);

View File

@ -2,7 +2,6 @@ import 'package:oxen_wallet/src/node/node.dart';
import 'package:oxen_wallet/src/node/sync_status.dart';
import 'package:oxen_wallet/src/wallet/balance.dart';
import 'package:oxen_wallet/src/wallet/transaction/pending_transaction.dart';
import 'package:oxen_wallet/src/wallet/transaction/transaction_creation_credentials.dart';
import 'package:oxen_wallet/src/wallet/transaction/transaction_history.dart';
import 'package:oxen_wallet/src/wallet/wallet.dart';
import 'package:oxen_wallet/src/wallet/wallet_description.dart';
@ -10,130 +9,132 @@ import 'package:oxen_wallet/src/wallet/wallet_type.dart';
import 'package:rxdart/rxdart.dart';
class WalletService extends Wallet {
WalletService() {
_currentWallet = null;
walletType = WalletType.none;
_syncStatus = BehaviorSubject<SyncStatus>();
_onBalanceChange = BehaviorSubject<Balance>();
WalletService() :
_currentWallet = null,
_syncStatus = BehaviorSubject<SyncStatus>(),
_onBalanceChange = BehaviorSubject<Balance>(),
_onWalletChanged = BehaviorSubject<Wallet>();
}
@override
Observable<Balance> get onBalanceChange => _onBalanceChange.stream;
Stream<Balance> get onBalanceChange => _onBalanceChange.stream;
@override
Observable<SyncStatus> get syncStatus => _syncStatus.stream;
Stream<SyncStatus> get syncStatus => _syncStatus.stream;
@override
Observable<String> get onAddressChange => _currentWallet.onAddressChange;
Stream<String> get onAddressChange => _currentWallet!.onAddressChange;
@override
Observable<String> get onNameChange => _currentWallet.onNameChange;
Stream<String> get onNameChange => _currentWallet!.onNameChange;
@override
String get address => _currentWallet.address;
String get address => _currentWallet!.address;
@override
String get name => _currentWallet.name;
String get name => _currentWallet!.name;
@override
WalletType get walletType => _currentWallet.walletType;
WalletType get walletType => _currentWallet?.walletType ?? WalletType.none;
Observable<Wallet> get onWalletChange => _onWalletChanged.stream;
Stream<Wallet> get onWalletChange => _onWalletChanged.stream;
SyncStatus get syncStatusValue => _syncStatus.value;
Wallet get currentWallet => _currentWallet;
Wallet? get currentWallet => _currentWallet;
set currentWallet(Wallet wallet) {
set currentWallet(Wallet? wallet) {
_currentWallet = wallet;
if (wallet == null) {
return;
}
_currentWallet.onBalanceChange
_currentWallet!.onBalanceChange
.listen((wallet) => _onBalanceChange.add(wallet));
_currentWallet.syncStatus.listen((status) => _syncStatus.add(status));
_currentWallet!.syncStatus.listen((status) => _syncStatus.add(status));
_onWalletChanged.add(wallet);
final type = wallet.getType();
final type = wallet.walletType;
wallet.getName().then(
(name) => description = WalletDescription(name: name, type: type));
}
BehaviorSubject<Wallet> _onWalletChanged;
BehaviorSubject<Balance> _onBalanceChange;
BehaviorSubject<SyncStatus> _syncStatus;
Wallet _currentWallet;
final BehaviorSubject<Wallet> _onWalletChanged;
final BehaviorSubject<Balance> _onBalanceChange;
final BehaviorSubject<SyncStatus> _syncStatus;
Wallet? _currentWallet;
WalletDescription description;
WalletDescription? description;
@override
WalletType getType() => WalletType.monero;
Future<String> getFilename() => _currentWallet!.getFilename();
@override
Future<String> getFilename() => _currentWallet.getFilename();
Future<String> getName() => _currentWallet!.getName();
@override
Future<String> getName() => _currentWallet.getName();
Future<String> getAddress() => _currentWallet!.getAddress();
@override
Future<String> getAddress() => _currentWallet.getAddress();
Future<String> getSeed() => _currentWallet!.getSeed();
@override
Future<String> getSeed() => _currentWallet.getSeed();
Future<Map<String, String>> getKeys() => _currentWallet!.getKeys();
@override
Future<Map<String, String>> getKeys() => _currentWallet.getKeys();
Future<int> getFullBalance() => _currentWallet!.getFullBalance();
@override
Future<int> getFullBalance() => _currentWallet.getFullBalance();
Future<int> getUnlockedBalance() => _currentWallet!.getUnlockedBalance();
@override
Future<int> getUnlockedBalance() => _currentWallet.getUnlockedBalance();
int getCurrentHeight() => _currentWallet!.getCurrentHeight();
@override
int getCurrentHeight() => _currentWallet.getCurrentHeight();
bool isRefreshing() => currentWallet!.isRefreshing();
@override
bool isRefreshing() => currentWallet.isRefreshing();
Future<int> getNodeHeight() => _currentWallet!.getNodeHeight();
@override
Future<int> getNodeHeight() => _currentWallet.getNodeHeight();
Future<bool> isConnected() => _currentWallet!.isConnected();
@override
Future<bool> isConnected() => _currentWallet.isConnected();
Future close() => _currentWallet!.close();
@override
Future close() => _currentWallet.close();
Future<void> connectToNode(
{required Node? node, bool useSSL = false, bool isLightWallet = false}) async {
if (node == null)
return;
@override
Future connectToNode(
{Node node, bool useSSL = false, bool isLightWallet = false}) =>
_currentWallet.connectToNode(
await _currentWallet!.connectToNode(
node: node, useSSL: useSSL, isLightWallet: isLightWallet);
}
@override
Future startSync() => _currentWallet.startSync();
Future startSync() => _currentWallet!.startSync();
@override
TransactionHistory getHistory() => _currentWallet.getHistory();
TransactionHistory getHistory() => _currentWallet!.getHistory();
@override
Future<PendingTransaction> createStake(
TransactionCreationCredentials credentials) =>
_currentWallet.createStake(credentials);
Future<PendingTransaction> createStake({
required String snPubkey,
required String? amount})
=> _currentWallet!.createStake(snPubkey: snPubkey, amount: amount);
@override
Future<PendingTransaction> createTransaction(
TransactionCreationCredentials credentials) =>
_currentWallet.createTransaction(credentials);
Future<PendingTransaction> createTransaction({
required String recipient,
required String? amount,
OxenTransactionPriority priority = OxenTransactionPriority.blink})
=> _currentWallet!.createTransaction(recipient: recipient, amount: amount, priority: priority);
@override
Future updateInfo() async => _currentWallet.updateInfo();
Future updateInfo() async => _currentWallet!.updateInfo();
@override
Future rescan({int restoreHeight = 0}) async =>
_currentWallet.rescan(restoreHeight: restoreHeight);
_currentWallet!.rescan(restoreHeight: restoreHeight);
}

View File

@ -1,96 +0,0 @@
import 'dart:convert';
import 'package:dio/dio.dart' as __dio;
import 'package:crypto/crypto.dart' as crypto;
import 'dart:math' as math;
class DigestRequest {
final md5 = crypto.md5;
String generateCnonce() {
final rnd = math.Random.secure();
final values = List<int>.generate(32, (i) => rnd.nextInt(256));
return base64Url.encode(values).substring(0, 8);
}
String generateHA1({String realm, String username, String password}) {
final ha1CredentialsData =
Utf8Encoder().convert('$username:$realm:$password');
final ha1 = md5.convert(ha1CredentialsData).toString();
return ha1;
}
String generateHA2({String method, String uri}) {
final ha2Data = Utf8Encoder().convert('$method:$uri');
final ha2 = md5.convert(ha2Data).toString();
return ha2;
}
String generateResponseString(
{String ha1,
String ha2,
String nonce,
String nonceCount,
String cnonce,
String qop}) {
final responseData =
Utf8Encoder().convert('$ha1:$nonce:$nonceCount:$cnonce:$qop:$ha2');
final response = md5.convert(responseData).toString();
return response;
}
Map<String, String> parsetAuthorizationHeader({String source}) {
final authHeaderParts =
source.substring(7).split(',').map((item) => item.trim());
final authenticate = <String, String>{};
for (final part in authHeaderParts) {
final kv = part.split('=');
authenticate[kv[0]] =
kv.getRange(1, kv.length).join('=').replaceAll('"', '');
}
return authenticate;
}
Future<__dio.Response> request(
{String uri, String login, String password, Map<String, dynamic> requestBody}) async {
const path = '/json_rpc';
const method = 'POST';
final url = Uri.http(uri, path);
final dio = __dio.Dio();
final headers = {'Content-type': 'application/json'};
final body =
json.encode(requestBody);
final credentialsResponse = await dio.post<Object>(url.toString(),
options: __dio.Options(headers: headers, validateStatus: (_) => true));
final authenticate = parsetAuthorizationHeader(
source: credentialsResponse.headers['www-authenticate'].first);
final qop = authenticate['qop'];
final algorithm = 'MD5';
final realm = 'monero-rpc';
final nonce = authenticate['nonce'];
final cnonce = generateCnonce();
final nonceCount = '00000001';
final ha1 = generateHA1(realm: realm, username: login, password: password);
final ha2 = generateHA2(method: method, uri: path);
final response = generateResponseString(
ha1: ha1,
ha2: ha2,
nonce: nonce,
nonceCount: nonceCount,
cnonce: cnonce,
qop: qop);
final authorizationHeaders = {
'Content-type': 'application/json',
'Authorization':
'Digest username="$login",realm="$realm",nonce="$nonce",uri="$path",algorithm="$algorithm",qop=$qop,nc=$nonceCount,cnonce="$cnonce",response="$response"'
};
return await dio.post<Object>(url.toString(),
options: __dio.Options(headers: authorizationHeaders), data: body);
}
}

View File

@ -1,20 +1,18 @@
import 'dart:convert';
import 'package:flutter/foundation.dart';
import 'package:hive/hive.dart';
import 'package:http/http.dart' as http;
import 'package:oxen_wallet/src/node/digest_request.dart';
part 'node.g.dart';
@HiveType(typeId: 1)
class Node extends HiveObject {
Node({@required this.uri, this.login, this.password});
Node({required this.uri, this.login, this.password});
Node.fromMap(Map map)
: uri = (map['uri'] ?? '') as String,
login = map['login'] as String,
password = map['password'] as String;
login = map['login'] as String?,
password = map['password'] as String?;
static const boxName = 'Nodes';
@ -22,10 +20,10 @@ class Node extends HiveObject {
String uri;
@HiveField(1)
String login;
String? login;
@HiveField(2)
String password;
String? password;
Future<bool> isOnline() async {
final resBody = await sendRPCRequest('get_info');
@ -33,19 +31,21 @@ class Node extends HiveObject {
}
Future<Map<String, dynamic>> sendRPCRequest(String method,
{Map params}) async {
{Map? params}) async {
Map<String, dynamic> resultBody;
final requestBody = params != null
? {'jsonrpc': '2.0', 'id': '0', 'method': method, 'params': params}
: {'jsonrpc': '2.0', 'id': '0', 'method': method};
// Disable: the auth code was removed as it only supported Digest-MD5 auth, which is insecure and deprecated.
/*
if (login != null && password != null) {
final digestRequest = DigestRequest();
final response = await digestRequest.request(
uri: uri, login: login, password: password, requestBody: requestBody);
uri: uri, login: login!, password: password!, requestBody: requestBody);
resultBody = response.data as Map<String, dynamic>;
} else {
} else */ {
final url = Uri.http(uri, '/json_rpc');
final headers = {'Content-type': 'application/json'};
final body = json.encode(requestBody);

View File

@ -10,13 +10,12 @@ Future<List<Node>> loadDefaultNodes() async {
final nodesRaw = await rootBundle.loadString('assets/$nodeListFileName');
final nodes = loadYaml(nodesRaw) as YamlList;
return nodes.map((dynamic raw) {
if (raw is Map) {
return Node.fromMap(raw);
}
return null;
}).toList();
final n = <Node>[];
nodes.forEach((dynamic raw) {
if (raw is Map)
n.add(Node.fromMap(raw));
});
return n;
}
Future resetToDefault(Box<Node> nodeSource) async {

View File

@ -1,11 +1,11 @@
import 'package:oxen_wallet/generated/l10n.dart';
import 'package:oxen_wallet/l10n.dart';
abstract class SyncStatus {
const SyncStatus();
double progress();
String title();
String title(AppLocalizations t);
}
class SyncingSyncStatus extends SyncStatus {
@ -18,7 +18,7 @@ class SyncingSyncStatus extends SyncStatus {
double progress() => ptc;
@override
String title() => S.current.Blocks_remaining('$blocksLeft');
String title(AppLocalizations t) => t.blocks_remaining('$blocksLeft');
@override
String toString() => '$blocksLeft';
@ -29,7 +29,7 @@ class SyncedSyncStatus extends SyncStatus {
double progress() => 1.0;
@override
String title() => S.current.sync_status_synchronized;
String title(AppLocalizations t) => t.sync_status_synchronized;
}
class NotConnectedSyncStatus extends SyncStatus {
@ -39,7 +39,7 @@ class NotConnectedSyncStatus extends SyncStatus {
double progress() => 0.0;
@override
String title() => S.current.sync_status_not_connected;
String title(AppLocalizations t) => t.sync_status_not_connected;
}
class StartingSyncStatus extends SyncStatus {
@ -47,7 +47,7 @@ class StartingSyncStatus extends SyncStatus {
double progress() => 0.0;
@override
String title() => S.current.sync_status_starting_sync;
String title(AppLocalizations t) => t.sync_status_starting_sync;
}
class FailedSyncStatus extends SyncStatus {
@ -55,7 +55,7 @@ class FailedSyncStatus extends SyncStatus {
double progress() => 1.0;
@override
String title() => S.current.sync_status_failed_connect;
String title(AppLocalizations t) => t.sync_status_failed_connect;
}
class ConnectingSyncStatus extends SyncStatus {
@ -63,7 +63,7 @@ class ConnectingSyncStatus extends SyncStatus {
double progress() => 0.0;
@override
String title() => S.current.sync_status_connecting;
String title(AppLocalizations t) => t.sync_status_connecting;
}
class ConnectedSyncStatus extends SyncStatus {
@ -71,5 +71,5 @@ class ConnectedSyncStatus extends SyncStatus {
double progress() => 0.0;
@override
String title() => S.current.sync_status_connected;
String title(AppLocalizations t) => t.sync_status_connected;
}

View File

@ -1,5 +1,4 @@
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:mobx/mobx.dart';
import 'package:oxen_wallet/src/node/node.dart';
import 'package:oxen_wallet/src/node/sync_status.dart';
@ -12,19 +11,19 @@ import 'package:oxen_wallet/src/stores/price/price_store.dart';
import 'package:oxen_wallet/src/stores/authentication/authentication_store.dart';
import 'package:oxen_wallet/src/stores/login/login_store.dart';
Timer _reconnectionTimer;
ReactionDisposer _connectToNodeDisposer;
ReactionDisposer _onSyncStatusChangeDisposer;
ReactionDisposer _onCurrentWalletChangeDisposer;
Timer? _reconnectionTimer;
ReactionDisposer? _connectToNodeDisposer;
ReactionDisposer? _onSyncStatusChangeDisposer;
ReactionDisposer? _onCurrentWalletChangeDisposer;
void setReactions(
{@required SettingsStore settingsStore,
@required PriceStore priceStore,
@required SyncStore syncStore,
@required WalletStore walletStore,
@required WalletService walletService,
@required AuthenticationStore authenticationStore,
@required LoginStore loginStore}) {
{required SettingsStore settingsStore,
required PriceStore priceStore,
required SyncStore syncStore,
required WalletStore walletStore,
required WalletService walletService,
required AuthenticationStore authenticationStore,
required LoginStore loginStore}) {
connectToNode(settingsStore: settingsStore, walletStore: walletStore);
onSyncStatusChange(
syncStore: syncStore,
@ -42,17 +41,17 @@ void setReactions(
});
}
void connectToNode({SettingsStore settingsStore, WalletStore walletStore}) {
void connectToNode({required SettingsStore settingsStore, required WalletStore walletStore}) {
_connectToNodeDisposer?.call();
_connectToNodeDisposer = reaction((_) => settingsStore.node,
(Node node) async => await walletStore.connectToNode(node: node));
(Node? node) async => await walletStore.connectToNode(node: node));
}
void onCurrentWalletChange(
{WalletStore walletStore,
SettingsStore settingsStore,
PriceStore priceStore}) {
{required WalletStore walletStore,
required SettingsStore settingsStore,
required PriceStore priceStore}) {
_onCurrentWalletChangeDisposer?.call();
reaction((_) => walletStore.name, (String _) {
@ -62,9 +61,9 @@ void onCurrentWalletChange(
}
void onSyncStatusChange(
{SyncStore syncStore,
WalletStore walletStore,
SettingsStore settingsStore}) {
{required SyncStore syncStore,
required WalletStore walletStore,
required SettingsStore settingsStore}) {
_onSyncStatusChangeDisposer?.call();
reaction((_) => syncStore.status, (SyncStatus status) async {
@ -79,7 +78,7 @@ void onSyncStatusChange(
});
}
void startReconnectionObserver({SyncStore syncStore, WalletStore walletStore}) {
void startReconnectionObserver({required SyncStore syncStore, required WalletStore walletStore}) {
_reconnectionTimer?.cancel();
_reconnectionTimer = Timer.periodic(Duration(seconds: 1060), (_) async {
try {

View File

@ -1,18 +1,17 @@
import 'package:provider/provider.dart';
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:flutter_slidable/flutter_slidable.dart';
import 'package:oxen_wallet/palette.dart';
import 'package:oxen_wallet/routes.dart';
import 'package:oxen_wallet/generated/l10n.dart';
import 'package:oxen_wallet/l10n.dart';
import 'package:oxen_wallet/src/stores/account_list/account_list_store.dart';
import 'package:oxen_wallet/src/stores/wallet/wallet_store.dart';
import 'package:oxen_wallet/src/screens/base_page.dart';
class AccountListPage extends BasePage {
@override
String get title => S.current.accounts;
String getTitle(AppLocalizations t) => t.accounts;
@override
Widget trailing(BuildContext context) {
@ -56,7 +55,7 @@ class AccountListPage extends BasePage {
child: Observer(builder: (_) {
final accounts = accountListStore.accounts;
return ListView.builder(
itemCount: accounts == null ? 0 : accounts.length,
itemCount: accounts.length,
itemBuilder: (BuildContext context, int index) {
final account = accounts[index];
@ -65,7 +64,24 @@ class AccountListPage extends BasePage {
return Slidable(
key: Key(account.id.toString()),
actionPane: SlidableDrawerActionPane(),
endActionPane: ActionPane(
motion: const DrawerMotion(),
children: [
SlidableAction(
label: tr(context).edit,
backgroundColor: Colors.blue,
icon: Icons.edit,
onPressed: (context) async {
await Navigator.of(context).pushNamed(
Routes.accountCreation,
arguments: account);
// await accountListStore.updateAccountList().then((_) {
// if (isCurrent) walletStore.setAccount(accountListStore.accounts[index]);
// });
},
)
],
),
child: Container(
color: isCurrent ? currentColor : notCurrentColor,
child: Column(
@ -78,7 +94,7 @@ class AccountListPage extends BasePage {
color: Theme.of(context)
.primaryTextTheme
.headline5
.color),
?.color),
),
onTap: () {
if (isCurrent) return;
@ -94,21 +110,6 @@ class AccountListPage extends BasePage {
],
),
),
secondaryActions: <Widget>[
IconSlideAction(
caption: S.of(context).edit,
color: Colors.blue,
icon: Icons.edit,
onTap: () async {
await Navigator.of(context).pushNamed(
Routes.accountCreation,
arguments: account);
// await accountListStore.updateAccountList().then((_) {
// if (isCurrent) walletStore.setAccount(accountListStore.accounts[index]);
// });
},
)
],
);
});
});

View File

@ -1,7 +1,6 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:oxen_wallet/generated/l10n.dart';
import 'package:oxen_wallet/l10n.dart';
import 'package:oxen_wallet/src/screens/base_page.dart';
import 'package:oxen_wallet/src/stores/account_list/account_list_store.dart';
import 'package:oxen_wallet/src/wallet/oxen/account.dart';
@ -13,10 +12,10 @@ import 'package:provider/provider.dart';
class AccountPage extends BasePage {
AccountPage({this.account});
final Account account;
final Account? account;
@override
String get title => 'Account';
String getTitle(AppLocalizations t) => t.account;
@override
Widget body(BuildContext context) => AccountForm(account);
@ -25,7 +24,7 @@ class AccountPage extends BasePage {
class AccountForm extends StatefulWidget {
AccountForm(this.account);
final Account account;
final Account? account;
@override
AccountFormState createState() => AccountFormState();
@ -37,7 +36,7 @@ class AccountFormState extends State<AccountForm> {
@override
void initState() {
if (widget.account != null) _textController.text = widget.account.label;
if (widget.account != null) _textController.text = widget.account!.label;
super.initState();
}
@ -60,10 +59,10 @@ class AccountFormState extends State<AccountForm> {
children: <Widget>[
Center(
child: OxenTextField(
hintText: S.of(context).account,
hintText: tr(context).account,
controller: _textController,
validator: (value) {
accountListStore.validateAccountName(value);
accountListStore.validateAccountName(value ?? '', tr(context));
return accountListStore.errorMessage;
},
),
@ -74,24 +73,24 @@ class AccountFormState extends State<AccountForm> {
bottomSection: Observer(
builder: (_) => LoadingPrimaryButton(
onPressed: () async {
if (!_formKey.currentState.validate()) {
if (!(_formKey.currentState?.validate() ?? false)) {
return;
}
if (widget.account != null) {
await accountListStore.renameAccount(
index: widget.account.id, label: _textController.text);
index: widget.account!.id, label: _textController.text);
} else {
await accountListStore.addAccount(
label: _textController.text);
}
Navigator.of(context).pop(_textController.text);
},
text: widget.account != null ? 'Rename' : S.of(context).add,
text: widget.account != null ? 'Rename' : tr(context).add,
color:
Theme.of(context).primaryTextTheme.button.backgroundColor,
Theme.of(context).primaryTextTheme.button?.backgroundColor,
borderColor:
Theme.of(context).primaryTextTheme.button.decorationColor,
Theme.of(context).primaryTextTheme.button?.decorationColor,
isLoading: accountListStore.isAccountCreating,
)),
);

View File

@ -3,10 +3,9 @@ import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:flutter_slidable/flutter_slidable.dart';
import 'package:oxen_wallet/generated/l10n.dart';
import 'package:oxen_wallet/l10n.dart';
import 'package:oxen_wallet/palette.dart';
import 'package:oxen_wallet/routes.dart';
import 'package:oxen_wallet/src/domain/common/crypto_currency.dart';
import 'package:oxen_wallet/src/screens/base_page.dart';
import 'package:oxen_wallet/src/stores/address_book/address_book_store.dart';
import 'package:oxen_wallet/src/widgets/oxen_dialog.dart';
@ -18,10 +17,10 @@ class AddressBookPage extends BasePage {
final bool isEditable;
@override
String get title => S.current.address_book;
String getTitle(AppLocalizations t) => t.address_book;
@override
Widget trailing(BuildContext context) {
Widget? trailing(BuildContext context) {
if (!isEditable) return null;
final addressBookStore = Provider.of<AddressBookStore>(context);
@ -63,9 +62,7 @@ class AddressBookPage extends BasePage {
color: Theme.of(context).dividerTheme.color,
height: 1.0,
),
itemCount: addressBookStore.contactList == null
? 0
: addressBookStore.contactList.length,
itemCount: addressBookStore.contactList.length,
itemBuilder: (BuildContext context, int index) {
final contact = addressBookStore.contactList[index];
@ -82,7 +79,7 @@ class AddressBookPage extends BasePage {
if (isCopied) {
await Clipboard.setData(
ClipboardData(text: contact.address));
Scaffold.of(context).showSnackBar(
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Copied to Clipboard'),
backgroundColor: Colors.green,
@ -96,14 +93,14 @@ class AddressBookPage extends BasePage {
width: 48.0,
alignment: Alignment.center,
decoration: BoxDecoration(
color: _getCurrencyBackgroundColor(contact.type),
color: OxenPalette.tealWithOpacity,
borderRadius: BorderRadius.circular(6.0),
),
child: Text(
contact.type.toString(),
'OXEN',
style: TextStyle(
fontSize: 11.0,
color: _getCurrencyTextColor(contact.type),
color: OxenPalette.teal,
),
),
),
@ -112,7 +109,7 @@ class AddressBookPage extends BasePage {
style: TextStyle(
fontSize: 16.0,
color:
Theme.of(context).primaryTextTheme.headline6.color),
Theme.of(context).primaryTextTheme.headline6?.color),
),
);
@ -120,128 +117,63 @@ class AddressBookPage extends BasePage {
? content
: Slidable(
key: Key('${contact.key}'),
actionPane: SlidableDrawerActionPane(),
child: content,
secondaryActions: <Widget>[
IconSlideAction(
caption: 'Edit',
color: Colors.blue,
icon: Icons.edit,
onTap: () async {
await Navigator.of(context).pushNamed(
Routes.addressBookAddContact,
arguments: contact);
endActionPane: ActionPane(
motion: const DrawerMotion(),
children: [
SlidableAction(
label: 'Edit',
backgroundColor: Colors.blue,
icon: Icons.edit,
onPressed: (context) async {
await Navigator.of(context).pushNamed(
Routes.addressBookAddContact,
arguments: contact);
await addressBookStore.updateContactList();
},
),
SlidableAction(
label: 'Delete',
backgroundColor: Colors.red,
icon: CupertinoIcons.delete,
onPressed: (context) async {
await showAlertDialog(context).then(
(isDelete) async {
if (isDelete) {
await addressBookStore.delete(contact: contact);
await addressBookStore.updateContactList();
}
});
},
),
]
),
startActionPane: ActionPane(
motion: const DrawerMotion(),
dismissible: DismissiblePane(
onDismissed: () async {
await addressBookStore.delete(contact: contact);
await addressBookStore.updateContactList();
},
),
IconSlideAction(
caption: 'Delete',
color: Colors.red,
icon: CupertinoIcons.delete,
onTap: () async {
await showAlertDialog(context)
.then((isDelete) async {
if (isDelete != null && isDelete) {
await addressBookStore.delete(
contact: contact);
await addressBookStore.updateContactList();
}
});
confirmDismiss: () async {
return await showAlertDialog(context);
},
),
],
dismissal: SlidableDismissal(
child: SlidableDrawerDismissal(),
onDismissed: (actionType) async {
await addressBookStore.delete(contact: contact);
await addressBookStore.updateContactList();
},
onWillDismiss: (actionType) async {
return await showAlertDialog(context);
},
children: [],
),
child: content,
);
}),
));
}
Color _getCurrencyBackgroundColor(CryptoCurrency currency) {
Color color;
switch (currency) {
case CryptoCurrency.oxen:
color = OxenPalette.tealWithOpacity;
break;
case CryptoCurrency.ada:
color = Colors.blue[200];
break;
case CryptoCurrency.bch:
color = Colors.orangeAccent;
break;
case CryptoCurrency.bnb:
color = Colors.blue;
break;
case CryptoCurrency.btc:
color = Colors.orange;
break;
case CryptoCurrency.dash:
color = Colors.blue;
break;
case CryptoCurrency.eos:
color = Colors.orangeAccent;
break;
case CryptoCurrency.eth:
color = Colors.black;
break;
case CryptoCurrency.ltc:
color = Colors.blue[200];
break;
case CryptoCurrency.nano:
color = Colors.orange;
break;
case CryptoCurrency.trx:
color = Colors.black;
break;
case CryptoCurrency.usdt:
color = Colors.blue[200];
break;
case CryptoCurrency.xlm:
color = color = Colors.blue;
break;
case CryptoCurrency.xrp:
color = Colors.orangeAccent;
break;
default:
color = Colors.white;
}
return color;
}
Color _getCurrencyTextColor(CryptoCurrency currency) {
Color color;
switch (currency) {
case CryptoCurrency.xmr:
color = OxenPalette.teal;
break;
case CryptoCurrency.ltc:
case CryptoCurrency.ada:
case CryptoCurrency.usdt:
color = Palette.lightBlue;
break;
default:
color = Colors.white;
}
return color;
}
Future<bool> showAlertDialog(BuildContext context) async {
var result = false;
await showConfirmOxenDialog(context, 'Remove contact',
'Are you sure that you want to remove selected contact?',
await showConfirmOxenDialog(context, tr(context).remove_contact,
tr(context).remove_contact_confirm,
onDismiss: (context) => Navigator.pop(context, false),
onConfirm: (context) {
result = true;
Navigator.pop(context, true);
return true;
});
return result;
}

View File

@ -1,12 +1,9 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:oxen_wallet/generated/l10n.dart';
import 'package:oxen_wallet/l10n.dart';
import 'package:oxen_wallet/src/domain/common/contact.dart';
import 'package:oxen_wallet/src/domain/common/crypto_currency.dart';
import 'package:oxen_wallet/src/screens/base_page.dart';
import 'package:oxen_wallet/src/stores/address_book/address_book_store.dart';
import 'package:oxen_wallet/src/widgets/address_text_field.dart';
import 'package:oxen_wallet/src/widgets/oxen_dialog.dart';
import 'package:oxen_wallet/src/widgets/oxen_text_field.dart';
import 'package:oxen_wallet/src/widgets/primary_button.dart';
import 'package:oxen_wallet/src/widgets/scollable_with_bottom_section.dart';
@ -15,10 +12,10 @@ import 'package:provider/provider.dart';
class ContactPage extends BasePage {
ContactPage({this.contact});
final Contact contact;
final Contact? contact;
@override
String get title => S.current.contact;
String getTitle(AppLocalizations t) => t.contact;
@override
Widget body(BuildContext context) => ContactForm(contact);
@ -27,7 +24,7 @@ class ContactPage extends BasePage {
class ContactForm extends StatefulWidget {
ContactForm(this.contact);
final Contact contact;
final Contact? contact;
@override
State<ContactForm> createState() => ContactFormState();
@ -36,99 +33,24 @@ class ContactForm extends StatefulWidget {
class ContactFormState extends State<ContactForm> {
final _formKey = GlobalKey<FormState>();
final _contactNameController = TextEditingController();
final _currencyTypeController = TextEditingController();
final _addressController = TextEditingController();
CryptoCurrency _selectedCrypto = CryptoCurrency.oxen;
@override
void initState() {
super.initState();
if (widget.contact == null) {
_currencyTypeController.text = _selectedCrypto.toString();
} else {
_selectedCrypto = widget.contact.type;
_contactNameController.text = widget.contact.name;
_currencyTypeController.text = _selectedCrypto.toString();
_addressController.text = widget.contact.address;
if (widget.contact != null) {
_contactNameController.text = widget.contact!.name;
_addressController.text = widget.contact!.address;
}
}
@override
void dispose() {
_contactNameController.dispose();
_currencyTypeController.dispose();
_addressController.dispose();
super.dispose();
}
Future<void> _setCurrencyType(BuildContext context) async {
var currencyType = CryptoCurrency.all[0].toString();
var selectedCurrency = CryptoCurrency.all[0];
await showDialog<void>(
context: context,
builder: (BuildContext context) {
return OxenDialog(
body: Container(
padding: EdgeInsets.all(30),
child: Column(
children: [
Padding(
padding: EdgeInsets.all(15),
child: Text(S.of(context).please_select,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 18,
decoration: TextDecoration.none,
color: Theme.of(context)
.primaryTextTheme
.caption
.color))),
Padding(
padding: EdgeInsets.only(top: 15, bottom: 30),
child: Container(
height: 150.0,
child: CupertinoPicker(
backgroundColor: Theme.of(context).backgroundColor,
itemExtent: 45.0,
onSelectedItemChanged: (int index) {
selectedCurrency = CryptoCurrency.all[index];
currencyType = CryptoCurrency.all[index].toString();
},
children: List.generate(CryptoCurrency.all.length,
(int index) {
return Center(
child: Text(
CryptoCurrency.all[index].toString(),
style: TextStyle(
color: Theme.of(context)
.primaryTextTheme
.caption
.color),
),
);
})),
),
),
PrimaryButton(
text: S.of(context).ok,
color:
Theme.of(context).primaryTextTheme.button.backgroundColor,
borderColor:
Theme.of(context).primaryTextTheme.button.decorationColor,
onPressed: () {
_selectedCrypto = selectedCurrency;
_currencyTypeController.text = currencyType;
Navigator.of(context).pop();
},
)
],
),
));
});
}
@override
Widget build(BuildContext context) {
final addressBookStore = Provider.of<AddressBookStore>(context);
@ -140,31 +62,20 @@ class ContactFormState extends State<ContactForm> {
mainAxisSize: MainAxisSize.min,
children: <Widget>[
OxenTextField(
hintText: S.of(context).contact_name,
hintText: tr(context).contact_name,
controller: _contactNameController,
validator: (value) {
addressBookStore.validateContactName(value);
addressBookStore.validateContactName(value ?? '', tr(context));
return addressBookStore.errorMessage;
},
),
SizedBox(height: 14.0),
Container(
child: InkWell(
onTap: () => _setCurrencyType(context),
child: IgnorePointer(
child: OxenTextField(
controller: _currencyTypeController,
),
),
),
),
SizedBox(height: 14.0),
AddressTextField(
controller: _addressController,
options: [AddressTextFieldOption.qrCode],
validator: (value) {
addressBookStore.validateAddress(value,
cryptoCurrency: _selectedCrypto);
addressBookStore.validateAddress(value ?? '',
l10n: tr(context));
return addressBookStore.errorMessage;
},
)
@ -177,40 +88,34 @@ class ContactFormState extends State<ContactForm> {
child: PrimaryButton(
onPressed: () {
setState(() {
_selectedCrypto = CryptoCurrency.xmr;
_contactNameController.text = '';
_currencyTypeController.text = _selectedCrypto.toString();
_addressController.text = '';
});
},
text: S.of(context).reset,
text: tr(context).reset,
color:
Theme.of(context).accentTextTheme.button.backgroundColor,
Theme.of(context).accentTextTheme.button?.backgroundColor,
borderColor:
Theme.of(context).accentTextTheme.button.decorationColor),
Theme.of(context).accentTextTheme.button?.decorationColor),
),
SizedBox(width: 20),
Expanded(
child: PrimaryButton(
onPressed: () async {
if (!_formKey.currentState.validate()) return;
if (!(_formKey.currentState?.validate() ?? false)) return;
try {
if (widget.contact == null) {
final newContact = Contact(
name: _contactNameController.text,
address: _addressController.text,
type: _selectedCrypto);
address: _addressController.text);
await addressBookStore.add(contact: newContact);
} else {
widget.contact.name = _contactNameController.text;
widget.contact.address = _addressController.text;
widget.contact
.updateCryptoCurrency(currency: _selectedCrypto);
widget.contact!.name = _contactNameController.text;
widget.contact!.address = _addressController.text;
await addressBookStore.update(
contact: widget.contact);
await addressBookStore.update(contact: widget.contact!);
}
Navigator.pop(context);
} catch (e) {
@ -226,21 +131,21 @@ class ContactFormState extends State<ContactForm> {
FlatButton(
onPressed: () =>
Navigator.of(context).pop(),
child: Text(S.of(context).ok))
child: Text(tr(context).ok))
],
);
});
}
},
text: S.of(context).save,
text: tr(context).save,
color: Theme.of(context)
.primaryTextTheme
.button
.backgroundColor,
?.backgroundColor,
borderColor: Theme.of(context)
.primaryTextTheme
.button
.decorationColor))
?.decorationColor))
],
));
}

View File

@ -2,7 +2,7 @@ import 'package:mobx/mobx.dart';
import 'package:provider/provider.dart';
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:oxen_wallet/generated/l10n.dart';
import 'package:oxen_wallet/l10n.dart';
import 'package:oxen_wallet/src/stores/auth/auth_state.dart';
import 'package:oxen_wallet/src/stores/auth/auth_store.dart';
import 'package:oxen_wallet/src/screens/pin_code/pin_code.dart';
@ -14,7 +14,7 @@ typedef OnAuthenticationFinished = void Function(bool, AuthPageState);
class AuthPage extends StatefulWidget {
AuthPage({this.onAuthenticationFinished, this.closable = true});
final OnAuthenticationFinished onAuthenticationFinished;
final OnAuthenticationFinished? onAuthenticationFinished;
final bool closable;
@override
@ -25,12 +25,15 @@ class AuthPageState extends State<AuthPage> {
final _key = GlobalKey<ScaffoldState>();
final _pinCodeKey = GlobalKey<PinCodeState>();
void changeProcessText(String text) {
_key.currentState.showSnackBar(
void changeProcessText(BuildContext context, String text) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(text), backgroundColor: Colors.green));
}
void close() => Navigator.of(_key.currentContext).pop();
void close() {
if (_key.currentContext != null)
Navigator.of(_key.currentContext!).pop();
}
@override
Widget build(BuildContext context) {
@ -38,15 +41,15 @@ class AuthPageState extends State<AuthPage> {
final settingsStore = Provider.of<SettingsStore>(context);
if (settingsStore.allowBiometricAuthentication) {
WidgetsBinding.instance.addPostFrameCallback((_) {
WidgetsBinding.instance?.addPostFrameCallback((_) {
final biometricAuth = BiometricAuth();
biometricAuth.isAuthenticated().then(
biometricAuth.isAuthenticated(tr(context)).then(
(isAuth) {
if (isAuth) {
authStore.biometricAuth();
_key.currentState.showSnackBar(
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(S.of(context).authenticated),
content: Text(tr(context).authenticated),
backgroundColor: Colors.green,
),
);
@ -58,61 +61,46 @@ class AuthPageState extends State<AuthPage> {
reaction((_) => authStore.state, (AuthState state) {
if (state is AuthenticatedSuccessfully) {
WidgetsBinding.instance.addPostFrameCallback((_) {
WidgetsBinding.instance?.addPostFrameCallback((_) {
if (widget.onAuthenticationFinished != null) {
widget.onAuthenticationFinished(true, this);
widget.onAuthenticationFinished!(true, this);
} else {
_key.currentState.showSnackBar(
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(S.of(context).authenticated),
content: Text(tr(context).authenticated),
backgroundColor: Colors.green,
),
);
}
});
}
if (state is AuthenticationInProgress) {
WidgetsBinding.instance.addPostFrameCallback((_) {
_key.currentState.showSnackBar(
} else if (state is AuthenticationFailure) {
WidgetsBinding.instance?.addPostFrameCallback((_) {
_pinCodeKey.currentState?.clear();
ScaffoldMessenger.of(context).hideCurrentSnackBar();
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(S.of(context).authentication),
backgroundColor: Colors.green,
),
);
});
}
if (state is AuthenticationFailure) {
WidgetsBinding.instance.addPostFrameCallback((_) {
_pinCodeKey.currentState.clear();
_key.currentState.hideCurrentSnackBar();
_key.currentState.showSnackBar(
SnackBar(
content: Text(S.of(context).failed_authentication(state.error)),
content: Text(tr(context).failed_authentication(state.error)),
backgroundColor: Colors.red,
),
);
if (widget.onAuthenticationFinished != null) {
widget.onAuthenticationFinished(false, this);
widget.onAuthenticationFinished!(false, this);
}
});
}
if (state is AuthenticationBanned) {
WidgetsBinding.instance.addPostFrameCallback((_) {
_pinCodeKey.currentState.clear();
_key.currentState.hideCurrentSnackBar();
_key.currentState.showSnackBar(
} else if (state is AuthenticationBanned) {
WidgetsBinding.instance?.addPostFrameCallback((_) {
_pinCodeKey.currentState?.clear();
ScaffoldMessenger.of(context).hideCurrentSnackBar();
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(S.of(context).failed_authentication(state.error)),
content: Text(tr(context).failed_authentication(state.error)),
backgroundColor: Colors.red,
),
);
if (widget.onAuthenticationFinished != null) {
widget.onAuthenticationFinished(false, this);
widget.onAuthenticationFinished!(false, this);
}
});
}
@ -128,6 +116,7 @@ class AuthPageState extends State<AuthPage> {
resizeToAvoidBottomInset: false,
body: PinCode(
(pin, _) => authStore.auth(
l10n: tr(context),
password: pin.fold('', (ac, val) => ac + '$val')),
false,
_pinCodeKey));

View File

@ -9,11 +9,11 @@ import 'package:provider/provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
Widget createLoginPage(
{@required SharedPreferences sharedPreferences,
@required UserService userService,
@required WalletService walletService,
@required WalletListService walletListService,
@required AuthenticationStore authenticationStore}) =>
{required SharedPreferences sharedPreferences,
required UserService userService,
required WalletService walletService,
required WalletListService walletListService,
required AuthenticationStore authenticationStore}) =>
Provider(
create: (_) => AuthStore(
sharedPreferences: sharedPreferences,

View File

@ -7,10 +7,10 @@ import 'package:oxen_wallet/src/screens/auth/auth_page.dart';
import 'package:oxen_wallet/src/stores/auth/auth_store.dart';
Widget createUnlockPage(
{@required SharedPreferences sharedPreferences,
@required UserService userService,
@required WalletService walletService,
@required Function(bool, AuthPageState) onAuthenticationFinished}) =>
{required SharedPreferences sharedPreferences,
required UserService userService,
required WalletService walletService,
required Function(bool, AuthPageState) onAuthenticationFinished}) =>
WillPopScope(
onWillPop: () async => false,
child: Provider(
@ -20,4 +20,4 @@ Widget createUnlockPage(
walletService: walletService),
child: AuthPage(
onAuthenticationFinished: onAuthenticationFinished,
closable: false)));
closable: false)));

View File

@ -4,11 +4,12 @@ import 'package:oxen_wallet/src/widgets/nav_bar.dart';
import 'package:provider/provider.dart';
import 'package:oxen_wallet/themes.dart';
import 'package:oxen_wallet/theme_changer.dart';
import 'package:oxen_wallet/l10n.dart';
enum AppBarStyle { regular, withShadow }
abstract class BasePage extends StatelessWidget {
String get title => null;
String? getTitle(AppLocalizations t) { return null; }
bool get isModalBackButton => false;
@ -20,8 +21,8 @@ abstract class BasePage extends StatelessWidget {
void onClose(BuildContext context) => Navigator.of(context).pop();
Widget leading(BuildContext context) {
if (ModalRoute.of(context).isFirst) {
Widget? leading(BuildContext context) {
if (ModalRoute.of(context)?.isFirst ?? false) {
return null;
}
@ -43,7 +44,8 @@ abstract class BasePage extends StatelessWidget {
);
}
Widget middle(BuildContext context) {
Widget? middle(BuildContext context) {
final title = getTitle(tr(context));
return title == null
? null
: Text(
@ -51,13 +53,13 @@ abstract class BasePage extends StatelessWidget {
style: TextStyle(
fontSize: 16.0,
fontWeight: FontWeight.w600,
color: Theme.of(context).primaryTextTheme.headline6.color),
color: Theme.of(context).primaryTextTheme.headline6?.color),
);
}
Widget trailing(BuildContext context) => null;
Widget? trailing(BuildContext context) => null;
Widget floatingActionButton(BuildContext context) => null;
Widget? floatingActionButton(BuildContext context) => null;
ObstructingPreferredSizeWidget appBar(BuildContext context) {
final _themeChanger = Provider.of<ThemeChanger>(context);
@ -98,7 +100,7 @@ abstract class BasePage extends StatelessWidget {
Widget body(BuildContext context);
Widget bottomNavigationBar(BuildContext context) => null;
Widget? bottomNavigationBar(BuildContext context) => null;
@override
Widget build(BuildContext context) {

View File

@ -1,6 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:oxen_wallet/generated/l10n.dart';
import 'package:oxen_wallet/l10n.dart';
import 'package:oxen_wallet/src/screens/base_page.dart';
import 'package:yaml/yaml.dart';
@ -8,7 +8,7 @@ class ChangelogPage extends BasePage {
final String changelogPath = 'assets/changelog.yml';
@override
String get title => S.current.changelog;
String getTitle(AppLocalizations t) => t.changelog;
@override
Widget body(BuildContext context) {
@ -41,7 +41,7 @@ class ChangelogPage extends BasePage {
},
separatorBuilder: (_, __) =>
Divider(color: Theme.of(context).dividerTheme.color, height: 1.0),
itemCount: changelogs == null ? 0 : changelogs.length,
itemCount: changelogs.length,
);
},
future: rootBundle.loadString(changelogPath),

View File

@ -1,15 +1,14 @@
import 'dart:io';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:oxen_wallet/generated/l10n.dart';
import 'package:oxen_wallet/l10n.dart';
import 'package:oxen_wallet/palette.dart';
import 'package:oxen_wallet/routes.dart';
import 'package:oxen_wallet/src/screens/base_page.dart';
import 'package:oxen_wallet/src/widgets/primary_button.dart';
class DangerzonePage extends BasePage {
DangerzonePage({this.nextPage});
DangerzonePage({required this.nextPage});
final String nextPage;
@ -20,8 +19,8 @@ class DangerzonePage extends BasePage {
final textScaleFactor = _screenWidth < _baseWidth ? 0.76 : 1.0;
final appStore = Platform.isAndroid ? 'Play Store' : 'AppStore';
final item = nextPage == Routes.dangerzoneSeed
? S.of(context).seed_title
: S.of(context).keys_title;
? tr(context).seed_title
: tr(context).keys_title;
return Column(children: <Widget>[
Expanded(
@ -36,7 +35,7 @@ class DangerzonePage extends BasePage {
Padding(
padding: EdgeInsets.all(10),
child: Text(
S.of(context).dangerzone,
tr(context).dangerzone,
style: TextStyle(
fontSize: 30.0,
fontWeight: FontWeight.bold,
@ -48,7 +47,7 @@ class DangerzonePage extends BasePage {
Padding(
padding: EdgeInsets.all(10),
child: Text(
S.of(context).never_give_your(item),
tr(context).never_give_your(item),
style: TextStyle(
fontSize: 22.0,
color: Palette.lightBlue,
@ -59,7 +58,7 @@ class DangerzonePage extends BasePage {
Padding(
padding: EdgeInsets.all(10),
child: Text(
S.of(context).dangerzone_warning(
tr(context).dangerzone_warning(
item, appStore
),
style: TextStyle(
@ -77,10 +76,10 @@ class DangerzonePage extends BasePage {
onPressed: () {
Navigator.popAndPushNamed(context, nextPage);
},
text: S.of(context).yes_im_sure,
color: Theme.of(context).primaryTextTheme.button.backgroundColor,
text: tr(context).yes_im_sure,
color: Theme.of(context).primaryTextTheme.button?.backgroundColor,
borderColor:
Theme.of(context).primaryTextTheme.button.decorationColor),
Theme.of(context).primaryTextTheme.button?.decorationColor),
)
]);
}

View File

@ -1,15 +1,11 @@
import 'dart:io';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:oxen_wallet/generated/l10n.dart';
import 'package:oxen_wallet/l10n.dart';
import 'package:oxen_wallet/palette.dart';
import 'package:oxen_wallet/routes.dart';
import 'package:oxen_wallet/src/screens/base_page.dart';
import 'package:oxen_wallet/src/widgets/primary_button.dart';
class DangerzoneRemoveWalletPage extends BasePage {
DangerzoneRemoveWalletPage({this.onConfirmed});
DangerzoneRemoveWalletPage({required this.onConfirmed});
final void Function() onConfirmed;
@ -32,7 +28,7 @@ class DangerzoneRemoveWalletPage extends BasePage {
Padding(
padding: EdgeInsets.all(10),
child: Text(
S.of(context).dangerzone,
tr(context).dangerzone,
style: TextStyle(
fontSize: 30.0,
fontWeight: FontWeight.bold,
@ -44,7 +40,7 @@ class DangerzoneRemoveWalletPage extends BasePage {
Padding(
padding: EdgeInsets.all(10),
child: Text(
S.of(context).remove_wallet_confirmation,
tr(context).remove_wallet_confirmation,
style: TextStyle(
fontSize: 22.0,
color: Palette.lightBlue,
@ -55,7 +51,7 @@ class DangerzoneRemoveWalletPage extends BasePage {
Padding(
padding: EdgeInsets.all(10),
child: Text(
S.of(context).dangerzone_remove_wallet_warning,
tr(context).dangerzone_remove_wallet_warning,
style: TextStyle(
fontSize: 16.0,
color: Palette.lightBlue,
@ -72,10 +68,9 @@ class DangerzoneRemoveWalletPage extends BasePage {
onConfirmed();
Navigator.of(context).pop();
},
text: S.of(context).yes_im_sure,
color: Theme.of(context).primaryTextTheme.button.backgroundColor,
borderColor:
Theme.of(context).primaryTextTheme.button.decorationColor),
text: tr(context).yes_im_sure,
color: Theme.of(context).primaryTextTheme.button?.backgroundColor,
borderColor: Theme.of(context).primaryTextTheme.button?.decorationColor),
)
]);
}

View File

@ -11,11 +11,11 @@ import 'package:oxen_wallet/src/stores/wallet/wallet_store.dart';
import 'package:provider/provider.dart';
Widget createDashboardPage(
{@required WalletService walletService,
@required PriceStore priceStore,
@required Box<TransactionDescription> transactionDescriptions,
@required SettingsStore settingsStore,
@required WalletStore walletStore}) =>
{required WalletService walletService,
required PriceStore priceStore,
required Box<TransactionDescription> transactionDescriptions,
required SettingsStore settingsStore,
required WalletStore walletStore}) =>
Provider(
create: (_) => ActionListStore(
walletService: walletService,

View File

@ -1,8 +1,6 @@
import 'package:date_range_picker/date_range_picker.dart' as date_rage_picker;
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:oxen_wallet/generated/l10n.dart';
import 'package:oxen_wallet/l10n.dart';
import 'package:oxen_wallet/palette.dart';
import 'package:oxen_wallet/routes.dart';
import 'package:oxen_wallet/src/domain/common/balance_display_mode.dart';
@ -20,6 +18,7 @@ import 'package:oxen_wallet/src/stores/sync/sync_store.dart';
import 'package:oxen_wallet/src/stores/wallet/wallet_store.dart';
import 'package:oxen_wallet/src/widgets/picker.dart';
import 'package:provider/provider.dart';
import 'package:intl/intl.dart';
class DashboardPage extends BasePage {
final _bodyKey = GlobalKey();
@ -32,7 +31,7 @@ class DashboardPage extends BasePage {
padding: EdgeInsets.all(0),
onPressed: () => _presentWalletMenu(context),
child: Icon(Icons.sync_rounded,
color: Theme.of(context).primaryTextTheme.caption.color,
color: Theme.of(context).primaryTextTheme.caption?.color,
size: 30)));
}
@ -47,15 +46,17 @@ class DashboardPage extends BasePage {
Text(
walletStore.name,
style: TextStyle(
color: Theme.of(context).primaryTextTheme.headline6.color),
color: Theme.of(context).primaryTextTheme.headline6?.color),
overflow: TextOverflow.ellipsis,
),
SizedBox(height: 5),
Text(
walletStore.account != null ? '${walletStore.account.label}' : '',
'${walletStore.account.label}',
style: TextStyle(
fontWeight: FontWeight.w400,
fontSize: 10,
color: Theme.of(context).primaryTextTheme.headline6.color),
color: Theme.of(context).primaryTextTheme.headline6?.color),
overflow: TextOverflow.ellipsis,
),
]);
});
@ -69,7 +70,7 @@ class DashboardPage extends BasePage {
padding: EdgeInsets.all(0),
onPressed: () => Navigator.of(context).pushNamed(Routes.profile),
child: Icon(Icons.account_circle_rounded,
color: Theme.of(context).primaryTextTheme.caption.color,
color: Theme.of(context).primaryTextTheme.caption?.color,
size: 30)),
);
}
@ -84,7 +85,7 @@ class DashboardPage extends BasePage {
builder: (_) => Picker(
items: walletMenu.items,
selectedAtIndex: -1,
title: S.of(bodyContext).wallet_menu,
title: tr(bodyContext).wallet_menu,
pickerHeight: 300,
onItemSelected: (String item) =>
walletMenu.action(walletMenu.items.indexOf(item))),
@ -93,7 +94,7 @@ class DashboardPage extends BasePage {
}
class DashboardPageBody extends StatefulWidget {
DashboardPageBody({Key key}) : super(key: key);
DashboardPageBody({required Key key}) : super(key: key);
@override
DashboardPageBodyState createState() => DashboardPageBodyState();
@ -113,13 +114,13 @@ class DashboardPageBodyState extends State<DashboardPageBody> {
final actionListStore = Provider.of<ActionListStore>(context);
final syncStore = Provider.of<SyncStore>(context);
final settingsStore = Provider.of<SettingsStore>(context);
final transactionDateFormat = settingsStore.getCurrentDateFormat(
formatUSA: 'MMMM d, yyyy, HH:mm', formatDefault: 'd MMMM yyyy, HH:mm');
final t = tr(context);
final transactionDateFormat = DateFormat.yMMMMd(t.localeName).add_jm();
return Observer(
key: _listObserverKey,
builder: (_) {
final items = actionListStore.items ?? <String>[];
final items = actionListStore.items;
final itemsCount = items.length + 2;
return ListView.builder(
@ -144,23 +145,18 @@ class DashboardPageBodyState extends State<DashboardPageBody> {
key: _syncingObserverKey,
builder: (_) {
final status = syncStore.status;
final statusText = status.title();
final statusText = status.title(t);
final progress = syncStore.status.progress();
final isFailure = status is FailedSyncStatus;
var descriptionText = '';
if (status is SyncingSyncStatus) {
descriptionText = S
.of(context)
.Blocks_remaining(
syncStore.status.toString());
descriptionText = t.blocks_remaining(syncStore.status.toString());
}
if (status is FailedSyncStatus) {
descriptionText = S
.of(context)
.please_try_to_connect_to_another_node;
descriptionText = t.please_try_to_connect_to_another_node;
}
return Container(
@ -209,15 +205,12 @@ class DashboardPageBodyState extends State<DashboardPageBody> {
settingsStore.balanceDisplayMode;
final displayMode = balanceStore
.isReversing
? (savedDisplayMode ==
BalanceDisplayMode
.availableBalance
? (savedDisplayMode == BalanceDisplayMode.availableBalance
? BalanceDisplayMode.fullBalance
: BalanceDisplayMode
.availableBalance)
: BalanceDisplayMode.availableBalance)
: savedDisplayMode;
return Text(displayMode.toString(),
return Text(displayMode.getTitle(t),
style: TextStyle(
color: OxenPalette.teal,
fontSize: 16));
@ -228,29 +221,16 @@ class DashboardPageBodyState extends State<DashboardPageBody> {
final savedDisplayMode =
settingsStore.balanceDisplayMode;
var balance = '---';
final displayMode = balanceStore
.isReversing
? (savedDisplayMode ==
BalanceDisplayMode
.availableBalance
final displayMode = balanceStore.isReversing
? (savedDisplayMode == BalanceDisplayMode.availableBalance
? BalanceDisplayMode.fullBalance
: BalanceDisplayMode
.availableBalance)
: BalanceDisplayMode.availableBalance)
: savedDisplayMode;
if (displayMode ==
BalanceDisplayMode.availableBalance) {
balance = balanceStore
.unlockedBalanceString ??
'0.0';
}
if (displayMode ==
BalanceDisplayMode.fullBalance) {
balance =
balanceStore.fullBalanceString ??
'0.0';
}
if (displayMode == BalanceDisplayMode.availableBalance)
balance = balanceStore.unlockedBalanceString;
else if (displayMode == BalanceDisplayMode.fullBalance)
balance = balanceStore.fullBalanceString;
return Text(
balance,
@ -258,7 +238,7 @@ class DashboardPageBodyState extends State<DashboardPageBody> {
color: Theme.of(context)
.primaryTextTheme
.caption
.color,
?.color,
fontSize: 42),
);
}),
@ -272,32 +252,20 @@ class DashboardPageBodyState extends State<DashboardPageBody> {
final displayMode = settingsStore
.enableFiatCurrency
? (balanceStore.isReversing
? (savedDisplayMode ==
BalanceDisplayMode
.availableBalance
? BalanceDisplayMode
.fullBalance
: BalanceDisplayMode
.availableBalance)
? (savedDisplayMode == BalanceDisplayMode.availableBalance
? BalanceDisplayMode.fullBalance
: BalanceDisplayMode.availableBalance)
: savedDisplayMode)
: BalanceDisplayMode
.hiddenBalance;
final symbol = settingsStore
.fiatCurrency
.toString();
: BalanceDisplayMode.hiddenBalance;
final symbol = settingsStore.fiatCurrency.toString();
var balance = '---';
if (displayMode ==
BalanceDisplayMode
.availableBalance) {
balance =
'${balanceStore.fiatUnlockedBalance} $symbol';
if (displayMode == BalanceDisplayMode.availableBalance) {
balance = '${balanceStore.fiatUnlockedBalance} $symbol';
}
if (displayMode ==
BalanceDisplayMode.fullBalance) {
balance =
'${balanceStore.fiatFullBalance} $symbol';
if (displayMode == BalanceDisplayMode.fullBalance) {
balance = '${balanceStore.fiatFullBalance} $symbol';
}
return Text(balance,
@ -326,7 +294,7 @@ class DashboardPageBodyState extends State<DashboardPageBody> {
rootNavigator: true)
.pushNamed(Routes.send),
),
Text(S.of(context).send)
Text(t.send)
],
),
Column(
@ -339,7 +307,7 @@ class DashboardPageBodyState extends State<DashboardPageBody> {
rootNavigator: true)
.pushNamed(Routes.receive),
),
Text(S.of(context).receive)
Text(t.receive)
],
)
],
@ -359,83 +327,74 @@ class DashboardPageBodyState extends State<DashboardPageBody> {
PopupMenuButton<int>(
itemBuilder: (context) => [
PopupMenuItem(
enabled: false,
value: -1,
child: Text(S.of(context).transactions,
style: TextStyle(
fontWeight: FontWeight.bold,
color: Theme.of(context)
.primaryTextTheme
.caption
.color))),
enabled: false,
value: -1,
child: Text(t.transactions,
style: TextStyle(
fontWeight: FontWeight.bold,
color: Theme.of(context).primaryTextTheme.caption?.color
)
)
),
PopupMenuItem(
value: 0,
child: Observer(
builder: (_) => Row(
mainAxisAlignment:
MainAxisAlignment
.spaceBetween,
children: [
Text(S.of(context).incoming),
Checkbox(
value: actionListStore
.transactionFilterStore
.displayIncoming,
onChanged: (value) =>
actionListStore
.transactionFilterStore
.toggleIncoming(),
)
]))),
value: 0,
child: Observer(
builder: (_) => Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(t.incoming),
Checkbox(
value: actionListStore.transactionFilterStore.displayIncoming,
onChanged: (value) => actionListStore.transactionFilterStore.toggleIncoming(),
)
]
)
)
),
PopupMenuItem(
value: 1,
child: Observer(
builder: (_) => Row(
mainAxisAlignment:
MainAxisAlignment
.spaceBetween,
children: [
Text(S.of(context).outgoing),
Checkbox(
value: actionListStore
.transactionFilterStore
.displayOutgoing,
onChanged: (value) =>
actionListStore
.transactionFilterStore
.toggleOutgoing(),
)
]))),
value: 1,
child: Observer(
builder: (_) => Row(
mainAxisAlignment:MainAxisAlignment.spaceBetween,
children: [
Text(t.outgoing),
Checkbox(
value: actionListStore.transactionFilterStore.displayOutgoing,
onChanged: (value) => actionListStore.transactionFilterStore.toggleOutgoing(),
)
]
)
)
),
PopupMenuItem(
value: 2,
child:
Text(S.of(context).transactions_by_date)),
value: 2,
child: Text(t.transactions_by_date)
),
],
child: Text(S.of(context).filters,
style: TextStyle(
fontSize: 16.0,
color: Theme.of(context)
.primaryTextTheme
.subtitle2
.color)),
child: Text(t.filters,
style: TextStyle(
fontSize: 16.0,
color: Theme.of(context).primaryTextTheme.subtitle2?.color
)
),
onSelected: (item) async {
if (item == 2) {
final picked =
await date_rage_picker.showDatePicker(
context: context,
initialFirstDate: DateTime.now()
.subtract(Duration(days: 1)),
initialLastDate: (DateTime.now()),
firstDate: DateTime(2015),
lastDate: DateTime.now()
.add(Duration(days: 1)));
final picked = await showDateRangePicker(
context: context,
initialDateRange: DateTimeRange(
start: DateTime.now().subtract(Duration(days: 1)),
end: DateTime.now()
),
firstDate: DateTime(2018),
lastDate: DateTime.now()
);
if (picked != null && picked.length == 2) {
actionListStore.transactionFilterStore
.changeStartDate(picked.first);
actionListStore.transactionFilterStore
.changeEndDate(picked.last);
}
actionListStore.transactionFilterStore.changeStartDate(picked?.start);
// Add 1d to the end date because we want the picker returns the
// DateTime of the beginning of the end date, but we want to include
// everything on that date as well.
actionListStore.transactionFilterStore.changeEndDate(
picked == null ? null : picked.end.add(Duration(days: 1)));
}
},
)
@ -476,7 +435,8 @@ class DashboardPageBodyState extends State<DashboardPageBody> {
transactionDateFormat.format(transaction.date),
formattedAmount: formattedAmount,
formattedFiatAmount: formattedFiatAmount,
isPending: transaction.isPending);
isPending: transaction.isPending,
isStake: transaction.isStake);
}
return Container();

View File

@ -1,38 +1,56 @@
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:oxen_wallet/generated/l10n.dart';
import 'package:oxen_wallet/l10n.dart';
import 'package:oxen_wallet/palette.dart';
import 'package:oxen_wallet/src/stores/settings/settings_store.dart';
import 'package:provider/provider.dart';
extension RelativeDateHelpers on DateTime {
bool isToday([DateTime? now]) {
now ??= DateTime.now();
return now.day == day && now.month == month && now.year == year;
}
bool isYesterday([DateTime? now]) {
now ??= DateTime.now();
return isToday(now.subtract(Duration(days: 1)));
}
bool isPastWeek([DateTime? now]) {
now ??= DateTime.now();
// diffDays gives us the integer days difference, but that is a pain because a value of 6 could
// be anywhere from 6.00 to 6.99 days ago, while the date 6 days before now will only partially
// overlap with that range, so we have to muck around a bit to deal with those edge cases.
final diffDays = difference(now).inDays;
if (diffDays >= -5 && diffDays <= -1)
return true;
if (diffDays == 0) // if diff is 0 then this is anywhere from -0.99 to 0.99: allow yesterday and today but not tomorrow
return isToday(now) || isYesterday(now);
if (diffDays == -6) // if -6 then allow the date that was 6 days ago but not the one that was 7 days ago
return isToday(now.subtract(Duration(days: 6)));
return false;
}
}
class DateSectionRow extends StatelessWidget {
DateSectionRow({this.date});
DateSectionRow({required this.date});
static final nowDate = DateTime.now();
final DateTime date;
@override
Widget build(BuildContext context) {
final diffDays = date.difference(nowDate).inDays;
final isToday = nowDate.day == date.day &&
nowDate.month == date.month &&
nowDate.year == date.year;
final settingsStore = Provider.of<SettingsStore>(context);
final currentLanguage = settingsStore.languageCode;
final dateSectionDateFormat = settingsStore.getCurrentDateFormat(
formatUSA: 'MMM d', formatDefault: 'd MMM');
var title = '';
final t = tr(context);
if (isToday) {
title = S.of(context).today;
} else if (diffDays == 0) {
title = S.of(context).yesterday;
} else if (diffDays > -7 && diffDays < 0) {
final dateFormat = DateFormat.EEEE(currentLanguage);
title = dateFormat.format(date);
} else {
title = dateSectionDateFormat.format(date);
}
String title;
if (date.isToday())
title = t.today;
else if (date.isYesterday())
title = t.yesterday;
else if (date.isPastWeek())
title = DateFormat.EEEE(t.localeName).format(date);
else if (date.isAfter(DateTime.now().subtract(Duration(days: 304))))
// If within (approximately) the last 10 months then don't include the year
title = DateFormat.MMMd(t.localeName).format(date);
else
title = DateFormat.yMMMd(t.localeName).format(date);
return Padding(
padding: const EdgeInsets.only(top: 10, bottom: 10),

View File

@ -1,16 +1,17 @@
import 'package:flutter/material.dart';
import 'package:oxen_wallet/generated/l10n.dart';
import 'package:oxen_wallet/l10n.dart';
import 'package:oxen_wallet/palette.dart';
import 'package:oxen_wallet/src/wallet/transaction/transaction_direction.dart';
class TransactionRow extends StatelessWidget {
TransactionRow(
{this.direction,
this.formattedDate,
this.formattedAmount,
this.formattedFiatAmount,
this.isPending,
@required this.onTap});
{required this.direction,
required this.formattedDate,
required this.formattedAmount,
required this.formattedFiatAmount,
required this.isPending,
required this.isStake,
required this.onTap});
final VoidCallback onTap;
final TransactionDirection direction;
@ -18,6 +19,7 @@ class TransactionRow extends StatelessWidget {
final String formattedAmount;
final String formattedFiatAmount;
final bool isPending;
final bool isStake;
@override
Widget build(BuildContext context) {
@ -35,19 +37,23 @@ class TransactionRow extends StatelessWidget {
Container(
height: 27,
width: 27,
decoration: BoxDecoration(
color: direction == TransactionDirection.incoming
? OxenPalette.limeWithOpacity
: isStake
? OxenPalette.navyWithOpacity
: OxenPalette.lightRedWithOpacity,
shape: BoxShape.circle,
),
child: Icon(
direction == TransactionDirection.incoming
? Icons.arrow_downward_rounded
: Icons.arrow_upward_rounded,
color: direction == TransactionDirection.incoming
? OxenPalette.lime
: OxenPalette.lightRed,
),
decoration: BoxDecoration(
color: direction == TransactionDirection.incoming
? OxenPalette.limeWithOpacity
: OxenPalette.lightRedWithOpacity,
shape: BoxShape.circle,
: isStake
? OxenPalette.teal
: OxenPalette.lightRed,
),
),
Expanded(
@ -60,15 +66,17 @@ class TransactionRow extends StatelessWidget {
children: <Widget>[
Text(
(direction == TransactionDirection.incoming
? S.of(context).received
: S.of(context).sent) +
(isPending ? S.of(context).pending : ''),
? tr(context).received
: isStake
? tr(context).stake
: tr(context).sent) +
(isPending ? tr(context).pending : ''),
style: TextStyle(
fontSize: 16,
color: Theme.of(context)
.primaryTextTheme
.subtitle1
.color)),
?.color)),
Text(formattedAmount,
style: const TextStyle(
fontSize: 16, color: Palette.purpleBlue))

View File

@ -1,5 +1,5 @@
import 'package:flutter/material.dart';
import 'package:oxen_wallet/generated/l10n.dart';
import 'package:oxen_wallet/l10n.dart';
import 'package:oxen_wallet/routes.dart';
import 'package:oxen_wallet/src/stores/balance/balance_store.dart';
import 'package:oxen_wallet/src/stores/wallet/wallet_store.dart';
@ -7,13 +7,14 @@ import 'package:oxen_wallet/src/widgets/oxen_dialog.dart';
import 'package:provider/provider.dart';
class WalletMenu {
WalletMenu(this.context);
WalletMenu(this.context)
: items = [
tr(context).reconnect,
tr(context).rescan,
tr(context).reload_fiat
];
final List<String> items = [
S.current.reconnect,
S.current.rescan,
S.current.reload_fiat
];
final List<String> items;
final BuildContext context;
@ -35,7 +36,7 @@ class WalletMenu {
final walletStore = context.read<WalletStore>();
await showSimpleOxenDialog(
context, S.of(context).reconnection, S.of(context).reconnect_alert_text,
context, tr(context).reconnection, tr(context).reconnect_alert_text,
onPressed: (context) {
walletStore.reconnect();
Navigator.of(context).pop();

View File

@ -1,7 +1,7 @@
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/services.dart';
import 'package:oxen_wallet/l10n.dart';
import 'package:oxen_wallet/palette.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:oxen_wallet/src/screens/base_page.dart';
@ -16,7 +16,7 @@ class DisclaimerPage extends BasePage {
bool get isModalBackButton => false;
@override
String get title => 'Terms of Use';
String getTitle(AppLocalizations t) => t.settings_terms_and_conditions;
@override
Widget body(BuildContext context) => DisclaimerPageBody(isReadOnly: true);
@ -77,7 +77,7 @@ class DisclaimerBodyState extends State<DisclaimerPageBody> {
void initState() {
super.initState();
getFileLines();
if (_isAccepted) WidgetsBinding.instance.addPostFrameCallback(_afterLayout);
if (_isAccepted) WidgetsBinding.instance?.addPostFrameCallback(_afterLayout);
}
@override
@ -222,16 +222,16 @@ class DisclaimerBodyState extends State<DisclaimerPageBody> {
padding:
EdgeInsets.only(left: 25.0, right: 25.0, bottom: 25.0),
child: PrimaryButton(
onPressed: _checked ? () {} : null,
onPressed: () {},
text: 'Accept',
color: Theme.of(context)
.primaryTextTheme
.button
.backgroundColor,
?.backgroundColor,
borderColor: Theme.of(context)
.primaryTextTheme
.button
.decorationColor,
?.decorationColor,
),
)
: Offstage(),

View File

@ -1,25 +1,25 @@
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:provider/provider.dart';
import 'package:oxen_wallet/generated/l10n.dart';
import 'package:oxen_wallet/src/stores/settings/settings_store.dart';
import 'package:oxen_wallet/l10n.dart';
import 'package:oxen_wallet/src/screens/base_page.dart';
class FaqPage extends BasePage {
@override
String get title => S.current.faq;
String getTitle(AppLocalizations t) => t.faq;
@override
Widget body(BuildContext context) {
return FutureBuilder(
builder: (context, snapshot) {
if (!snapshot.hasData)
return SizedBox.shrink();
final faqItems = jsonDecode(snapshot.data.toString()) as List;
return ListView.separated(
itemBuilder: (BuildContext context, int index) {
final itemTitle = faqItems[index]['question'].toString();
final itemChild = faqItems[index]['answer'].toString();
final itemChild = faqItems[index]['answer'].toString() + '\n';
return ExpansionTile(
title: Text(itemTitle),
@ -41,7 +41,7 @@ class FaqPage extends BasePage {
},
separatorBuilder: (_, __) =>
Divider(color: Theme.of(context).dividerTheme.color, height: 1.0),
itemCount: faqItems == null ? 0 : faqItems.length,
itemCount: faqItems.length,
);
},
future: rootBundle.loadString(getFaqPath(context)),
@ -49,13 +49,10 @@ class FaqPage extends BasePage {
}
String getFaqPath(BuildContext context) {
final settingsStore = context.read<SettingsStore>();
switch (settingsStore.languageCode) {
case 'en':
return 'assets/faq/faq_en.json';
switch (tr(context).localeName) {
case 'de':
return 'assets/faq/faq_de.json';
case 'en':
default:
return 'assets/faq/faq_en.json';
}

View File

@ -3,8 +3,7 @@ import 'package:provider/provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:oxen_wallet/generated/l10n.dart';
import 'package:oxen_wallet/l10n.dart';
import 'package:oxen_wallet/src/stores/wallet_creation/wallet_creation_store.dart';
import 'package:oxen_wallet/src/stores/wallet_creation/wallet_creation_state.dart';
import 'package:oxen_wallet/src/domain/services/wallet_list_service.dart';
@ -19,16 +18,16 @@ import 'package:oxen_wallet/src/util/generate_name.dart';
class NewWalletPage extends BasePage {
NewWalletPage(
{@required this.walletsService,
@required this.walletService,
@required this.sharedPreferences});
{required this.walletsService,
required this.walletService,
required this.sharedPreferences});
final WalletListService walletsService;
final WalletService walletService;
final SharedPreferences sharedPreferences;
@override
String get title => S.current.new_wallet;
String getTitle(AppLocalizations t) => t.new_wallet;
@override
Widget body(BuildContext context) => WalletNameForm();
@ -64,7 +63,7 @@ class _WalletNameFormState extends State<WalletNameForm> {
}
if (state is WalletCreationFailure) {
WidgetsBinding.instance.addPostFrameCallback((_) {
WidgetsBinding.instance?.addPostFrameCallback((_) {
showDialog<void>(
context: context,
builder: (BuildContext context) {
@ -72,7 +71,7 @@ class _WalletNameFormState extends State<WalletNameForm> {
content: Text(state.error),
actions: <Widget>[
FlatButton(
child: Text(S.of(context).ok),
child: Text(tr(context).ok),
onPressed: () => Navigator.of(context).pop(),
),
],
@ -96,12 +95,12 @@ class _WalletNameFormState extends State<WalletNameForm> {
child: TextFormField(
style: TextStyle(
fontSize: 24.0,
color: Theme.of(context).accentTextTheme.subtitle2.color),
color: Theme.of(context).accentTextTheme.subtitle2?.color),
controller: nameController,
decoration: InputDecoration(
hintStyle: TextStyle(
fontSize: 24.0, color: Theme.of(context).hintColor),
hintText: S.of(context).wallet_name,
hintText: tr(context).wallet_name,
focusedBorder: UnderlineInputBorder(
borderSide:
BorderSide(color: OxenPalette.teal, width: 2.0)),
@ -110,14 +109,14 @@ class _WalletNameFormState extends State<WalletNameForm> {
color: Theme.of(context).focusColor,
width: 1.0))),
validator: (value) {
walletCreationStore.validateWalletName(value);
walletCreationStore.validateWalletName(value ?? '', tr(context));
return walletCreationStore.errorMessage;
},
)),
),
Padding(padding: EdgeInsets.only(bottom: 20),
child: Text(
S.of(context).seed_language_choose,
tr(context).seed_language_choose,
textAlign: TextAlign.center,
style: TextStyle(fontSize: 16.0),
),
@ -130,15 +129,15 @@ class _WalletNameFormState extends State<WalletNameForm> {
builder: (context) {
return LoadingPrimaryButton(
onPressed: () {
if (_formKey.currentState.validate()) {
if (_formKey.currentState?.validate() ?? false) {
walletCreationStore.create(name: nameController.text,
language: seedLanguageStore.selectedSeedLanguage);
}
},
text: S.of(context).continue_text,
color: Theme.of(context).primaryTextTheme.button.backgroundColor,
text: tr(context).continue_text,
color: Theme.of(context).primaryTextTheme.button?.backgroundColor,
borderColor:
Theme.of(context).primaryTextTheme.button.decorationColor,
Theme.of(context).primaryTextTheme.button?.decorationColor,
isLoading: walletCreationStore.state is WalletIsCreating,
);
},

View File

@ -1,6 +1,5 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:oxen_wallet/generated/l10n.dart';
import 'package:oxen_wallet/l10n.dart';
import 'package:oxen_wallet/src/screens/base_page.dart';
import 'package:oxen_wallet/src/stores/node_list/node_list_store.dart';
import 'package:oxen_wallet/src/widgets/oxen_text_field.dart';
@ -10,7 +9,7 @@ import 'package:provider/provider.dart';
class NewNodePage extends BasePage {
@override
String get title => S.current.node_new;
String getTitle(AppLocalizations t) => t.node_new;
@override
Widget body(BuildContext context) => NewNodePageForm();
@ -51,39 +50,42 @@ class NewNodeFormState extends State<NewNodePageForm> {
child: Column(
children: <Widget>[
OxenTextField(
hintText: S.of(context).node_address,
hintText: tr(context).node_address,
controller: _nodeAddressController,
validator: (value) {
nodeList.validateNodeAddress(value);
nodeList.validateNodeAddress(value ?? '', tr(context));
return nodeList.errorMessage;
},
),
Padding(
padding: EdgeInsets.only(top: 20),
child: OxenTextField(
hintText: S.of(context).node_port,
hintText: tr(context).node_port,
controller: _nodePortController,
keyboardType: TextInputType.numberWithOptions(
signed: false, decimal: false),
validator: (value) {
nodeList.validateNodePort(value);
nodeList.validateNodePort(value ?? '', tr(context));
return nodeList.errorMessage;
},
)),
// Disable login/password fields for now: oxend currently doesn't support
// Digest MD5 auth (because it is deprecated and insecure), and the wallet2
// code *only* supports Digest MD5 auth.
/*
Padding(
padding: EdgeInsets.only(top: 20),
child: OxenTextField(
hintText: S.of(context).login,
hintText: tr(context).login,
controller: _loginController,
validator: (value) => null,
)),
Padding(
padding: EdgeInsets.only(top: 20),
child: OxenTextField(
hintText: S.of(context).password,
hintText: tr(context).password,
controller: _passwordController,
validator: (value) => null,
)),
*/
],
))),
bottomSection: Container(
@ -99,18 +101,18 @@ class NewNodeFormState extends State<NewNodePageForm> {
_loginController.text = '';
_passwordController.text = '';
},
text: S.of(context).reset,
text: tr(context).reset,
color:
Theme.of(context).accentTextTheme.button.backgroundColor,
Theme.of(context).accentTextTheme.button?.backgroundColor,
borderColor:
Theme.of(context).accentTextTheme.button.decorationColor),
Theme.of(context).accentTextTheme.button?.decorationColor),
)),
Flexible(
child: Container(
padding: EdgeInsets.only(left: 8.0),
child: PrimaryButton(
onPressed: () async {
if (!_formKey.currentState.validate()) {
if (!(_formKey.currentState?.validate() ?? false)) {
return;
}
@ -122,11 +124,11 @@ class NewNodeFormState extends State<NewNodePageForm> {
Navigator.of(context).pop();
},
text: S.of(context).save,
text: tr(context).save,
color:
Theme.of(context).primaryTextTheme.button.backgroundColor,
Theme.of(context).primaryTextTheme.button?.backgroundColor,
borderColor:
Theme.of(context).primaryTextTheme.button.decorationColor,
Theme.of(context).primaryTextTheme.button?.decorationColor,
),
)),
],

View File

@ -1,7 +1,7 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:oxen_wallet/generated/l10n.dart';
import 'package:oxen_wallet/l10n.dart';
import 'package:oxen_wallet/palette.dart';
import 'package:oxen_wallet/routes.dart';
import 'package:oxen_wallet/src/screens/base_page.dart';
@ -15,7 +15,7 @@ class NodeListPage extends BasePage {
NodeListPage();
@override
String get title => S.current.nodes;
String getTitle(AppLocalizations t) => t.nodes;
@override
Widget trailing(context) {
@ -31,8 +31,8 @@ class NodeListPage extends BasePage {
onPressed: () async {
await showConfirmOxenDialog(
context,
S.of(context).node_reset_settings_title,
S.of(context).nodes_list_reset_to_default_message,
tr(context).node_reset_settings_title,
tr(context).nodes_list_reset_to_default_message,
onFutureConfirm: (context) async {
Navigator.pop(context);
await nodeList.reset();
@ -41,10 +41,10 @@ class NodeListPage extends BasePage {
});
},
child: Text(
S.of(context).reset,
tr(context).reset,
style: TextStyle(
fontSize: 16.0,
color: Theme.of(context).primaryTextTheme.subtitle2.color),
color: Theme.of(context).primaryTextTheme.subtitle2?.color),
)),
),
Container(
@ -105,7 +105,7 @@ class NodeListPageBodyState extends State<NodeListPageBody> {
return Observer(builder: (_) {
final isCurrent = settings.node == null
? false
: node.key == settings.node.key;
: node.key == settings.node!.key;
final content = Container(
color: isCurrent ? currentColor : notCurrentColor,
@ -117,7 +117,7 @@ class NodeListPageBodyState extends State<NodeListPageBody> {
color: Theme.of(context)
.primaryTextTheme
.headline6
.color),
?.color),
),
trailing: FutureBuilder(
future: nodeList.isNodeOnline(node),
@ -133,7 +133,7 @@ class NodeListPageBodyState extends State<NodeListPageBody> {
onTap: () async {
if (!isCurrent) {
await showSimpleOxenDialog(context, '',
S.of(context).change_current_node(node.uri),
tr(context).change_current_node(node.uri),
onPressed: (context) async {
Navigator.of(context).pop();
await settings.setCurrentNode(node: node);
@ -150,14 +150,13 @@ class NodeListPageBodyState extends State<NodeListPageBody> {
var result = false;
await showConfirmOxenDialog(
context,
S.of(context).remove_node,
S.of(context).remove_node_message,
tr(context).remove_node,
tr(context).remove_node_message,
onDismiss: (context) =>
Navigator.pop(context, false),
onConfirm: (context) {
result = true;
Navigator.pop(context, true);
return true;
});
return result;
},
@ -177,7 +176,7 @@ class NodeListPageBodyState extends State<NodeListPageBody> {
color: Colors.white,
),
Text(
S.of(context).delete,
tr(context).delete,
style: TextStyle(color: Colors.white),
)
],

View File

@ -0,0 +1,61 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:oxen_wallet/l10n.dart';
import 'package:oxen_wallet/palette.dart';
Widget oxenAmountField({
required GestureTapCallback setAll,
required TextEditingController controller,
required BuildContext context,
FormFieldValidator<String>? validator,
}) {
final theme = Theme.of(context);
return Padding(
padding: const EdgeInsets.only(top: 20),
child: TextFormField(
style: TextStyle(
fontSize: 18.0,
color: theme.accentTextTheme.overline?.color),
controller: controller,
keyboardType: TextInputType.numberWithOptions(signed: false, decimal: true),
inputFormatters: [
FilteringTextInputFormatter.deny(RegExp('[- ]'))
],
validator: validator,
decoration: InputDecoration(
prefixIcon: SizedBox(
width: 75,
child: Padding(
padding: EdgeInsets.only(left: 8, top: 12),
child: Text(
'OXEN:',
style: TextStyle(fontSize: 18, color: theme.accentTextTheme.overline?.color)
)
),
),
suffixIcon: Container(
width: 1,
padding: EdgeInsets.only(top: 0),
child: Center(
child: InkWell(
onTap: setAll,
child: Text(
tr(context).all,
style: TextStyle(fontSize: 14, color: theme.accentTextTheme.overline?.decorationColor)
)
)
),
),
hintStyle: TextStyle(fontSize: 18.0, color: theme.hintColor),
hintText: '0.0000',
focusedBorder: OutlineInputBorder(borderSide: BorderSide(color: OxenPalette.teal, width: 2.0)),
enabledBorder: OutlineInputBorder(borderSide: BorderSide(color: theme.focusColor, width: 1.0)),
errorBorder: OutlineInputBorder(borderSide: BorderSide(color: OxenPalette.red, width: 1.0)),
focusedErrorBorder: OutlineInputBorder(borderSide: BorderSide(color: OxenPalette.red, width: 1.0)),
errorStyle: TextStyle(color: OxenPalette.red)
),
),
);
}

View File

@ -1,15 +1,14 @@
import 'package:provider/provider.dart';
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:oxen_wallet/palette.dart';
import 'package:oxen_wallet/src/stores/settings/settings_store.dart';
import 'package:oxen_wallet/generated/l10n.dart';
import 'package:oxen_wallet/l10n.dart';
abstract class PinCodeWidget extends StatefulWidget {
PinCodeWidget({Key key, this.onPinCodeEntered, this.hasLengthSwitcher})
PinCodeWidget({Key? key, this.onPinCodeEntered, required this.hasLengthSwitcher})
: super(key: key);
final Function(List<int> pin, PinCodeState state) onPinCodeEntered;
final Function(List<int> pin, PinCodeState state)? onPinCodeEntered;
final bool hasLengthSwitcher;
}
@ -27,29 +26,24 @@ class PinCode extends PinCodeWidget {
class PinCodeState<T extends PinCodeWidget> extends State<T> {
static const defaultPinLength = 4;
static const sixPinLength = 6;
static const fourPinLength = 4;
static final deleteIcon = Icon(Icons.backspace, color: Palette.blueGrey);
final _gridViewKey = GlobalKey();
int pinLength = defaultPinLength;
List<int> pin = List<int>.filled(defaultPinLength, null);
String title = S.current.enter_your_pin;
List<int> pin = <int>[];
String title = '';
double _aspectRatio = 0;
void setTitle(String title) => setState(() => this.title = title);
void clear() => setState(() => pin = List<int>.filled(pinLength, null));
void clear() => setState(() => pin.clear());
void onPinCodeEntered(PinCodeState state) =>
widget.onPinCodeEntered(state.pin, this);
void onPinCodeEntered(PinCodeState state) => widget.onPinCodeEntered?.call(state.pin, this);
void changePinLength(int length) {
final newPin = List<int>.filled(length, null);
setState(() {
pinLength = length;
pin = newPin;
pin.clear();
});
}
@ -61,8 +55,12 @@ class PinCodeState<T extends PinCodeWidget> extends State<T> {
}
void calculateAspectRatio() {
if (_gridViewKey.currentContext == null) {
_aspectRatio = 0;
return;
}
final renderBox =
_gridViewKey.currentContext.findRenderObject() as RenderBox;
_gridViewKey.currentContext!.findRenderObject() as RenderBox;
final cellWidth = renderBox.size.width / 3;
final cellHeight = renderBox.size.height / 4;
@ -76,7 +74,7 @@ class PinCodeState<T extends PinCodeWidget> extends State<T> {
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback(afterLayout);
WidgetsBinding.instance?.addPostFrameCallback(afterLayout);
}
void afterLayout(dynamic _) {
@ -94,7 +92,7 @@ class PinCodeState<T extends PinCodeWidget> extends State<T> {
padding: EdgeInsets.only(left: 40.0, right: 40.0, bottom: 40.0),
child: Column(children: <Widget>[
Spacer(flex: 2),
Text(title,
Text(title.isNotEmpty ? title : tr(context).enter_your_pin,
style: TextStyle(fontSize: 24, color: Palette.wildDarkBlue)),
Spacer(flex: 3),
Container(
@ -103,7 +101,7 @@ class PinCodeState<T extends PinCodeWidget> extends State<T> {
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: List.generate(pinLength, (index) {
const size = 10.0;
final isFilled = pin[index] != null;
final isFilled = index < pin.length;
return Container(
width: size,
@ -120,12 +118,10 @@ class PinCodeState<T extends PinCodeWidget> extends State<T> {
if (widget.hasLengthSwitcher) ...[
FlatButton(
onPressed: () {
changePinLength(pinLength == PinCodeState.fourPinLength
? PinCodeState.sixPinLength
: PinCodeState.fourPinLength);
changePinLength(pinLength == 4 ? 6 : 4);
},
child: Text(
_changePinLengthText(),
_changePinLengthText(tr(context)),
style: TextStyle(fontSize: 16.0, color: Palette.wildDarkBlue),
))
],
@ -190,52 +186,24 @@ class PinCodeState<T extends PinCodeWidget> extends State<T> {
}
void _push(int num) {
if (currentPinLength() >= pinLength) {
if (pin.length >= pinLength)
return;
}
for (var i = 0; i < pin.length; i++) {
if (pin[i] == null) {
setState(() => pin[i] = num);
break;
}
}
setState(() => pin.add(num));
final _currentPinLength = currentPinLength();
if (_currentPinLength == pinLength) {
// ignore: invariant_booleans
if (pin.length == pinLength)
onPinCodeEntered(this);
}
}
void _pop() {
if (currentPinLength() == 0) {
if (pin.isEmpty)
return;
}
for (var i = pin.length - 1; i >= 0; i--) {
if (pin[i] != null) {
setState(() => pin[i] = null);
break;
}
}
pin.removeLast();
}
int currentPinLength() {
return pin.fold(0, (v, e) {
if (e != null) {
return v + 1;
}
return v;
});
}
String _changePinLengthText() {
return S.current.use +
(pinLength == PinCodeState.fourPinLength
? '${PinCodeState.sixPinLength}'
: '${PinCodeState.fourPinLength}') +
S.current.digit_pin;
String _changePinLengthText(AppLocalizations l10n) {
return l10n.use_n_digit_pin(pinLength == 4 ? '6' : '4');
}
}

View File

@ -1,6 +1,5 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:oxen_wallet/generated/l10n.dart';
import 'package:oxen_wallet/l10n.dart';
import 'package:oxen_wallet/routes.dart';
import 'package:oxen_wallet/src/screens/base_page.dart';
import 'package:oxen_wallet/src/screens/auth/auth_page.dart';
@ -18,7 +17,7 @@ class ProfilePage extends BasePage {
padding: EdgeInsets.all(0),
onPressed: () => Navigator.of(context).pushNamed(Routes.settings),
child: Icon(Icons.settings_rounded,
color: Theme.of(context).primaryTextTheme.caption.color,
color: Theme.of(context).primaryTextTheme.caption?.color,
size: 25)),
);
}
@ -28,7 +27,7 @@ class ProfilePage extends BasePage {
}
class ProfilePageBody extends StatefulWidget {
ProfilePageBody({Key key}) : super(key: key);
ProfilePageBody({required Key key}) : super(key: key);
@override
ProfilePageBodyState createState() => ProfilePageBodyState();
@ -37,6 +36,7 @@ class ProfilePageBody extends StatefulWidget {
class ProfilePageBodyState extends State<ProfilePageBody> {
@override
Widget build(BuildContext context) {
final t = tr(context);
return SingleChildScrollView(
child: Column(
children: <Widget>[
@ -46,40 +46,40 @@ class ProfilePageBodyState extends State<ProfilePageBody> {
children: [
NavListArrow(
leading: Icon(Icons.account_balance_wallet_rounded,
color: Theme.of(context).primaryTextTheme.headline6.color),
text: S.current.wallets,
color: Theme.of(context).primaryTextTheme.headline6?.color),
text: t.wallets,
onTap: () =>
Navigator.of(context).pushNamed(Routes.walletList)),
NavListArrow(
leading: Icon(Icons.settings_rounded,
color: Theme.of(context).primaryTextTheme.headline6.color),
text: S.current.settings_title,
color: Theme.of(context).primaryTextTheme.headline6?.color),
text: t.settings_title,
onTap: () =>
Navigator.of(context).pushNamed(Routes.settings)),
NavListHeader(title: S.current.wallet_menu),
NavListHeader(title: t.wallet_menu),
NavListArrow(
leading: Icon(Icons.attach_money_rounded,
color: Theme.of(context).primaryTextTheme.headline6.color),
text: S.current.title_stakes,
color: Theme.of(context).primaryTextTheme.headline6?.color),
text: t.title_stakes,
onTap: () =>
Navigator.of(context).pushNamed(Routes.stake)),
NavListArrow(
leading: Icon(Icons.contacts_rounded,
color: Theme.of(context).primaryTextTheme.headline6.color),
text: S.current.address_book_menu,
color: Theme.of(context).primaryTextTheme.headline6?.color),
text: t.address_book_menu,
onTap: () =>
Navigator.of(context).pushNamed(Routes.addressBook)),
NavListArrow(
leading: Icon(Icons.account_circle_rounded,
color: Theme.of(context).primaryTextTheme.headline6.color),
text: S.current.accounts,
color: Theme.of(context).primaryTextTheme.headline6?.color),
text: t.accounts,
onTap: () =>
Navigator.of(context).pushNamed(Routes.accountList)),
NavListHeader(title: S.current.dangerzone),
NavListHeader(title: t.dangerzone),
NavListArrow(
leading: Icon(Icons.vpn_key_rounded,
color: Theme.of(context).primaryTextTheme.headline6.color),
text: S.current.show_keys,
color: Theme.of(context).primaryTextTheme.headline6?.color),
text: t.show_keys,
onTap: () => Navigator.of(context).pushNamed(Routes.auth,
arguments: (bool isAuthenticatedSuccessfully,
AuthPageState auth) =>
@ -89,8 +89,8 @@ class ProfilePageBodyState extends State<ProfilePageBody> {
: null)),
NavListArrow(
leading: Icon(Icons.vpn_key_rounded,
color: Theme.of(context).primaryTextTheme.headline6.color),
text: S.current.show_seed,
color: Theme.of(context).primaryTextTheme.headline6?.color),
text: t.show_seed,
onTap: () => Navigator.of(context).pushNamed(Routes.auth,
arguments: (bool isAuthenticatedSuccessfully,
AuthPageState auth) =>

View File

@ -1,30 +0,0 @@
import 'package:flutter/material.dart';
import 'package:qr/qr.dart';
import 'package:oxen_wallet/src/screens/receive/qr_painter.dart';
class QrImage extends StatelessWidget {
QrImage({
@required String data,
this.size = 100.0,
this.backgroundColor,
Color foregroundColor = Colors.black,
int version = 7,
int errorCorrectionLevel = QrErrorCorrectLevel.L,
}) : _painter = QrPainter(data, foregroundColor, version, errorCorrectionLevel);
final QrPainter _painter;
final Color backgroundColor;
final double size;
@override
Widget build(BuildContext context) {
return Container(
width: size,
height: size,
color: backgroundColor,
child: CustomPaint(
painter: _painter,
),
);
}
}

View File

@ -1,48 +0,0 @@
import 'package:flutter/material.dart';
import 'package:qr/qr.dart';
class QrPainter extends CustomPainter {
QrPainter(
String data,
this.color,
this.version,
this.errorCorrectionLevel,
) : _qr = QrCode(version, errorCorrectionLevel) {
_p.color = color;
_qr.addData(data);
_qr.make();
}
final int version;
final int errorCorrectionLevel;
final Color color;
final QrCode _qr;
final _p = Paint()..style = PaintingStyle.fill;
@override
void paint(Canvas canvas, Size size) {
final squareSize = size.shortestSide / _qr.moduleCount;
for (var x = 0; x < _qr.moduleCount; x++) {
for (var y = 0; y < _qr.moduleCount; y++) {
if (_qr.isDark(y, x)) {
final squareRect = Rect.fromLTWH(
x * squareSize, y * squareSize, squareSize, squareSize);
canvas.drawRect(squareRect, _p);
}
}
}
}
@override
bool shouldRepaint(CustomPainter oldDelegate) {
if (oldDelegate is QrPainter) {
return color != oldDelegate.color ||
errorCorrectionLevel != oldDelegate.errorCorrectionLevel ||
version != oldDelegate.version;
}
return false;
}
}

View File

@ -1,24 +1,23 @@
import 'package:esys_flutter_share/esys_flutter_share.dart';
import 'package:flutter/cupertino.dart';
import 'package:share_plus/share_plus.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:oxen_wallet/generated/l10n.dart';
import 'package:oxen_wallet/l10n.dart';
import 'package:oxen_wallet/palette.dart';
import 'package:oxen_wallet/routes.dart';
import 'package:oxen_wallet/src/screens/base_page.dart';
import 'package:oxen_wallet/src/screens/receive/qr_image.dart';
import 'package:oxen_wallet/src/stores/subaddress_list/subaddress_list_store.dart';
import 'package:oxen_wallet/src/stores/wallet/wallet_store.dart';
import 'package:oxen_wallet/src/widgets/oxen_text_field.dart';
import 'package:provider/provider.dart';
import 'package:qr_flutter/qr_flutter.dart';
class ReceivePage extends BasePage {
@override
bool get isModalBackButton => true;
@override
String get title => S.current.receive;
String getTitle(AppLocalizations t) => t.receive;
@override
Widget trailing(BuildContext context) {
@ -33,8 +32,7 @@ class ReceivePage extends BasePage {
highlightColor: Colors.transparent,
splashColor: Colors.transparent,
padding: EdgeInsets.all(0),
onPressed: () => Share.text(
'Share address', walletStore.subaddress.address, 'text/plain'),
onPressed: () => Share.share(walletStore.subaddress.address),
child: Icon(
Icons.share,
size: 30.0,
@ -72,7 +70,7 @@ class ReceiveBodyState extends State<ReceiveBody> {
final notCurrentColor = Theme.of(context).scaffoldBackgroundColor;
amountController.addListener(() {
if (_formKey.currentState.validate()) {
if (_formKey.currentState?.validate() ?? false) {
walletStore.onChangedAmountValue(amountController.text);
} else {
walletStore.onChangedAmountValue('');
@ -100,14 +98,15 @@ class ReceiveBodyState extends State<ReceiveBody> {
flex: 2,
child: AspectRatio(
aspectRatio: 1.0,
child: Container(
padding: EdgeInsets.all(5),
color: Colors.white,
child: QrImage(
data: walletStore.subaddress.address +
walletStore.amountValue,
backgroundColor: Colors.transparent,
),
child: QrImage(
size: 100.0,
version: QrVersions.auto,
errorCorrectionLevel: QrErrorCorrectLevel.M,
data: walletStore.subaddress.address + walletStore.amountValue,
embeddedImage: AssetImage('assets/images/oxen.png'),
embeddedImageStyle: QrEmbeddedImageStyle(size: Size(40, 40)),
backgroundColor: OxenPalette.whiteBlue,
foregroundColor: OxenPalette.navy,
),
)),
Spacer(flex: 1)
@ -125,9 +124,9 @@ class ReceiveBodyState extends State<ReceiveBody> {
onTap: () {
Clipboard.setData(ClipboardData(
text: walletStore.subaddress.address));
Scaffold.of(context).showSnackBar(SnackBar(
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text(
S.of(context).copied_to_clipboard,
tr(context).copied_to_clipboard,
style: TextStyle(color: Colors.white),
),
backgroundColor: Colors.green,
@ -142,7 +141,7 @@ class ReceiveBodyState extends State<ReceiveBody> {
color: Theme.of(context)
.primaryTextTheme
.headline6
.color)
?.color)
)
)
)
@ -161,9 +160,9 @@ class ReceiveBodyState extends State<ReceiveBody> {
inputFormatters: [
FilteringTextInputFormatter.deny(RegExp('[- ]'))
],
hintText: S.of(context).amount,
hintText: tr(context).amount,
validator: (value) {
walletStore.validateAmount(value);
walletStore.validateAmount(value ?? '', tr(context));
return walletStore.errorMessage;
},
controller: amountController
@ -177,18 +176,18 @@ class ReceiveBodyState extends State<ReceiveBody> {
children: <Widget>[
Expanded(
child: Container(
color: Theme.of(context).accentTextTheme.headline5.color,
color: Theme.of(context).accentTextTheme.headline5?.color,
child: Column(
children: <Widget>[
ListTile(
title: Text(
S.of(context).subaddresses,
tr(context).subaddresses,
style: TextStyle(
fontSize: 16.0,
color: Theme.of(context)
.primaryTextTheme
.headline5
.color),
?.color),
),
trailing: Container(
width: 28.0,
@ -252,7 +251,7 @@ class ReceiveBodyState extends State<ReceiveBody> {
color: Theme.of(context)
.primaryTextTheme
.headline5
.color),
?.color),
),
)
]),

View File

@ -5,12 +5,12 @@ import 'package:oxen_wallet/src/screens/base_page.dart';
import 'package:oxen_wallet/src/widgets/blockchain_height_widget.dart';
import 'package:oxen_wallet/src/widgets/primary_button.dart';
import 'package:oxen_wallet/src/stores/rescan/rescan_wallet_store.dart';
import 'package:oxen_wallet/generated/l10n.dart';
import 'package:oxen_wallet/l10n.dart';
class RescanPage extends BasePage {
final blockchainKey = GlobalKey<BlockchainHeightState>();
@override
String get title => S.current.rescan;
String getTitle(AppLocalizations t) => t.rescan;
@override
Widget body(BuildContext context) {
@ -25,16 +25,17 @@ class RescanPage extends BasePage {
builder: (_) => LoadingPrimaryButton(
isLoading:
rescanWalletStore.state == RescanWalletState.rescaning,
text: S.of(context).rescan,
text: tr(context).rescan,
onPressed: () async {
await rescanWalletStore.rescanCurrentWallet(
restoreHeight: blockchainKey.currentState.height);
if (blockchainKey.currentState != null)
await rescanWalletStore.rescanCurrentWallet(
restoreHeight: blockchainKey.currentState!.height);
Navigator.of(context).pop();
},
color:
Theme.of(context).primaryTextTheme.button.backgroundColor,
Theme.of(context).primaryTextTheme.button?.backgroundColor,
borderColor:
Theme.of(context).primaryTextTheme.button.decorationColor))
Theme.of(context).primaryTextTheme.button?.decorationColor))
]),
);
}

View File

@ -6,13 +6,13 @@ import 'package:oxen_wallet/src/screens/restore/widgets/restore_button.dart';
import 'package:oxen_wallet/src/screens/restore/widgets/image_widget.dart';
import 'package:oxen_wallet/src/screens/restore/widgets/base_restore_widget.dart';
import 'package:oxen_wallet/src/screens/base_page.dart';
import 'package:oxen_wallet/generated/l10n.dart';
import 'package:oxen_wallet/l10n.dart';
class RestoreOptionsPage extends BasePage {
static const _aspectRatioImage = 2.086;
@override
String get title => S.current.restore_restore_wallet;
String getTitle(AppLocalizations t) => t.restore_restore_wallet;
@override
Color get backgroundColor => Palette.creamyGrey;
@ -24,6 +24,8 @@ class RestoreOptionsPage extends BasePage {
Widget body(BuildContext context) {
final isLargeScreen = MediaQuery.of(context).size.height > largeHeight;
final t = tr(context);
return BaseRestoreWidget(
firstRestoreButton: RestoreButton(
onPressed: () =>
@ -36,9 +38,9 @@ class RestoreOptionsPage extends BasePage {
),
titleColor: Palette.lightViolet,
color: Palette.lightViolet,
title: S.of(context).restore_title_from_seed_keys,
description: S.of(context).restore_description_from_seed_keys,
textButton: S.of(context).restore_next,
title: t.restore_title_from_seed_keys,
description: t.restore_description_from_seed_keys,
textButton: t.restore_next,
),
secondRestoreButton: RestoreButton(
onPressed: () {},
@ -49,9 +51,9 @@ class RestoreOptionsPage extends BasePage {
),
titleColor: OxenPalette.teal,
color: OxenPalette.teal,
title: S.of(context).restore_title_from_backup,
description: S.of(context).restore_description_from_backup,
textButton: S.of(context).restore_next,
title: t.restore_title_from_backup,
description: t.restore_description_from_backup,
textButton: t.restore_next,
),
isLargeScreen: isLargeScreen,
);

View File

@ -1,11 +1,9 @@
import 'package:mobx/mobx.dart';
import 'package:provider/provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:flutter/services.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:oxen_wallet/generated/l10n.dart';
import 'package:oxen_wallet/l10n.dart';
import 'package:oxen_wallet/src/domain/services/wallet_list_service.dart';
import 'package:oxen_wallet/src/domain/services/wallet_service.dart';
import 'package:oxen_wallet/src/stores/wallet_restoration/wallet_restoration_store.dart';
@ -19,16 +17,16 @@ import 'package:oxen_wallet/src/stores/seed_language/seed_language_store.dart';
class RestoreWalletFromKeysPage extends BasePage {
RestoreWalletFromKeysPage(
{@required this.walletsService,
@required this.sharedPreferences,
@required this.walletService});
{required this.walletsService,
required this.sharedPreferences,
required this.walletService});
final WalletListService walletsService;
final WalletService walletService;
final SharedPreferences sharedPreferences;
@override
String get title => S.current.restore_title_from_keys;
String getTitle(AppLocalizations t) => t.restore_title_from_keys;
@override
Widget body(BuildContext context) => RestoreFromKeysFrom();
@ -58,7 +56,7 @@ class _RestoreFromKeysFromState extends State<RestoreFromKeysFrom> {
}
if (state is WalletRestorationFailure) {
WidgetsBinding.instance.addPostFrameCallback((_) {
WidgetsBinding.instance?.addPostFrameCallback((_) {
showDialog<void>(
context: context,
builder: (BuildContext context) {
@ -66,7 +64,7 @@ class _RestoreFromKeysFromState extends State<RestoreFromKeysFrom> {
content: Text(state.error),
actions: <Widget>[
FlatButton(
child: Text(S.of(context).ok),
child: Text(tr(context).ok),
onPressed: () => Navigator.of(context).pop(),
),
],
@ -97,7 +95,7 @@ class _RestoreFromKeysFromState extends State<RestoreFromKeysFrom> {
decoration: InputDecoration(
hintStyle:
TextStyle(color: Theme.of(context).hintColor),
hintText: S.of(context).restore_wallet_name,
hintText: tr(context).restore_wallet_name,
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(
color: OxenPalette.teal, width: 2.0)),
@ -106,7 +104,7 @@ class _RestoreFromKeysFromState extends State<RestoreFromKeysFrom> {
color: Theme.of(context).focusColor,
width: 1.0))),
validator: (value) {
walletRestorationStore.validateWalletName(value);
walletRestorationStore.validateWalletName(value ?? '', tr(context));
return walletRestorationStore.errorMessage;
},
),
@ -126,7 +124,7 @@ class _RestoreFromKeysFromState extends State<RestoreFromKeysFrom> {
decoration: InputDecoration(
hintStyle:
TextStyle(color: Theme.of(context).hintColor),
hintText: S.of(context).restore_address,
hintText: tr(context).restore_address,
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(
color: OxenPalette.teal, width: 2.0)),
@ -135,7 +133,7 @@ class _RestoreFromKeysFromState extends State<RestoreFromKeysFrom> {
color: Theme.of(context).focusColor,
width: 1.0))),
validator: (value) {
walletRestorationStore.validateAddress(value);
walletRestorationStore.validateAddress(value ?? '', l10n: tr(context));
return walletRestorationStore.errorMessage;
},
),
@ -153,7 +151,7 @@ class _RestoreFromKeysFromState extends State<RestoreFromKeysFrom> {
decoration: InputDecoration(
hintStyle:
TextStyle(color: Theme.of(context).hintColor),
hintText: S.of(context).restore_view_key_private,
hintText: tr(context).restore_view_key_private,
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(
color: OxenPalette.teal, width: 2.0)),
@ -162,7 +160,7 @@ class _RestoreFromKeysFromState extends State<RestoreFromKeysFrom> {
color: Theme.of(context).focusColor,
width: 1.0))),
validator: (value) {
walletRestorationStore.validateKeys(value);
walletRestorationStore.validateKeys(value ?? '', tr(context));
return walletRestorationStore.errorMessage;
},
),
@ -180,7 +178,7 @@ class _RestoreFromKeysFromState extends State<RestoreFromKeysFrom> {
decoration: InputDecoration(
hintStyle:
TextStyle(color: Theme.of(context).hintColor),
hintText: S.of(context).restore_spend_key_private,
hintText: tr(context).restore_spend_key_private,
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(
color: OxenPalette.teal, width: 2.0)),
@ -189,7 +187,7 @@ class _RestoreFromKeysFromState extends State<RestoreFromKeysFrom> {
color: Theme.of(context).focusColor,
width: 1.0))),
validator: (value) {
walletRestorationStore.validateKeys(value);
walletRestorationStore.validateKeys(value ?? '', tr(context));
return walletRestorationStore.errorMessage;
},
),
@ -205,20 +203,22 @@ class _RestoreFromKeysFromState extends State<RestoreFromKeysFrom> {
bottomSection: Observer(builder: (_) {
return LoadingPrimaryButton(
onPressed: () {
if (_formKey.currentState.validate()) {
if (_formKey.currentState == null || _blockchainHeightKey.currentState == null)
return;
if (_formKey.currentState!.validate()) {
walletRestorationStore.restoreFromKeys(
name: _nameController.text,
language: seedLanguageStore.selectedSeedLanguage,
address: _addressController.text,
viewKey: _viewKeyController.text,
spendKey: _spendKeyController.text,
restoreHeight: _blockchainHeightKey.currentState.height);
restoreHeight: _blockchainHeightKey.currentState!.height);
}
},
text: S.of(context).restore_recover,
color: Theme.of(context).primaryTextTheme.button.backgroundColor,
text: tr(context).restore_recover,
color: Theme.of(context).primaryTextTheme.button?.backgroundColor,
borderColor:
Theme.of(context).primaryTextTheme.button.decorationColor);
Theme.of(context).primaryTextTheme.button?.decorationColor);
}),
);
}

View File

@ -1,9 +1,8 @@
import 'package:mobx/mobx.dart';
import 'package:provider/provider.dart';
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:oxen_wallet/generated/l10n.dart';
import 'package:oxen_wallet/l10n.dart';
import 'package:oxen_wallet/src/stores/wallet_restoration/wallet_restoration_store.dart';
import 'package:oxen_wallet/src/stores/wallet_restoration/wallet_restoration_state.dart';
import 'package:oxen_wallet/src/screens/base_page.dart';
@ -14,7 +13,7 @@ import 'package:oxen_wallet/palette.dart';
class RestoreWalletFromSeedDetailsPage extends BasePage {
@override
String get title => S.current.restore_wallet_restore_description;
String getTitle(AppLocalizations t) => t.restore_wallet_restore_description;
@override
Widget body(BuildContext context) => RestoreFromSeedDetailsForm();
@ -42,7 +41,7 @@ class _RestoreFromSeedDetailsFormState
}
if (state is WalletRestorationFailure) {
WidgetsBinding.instance.addPostFrameCallback((_) {
WidgetsBinding.instance?.addPostFrameCallback((_) {
showDialog<void>(
context: context,
builder: (BuildContext context) {
@ -50,7 +49,7 @@ class _RestoreFromSeedDetailsFormState
content: Text(state.error),
actions: <Widget>[
FlatButton(
child: Text(S.of(context).ok),
child: Text(tr(context).ok),
onPressed: () => Navigator.of(context).pop(),
),
],
@ -83,7 +82,7 @@ class _RestoreFromSeedDetailsFormState
decoration: InputDecoration(
hintStyle: TextStyle(
color: Theme.of(context).hintColor),
hintText: S.of(context).restore_wallet_name,
hintText: tr(context).restore_wallet_name,
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(
color: OxenPalette.teal,
@ -94,7 +93,7 @@ class _RestoreFromSeedDetailsFormState
width: 1.0))),
validator: (value) {
walletRestorationStore
.validateWalletName(value);
.validateWalletName(value ?? '', tr(context));
return walletRestorationStore.errorMessage;
},
),
@ -109,17 +108,17 @@ class _RestoreFromSeedDetailsFormState
bottomSection: Observer(builder: (_) {
return LoadingPrimaryButton(
onPressed: () {
if (_formKey.currentState.validate()) {
if (_formKey.currentState!.validate()) {
walletRestorationStore.restoreFromSeed(
name: _nameController.text,
restoreHeight: _blockchainHeightKey.currentState.height);
restoreHeight: _blockchainHeightKey.currentState!.height);
}
},
isLoading: walletRestorationStore.state is WalletIsRestoring,
text: S.of(context).restore_recover,
color: Theme.of(context).primaryTextTheme.button.backgroundColor,
text: tr(context).restore_recover,
color: Theme.of(context).primaryTextTheme.button?.backgroundColor,
borderColor:
Theme.of(context).primaryTextTheme.button.decorationColor);
Theme.of(context).primaryTextTheme.button?.decorationColor);
}),
);
}

View File

@ -1,10 +1,9 @@
import 'package:provider/provider.dart';
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/services.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:oxen_wallet/routes.dart';
import 'package:oxen_wallet/generated/l10n.dart';
import 'package:oxen_wallet/l10n.dart';
import 'package:oxen_wallet/src/domain/services/wallet_list_service.dart';
import 'package:oxen_wallet/src/domain/services/wallet_service.dart';
import 'package:oxen_wallet/src/screens/base_page.dart';
@ -14,9 +13,9 @@ import 'package:oxen_wallet/src/stores/seed_language/seed_language_store.dart';
class RestoreWalletFromSeedPage extends BasePage {
RestoreWalletFromSeedPage(
{@required this.walletsService,
@required this.walletService,
@required this.sharedPreferences});
{required this.walletsService,
required this.walletService,
required this.sharedPreferences});
final WalletListService walletsService;
final WalletService walletService;
@ -24,23 +23,23 @@ class RestoreWalletFromSeedPage extends BasePage {
final formKey = GlobalKey<_RestoreFromSeedFormState>();
@override
String get title => S.current.restore_title_from_seed;
String getTitle(AppLocalizations t) => t.restore_title_from_seed;
@override
Widget trailing(BuildContext context) => SizedBox(
width: 80,
height: 20,
child: FlatButton(
child: Text(S.of(context).clear),
padding: EdgeInsets.all(0),
onPressed: () => formKey?.currentState?.clear()));
onPressed: () => formKey.currentState?.clear(),
child: Text(tr(context).clear)));
@override
Widget body(BuildContext context) => RestoreFromSeedForm(key: formKey);
}
class RestoreFromSeedForm extends StatefulWidget {
RestoreFromSeedForm({Key key}) : super(key: key);
RestoreFromSeedForm({required Key key}) : super(key: key);
@override
_RestoreFromSeedFormState createState() => _RestoreFromSeedFormState();
@ -48,7 +47,7 @@ class RestoreFromSeedForm extends StatefulWidget {
class _RestoreFromSeedFormState extends State<RestoreFromSeedForm> {
final _seedKey = GlobalKey<SeedWidgetState>();
void clear() => _seedKey.currentState.clear();
void clear() => _seedKey.currentState?.clear();
@override
Widget build(BuildContext context) {
@ -62,10 +61,10 @@ class _RestoreFromSeedFormState extends State<RestoreFromSeedForm> {
padding: EdgeInsets.only(left: 20.0, right: 20.0),
child: SeedWidget(
key: _seedKey,
onMnemoticChange: (seed) => walletRestorationStore.setSeed(seed),
onMnemonicChange: (seed) => walletRestorationStore.setSeed(seed),
onFinish: () => Navigator.of(context).pushNamed(
Routes.restoreWalletFromSeedDetails,
arguments: _seedKey.currentState.items),
arguments: _seedKey.currentState?.items),
seedLanguage: seedLanguageStore.selectedSeedLanguage,
),
),

View File

@ -6,7 +6,7 @@ import 'package:oxen_wallet/src/screens/restore/widgets/restore_button.dart';
import 'package:oxen_wallet/src/screens/restore/widgets/image_widget.dart';
import 'package:oxen_wallet/src/screens/restore/widgets/base_restore_widget.dart';
import 'package:oxen_wallet/src/screens/base_page.dart';
import 'package:oxen_wallet/generated/l10n.dart';
import 'package:oxen_wallet/l10n.dart';
import 'package:oxen_wallet/src/stores/seed_language/seed_language_store.dart';
import 'package:provider/provider.dart';
@ -14,7 +14,7 @@ class RestoreWalletOptionsPage extends BasePage {
static const _aspectRatioImage = 2.086;
@override
String get title => S.current.restore_seed_keys_restore;
String getTitle(AppLocalizations t) => t.restore_seed_keys_restore;
@override
Color get backgroundColor => Palette.creamyGrey;
@ -39,9 +39,9 @@ class RestoreWalletOptionsPage extends BasePage {
isLargeScreen: isLargeScreen),
titleColor: Palette.lightViolet,
color: Palette.lightViolet,
title: S.of(context).restore_title_from_seed,
description: S.of(context).restore_description_from_seed,
textButton: S.of(context).restore_next,
title: tr(context).restore_title_from_seed,
description: tr(context).restore_description_from_seed,
textButton: tr(context).restore_next,
),
secondRestoreButton: RestoreButton(
onPressed: () {
@ -54,9 +54,9 @@ class RestoreWalletOptionsPage extends BasePage {
isLargeScreen: isLargeScreen),
titleColor: OxenPalette.teal,
color: OxenPalette.teal,
title: S.of(context).restore_title_from_keys,
description: S.of(context).restore_description_from_keys,
textButton: S.of(context).restore_next,
title: tr(context).restore_title_from_keys,
description: tr(context).restore_description_from_keys,
textButton: tr(context).restore_next,
),
isLargeScreen: isLargeScreen,
);

View File

@ -4,8 +4,8 @@ const largeHeight = 700;
class BaseRestoreWidget extends StatelessWidget {
BaseRestoreWidget({
@required this.firstRestoreButton,
@required this.secondRestoreButton,
required this.firstRestoreButton,
required this.secondRestoreButton,
this.isLargeScreen = false
});
@ -42,4 +42,4 @@ class BaseRestoreWidget extends StatelessWidget {
)
);
}
}
}

View File

@ -2,8 +2,8 @@ import 'package:flutter/material.dart';
class ImageWidget extends StatelessWidget {
ImageWidget({
@required this.image,
@required this.aspectRatioImage,
required this.image,
required this.aspectRatioImage,
this.isLargeScreen = false});
final Image image;
@ -26,4 +26,4 @@ class ImageWidget extends StatelessWidget {
)
: image;
}
}
}

View File

@ -4,10 +4,10 @@ import 'package:auto_size_text/auto_size_text.dart';
class RestoreButton extends StatelessWidget {
const RestoreButton(
{@required this.onPressed,
@required this.imageWidget,
@required this.color,
@required this.titleColor,
{required this.onPressed,
required this.imageWidget,
required this.color,
required this.titleColor,
this.title = '',
this.description = '',
this.textButton = ''});
@ -25,7 +25,7 @@ class RestoreButton extends StatelessWidget {
return Container(
margin: EdgeInsets.only(top: 20.0, bottom: 20.0),
decoration: BoxDecoration(
color: Theme.of(context).accentTextTheme.headline5.backgroundColor,
color: Theme.of(context).accentTextTheme.headline5?.backgroundColor,
borderRadius: BorderRadius.all(Radius.circular(20.0)),
boxShadow: [
BoxShadow(
@ -63,7 +63,7 @@ class RestoreButton extends StatelessWidget {
description,
textAlign: TextAlign.center,
style: TextStyle(
color: Theme.of(context).accentTextTheme.subtitle1.color,
color: Theme.of(context).accentTextTheme.subtitle1?.color,
),
maxLines: 2,
)
@ -81,7 +81,7 @@ class RestoreButton extends StatelessWidget {
color: Theme.of(context)
.accentTextTheme
.headline5
.decorationColor,
?.decorationColor ?? OxenPalette.teal,
width: 1.15)),
color: Colors.transparent,
),

View File

@ -20,22 +20,22 @@ import 'package:provider/provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
class Root extends StatefulWidget {
Root({Key key}) : super(key: key);
Root({Key? key}) : super(key: key);
@override
RootState createState() => RootState();
}
class RootState extends State<Root> with WidgetsBindingObserver {
bool _isInactive;
bool _postFrameCallback;
AuthenticationStore _authenticationStore;
bool _isInactive = false;
bool _postFrameCallback = false;
AuthenticationStore? _authenticationStore;
@override
void initState() {
_isInactive = false;
_postFrameCallback = false;
WidgetsBinding.instance.addObserver(this);
WidgetsBinding.instance?.addObserver(this);
super.initState();
}
@ -45,10 +45,9 @@ class RootState extends State<Root> with WidgetsBindingObserver {
case AppLifecycleState.paused:
if (isQrScannerShown) return;
if (!_isInactive &&
_authenticationStore.state ==
AuthenticationState.authenticated ||
_authenticationStore.state == AuthenticationState.active) {
if (!_isInactive && _authenticationStore != null &&
(_authenticationStore!.state == AuthenticationState.authenticated ||
_authenticationStore!.state == AuthenticationState.active)) {
setState(() => _isInactive = true);
}
@ -75,7 +74,7 @@ class RootState extends State<Root> with WidgetsBindingObserver {
if (_isInactive && !_postFrameCallback) {
_postFrameCallback = true;
WidgetsBinding.instance.addPostFrameCallback((_) {
WidgetsBinding.instance?.addPostFrameCallback((_) {
Navigator.of(context).pushNamed(Routes.unlock,
arguments: (bool isAuthenticatedSuccessfully, AuthPageState auth) {
if (!isAuthenticatedSuccessfully) return;
@ -90,7 +89,7 @@ class RootState extends State<Root> with WidgetsBindingObserver {
}
return Observer(builder: (_) {
final state = _authenticationStore.state;
final state = _authenticationStore!.state;
if (state == AuthenticationState.denied) return WelcomePage();
if (state == AuthenticationState.readyToLogin) {
@ -117,7 +116,7 @@ class RootState extends State<Root> with WidgetsBindingObserver {
settingsStore: settingsStore,
walletService: walletService,
callback: () =>
_authenticationStore.state = AuthenticationState.authenticated);
_authenticationStore?.state = AuthenticationState.authenticated);
}
return Container(color: Colors.white);

View File

@ -6,9 +6,9 @@ import 'package:oxen_wallet/src/stores/settings/settings_store.dart';
import 'package:oxen_wallet/src/stores/wallet_seed/wallet_seed_store.dart';
Widget createSeedPage(
{@required SettingsStore settingsStore,
@required WalletService walletService,
@required void Function() callback}) =>
{required SettingsStore settingsStore,
required WalletService walletService,
required void Function()? callback}) =>
Provider(
create: (_) => WalletSeedStore(walletService: walletService),
child: SeedPage(onCloseCallback: callback));
child: SeedPage(onCloseCallback: callback));

View File

@ -1,11 +1,10 @@
import 'package:provider/provider.dart';
import 'package:esys_flutter_share/esys_flutter_share.dart';
import 'package:share_plus/share_plus.dart';
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/services.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:oxen_wallet/palette.dart';
import 'package:oxen_wallet/generated/l10n.dart';
import 'package:oxen_wallet/l10n.dart';
import 'package:oxen_wallet/src/widgets/primary_button.dart';
import 'package:oxen_wallet/src/stores/wallet_seed/wallet_seed_store.dart';
import 'package:oxen_wallet/src/screens/base_page.dart';
@ -20,23 +19,23 @@ class SeedPage extends BasePage {
bool get isModalBackButton => true;
@override
String get title => S.current.seed_title;
String getTitle(AppLocalizations t) => t.seed_title;
final VoidCallback onCloseCallback;
final VoidCallback? onCloseCallback;
@override
void onClose(BuildContext context) =>
onCloseCallback != null ? onCloseCallback() : Navigator.of(context).pop();
onCloseCallback != null ? onCloseCallback!() : Navigator.of(context).pop();
@override
Widget leading(BuildContext context) {
Widget? leading(BuildContext context) {
return onCloseCallback != null ? Offstage() : super.leading(context);
}
@override
Widget body(BuildContext context) {
final walletSeedStore = Provider.of<WalletSeedStore>(context);
String _seed;
var _seed = '';
return Container(
padding: EdgeInsets.all(30.0),
@ -67,14 +66,14 @@ class SeedPage extends BasePage {
padding: EdgeInsets.only(bottom: 20.0),
margin: EdgeInsets.only(bottom: 10.0),
child: Text(
walletSeedStore.name ?? '',
walletSeedStore.name,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 18.0,
color: Theme.of(context)
.primaryTextTheme
.button
.color),
?.color),
),
))
],
@ -90,7 +89,7 @@ class SeedPage extends BasePage {
color: Theme.of(context)
.primaryTextTheme
.headline6
.color),
?.color),
)
],
);
@ -104,19 +103,16 @@ class SeedPage extends BasePage {
child: Container(
padding: EdgeInsets.only(right: 8.0),
child: PrimaryButton(
onPressed: () => Share.text(
S.of(context).seed_share,
_seed,
'text/plain'),
onPressed: () => Share.share(_seed),
color: Theme.of(context)
.primaryTextTheme
.button
.backgroundColor,
?.backgroundColor,
borderColor: Theme.of(context)
.primaryTextTheme
.button
.decorationColor,
text: S.of(context).save),
?.decorationColor,
text: tr(context).save),
)),
Flexible(
child: Container(
@ -128,24 +124,21 @@ class SeedPage extends BasePage {
ClipboardData(text: _seed));
Scaffold.of(context).showSnackBar(
SnackBar(
content: Text(S
.of(context)
.copied_to_clipboard),
content: Text(tr(context).copied_to_clipboard),
backgroundColor: Colors.green,
duration:
Duration(milliseconds: 1500),
duration: Duration(milliseconds: 1500),
),
);
},
text: S.of(context).copy,
text: tr(context).copy,
color: Theme.of(context)
.accentTextTheme
.caption
.backgroundColor,
?.backgroundColor,
borderColor: Theme.of(context)
.accentTextTheme
.caption
.decorationColor),
?.decorationColor),
)))
],
),
@ -157,7 +150,7 @@ class SeedPage extends BasePage {
onCloseCallback != null
? PrimaryButton(
onPressed: () => onClose(context),
text: S.of(context).restore_next,
text: tr(context).restore_next,
color: Palette.darkGrey,
borderColor: Palette.darkGrey)
: Offstage()

View File

@ -1,6 +1,5 @@
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:oxen_wallet/generated/l10n.dart';
import 'package:oxen_wallet/l10n.dart';
import 'package:oxen_wallet/src/widgets/primary_button.dart';
import 'package:oxen_wallet/src/screens/base_page.dart';
import 'package:oxen_wallet/src/screens/seed_language/widgets/seed_language_picker.dart';
@ -25,7 +24,7 @@ class SeedLanguage extends BasePage {
children: <Widget>[
imageSeed,
Text(
S.of(context).seed_language_choose,
tr(context).seed_language_choose,
textAlign: TextAlign.center,
style: TextStyle(fontSize: 16.0),
),
@ -40,11 +39,11 @@ class SeedLanguage extends BasePage {
PrimaryButton(
onPressed: () =>
Navigator.of(context).popAndPushNamed(seedLanguageStore.currentRoute),
text: S.of(context).seed_language_next,
text: tr(context).seed_language_next,
color:
Theme.of(context).primaryTextTheme.button.backgroundColor,
Theme.of(context).primaryTextTheme.button?.backgroundColor,
borderColor:
Theme.of(context).primaryTextTheme.button.decorationColor),
Theme.of(context).primaryTextTheme.button?.decorationColor),
],
),
);

View File

@ -4,24 +4,27 @@ import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:provider/provider.dart';
import 'package:oxen_wallet/src/stores/seed_language/seed_language_store.dart';
import 'package:oxen_wallet/src/widgets/present_picker.dart';
import 'package:oxen_wallet/generated/l10n.dart';
import 'package:oxen_wallet/l10n.dart';
class SeedLanguagePicker extends StatelessWidget {
final List<String> seedLocales = [
S.current.seed_language_english,
S.current.seed_language_chinese,
S.current.seed_language_dutch,
S.current.seed_language_german,
S.current.seed_language_japanese,
S.current.seed_language_portuguese,
S.current.seed_language_russian,
S.current.seed_language_spanish,
S.current.seed_language_french,
S.current.seed_language_italian
];
List<String> getSeedLocales(AppLocalizations l10n) {
return [
l10n.seed_language_english,
l10n.seed_language_chinese,
l10n.seed_language_dutch,
l10n.seed_language_german,
l10n.seed_language_japanese,
l10n.seed_language_portuguese,
l10n.seed_language_russian,
l10n.seed_language_spanish,
l10n.seed_language_french,
l10n.seed_language_italian
];
}
@override
Widget build(BuildContext context) {
final seedLocales = getSeedLocales(tr(context));
final seedLanguageStore = Provider.of<SeedLanguageStore>(context);
return Observer(
@ -32,7 +35,7 @@ class SeedLanguagePicker extends StatelessWidget {
//width: double.infinity,
decoration: BoxDecoration(
border: Border.all(
color: Theme.of(context).dividerTheme.color
color: Theme.of(context).dividerTheme.color ?? Palette.lightGrey
),
borderRadius: BorderRadius.circular(8.0)
),
@ -45,6 +48,7 @@ class SeedLanguagePicker extends StatelessWidget {
}
Future<void> _setSeedLanguage(BuildContext context) async {
final seedLocales = getSeedLocales(tr(context));
final seedLanguageStore = context.read<SeedLanguageStore>();
var selectedSeedLanguage = await presentPicker(context, seedLocales);

View File

@ -1,16 +1,15 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:mobx/mobx.dart';
import 'package:oxen_wallet/generated/l10n.dart';
import 'package:oxen_wallet/l10n.dart';
import 'package:oxen_wallet/palette.dart';
import 'package:oxen_wallet/routes.dart';
import 'package:oxen_wallet/src/domain/common/balance_display_mode.dart';
import 'package:oxen_wallet/src/domain/common/crypto_currency.dart';
import 'package:oxen_wallet/src/node/sync_status.dart';
import 'package:oxen_wallet/src/screens/auth/auth_page.dart';
import 'package:oxen_wallet/src/screens/base_page.dart';
import 'package:oxen_wallet/src/screens/oxen_amount.dart';
import 'package:oxen_wallet/src/stores/balance/balance_store.dart';
import 'package:oxen_wallet/src/stores/send/send_store.dart';
import 'package:oxen_wallet/src/stores/send/sending_state.dart';
@ -26,7 +25,7 @@ import 'package:provider/provider.dart';
class SendPage extends BasePage {
@override
String get title => S.current.send_title;
String getTitle(AppLocalizations t) => t.send_title;
@override
bool get isModalBackButton => true;
@ -71,10 +70,10 @@ class SendFormState extends State<SendForm> {
await sendStore.isOpenaliasRecord(_addressController.text);
if (isOpenAlias) {
_addressController.text = sendStore.recordAddress;
_addressController.text = sendStore.recordAddress ?? '';
await showSimpleOxenDialog(context, S.of(context).openalias_alert_title,
S.of(context).openalias_alert_content(sendStore.recordName),
await showSimpleOxenDialog(context, tr(context).openalias_alert_title,
tr(context).openalias_alert_content(sendStore.recordName ?? ''),
onPressed: (_) => Navigator.of(context).pop());
}
}
@ -90,6 +89,8 @@ class SendFormState extends State<SendForm> {
_setEffects(context);
final t = tr(context);
return ScrollableWithBottomSection(
contentPadding: EdgeInsets.all(0),
content: GestureDetector(
@ -115,7 +116,7 @@ class SendFormState extends State<SendForm> {
color: Theme.of(context)
.accentTextTheme
.subtitle2
.backgroundColor))),
?.backgroundColor ?? OxenPalette.black))),
child: SizedBox(
height: 56,
width: double.infinity,
@ -127,7 +128,7 @@ class SendFormState extends State<SendForm> {
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(S.of(context).send_your_wallet,
Text(t.send_your_wallet,
style: TextStyle(
fontSize: 12, color: OxenPalette.teal)),
Text(walletStore.name,
@ -136,7 +137,7 @@ class SendFormState extends State<SendForm> {
color: Theme.of(context)
.accentTextTheme
.overline
.color,
?.color,
height: 1.25)),
]);
}),
@ -151,13 +152,13 @@ class SendFormState extends State<SendForm> {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(S.current.oxen_available_balance,
Text(t.oxen_available_balance,
style: TextStyle(
fontSize: 12,
color: Theme.of(context)
.accentTextTheme
.overline
.backgroundColor,
?.backgroundColor,
)),
Text(availableBalance,
style: TextStyle(
@ -165,7 +166,7 @@ class SendFormState extends State<SendForm> {
color: Theme.of(context)
.accentTextTheme
.overline
.color,
?.color,
height: 1.1)),
]);
})
@ -181,107 +182,39 @@ class SendFormState extends State<SendForm> {
child: Column(children: <Widget>[
AddressTextField(
controller: _addressController,
placeholder: S.of(context).send_oxen_address,
placeholder: t.send_oxen_address,
focusNode: _focusNodeAddress,
onURIScanned: (uri) {
var address = '';
var amount = '';
if (uri != null) {
address = uri.path;
amount = uri.queryParameters['tx_amount'];
} else {
address = uri.toString();
}
_addressController.text = address;
_cryptoAmountController.text = amount;
_addressController.text = uri.path;
_cryptoAmountController.text = uri.queryParameters['tx_amount'] ?? '';
},
options: [
AddressTextFieldOption.qrCode,
AddressTextFieldOption.addressBook
],
validator: (value) {
sendStore.validateAddress(value,
cryptoCurrency: CryptoCurrency.oxen);
sendStore.validateAddress(value ?? '', l10n: t);
return sendStore.errorMessage;
},
),
oxenAmountField(
context: context,
setAll: () => sendStore.setSendAll(t),
controller: _cryptoAmountController,
validator: (value) {
sendStore.validateOXEN(value ?? '', balanceStore.unlockedBalance, t);
return sendStore.errorMessage;
},
),
Padding(
padding: const EdgeInsets.only(top: 20),
child: TextFormField(
child: !settingsStore.enableFiatCurrency ? null : TextFormField(
style: TextStyle(
fontSize: 18.0,
color: Theme.of(context)
.accentTextTheme
.overline
.color),
controller: _cryptoAmountController,
keyboardType: TextInputType.numberWithOptions(
signed: false, decimal: true),
inputFormatters: [
FilteringTextInputFormatter.deny(RegExp('[- ]'))
],
decoration: InputDecoration(
prefixIcon: SizedBox(
width: 75,
child: Padding(
padding: EdgeInsets.only(left: 8, top: 12),
child: Text('OXEN:',
style: TextStyle(
fontSize: 18,
color: Theme.of(context)
.accentTextTheme
.overline
.color))),
),
suffixIcon: Container(
width: 1,
padding: EdgeInsets.only(top: 0),
child: Center(
child: InkWell(
onTap: () => sendStore.setSendAll(),
child: Text(S.of(context).all,
style: TextStyle(
fontSize: 10,
color: Theme.of(context)
.accentTextTheme
.overline
.decorationColor)))),
),
hintStyle: TextStyle(
fontSize: 18.0,
color: Theme.of(context).hintColor),
hintText: '0.0000',
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
color: OxenPalette.teal, width: 2.0)),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Theme.of(context).focusColor,
width: 1.0)),
errorBorder: OutlineInputBorder(
borderSide: BorderSide(
color: OxenPalette.red, width: 1.0)),
focusedErrorBorder: OutlineInputBorder(
borderSide: BorderSide(
color: OxenPalette.red, width: 1.0)),
errorStyle: TextStyle(color: OxenPalette.red)),
validator: (value) {
sendStore.validateOXEN(
value, balanceStore.unlockedBalance);
return sendStore.errorMessage;
}),
),
Padding(
padding: const EdgeInsets.only(top: 20),
child: TextFormField(
style: TextStyle(
fontSize: 18.0,
color: Theme.of(context)
.accentTextTheme
.overline
.color),
?.color),
controller: _fiatAmountController,
keyboardType: TextInputType.numberWithOptions(
signed: false, decimal: true),
@ -300,7 +233,7 @@ class SendFormState extends State<SendForm> {
color: Theme.of(context)
.accentTextTheme
.overline
.color))),
?.color))),
),
hintStyle: TextStyle(
fontSize: 18.0,
@ -326,14 +259,14 @@ class SendFormState extends State<SendForm> {
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(S.of(context).send_estimated_fee,
Text(t.send_estimated_fee,
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w500,
color: Theme.of(context)
.accentTextTheme
.overline
.backgroundColor,
?.backgroundColor,
)),
Text(
'${calculateEstimatedFee(priority: settingsStore.transactionPriority)} OXEN',
@ -343,7 +276,7 @@ class SendFormState extends State<SendForm> {
color: Theme.of(context)
.primaryTextTheme
.overline
.backgroundColor,
?.backgroundColor,
))
],
),
@ -351,15 +284,14 @@ class SendFormState extends State<SendForm> {
SizedBox(
width: double.infinity,
child: Text(
S.of(context).send_priority(
settingsStore.transactionPriority.toString()),
t.send_priority(settingsStore.transactionPriority.getTitle(t)),
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.w500,
color: Theme.of(context)
.primaryTextTheme
.subtitle2
.color,
?.color,
height: 1.3)),
),
]),
@ -370,12 +302,12 @@ class SendFormState extends State<SendForm> {
),
bottomSection: Observer(builder: (_) {
return SlideToAct(
text: S.of(context).send_title,
outerColor: Theme.of(context).primaryTextTheme.subtitle2.color,
text: t.send_title,
outerColor: Theme.of(context).primaryTextTheme.subtitle2?.color,
innerColor: OxenPalette.teal,
onFutureSubmit: syncStore.status is SyncedSyncStatus
? () async {
if (_formKey.currentState.validate()) {
if (_formKey.currentState?.validate() ?? false) {
var isSuccessful = false;
await Navigator.of(context).pushNamed(Routes.auth,
@ -387,7 +319,8 @@ class SendFormState extends State<SendForm> {
}
await sendStore.createTransaction(
address: _addressController.text);
recipient: _addressController.text,
l10n: t);
Navigator.of(auth.context).pop();
isSuccessful = true;
@ -437,30 +370,32 @@ class SendFormState extends State<SendForm> {
reaction((_) => sendStore.state, (SendingState state) {
if (state is SendingFailed) {
WidgetsBinding.instance.addPostFrameCallback((_) {
showSimpleOxenDialog(context, S.of(context).error, state.error,
WidgetsBinding.instance?.addPostFrameCallback((_) {
showSimpleOxenDialog(context, tr(context).error, state.error,
onPressed: (_) => Navigator.of(context).pop());
});
}
if (state is TransactionCreatedSuccessfully) {
WidgetsBinding.instance.addPostFrameCallback((_) {
showSimpleOxenDialog(
context,
S.of(context).confirm_sending,
S.of(context).commit_transaction_amount_fee(
sendStore.pendingTransaction.amount,
sendStore.pendingTransaction.fee), onPressed: (_) {
Navigator.of(context).pop();
sendStore.commitTransaction();
});
if (state is TransactionCreatedSuccessfully && sendStore.pendingTransaction != null) {
WidgetsBinding.instance?.addPostFrameCallback((_) {
showConfirmOxenDialog(
context,
tr(context).confirm_sending,
tr(context).confirm_transaction_amount_fee(
sendStore.pendingTransaction!.amount,
sendStore.pendingTransaction!.fee),
onConfirm: (_) {
Navigator.of(context).pop();
sendStore.commitTransaction();
}
);
});
}
if (state is TransactionCommitted) {
WidgetsBinding.instance.addPostFrameCallback((_) {
WidgetsBinding.instance?.addPostFrameCallback((_) {
showSimpleOxenDialog(
context, S.of(context).sending, S.of(context).transaction_sent,
context, tr(context).sending, tr(context).transaction_sent,
onPressed: (_) {
_addressController.text = '';
_cryptoAmountController.text = '';

View File

@ -1,65 +0,0 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:oxen_wallet/generated/l10n.dart';
import 'package:oxen_wallet/src/domain/common/language.dart';
import 'package:oxen_wallet/src/screens/base_page.dart';
import 'package:oxen_wallet/src/stores/settings/settings_store.dart';
import 'package:oxen_wallet/src/widgets/oxen_dialog.dart';
import 'package:provider/provider.dart';
class ChangeLanguage extends BasePage {
@override
String get title => S.current.settings_change_language;
@override
Widget body(BuildContext context) {
final settingsStore = Provider.of<SettingsStore>(context);
final currentLanguage = Provider.of<Language>(context);
final currentColor = Theme.of(context).selectedRowColor;
final notCurrentColor =
Theme.of(context).accentTextTheme.subtitle1.backgroundColor;
return Container(
padding: EdgeInsets.only(top: 10.0, bottom: 10.0),
child: ListView.builder(
itemCount: languages.values.length,
itemBuilder: (BuildContext context, int index) {
final isCurrent = settingsStore.languageCode == null
? false
: languages.keys.elementAt(index) == settingsStore.languageCode;
return Container(
margin: EdgeInsets.only(top: 10.0, bottom: 10.0),
color: isCurrent ? currentColor : notCurrentColor,
child: ListTile(
title: Text(
languages.values.elementAt(index),
style: TextStyle(
fontSize: 16.0,
color:
Theme.of(context).primaryTextTheme.headline6.color),
),
onTap: () async {
if (!isCurrent) {
await showSimpleOxenDialog(
context,
S.of(context).change_language,
S.of(context).change_language_to(
languages.values.elementAt(index)),
onPressed: (context) {
settingsStore.saveLanguageCode(
languageCode: languages.keys.elementAt(index));
currentLanguage.setCurrentLanguage(
languages.keys.elementAt(index));
Navigator.of(context).pop();
},
);
}
},
),
);
},
));
}
}

View File

@ -4,18 +4,18 @@ import 'package:oxen_wallet/src/screens/settings/attributes.dart';
class SettingsItem {
SettingsItem(
{this.onTaped,
this.title,
required this.title,
this.link,
this.image,
this.widget,
this.attribute,
required this.attribute,
this.widgetBuilder});
final VoidCallback onTaped;
final VoidCallback? onTaped;
final String title;
final String link;
final Image image;
final Widget widget;
final String? link;
final Image? image;
final Widget? widget;
final Attributes attribute;
final WidgetBuilder widgetBuilder;
final WidgetBuilder? widgetBuilder;
}

View File

@ -1,7 +1,6 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:oxen_wallet/generated/l10n.dart';
import 'package:oxen_wallet/palette.dart';
import 'package:oxen_wallet/routes.dart';
import 'package:oxen_wallet/src/domain/common/balance_display_mode.dart';
@ -11,6 +10,7 @@ import 'package:oxen_wallet/src/screens/base_page.dart';
import 'package:oxen_wallet/src/screens/disclaimer/disclaimer_page.dart';
import 'package:oxen_wallet/src/screens/settings/attributes.dart';
import 'package:oxen_wallet/src/screens/settings/items/settings_item.dart';
import 'package:oxen_wallet/l10n.dart';
// Settings widgets
import 'package:oxen_wallet/src/screens/settings/widgets/settings_link_list_row.dart';
@ -28,7 +28,7 @@ import 'package:url_launcher/url_launcher.dart';
class SettingsPage extends BasePage {
@override
String get title => S.current.settings_title;
String getTitle(AppLocalizations l10n) => l10n.settings_title;
@override
Color get backgroundColor => Palette.lightGrey2;
@ -45,18 +45,21 @@ class SettingsForm extends StatefulWidget {
}
class SettingsFormState extends State<SettingsForm> {
final _sessionImage = Image.asset('assets/images/Session.png');
final _telegramImage = Image.asset('assets/images/Telegram.png');
final _twitterImage = Image.asset('assets/images/Twitter.png');
final _emailText = 'team@oxen.io';
final _sessionText = 'getsession.org';
final _githubText = 'github.com/oxen-io';
final _telegramText = 't.me/Oxen_Community';
final _twitterText = 'twitter.com/Oxen_io';
final _githubText = 'github.com/oxen-io';
final _emailUrl = 'mailto:team@oxen.io';
final _telegramUrl = 'https:t.me/Oxen_Community';
final _twitterUrl = 'https:twitter.com/Oxen_io';
final _githubUrl = 'https:github.com/oxen-io';
final _sessionUrl = 'https://getsession.org';
final _githubUrl = 'https://github.com/oxen-io';
final _telegramUrl = 'https://t.me/Oxen_Community';
final _twitterUrl = 'https://twitter.com/Oxen_io';
final _items = <SettingsItem>[];
@ -66,84 +69,85 @@ class SettingsFormState extends State<SettingsForm> {
void _setSettingsList() {
final settingsStore = context.read<SettingsStore>();
final t = tr(context);
_items.addAll([
SettingsItem(
title: S.current.settings_nodes, attribute: Attributes.header),
title: t.settings_nodes, attribute: Attributes.header),
SettingsItem(
onTaped: () => Navigator.of(context).pushNamed(Routes.nodeList),
title: S.current.settings_current_node,
title: t.settings_current_node,
widget: Observer(
builder: (_) => Text(
settingsStore.node == null ? '' : settingsStore.node.uri,
settingsStore.node?.uri ?? '',
textAlign: TextAlign.right,
style: TextStyle(
fontSize: 16.0,
color:
Theme.of(context).primaryTextTheme.subtitle2.color),
Theme.of(context).primaryTextTheme.subtitle2?.color),
)),
attribute: Attributes.widget),
SettingsItem(
title: S.current.settings_wallets, attribute: Attributes.header),
title: t.settings_wallets, attribute: Attributes.header),
SettingsItem(
onTaped: () => _setBalance(context),
title: S.current.settings_display_balance_as,
title: t.settings_display_balance_as,
widget: Observer(
builder: (_) => Text(
settingsStore.balanceDisplayMode.toString(),
settingsStore.balanceDisplayMode.getTitle(t),
textAlign: TextAlign.right,
style: TextStyle(
fontSize: 16.0,
color:
Theme.of(context).primaryTextTheme.subtitle2.color),
Theme.of(context).primaryTextTheme.subtitle2?.color),
)),
attribute: Attributes.widget),
SettingsItem(
onTaped: () => _setBalanceDetail(context),
title: S.current.settings_balance_detail,
title: t.settings_balance_detail,
widget: Observer(
builder: (_) => Text(
settingsStore.balanceDetail.toString(),
settingsStore.balanceDetail.getTitle(t),
textAlign: TextAlign.right,
style: TextStyle(
fontSize: 16.0,
color:
Theme.of(context).primaryTextTheme.subtitle2.color),
Theme.of(context).primaryTextTheme.subtitle2?.color),
)),
attribute: Attributes.widget),
SettingsItem(
title: S.current.settings_enable_fiat_currency,
title: t.settings_enable_fiat_currency,
attribute: Attributes.switcher),
SettingsItem(
onTaped: () => _setCurrency(context),
title: S.current.settings_currency,
title: t.settings_currency,
widget: Observer(
builder: (_) => Text(
settingsStore.fiatCurrency.toString(),
settingsStore.fiatCurrency.getTitle(t),
textAlign: TextAlign.right,
style: TextStyle(
fontSize: 16.0,
color:
Theme.of(context).primaryTextTheme.subtitle2.color),
Theme.of(context).primaryTextTheme.subtitle2?.color),
)),
attribute: Attributes.widget),
SettingsItem(
onTaped: () => _setTransactionPriority(context),
title: S.current.settings_fee_priority,
title: t.settings_fee_priority,
widget: Observer(
builder: (_) => Text(
settingsStore.transactionPriority.toString(),
settingsStore.transactionPriority.getTitle(t),
textAlign: TextAlign.right,
style: TextStyle(
fontSize: 16.0,
color:
Theme.of(context).primaryTextTheme.subtitle2.color),
Theme.of(context).primaryTextTheme.subtitle2?.color),
)),
attribute: Attributes.widget),
SettingsItem(
title: S.current.settings_save_recipient_address,
title: t.settings_save_recipient_address,
attribute: Attributes.switcher),
SettingsItem(
title: S.current.settings_personal, attribute: Attributes.header),
title: t.settings_personal, attribute: Attributes.header),
SettingsItem(
onTaped: () {
Navigator.of(context).pushNamed(Routes.auth,
@ -156,19 +160,19 @@ class SettingsFormState extends State<SettingsForm> {
Navigator.of(context).pop())
: null);
},
title: S.current.settings_change_pin,
title: t.settings_change_pin,
attribute: Attributes.arrow),
SettingsItem(
onTaped: () => Navigator.pushNamed(context, Routes.changeLanguage),
title: S.current.settings_change_language,
title: t.settings_change_language,
attribute: Attributes.arrow),
SettingsItem(
title: S.current.settings_allow_biometric_authentication,
title: t.settings_allow_biometric_authentication,
attribute: Attributes.switcher),
SettingsItem(
title: S.current.settings_dark_mode, attribute: Attributes.switcher),
title: t.settings_dark_mode, attribute: Attributes.switcher),
SettingsItem(
title: S.current.settings_support, attribute: Attributes.header),
title: t.settings_support, attribute: Attributes.header),
SettingsItem(
onTaped: () => _launchUrl(_emailUrl),
title: 'Email',
@ -181,6 +185,12 @@ class SettingsFormState extends State<SettingsForm> {
link: _githubText,
image: null,
attribute: Attributes.link),
SettingsItem(
onTaped: () => _launchUrl(_sessionUrl),
title: 'Session',
link: _sessionText,
image: _sessionImage,
attribute: Attributes.link),
SettingsItem(
onTaped: () => _launchUrl(_telegramUrl),
title: 'Telegram',
@ -200,15 +210,15 @@ class SettingsFormState extends State<SettingsForm> {
CupertinoPageRoute<void>(
builder: (BuildContext context) => DisclaimerPage()));
},
title: S.current.settings_terms_and_conditions,
title: t.settings_terms_and_conditions,
attribute: Attributes.arrow),
SettingsItem(
onTaped: () => Navigator.pushNamed(context, Routes.faq),
title: S.current.faq,
title: t.faq,
attribute: Attributes.arrow),
SettingsItem(
onTaped: () => Navigator.pushNamed(context, Routes.changelog),
title: S.current.changelog,
title: t.changelog,
attribute: Attributes.arrow)
]);
setState(() {});
@ -219,7 +229,7 @@ class SettingsFormState extends State<SettingsForm> {
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback(_afterLayout);
WidgetsBinding.instance?.addPostFrameCallback(_afterLayout);
}
Widget _getWidget(SettingsItem item) {
@ -246,7 +256,7 @@ class SettingsFormState extends State<SettingsForm> {
return SettingsTextListRow(
onTaped: item.onTaped,
title: item.title,
widget: item.widget,
widget: item.widget ?? Offstage(),
);
case Attributes.rawWidget:
return SettingRawWidgetListRow(widgetBuilder: item.widgetBuilder);
@ -286,7 +296,7 @@ class SettingsFormState extends State<SettingsForm> {
color: Theme.of(context)
.accentTextTheme
.headline5
.backgroundColor,
?.backgroundColor,
padding: EdgeInsets.only(
left: 20.0,
right: 20.0,
@ -302,7 +312,7 @@ class SettingsFormState extends State<SettingsForm> {
}),
ListTile(
contentPadding: EdgeInsets.only(left: 20.0),
title: Text(S.current.version(settingsStore.currentVersion),
title: Text(tr(context).version(settingsStore.currentVersion),
style: TextStyle(fontSize: 14.0, color: Palette.wildDarkBlue)),
)
],
@ -312,7 +322,7 @@ class SettingsFormState extends State<SettingsForm> {
Future<void> _setBalance(BuildContext context) async {
final settingsStore = context.read<SettingsStore>();
final selectedDisplayMode =
await presentPicker(context, BalanceDisplayMode.all);
await presentPicker(context, BalanceDisplayMode.all, initial: settingsStore.balanceDisplayMode);
if (selectedDisplayMode != null) {
await settingsStore.setCurrentBalanceDisplayMode(
@ -322,7 +332,7 @@ class SettingsFormState extends State<SettingsForm> {
Future<void> _setBalanceDetail(BuildContext context) async {
final settingsStore = context.read<SettingsStore>();
final balanceDetail = await presentPicker(context, AmountDetail.all);
final balanceDetail = await presentPicker(context, AmountDetail.all, initial: settingsStore.balanceDetail);
if (balanceDetail != null) {
await settingsStore.setCurrentBalanceDetail(balanceDetail: balanceDetail);
@ -331,7 +341,7 @@ class SettingsFormState extends State<SettingsForm> {
Future<void> _setCurrency(BuildContext context) async {
final settingsStore = context.read<SettingsStore>();
final selectedCurrency = await presentPicker(context, FiatCurrency.all);
final selectedCurrency = await presentPicker(context, FiatCurrency.all, initial: settingsStore.fiatCurrency);
if (selectedCurrency != null) {
await settingsStore.setCurrentFiatCurrency(currency: selectedCurrency);
@ -341,7 +351,7 @@ class SettingsFormState extends State<SettingsForm> {
Future<void> _setTransactionPriority(BuildContext context) async {
final settingsStore = context.read<SettingsStore>();
final selectedPriority =
await presentPicker(context, OxenTransactionPriority.all);
await presentPicker(context, OxenTransactionPriority.all, initial: settingsStore.transactionPriority);
if (selectedPriority != null) {
await settingsStore.setCurrentTransactionPriority(

View File

@ -3,17 +3,17 @@ import 'package:oxen_wallet/palette.dart';
class SettingsLinktListRow extends StatelessWidget {
SettingsLinktListRow(
{@required this.onTaped, this.title, this.link, this.image});
{this.onTaped, required this.title, this.link, this.image});
final VoidCallback onTaped;
final VoidCallback? onTaped;
final String title;
final String link;
final Image image;
final String? link;
final Image? image;
@override
Widget build(BuildContext context) {
return Container(
color: Theme.of(context).accentTextTheme.headline5.backgroundColor,
color: Theme.of(context).accentTextTheme.headline5?.backgroundColor,
child: ListTile(
contentPadding: EdgeInsets.only(left: 20.0, right: 20.0),
title: Row(
@ -28,13 +28,13 @@ class SettingsLinktListRow extends StatelessWidget {
style: TextStyle(
fontSize: 15.0,
fontWeight: FontWeight.w500,
color: Theme.of(context).primaryTextTheme.headline6.color),
color: Theme.of(context).primaryTextTheme.headline6?.color),
),
)
],
),
trailing: Text(
link,
trailing: link == null ? null : Text(
link!,
style: TextStyle(fontSize: 14.0, color: OxenPalette.teal),
),
onTap: onTaped,

View File

@ -1,15 +1,15 @@
import 'package:flutter/material.dart';
class SettingRawWidgetListRow extends StatelessWidget {
SettingRawWidgetListRow({@required this.widgetBuilder});
SettingRawWidgetListRow({this.widgetBuilder});
final WidgetBuilder widgetBuilder;
final WidgetBuilder? widgetBuilder;
@override
Widget build(BuildContext context) {
return Container(
color: Theme.of(context).accentTextTheme.headline5.backgroundColor,
child: widgetBuilder(context) ?? Container(),
color: Theme.of(context).accentTextTheme.headline5?.backgroundColor,
child: widgetBuilder?.call(context) ?? Container(),
);
}
}

View File

@ -1,6 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:oxen_wallet/generated/l10n.dart';
import 'package:oxen_wallet/l10n.dart';
import 'package:oxen_wallet/src/stores/settings/settings_store.dart';
import 'package:oxen_wallet/src/widgets/standart_switch.dart';
import 'package:oxen_wallet/theme_changer.dart';
@ -8,15 +8,15 @@ import 'package:oxen_wallet/themes.dart';
import 'package:provider/provider.dart';
class SettingsSwitchListRow extends StatelessWidget {
SettingsSwitchListRow({@required this.title});
SettingsSwitchListRow({required this.title});
final String title;
Widget _getSwitch(BuildContext context) {
Widget? _getSwitch(BuildContext context) {
final settingsStore = Provider.of<SettingsStore>(context);
final _themeChanger = Provider.of<ThemeChanger>(context);
if (title == S.of(context).settings_save_recipient_address) {
if (title == tr(context).settings_save_recipient_address) {
return Observer(
builder: (_) => StandartSwitch(
value: settingsStore.shouldSaveRecipientAddress,
@ -27,7 +27,7 @@ class SettingsSwitchListRow extends StatelessWidget {
}));
}
if (title == S.of(context).settings_allow_biometric_authentication) {
if (title == tr(context).settings_allow_biometric_authentication) {
return Observer(
builder: (_) => StandartSwitch(
value: settingsStore.allowBiometricAuthentication,
@ -39,7 +39,7 @@ class SettingsSwitchListRow extends StatelessWidget {
}));
}
if (title == S.of(context).settings_dark_mode) {
if (title == tr(context).settings_dark_mode) {
return Observer(
builder: (_) => StandartSwitch(
value: settingsStore.isDarkTheme,
@ -51,7 +51,7 @@ class SettingsSwitchListRow extends StatelessWidget {
}));
}
if (title == S.of(context).settings_enable_fiat_currency) {
if (title == tr(context).settings_enable_fiat_currency) {
return Observer(
builder: (_) => StandartSwitch(
value: settingsStore.enableFiatCurrency,
@ -68,13 +68,13 @@ class SettingsSwitchListRow extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
color: Theme.of(context).accentTextTheme.headline5.backgroundColor,
color: Theme.of(context).accentTextTheme.headline5?.backgroundColor,
child: ListTile(
contentPadding: EdgeInsets.only(left: 20.0, right: 20.0),
title: Text(title,
style: TextStyle(
fontSize: 16.0,
color: Theme.of(context).primaryTextTheme.headline6.color)),
color: Theme.of(context).primaryTextTheme.headline6?.color)),
trailing: _getSwitch(context)),
);
}

View File

@ -1,16 +1,16 @@
import 'package:flutter/material.dart';
class SettingsTextListRow extends StatelessWidget {
SettingsTextListRow({@required this.onTaped, this.title, this.widget});
SettingsTextListRow({this.onTaped, required this.title, required this.widget});
final VoidCallback onTaped;
final VoidCallback? onTaped;
final String title;
final Widget widget;
@override
Widget build(BuildContext context) {
return Container(
color: Theme.of(context).accentTextTheme.headline5.backgroundColor,
color: Theme.of(context).accentTextTheme.headline5?.backgroundColor,
child: ListTile(
contentPadding: EdgeInsets.only(left: 20.0, right: 20.0),
title: Row(
@ -21,7 +21,7 @@ class SettingsTextListRow extends StatelessWidget {
title,
style: TextStyle(
fontSize: 16.0,
color: Theme.of(context).primaryTextTheme.headline6.color),
color: Theme.of(context).primaryTextTheme.headline6?.color),
),
),
Flexible(child: widget)

View File

@ -1,20 +1,19 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:provider/provider.dart';
import 'package:oxen_wallet/src/stores/user/user_store.dart';
import 'package:oxen_wallet/src/screens/pin_code/pin_code.dart';
import 'package:oxen_wallet/src/screens/base_page.dart';
import 'package:oxen_wallet/src/stores/settings/settings_store.dart';
import 'package:oxen_wallet/generated/l10n.dart';
import 'package:oxen_wallet/l10n.dart';
class SetupPinCodePage extends BasePage {
SetupPinCodePage({this.onPinCodeSetup});
SetupPinCodePage({required this.onPinCodeSetup});
final Function(BuildContext, String) onPinCodeSetup;
@override
String get title => S.current.setup_pin;
String getTitle(AppLocalizations t) => t.setup_pin;
@override
Widget body(BuildContext context) =>
@ -23,7 +22,7 @@ class SetupPinCodePage extends BasePage {
class SetupPinCodeForm extends PinCodeWidget {
SetupPinCodeForm(
{@required this.onPinCodeSetup, @required bool hasLengthSwitcher})
{required this.onPinCodeSetup, required bool hasLengthSwitcher})
: super(hasLengthSwitcher: hasLengthSwitcher);
final Function(BuildContext, String) onPinCodeSetup;
@ -34,41 +33,37 @@ class SetupPinCodeForm extends PinCodeWidget {
class _SetupPinCodeFormState<WidgetType extends SetupPinCodeForm>
extends PinCodeState<WidgetType> {
_SetupPinCodeFormState() {
title = S.current.enter_your_pin;
}
bool isEnteredOriginalPin() => _originalPin.isNotEmpty;
Function(BuildContext) onPinCodeSetup;
List<int> _originalPin = [];
UserStore _userStore;
SettingsStore _settingsStore;
UserStore? _userStore;
SettingsStore? _settingsStore;
@override
void onPinCodeEntered(PinCodeState state) {
if (!isEnteredOriginalPin()) {
_originalPin = state.pin;
state.title = S.current.enter_your_pin_again;
_originalPin = [...state.pin];
state.setTitle(tr(context).enter_your_pin_again);
state.clear();
} else {
if (listEquals<int>(state.pin, _originalPin)) {
final String pin = state.pin.fold('', (ac, val) => ac + '$val');
_userStore.set(password: pin);
_settingsStore.setDefaultPinLength(pinLength: state.pinLength);
final pin = state.pin.join();
_userStore?.set(password: pin);
_settingsStore?.setDefaultPinLength(pinLength: state.pinLength);
showDialog<void>(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
return AlertDialog(
content: Text(S.of(context).setup_successful),
content: Text(tr(context).setup_successful),
actions: <Widget>[
FlatButton(
child: Text(S.of(context).ok),
child: Text(tr(context).ok),
onPressed: () {
Navigator.of(context).pop();
widget.onPinCodeSetup(context, pin);
reset();
reset(tr(context));
},
),
],
@ -79,10 +74,10 @@ class _SetupPinCodeFormState<WidgetType extends SetupPinCodeForm>
context: context,
builder: (BuildContext context) {
return AlertDialog(
content: Text(S.of(context).pin_is_incorrect),
content: Text(tr(context).pin_is_incorrect),
actions: <Widget>[
FlatButton(
child: Text(S.of(context).ok),
child: Text(tr(context).ok),
onPressed: () {
Navigator.of(context).pop();
},
@ -91,14 +86,14 @@ class _SetupPinCodeFormState<WidgetType extends SetupPinCodeForm>
);
});
reset();
reset(tr(context));
}
}
}
void reset() {
void reset(AppLocalizations l10n) {
clear();
setTitle(S.current.enter_your_pin);
setTitle(l10n.enter_your_pin);
_originalPin = [];
}

Some files were not shown because too many files have changed in this diff Show More