diff --git a/app/build.gradle b/app/build.gradle
index 5cd5378..c9d588c 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -1,5 +1,13 @@
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
+apply plugin: 'kotlin-android-extensions'
+
+kapt {
+ generateStubs = true
+ javacOptions {
+ option("-Xmaxerrs", 500)
+ }
+}
android {
compileSdkVersion 27
@@ -40,19 +48,24 @@ android {
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
- //androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
+ //androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
androidTestImplementation('com.android.support.test.espresso:espresso-core:3.0.1', {
exclude group: 'com.android.support', module: 'support-annotations'
})
+ implementation 'com.jaredrummler:material-spinner:1.2.5'
+ implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion"
//testCompile 'com.android.support.test:runner:1.0.1'
+ implementation 'com.afollestad.material-dialogs:core:0.9.6.0' //DTVV Thrusday 31 July 2018
implementation 'com.android.support:appcompat-v7:27.1.1'
+ implementation 'com.github.bumptech.glide:glide:4.7.1'
+ // Glide v4 uses this new annotation processor -- see https://bumptech.github.io/glide/doc/generatedapi.html
+ annotationProcessor 'com.github.bumptech.glide:compiler:4.7.1'
implementation 'com.android.support:support-v4:27.1.1'
implementation 'com.android.support:design:27.1.1'
implementation 'com.android.support:cardview-v7:27.1.1'
implementation 'com.android.support.constraint:constraint-layout:1.1.2'
implementation 'android.arch.lifecycle:runtime:1.1.1'
implementation 'android.arch.lifecycle:extensions:1.1.1'
- implementation 'android.arch.persistence.room:runtime:1.1.0'
implementation 'android.arch.paging:runtime:1.0.0'
implementation 'com.idescout.sql:sqlscout-server:2.0'
implementation 'com.google.code.gson:gson:2.8.0'
@@ -72,8 +85,15 @@ dependencies {
//testCompile 'junit:junit: 4.12'
testImplementation 'org.mockito:mockito-core:1.10.19'
+ implementation 'android.arch.persistence.room:runtime:1.1.0'
+
+ kapt 'android.arch.persistence.room:runtime:1.1.0'
annotationProcessor 'android.arch.lifecycle:compiler:1.1.1'
+ kapt 'android.arch.lifecycle:compiler:1.1.1'
+ annotationProcessor 'android.arch.lifecycle:compiler:1.1.1'
+ kapt 'android.arch.persistence.room:compiler:1.1.0'
annotationProcessor 'android.arch.persistence.room:compiler:1.1.0'
+ kapt 'com.jakewharton:butterknife-compiler:8.8.1'
annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'
implementation 'com.squareup.picasso:picasso:2.5.2'
diff --git a/app/schemas/cy.agorise.crystalwallet.dao.CrystalDatabase/3.json b/app/schemas/cy.agorise.crystalwallet.dao.CrystalDatabase/3.json
new file mode 100644
index 0000000..06d211c
--- /dev/null
+++ b/app/schemas/cy.agorise.crystalwallet.dao.CrystalDatabase/3.json
@@ -0,0 +1,704 @@
+{
+ "formatVersion": 1,
+ "database": {
+ "version": 3,
+ "identityHash": "5aa4eae5c7cf7e77a2ebc1d7a9dc7070",
+ "entities": [
+ {
+ "tableName": "account_seed",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT, `master_seed` TEXT, `type` TEXT)",
+ "fields": [
+ {
+ "fieldPath": "mId",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "mName",
+ "columnName": "name",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "mMasterSeed",
+ "columnName": "master_seed",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "type",
+ "columnName": "type",
+ "affinity": "TEXT",
+ "notNull": false
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "crypto_net_account",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `seed_id` INTEGER NOT NULL, `account_index` INTEGER NOT NULL, `crypto_net` TEXT, `name` TEXT, FOREIGN KEY(`seed_id`) REFERENCES `account_seed`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION )",
+ "fields": [
+ {
+ "fieldPath": "mId",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "mSeedId",
+ "columnName": "seed_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "mAccountIndex",
+ "columnName": "account_index",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "mCryptoNet",
+ "columnName": "crypto_net",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "mName",
+ "columnName": "name",
+ "affinity": "TEXT",
+ "notNull": false
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [
+ {
+ "name": "index_crypto_net_account_id",
+ "unique": false,
+ "columnNames": [
+ "id"
+ ],
+ "createSql": "CREATE INDEX `index_crypto_net_account_id` ON `${TABLE_NAME}` (`id`)"
+ },
+ {
+ "name": "index_crypto_net_account_seed_id",
+ "unique": false,
+ "columnNames": [
+ "seed_id"
+ ],
+ "createSql": "CREATE INDEX `index_crypto_net_account_seed_id` ON `${TABLE_NAME}` (`seed_id`)"
+ },
+ {
+ "name": "index_crypto_net_account_seed_id_crypto_net_account_index",
+ "unique": true,
+ "columnNames": [
+ "seed_id",
+ "crypto_net",
+ "account_index"
+ ],
+ "createSql": "CREATE UNIQUE INDEX `index_crypto_net_account_seed_id_crypto_net_account_index` ON `${TABLE_NAME}` (`seed_id`, `crypto_net`, `account_index`)"
+ }
+ ],
+ "foreignKeys": [
+ {
+ "table": "account_seed",
+ "onDelete": "NO ACTION",
+ "onUpdate": "NO ACTION",
+ "columns": [
+ "seed_id"
+ ],
+ "referencedColumns": [
+ "id"
+ ]
+ }
+ ]
+ },
+ {
+ "tableName": "crypto_coin_transaction",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `date` INTEGER, `is_input` INTEGER NOT NULL, `account_id` INTEGER NOT NULL, `amount` INTEGER NOT NULL, `id_currency` INTEGER NOT NULL, `is_confirmed` INTEGER NOT NULL, `from` TEXT, `to` TEXT, FOREIGN KEY(`account_id`) REFERENCES `crypto_net_account`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`id_currency`) REFERENCES `crypto_currency`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "date",
+ "columnName": "date",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "isInput",
+ "columnName": "is_input",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "accountId",
+ "columnName": "account_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "amount",
+ "columnName": "amount",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "idCurrency",
+ "columnName": "id_currency",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "isConfirmed",
+ "columnName": "is_confirmed",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "from",
+ "columnName": "from",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "to",
+ "columnName": "to",
+ "affinity": "TEXT",
+ "notNull": false
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [
+ {
+ "name": "index_crypto_coin_transaction_account_id",
+ "unique": false,
+ "columnNames": [
+ "account_id"
+ ],
+ "createSql": "CREATE INDEX `index_crypto_coin_transaction_account_id` ON `${TABLE_NAME}` (`account_id`)"
+ },
+ {
+ "name": "index_crypto_coin_transaction_id_currency",
+ "unique": false,
+ "columnNames": [
+ "id_currency"
+ ],
+ "createSql": "CREATE INDEX `index_crypto_coin_transaction_id_currency` ON `${TABLE_NAME}` (`id_currency`)"
+ }
+ ],
+ "foreignKeys": [
+ {
+ "table": "crypto_net_account",
+ "onDelete": "CASCADE",
+ "onUpdate": "NO ACTION",
+ "columns": [
+ "account_id"
+ ],
+ "referencedColumns": [
+ "id"
+ ]
+ },
+ {
+ "table": "crypto_currency",
+ "onDelete": "CASCADE",
+ "onUpdate": "NO ACTION",
+ "columns": [
+ "id_currency"
+ ],
+ "referencedColumns": [
+ "id"
+ ]
+ }
+ ]
+ },
+ {
+ "tableName": "contact",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT, `email` TEXT, `gravatar` TEXT)",
+ "fields": [
+ {
+ "fieldPath": "mId",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "mName",
+ "columnName": "name",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "mEmail",
+ "columnName": "email",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "mGravatar",
+ "columnName": "gravatar",
+ "affinity": "TEXT",
+ "notNull": false
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [
+ {
+ "name": "index_contact_id",
+ "unique": false,
+ "columnNames": [
+ "id"
+ ],
+ "createSql": "CREATE INDEX `index_contact_id` ON `${TABLE_NAME}` (`id`)"
+ },
+ {
+ "name": "index_contact_name",
+ "unique": true,
+ "columnNames": [
+ "name"
+ ],
+ "createSql": "CREATE UNIQUE INDEX `index_contact_name` ON `${TABLE_NAME}` (`name`)"
+ },
+ {
+ "name": "index_contact_email",
+ "unique": false,
+ "columnNames": [
+ "email"
+ ],
+ "createSql": "CREATE INDEX `index_contact_email` ON `${TABLE_NAME}` (`email`)"
+ }
+ ],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "contact_address",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `contact_id` INTEGER NOT NULL, `crypto_net` TEXT NOT NULL, `address` TEXT)",
+ "fields": [
+ {
+ "fieldPath": "mId",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "mContactId",
+ "columnName": "contact_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "mCryptoNet",
+ "columnName": "crypto_net",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "mAddress",
+ "columnName": "address",
+ "affinity": "TEXT",
+ "notNull": false
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [
+ {
+ "name": "index_contact_address_id",
+ "unique": true,
+ "columnNames": [
+ "id"
+ ],
+ "createSql": "CREATE UNIQUE INDEX `index_contact_address_id` ON `${TABLE_NAME}` (`id`)"
+ },
+ {
+ "name": "index_contact_address_contact_id_crypto_net",
+ "unique": true,
+ "columnNames": [
+ "contact_id",
+ "crypto_net"
+ ],
+ "createSql": "CREATE UNIQUE INDEX `index_contact_address_contact_id_crypto_net` ON `${TABLE_NAME}` (`contact_id`, `crypto_net`)"
+ }
+ ],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "crypto_currency",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT, `crypto_net` TEXT, `precision` INTEGER NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "mId",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "mName",
+ "columnName": "name",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "mCryptoNet",
+ "columnName": "crypto_net",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "mPrecision",
+ "columnName": "precision",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [
+ {
+ "name": "index_crypto_currency_crypto_net_name",
+ "unique": true,
+ "columnNames": [
+ "crypto_net",
+ "name"
+ ],
+ "createSql": "CREATE UNIQUE INDEX `index_crypto_currency_crypto_net_name` ON `${TABLE_NAME}` (`crypto_net`, `name`)"
+ }
+ ],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "crypto_coin_balance",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `account_id` INTEGER NOT NULL, `crypto_currency_id` INTEGER NOT NULL, `balance` INTEGER NOT NULL, FOREIGN KEY(`account_id`) REFERENCES `crypto_net_account`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION )",
+ "fields": [
+ {
+ "fieldPath": "mId",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "mAccountId",
+ "columnName": "account_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "mCryptoCurrencyId",
+ "columnName": "crypto_currency_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "mBalance",
+ "columnName": "balance",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [
+ {
+ "name": "index_crypto_coin_balance_id",
+ "unique": false,
+ "columnNames": [
+ "id"
+ ],
+ "createSql": "CREATE INDEX `index_crypto_coin_balance_id` ON `${TABLE_NAME}` (`id`)"
+ },
+ {
+ "name": "index_crypto_coin_balance_account_id",
+ "unique": false,
+ "columnNames": [
+ "account_id"
+ ],
+ "createSql": "CREATE INDEX `index_crypto_coin_balance_account_id` ON `${TABLE_NAME}` (`account_id`)"
+ },
+ {
+ "name": "index_crypto_coin_balance_account_id_crypto_currency_id",
+ "unique": true,
+ "columnNames": [
+ "account_id",
+ "crypto_currency_id"
+ ],
+ "createSql": "CREATE UNIQUE INDEX `index_crypto_coin_balance_account_id_crypto_currency_id` ON `${TABLE_NAME}` (`account_id`, `crypto_currency_id`)"
+ }
+ ],
+ "foreignKeys": [
+ {
+ "table": "crypto_net_account",
+ "onDelete": "NO ACTION",
+ "onUpdate": "NO ACTION",
+ "columns": [
+ "account_id"
+ ],
+ "referencedColumns": [
+ "id"
+ ]
+ }
+ ]
+ },
+ {
+ "tableName": "graphene_account",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`crypto_net_account_id` INTEGER NOT NULL, `account_name` TEXT, `account_id` TEXT, `upgraded_to_ltm` INTEGER NOT NULL, PRIMARY KEY(`crypto_net_account_id`), FOREIGN KEY(`crypto_net_account_id`) REFERENCES `crypto_net_account`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION )",
+ "fields": [
+ {
+ "fieldPath": "cryptoNetAccountId",
+ "columnName": "crypto_net_account_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "name",
+ "columnName": "account_name",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "accountId",
+ "columnName": "account_id",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "upgradedToLtm",
+ "columnName": "upgraded_to_ltm",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "crypto_net_account_id"
+ ],
+ "autoGenerate": false
+ },
+ "indices": [],
+ "foreignKeys": [
+ {
+ "table": "crypto_net_account",
+ "onDelete": "NO ACTION",
+ "onUpdate": "NO ACTION",
+ "columns": [
+ "crypto_net_account_id"
+ ],
+ "referencedColumns": [
+ "id"
+ ]
+ }
+ ]
+ },
+ {
+ "tableName": "bitshares_asset",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`crypto_curreny_id` INTEGER NOT NULL, `bitshares_id` TEXT, `asset_type` TEXT, PRIMARY KEY(`crypto_curreny_id`), FOREIGN KEY(`crypto_curreny_id`) REFERENCES `crypto_currency`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION )",
+ "fields": [
+ {
+ "fieldPath": "cryptoCurrencyId",
+ "columnName": "crypto_curreny_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "bitsharesId",
+ "columnName": "bitshares_id",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "assetType",
+ "columnName": "asset_type",
+ "affinity": "TEXT",
+ "notNull": false
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "crypto_curreny_id"
+ ],
+ "autoGenerate": false
+ },
+ "indices": [],
+ "foreignKeys": [
+ {
+ "table": "crypto_currency",
+ "onDelete": "NO ACTION",
+ "onUpdate": "NO ACTION",
+ "columns": [
+ "crypto_curreny_id"
+ ],
+ "referencedColumns": [
+ "id"
+ ]
+ }
+ ]
+ },
+ {
+ "tableName": "crypto_currency_equivalence",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `from_crypto_currency_id` INTEGER NOT NULL, `to_crypto_currency_id` INTEGER NOT NULL, `value` INTEGER NOT NULL, `last_checked` INTEGER, FOREIGN KEY(`from_crypto_currency_id`) REFERENCES `crypto_currency`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`to_crypto_currency_id`) REFERENCES `crypto_currency`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "fromCurrencyId",
+ "columnName": "from_crypto_currency_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "toCurrencyId",
+ "columnName": "to_crypto_currency_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "value",
+ "columnName": "value",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "lastChecked",
+ "columnName": "last_checked",
+ "affinity": "INTEGER",
+ "notNull": false
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [
+ {
+ "name": "index_crypto_currency_equivalence_from_crypto_currency_id_to_crypto_currency_id",
+ "unique": true,
+ "columnNames": [
+ "from_crypto_currency_id",
+ "to_crypto_currency_id"
+ ],
+ "createSql": "CREATE UNIQUE INDEX `index_crypto_currency_equivalence_from_crypto_currency_id_to_crypto_currency_id` ON `${TABLE_NAME}` (`from_crypto_currency_id`, `to_crypto_currency_id`)"
+ },
+ {
+ "name": "index_crypto_currency_equivalence_from_crypto_currency_id",
+ "unique": false,
+ "columnNames": [
+ "from_crypto_currency_id"
+ ],
+ "createSql": "CREATE INDEX `index_crypto_currency_equivalence_from_crypto_currency_id` ON `${TABLE_NAME}` (`from_crypto_currency_id`)"
+ },
+ {
+ "name": "index_crypto_currency_equivalence_to_crypto_currency_id",
+ "unique": false,
+ "columnNames": [
+ "to_crypto_currency_id"
+ ],
+ "createSql": "CREATE INDEX `index_crypto_currency_equivalence_to_crypto_currency_id` ON `${TABLE_NAME}` (`to_crypto_currency_id`)"
+ }
+ ],
+ "foreignKeys": [
+ {
+ "table": "crypto_currency",
+ "onDelete": "CASCADE",
+ "onUpdate": "NO ACTION",
+ "columns": [
+ "from_crypto_currency_id"
+ ],
+ "referencedColumns": [
+ "id"
+ ]
+ },
+ {
+ "table": "crypto_currency",
+ "onDelete": "CASCADE",
+ "onUpdate": "NO ACTION",
+ "columns": [
+ "to_crypto_currency_id"
+ ],
+ "referencedColumns": [
+ "id"
+ ]
+ }
+ ]
+ },
+ {
+ "tableName": "general_setting",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT, `value` TEXT)",
+ "fields": [
+ {
+ "fieldPath": "mId",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "mName",
+ "columnName": "name",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "mValue",
+ "columnName": "value",
+ "affinity": "TEXT",
+ "notNull": false
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [],
+ "foreignKeys": []
+ }
+ ],
+ "setupQueries": [
+ "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
+ "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, \"5aa4eae5c7cf7e77a2ebc1d7a9dc7070\")"
+ ]
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 0563193..d77e761 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -31,13 +31,15 @@
+
+
+
+
-
-
@@ -100,6 +102,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/java/cy/agorise/crystalwallet/activities/BackupSeedActivity.java b/app/src/main/java/cy/agorise/crystalwallet/activities/BackupSeedActivity.java
index 4cd2f7e..15b7d6b 100644
--- a/app/src/main/java/cy/agorise/crystalwallet/activities/BackupSeedActivity.java
+++ b/app/src/main/java/cy/agorise/crystalwallet/activities/BackupSeedActivity.java
@@ -3,12 +3,16 @@ package cy.agorise.crystalwallet.activities;
import android.arch.lifecycle.LiveData;
import android.arch.lifecycle.Observer;
import android.arch.lifecycle.ViewModelProviders;
+import android.content.ClipData;
+import android.content.ClipboardManager;
+import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.widget.Button;
import android.widget.TextView;
+import android.widget.Toast;
import butterknife.BindView;
import butterknife.ButterKnife;
@@ -17,19 +21,28 @@ import cy.agorise.crystalwallet.R;
import cy.agorise.crystalwallet.models.AccountSeed;
import cy.agorise.crystalwallet.viewmodels.AccountSeedViewModel;
+//tvBrainKey
public class BackupSeedActivity extends AppCompatActivity {
AccountSeedViewModel accountSeedViewModel;
- @BindView(R.id.tvMnemonic)
- TextView tvMnemonic;
+ @BindView(R.id.tvBrainKey)
+ TextView textfieldBrainkey;
@BindView(R.id.btnOk)
Button btnOk;
+ @BindView(R.id.btnCopy)
+ Button btnCopy;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.backup_seed);
+
+ //Note: Test porpouses
+ /*final TextView textView = findViewById(R.id.tvBrainKey);
+ textView.setText("sakk902909321o p3k21kldsa0'dsa90'e930eidakdñsakdñlsakdi90i03 2i90idopsasakk902909321op3k21 kldsa0'dsa90'e930eid akdñsakdñlsakdi90i032i90idopsa");
+ */
+
ButterKnife.bind(this);
long seedId = getIntent().getLongExtra("SEED_ID",-1);
@@ -41,7 +54,7 @@ public class BackupSeedActivity extends AppCompatActivity {
liveDataAccountSeed.observe(this, new Observer() {
@Override
public void onChanged(@Nullable AccountSeed accountSeed) {
- tvMnemonic.setText(accountSeed.getMasterSeed());
+ textfieldBrainkey.setText(accountSeed.getMasterSeed());
}
});
accountSeedViewModel.loadSeed(seedId);
@@ -56,4 +69,23 @@ public class BackupSeedActivity extends AppCompatActivity {
Intent intent = new Intent(this, IntroActivity.class);
startActivity(intent);
}
+
+ /*
+ * Clic on button copy to clipboard
+ * */
+ @OnClick(R.id.btnCopy)
+ public void btnCopyClick(){
+
+ /*
+ * Save to clipboard the brainkey chain
+ * */
+ ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
+ ClipData clip = ClipData.newPlainText(textfieldBrainkey.getText(), textfieldBrainkey.getText().toString());
+ clipboard.setPrimaryClip(clip);
+
+ /*
+ * Success message
+ * */
+ Toast.makeText(this.getBaseContext(),getResources().getString(R.string.window_seed_toast_clipboard), Toast.LENGTH_SHORT).show();
+ }
}
diff --git a/app/src/main/java/cy/agorise/crystalwallet/activities/BoardActivity.java b/app/src/main/java/cy/agorise/crystalwallet/activities/BoardActivity.java
index c9f5a16..90be602 100644
--- a/app/src/main/java/cy/agorise/crystalwallet/activities/BoardActivity.java
+++ b/app/src/main/java/cy/agorise/crystalwallet/activities/BoardActivity.java
@@ -8,6 +8,8 @@ import android.content.Intent;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
+import android.graphics.Color;
+import android.graphics.Typeface;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
@@ -17,16 +19,22 @@ import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.view.ViewPager;
-import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
+import android.text.Spannable;
+import android.text.SpannableString;
+import android.text.style.ForegroundColorSpan;
import android.util.Pair;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
+import android.view.ViewGroup;
import android.view.animation.LinearInterpolator;
import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
-import com.sjaramillo10.animatedtablayout.AnimatedTabLayout;
+import com.bumptech.glide.Glide;
+import com.bumptech.glide.request.RequestOptions;
import java.io.File;
@@ -39,6 +47,7 @@ import cy.agorise.crystalwallet.fragments.ContactsFragment;
import cy.agorise.crystalwallet.fragments.ReceiveTransactionFragment;
import cy.agorise.crystalwallet.fragments.SendTransactionFragment;
import cy.agorise.crystalwallet.fragments.TransactionsFragment;
+import cy.agorise.crystalwallet.views.natives.GIFView;
import de.hdodenhof.circleimageview.CircleImageView;
import cy.agorise.crystalwallet.viewmodels.CryptoNetBalanceListViewModel;
@@ -47,7 +56,7 @@ import cy.agorise.crystalwallet.viewmodels.CryptoNetBalanceListViewModel;
*
*/
-public class BoardActivity extends AppCompatActivity {
+public class BoardActivity extends CustomActivity {
@BindView(R.id.tabLayout)
public TabLayout tabLayout;
@@ -64,6 +73,9 @@ public class BoardActivity extends AppCompatActivity {
@BindView(R.id.fabAddContact)
public FloatingActionButton fabAddContact;
+ @BindView(R.id.imagevieGIF)
+ public GIFView imagevieGIF;
+
public BoardPagerAdapter boardAdapter;
/*
@@ -98,6 +110,61 @@ public class BoardActivity extends AppCompatActivity {
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
+ /*
+ * Set the bubbles animation
+ * */
+ imagevieGIF.centerCrop();
+ imagevieGIF.load(R.raw.burbujas);
+
+ /*
+ * Listener tabLayout to resalt text when clicked
+ * */
+ final TabLayout tabLayoutFinal = tabLayout;
+ tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
+ @Override
+ public void onTabSelected(final TabLayout.Tab tab) {
+
+ globalActivity.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+
+ LinearLayout tabLayout = (LinearLayout)((ViewGroup) tabLayoutFinal.getChildAt(0)).getChildAt(tab.getPosition());
+ tabLayout.setBackgroundColor(Color.TRANSPARENT);
+ TextView tabTextView = (TextView) tabLayout.getChildAt(1);
+ //tabTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP ,50);
+ Spannable WordtoSpan = new SpannableString(tabTextView.getText());
+ WordtoSpan.setSpan(new ForegroundColorSpan(Color.WHITE), 0, tabTextView.getText().length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+ tabTextView.setText(WordtoSpan);
+ tabTextView.setTypeface(tabTextView.getTypeface(), Typeface.BOLD);
+ }
+ });
+ }
+
+ @Override
+ public void onTabUnselected(final TabLayout.Tab tab) {
+
+ globalActivity.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+
+ LinearLayout tabLayout = (LinearLayout)((ViewGroup) tabLayoutFinal.getChildAt(0)).getChildAt(tab.getPosition());
+ TextView tabTextView = (TextView) tabLayout.getChildAt(1);
+ //tabTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP ,50);
+ Spannable WordtoSpan = new SpannableString(tabTextView.getText());
+ WordtoSpan.setSpan(new ForegroundColorSpan(globalActivity.getResources().getColor(R.color.lightGrayClear)), 0, tabTextView.getText().length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+ tabTextView.setText(WordtoSpan);
+ tabTextView.setTypeface(tabTextView.getTypeface(), Typeface.NORMAL);
+ }
+ });
+ }
+
+ @Override
+ public void onTabReselected(TabLayout.Tab tab) {
+
+
+ }
+ });
+
// Appbar animation
mSurfaceView.getHolder().addCallback(new SurfaceHolder.Callback() {
@Override
diff --git a/app/src/main/java/cy/agorise/crystalwallet/activities/CreateSeedActivity.java b/app/src/main/java/cy/agorise/crystalwallet/activities/CreateSeedActivity.java
deleted file mode 100644
index aa6d024..0000000
--- a/app/src/main/java/cy/agorise/crystalwallet/activities/CreateSeedActivity.java
+++ /dev/null
@@ -1,204 +0,0 @@
-package cy.agorise.crystalwallet.activities;
-
-import android.arch.lifecycle.ViewModelProviders;
-import android.content.Intent;
-import android.os.Bundle;
-import android.support.design.widget.TextInputEditText;
-import android.support.design.widget.TextInputLayout;
-import android.support.v7.app.AlertDialog;
-import android.support.v7.app.AppCompatActivity;
-import android.text.Editable;
-import android.view.ViewGroup;
-import android.widget.Button;
-
-import butterknife.BindView;
-import butterknife.ButterKnife;
-import butterknife.OnClick;
-import butterknife.OnTextChanged;
-import cy.agorise.crystalwallet.R;
-import cy.agorise.crystalwallet.requestmanagers.CryptoNetInfoRequestListener;
-import cy.agorise.crystalwallet.requestmanagers.CryptoNetInfoRequests;
-import cy.agorise.crystalwallet.requestmanagers.ValidateCreateBitsharesAccountRequest;
-import cy.agorise.crystalwallet.models.GrapheneAccount;
-import cy.agorise.crystalwallet.viewmodels.AccountSeedViewModel;
-import cy.agorise.crystalwallet.viewmodels.validators.CreateSeedValidator;
-import cy.agorise.crystalwallet.viewmodels.validators.UIValidatorListener;
-import cy.agorise.crystalwallet.viewmodels.validators.validationfields.ValidationField;
-
-public class CreateSeedActivity extends AppCompatActivity implements UIValidatorListener {
-
- AccountSeedViewModel accountSeedViewModel;
- CreateSeedValidator createSeedValidator;
-
- @BindView(R.id.tilPin)
- TextInputLayout tilPin;
-
- @BindView(R.id.tietPin)
- TextInputEditText tietPin;
-
- @BindView(R.id.tilPinConfirmation)
- TextInputLayout tilPinConfirmation;
-
- @BindView(R.id.tietPinConfirmation)
- TextInputEditText tietPinConfirmation;
-
- //@BindView(R.id.tvSeedWords)
- //TextView tvSeedWords;
-
- @BindView(R.id.tilAccountName)
- TextInputLayout tilAccountName;
-
- @BindView (R.id.tietAccountName)
- TextInputEditText tietAccountName;
-
- @BindView(R.id.btnCreate)
- Button btnCreate;
-
- @BindView(R.id.btnCancel)
- Button btnCancel;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.create_seed);
- ButterKnife.bind(this);
-
- tilPin.setErrorEnabled(true);
- tilPinConfirmation.setErrorEnabled(true);
- tilAccountName.setErrorEnabled(true);
-
- btnCreate.setEnabled(false);
- accountSeedViewModel = ViewModelProviders.of(this).get(AccountSeedViewModel.class);
- createSeedValidator = new CreateSeedValidator(this.getApplicationContext(),tietPin,tietPinConfirmation,tietAccountName);
- createSeedValidator.setListener(this);
- }
-
- @OnTextChanged(value = R.id.tietPin,
- callback = OnTextChanged.Callback.AFTER_TEXT_CHANGED)
- void afterPinChanged(Editable editable) {
- this.createSeedValidator.validate();
- }
-
- @OnTextChanged(value = R.id.tietPinConfirmation,
- callback = OnTextChanged.Callback.AFTER_TEXT_CHANGED)
- void afterPinConfirmationChanged(Editable editable) {
- this.createSeedValidator.validate();
- }
-
- /*@OnTextChanged(value = R.id.etSeedWords,
- callback = OnTextChanged.Callback.AFTER_TEXT_CHANGED)
- void afterSeedWordsChanged(Editable editable) {
- this.createSeedValidator.validate();
- }
-*/
-
- @OnTextChanged(value = R.id.tietAccountName,
- callback = OnTextChanged.Callback.AFTER_TEXT_CHANGED)
- void afterAccountNameChanged(Editable editable) {
- this.createSeedValidator.validate();
- }
-
- @OnClick(R.id.btnCancel)
- public void cancel(){
- this.finish();
- }
-
- @OnClick(R.id.btnCreate)
- public void createSeed(){
- if (this.createSeedValidator.isValid()) {
- // Make request to create a bitshare account
- final ValidateCreateBitsharesAccountRequest request =
- new ValidateCreateBitsharesAccountRequest(tietAccountName.getText().toString(), getApplicationContext());
-
-
- //Makes dialog to tell the user that the account is been created
- AlertDialog.Builder alertBuilder = new AlertDialog.Builder(CreateSeedActivity.this,R.style.AppTheme);
- alertBuilder.setView(R.layout.progress_creating_account);
- //alertBuilder.setTitle("Processing");
- //alertBuilder.setMessage("Creating Bitshares Account");
- final AlertDialog processDialog = alertBuilder.create();
- CreateSeedActivity.this.runOnUiThread(new Runnable() {
- @Override
- public void run() {
- processDialog.setCancelable(false);
- processDialog.show();
- processDialog.getWindow().setLayout(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
- }
- });
-
- request.setListener(new CryptoNetInfoRequestListener() {
- @Override
- public void onCarryOut() {
- processDialog.dismiss();
- if (request.getStatus().equals(ValidateCreateBitsharesAccountRequest.StatusCode.SUCCEEDED)) {
- GrapheneAccount accountSeed = request.getAccount();
- Intent intent = new Intent(getApplicationContext(), BackupSeedActivity.class);
- intent.putExtra("SEED_ID", accountSeed.getId());
- startActivity(intent);
- } else {
- createSeedValidator.validate();
- }
- }
- });
-
- Thread thread = new Thread() {
- @Override
- public void run() {
- CryptoNetInfoRequests.getInstance().addRequest(request);
- }
- };
-
- thread.start();
-
-
-
- //this.finish();
- }
- }
-
- @Override
- public void onValidationSucceeded(final ValidationField field) {
- final CreateSeedActivity activity = this;
-
- activity.runOnUiThread(new Runnable() {
- public void run() {
-
- if (field.getView() == tietPin) {
- tilPin.setError("");
- } else if (field.getView() == tietPinConfirmation){
- tilPinConfirmation.setError("");
- } else if (field.getView() == tietAccountName){
- tilAccountName.setError("");
- } //else if (field.getView() == etSeedWords){
- // tvSeedWordsError.setText("");
- //}
-
- if (activity.createSeedValidator.isValid()){
- btnCreate.setEnabled(true);
- } else {
- btnCreate.setEnabled(false);
- }
-
- }
- });
- }
-
- @Override
- public void onValidationFailed(final ValidationField field) {
- runOnUiThread(new Runnable() {
-
- @Override
- public void run() {
- if (field.getView() == tietPin) {
- tilPin.setError(field.getMessage());
- } else if (field.getView() == tietPinConfirmation){
- tilPinConfirmation.setError(field.getMessage());
- } else if (field.getView() == tietAccountName){
- tilAccountName.setError(field.getMessage());
- } //else if (field.getView() == etSeedWords){
- // tvSeedWordsError.setText(field.getMessage());
- //}
- }
- });
- }
-}
diff --git a/app/src/main/java/cy/agorise/crystalwallet/activities/CreateSeedActivity.kt b/app/src/main/java/cy/agorise/crystalwallet/activities/CreateSeedActivity.kt
new file mode 100644
index 0000000..e62f0b0
--- /dev/null
+++ b/app/src/main/java/cy/agorise/crystalwallet/activities/CreateSeedActivity.kt
@@ -0,0 +1,245 @@
+package cy.agorise.crystalwallet.activities
+
+import android.content.Context
+import android.content.Intent
+import android.os.Bundle
+import android.text.Editable
+import android.view.inputmethod.InputMethodManager
+import android.widget.Toast
+import butterknife.ButterKnife
+import butterknife.OnClick
+import butterknife.OnTextChanged
+import cy.agorise.crystalwallet.R
+import cy.agorise.crystalwallet.dialogs.material.CrystalDialog
+import cy.agorise.crystalwallet.requestmanagers.CryptoNetInfoRequests
+import cy.agorise.crystalwallet.requestmanagers.ValidateCreateBitsharesAccountRequest
+import cy.agorise.crystalwallet.viewmodels.validators.customImpl.interfaces.UIValidatorListener
+import cy.agorise.crystalwallet.viewmodels.validators.customImpl.validationFields.BitsharesAccountNameValidation
+import cy.agorise.crystalwallet.viewmodels.validators.customImpl.validationFields.BitsharesAccountNameValidation.OnAccountExist
+import cy.agorise.crystalwallet.viewmodels.validators.customImpl.validationFields.CustomValidationField
+import cy.agorise.crystalwallet.viewmodels.validators.customImpl.validationFields.PinDoubleConfirmationValidationField
+import cy.agorise.crystalwallet.views.natives.CustomTextInputEditText
+import kotlinx.android.synthetic.main.create_seed.*
+
+
+/*
+* This activity creates a new account with some security concerns
+* */
+class CreateSeedActivity : CustomActivity() {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ /*
+ * Assign the view to this controller
+ * */
+ setContentView(R.layout.create_seed)
+
+ /*
+ * Initialice butterknife MVC
+ * */
+ ButterKnife.bind(this)
+
+ /*
+ * Add the controls to the validator
+ * */
+ this.fieldsValidator.add(tietPin)
+ this.fieldsValidator.add(tietPinConfirmation)
+ this.fieldsValidator.add(tietAccountName)
+
+ /*
+ * Validations listener
+ * */
+ val uiValidatorListener = object : UIValidatorListener {
+
+ override fun onValidationSucceeded(customValidationField: CustomValidationField) {
+
+ try {
+
+ /*
+ * Remove error
+ * */
+ runOnUiThread {
+ val customTextInputEditText = customValidationField.currentView as CustomTextInputEditText
+ customTextInputEditText.error = null
+ }
+
+ } catch (e: Exception) {
+ e.printStackTrace()
+ }
+
+
+ /*
+ * Validate if can continue
+ * */
+ validateFieldsToContinue()
+ }
+
+ override fun onValidationFailed(customValidationField: CustomValidationField) {
+
+ /*
+ * Set error label
+ * */
+ runOnUiThread {
+ val customTextInputEditText = customValidationField.currentView as CustomTextInputEditText
+ customTextInputEditText.error = customTextInputEditText.fieldValidatorModel.message
+ }
+ }
+ }
+
+ /*
+ * Create the pin double validation
+ * */
+ val pinDoubleConfirmationValidationField = PinDoubleConfirmationValidationField(this, tietPin, tietPinConfirmation, uiValidatorListener)
+
+ /*
+ * Listener for the validation for success or fail
+ * */
+ tietPin?.setUiValidator(pinDoubleConfirmationValidationField) //Validator for the field
+ tietPinConfirmation?.setUiValidator(pinDoubleConfirmationValidationField) //Validator for the field
+
+ /*
+ * Account name validator
+ * */
+ val bitsharesAccountNameValidation = BitsharesAccountNameValidation(this, tietAccountName, uiValidatorListener)
+ val onAccountExist = object : OnAccountExist {
+ override fun onAccountExists() {
+ runOnUiThread { Toast.makeText(globalActivity, resources.getString(R.string.account_name_already_exist), Toast.LENGTH_LONG).show() }
+ }
+
+ }
+ bitsharesAccountNameValidation.setOnAccountExist(onAccountExist)
+ tietAccountName?.setUiValidator(bitsharesAccountNameValidation)
+
+ /*This button should not be enabled till all the fields be correctly filled*/
+ disableCreate()
+
+ /*
+ * Set the focus on the fisrt field and show keyboard
+ * */
+ tilPin?.requestFocus()
+ val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
+ imm.showSoftInput(tilPin, InputMethodManager.SHOW_IMPLICIT)
+ }
+
+
+ @OnTextChanged(value = R.id.tietPin, callback = OnTextChanged.Callback.AFTER_TEXT_CHANGED)
+ internal fun afterPinChanged(editable: Editable) {
+ this.fieldsValidator.validate()
+
+ /*
+ * Validate continue to create account
+ * */
+ validateFieldsToContinue()
+ }
+
+ @OnTextChanged(value = R.id.tietPinConfirmation, callback = OnTextChanged.Callback.AFTER_TEXT_CHANGED)
+ internal fun afterPinConfirmationChanged(editable: Editable) {
+ this.fieldsValidator.validate()
+
+ /*
+ * Validate continue to create account
+ * */
+ validateFieldsToContinue()
+ }
+
+ @OnTextChanged(value = R.id.tietAccountName, callback = OnTextChanged.Callback.AFTER_TEXT_CHANGED)
+ internal fun afterAccountNameChanged(editable: Editable) {
+ this.fieldsValidator.validate()
+
+ /*
+ * Always disable till the server response comes
+ * */
+ disableCreate()
+ }
+
+ @OnClick(R.id.btnCancel)
+ fun cancel() {
+
+ /*
+ * Exit of the activity
+ * */
+ this.finish()
+ }
+
+ @OnClick(R.id.btnCreate)
+ fun createSeed() {
+
+ // Make request to create a bitshare account
+ val request = ValidateCreateBitsharesAccountRequest(tietAccountName?.getText().toString(), applicationContext)
+
+ //DTVV: Friday 27 July 2018
+ //Makes dialog to tell the user that the account is been created
+ val creatingAccountMaterialDialog = CrystalDialog(this)
+ creatingAccountMaterialDialog.setText(this.resources.getString(R.string.window_create_seed_DialogMessage))
+ creatingAccountMaterialDialog.build()
+ this@CreateSeedActivity.runOnUiThread { creatingAccountMaterialDialog.show() }
+ request.setListener {
+ creatingAccountMaterialDialog.dismiss()
+ if (request.status == ValidateCreateBitsharesAccountRequest.StatusCode.SUCCEEDED) {
+ val accountSeed = request.account
+ val intent = Intent(applicationContext, BackupSeedActivity::class.java)
+ intent.putExtra("SEED_ID", accountSeed.id)
+ startActivity(intent)
+ } else {
+ fieldsValidator.validate()
+ }
+ }
+
+ val thread = object : Thread() {
+ override fun run() {
+
+ /*
+ *
+ * Run thread*/
+ CryptoNetInfoRequests.getInstance().addRequest(request)
+ }
+ }
+
+ thread.start()
+ }
+
+ /*
+ * Validate that all is complete to continue to create
+ * */
+ private fun validateFieldsToContinue() {
+
+ var result = false //Contains the final result
+
+ val pinValid: Boolean? = this.tietPin?.getFieldValidatorModel()?.isValid
+ val pinConfirmationValid = this.tietPinConfirmation?.getFieldValidatorModel()?.isValid
+ val pinAccountNameValid = this.tietAccountName?.getFieldValidatorModel()?.isValid
+
+ if (pinValid!! &&
+ pinConfirmationValid!! &&
+ pinAccountNameValid!!) {
+ result = true //Validation is correct
+ }
+
+
+ /*
+ * If the result is true so the user can continue to the creation of the account
+ * */
+ if (result) {
+ enableCreate()
+ } else {
+ disableCreate()
+ }
+ }
+
+ /*
+ * Enable create button
+ * */
+ private fun enableCreate() {
+ btnCreate?.setEnabled(true)
+ btnCreate?.setBackgroundColor(resources.getColor(R.color.colorPrimary))
+ }
+
+ /*
+ * Disable create button
+ * */
+ private fun disableCreate() {
+ btnCreate?.setEnabled(false)
+ btnCreate?.setBackground(resources.getDrawable(R.drawable.disable_style))
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/cy/agorise/crystalwallet/activities/CustomActivity.kt b/app/src/main/java/cy/agorise/crystalwallet/activities/CustomActivity.kt
new file mode 100644
index 0000000..71d9d99
--- /dev/null
+++ b/app/src/main/java/cy/agorise/crystalwallet/activities/CustomActivity.kt
@@ -0,0 +1,35 @@
+package cy.agorise.crystalwallet.activities
+
+import android.app.Activity
+import android.os.Bundle
+import android.support.v7.app.AppCompatActivity
+import cy.agorise.crystalwallet.util.FieldsValidator
+
+
+/*
+* Custom implementaion of the activity
+* */
+open class CustomActivity : AppCompatActivity() {
+
+ /*
+ * Contains the validator for general fields
+ * */
+ @JvmField protected var fieldsValidator = FieldsValidator()
+
+ /*
+ * Contains the global activity
+ * */
+ protected lateinit var globalActivity: Activity
+
+
+
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ /*
+ * Save the current activity for further reference
+ * */
+ this.globalActivity = this
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/cy/agorise/crystalwallet/activities/IntroActivity.java b/app/src/main/java/cy/agorise/crystalwallet/activities/IntroActivity.java
index 9d4eaf1..6fa59d2 100644
--- a/app/src/main/java/cy/agorise/crystalwallet/activities/IntroActivity.java
+++ b/app/src/main/java/cy/agorise/crystalwallet/activities/IntroActivity.java
@@ -12,6 +12,7 @@ import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Button;
+import android.widget.Toast;
import java.util.List;
@@ -19,23 +20,29 @@ import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import cy.agorise.crystalwallet.R;
+import cy.agorise.crystalwallet.apigenerator.GrapheneApiGenerator;
+import cy.agorise.crystalwallet.application.CrystalApplication;
import cy.agorise.crystalwallet.dao.CrystalDatabase;
+import cy.agorise.crystalwallet.dialogs.material.ToastIt;
+import cy.agorise.crystalwallet.enums.CryptoNet;
import cy.agorise.crystalwallet.fragments.ImportAccountOptionsFragment;
import cy.agorise.crystalwallet.models.AccountSeed;
import cy.agorise.crystalwallet.models.CryptoCoinBalance;
import cy.agorise.crystalwallet.models.CryptoCoinTransaction;
import cy.agorise.crystalwallet.models.CryptoNetAccount;
import cy.agorise.crystalwallet.models.GeneralSetting;
+import cy.agorise.crystalwallet.network.CryptoNetManager;
import cy.agorise.crystalwallet.randomdatagenerators.RandomCryptoCoinBalanceGenerator;
import cy.agorise.crystalwallet.randomdatagenerators.RandomCryptoNetAccountGenerator;
import cy.agorise.crystalwallet.randomdatagenerators.RandomSeedGenerator;
import cy.agorise.crystalwallet.randomdatagenerators.RandomTransactionsGenerator;
import cy.agorise.crystalwallet.application.CrystalSecurityMonitor;
+import cy.agorise.crystalwallet.util.NetworkUtility;
import cy.agorise.crystalwallet.viewmodels.AccountSeedListViewModel;
import cy.agorise.crystalwallet.viewmodels.TransactionListViewModel;
import cy.agorise.crystalwallet.views.TransactionListView;
-public class IntroActivity extends AppCompatActivity {
+public class IntroActivity extends CustomActivity {
TransactionListViewModel transactionListViewModel;
TransactionListView transactionListView;
@@ -53,8 +60,14 @@ public class IntroActivity extends AppCompatActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_intro);
+
ButterKnife.bind(this);
+ /*
+ * Test connection with server
+ * */
+ NetworkUtility.testServerConnnection(this);
+
// Appbar animation
mSurfaceView.getHolder().addCallback(new SurfaceHolder.Callback() {
@Override
@@ -137,21 +150,56 @@ public class IntroActivity extends AppCompatActivity {
@OnClick(R.id.btnCreateAccount)
public void createAccount() {
- Intent intent = new Intent(this, CreateSeedActivity.class);
- startActivity(intent);
+
+ /*
+ * Test connection with server, if no conection user can not continue
+ *
+ * */
+ final GrapheneApiGenerator.OnResponsesWebSocket onResponsesWebSocket = new GrapheneApiGenerator.OnResponsesWebSocket() {
+ @Override
+ public void onSuccess() {
+
+ /*
+ * Open the window to create seed and account
+ * */
+ Intent intent = new Intent(globalActivity, CreateSeedActivity.class);
+ startActivity(intent);
+ }
+ @Override
+ public void onError(Exception exception) {
+ //Nothing to implement, internally the user will see a toast
+ }
+ };
+ NetworkUtility.testServerConnnectionNormalError(this,onResponsesWebSocket);
}
@OnClick(R.id.btnImportAccount)
public void importAccount() {
- FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
- Fragment prev = getSupportFragmentManager().findFragmentByTag("importAccountOptions");
- if (prev != null) {
- ft.remove(prev);
- }
- ft.addToBackStack(null);
- // Create and show the dialog.
- ImportAccountOptionsFragment newFragment = ImportAccountOptionsFragment.newInstance();
- newFragment.show(ft, "importAccountOptions");
+ /*
+ * Test connection with server, if no conection user can not continue
+ *
+ * */
+ final GrapheneApiGenerator.OnResponsesWebSocket onResponsesWebSocket = new GrapheneApiGenerator.OnResponsesWebSocket() {
+ @Override
+ public void onSuccess() {
+
+ FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
+ Fragment prev = getSupportFragmentManager().findFragmentByTag("importAccountOptions");
+ if (prev != null) {
+ ft.remove(prev);
+ }
+ ft.addToBackStack(null);
+
+ // Create and show the dialog.
+ ImportAccountOptionsFragment newFragment = ImportAccountOptionsFragment.newInstance();
+ newFragment.show(ft, "importAccountOptions");
+ }
+ @Override
+ public void onError(Exception exception) {
+ //Nothing to implement, internally the user will see a toast
+ }
+ };
+ NetworkUtility.testServerConnnectionNormalError(this,onResponsesWebSocket);
}
}
diff --git a/app/src/main/java/cy/agorise/crystalwallet/activities/LicenseActivity.java b/app/src/main/java/cy/agorise/crystalwallet/activities/LicenseActivity.java
index 8964738..a0bed91 100644
--- a/app/src/main/java/cy/agorise/crystalwallet/activities/LicenseActivity.java
+++ b/app/src/main/java/cy/agorise/crystalwallet/activities/LicenseActivity.java
@@ -10,8 +10,11 @@ import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import cy.agorise.crystalwallet.R;
+import cy.agorise.crystalwallet.application.CrystalApplication;
import cy.agorise.crystalwallet.dao.CrystalDatabase;
+import cy.agorise.crystalwallet.enums.CryptoNet;
import cy.agorise.crystalwallet.models.GeneralSetting;
+import cy.agorise.crystalwallet.network.CryptoNetManager;
public class LicenseActivity extends AppCompatActivity {
@@ -23,6 +26,7 @@ public class LicenseActivity extends AppCompatActivity {
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_license);
+
ButterKnife.bind(this);
// TODO check if license has been agreed
diff --git a/app/src/main/java/cy/agorise/crystalwallet/activities/LoadingActivity.kt b/app/src/main/java/cy/agorise/crystalwallet/activities/LoadingActivity.kt
new file mode 100644
index 0000000..beb58ba
--- /dev/null
+++ b/app/src/main/java/cy/agorise/crystalwallet/activities/LoadingActivity.kt
@@ -0,0 +1,263 @@
+package cy.agorise.crystalwallet.activities
+
+import android.app.Activity
+import android.content.Intent
+import android.os.Bundle
+import android.os.Handler
+import butterknife.ButterKnife
+import kotlinx.android.synthetic.main.loading_activity.*
+import android.view.animation.AnimationUtils
+import android.widget.ImageView
+import butterknife.BindView
+import cy.agorise.crystalwallet.R
+
+
+/*
+* This activity is to show a loading window when it is needed
+* */
+class LoadingActivity : CustomActivity() {
+
+ @BindView(R.id.imageviewLoading)
+ lateinit var imageviewLoading:ImageView
+
+
+
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+
+ /*
+ * Construct the parent
+ * */
+ super.onCreate(savedInstanceState)
+
+ /*
+ * If the window was closed before be created so finish it
+ * */
+ if(destroyWindow!!){
+ finish()
+ }
+
+ /*
+ * Assign the view to this controller
+ * */
+ setContentView(cy.agorise.crystalwallet.R.layout.loading_activity)
+
+ /*
+ * Save the current activity
+ * */
+ currentActivity = this
+
+ /*
+ * If has to manage timer
+ * */
+ if(LoadingActivity.seconds != -1){
+
+ /*
+ * */
+ Handler().postDelayed({
+
+ /*
+ * Reset flag
+ * */
+ LoadingActivity.seconds = -1
+
+ finish() //Finish the current window
+ }, (LoadingActivity.seconds * 1000).toLong())
+ }
+
+ /*
+ * Initialice butterknife MVC
+ * */
+ ButterKnife.bind(this)
+
+ /*
+ * If has to change the loading sizes so
+ * */
+ if(loadinIconChangeSize){
+ imageviewLoading.layoutParams.width = loadingIconWidth
+ imageviewLoading.layoutParams.height = loadingIconHeigt
+ }
+
+ /*
+ * Rotate the image
+ * */
+ val rotation = AnimationUtils.loadAnimation(this, cy.agorise.crystalwallet.R.anim.rotate360)
+ imageviewLoading.startAnimation(rotation)
+
+ /*
+ * If listener is set deliver response
+ * */
+ if(onLoadingReady != null){
+ onLoadingReady!!.onLoadingReady()
+ }
+ }
+
+ /*
+ * This events hires when the window is destroyed
+ * */
+ override fun onDestroy() {
+ super.onDestroy()
+
+ /*
+ * If listener is set deliver response
+ * */
+ if(onLoadingClosed != null){
+ onLoadingClosed?.onLoadingClosed()
+ }
+ }
+
+ override fun onResume() {
+ super.onResume()
+
+ /*
+ * If the window was closed before be created so finish it
+ * */
+ if(destroyWindow!!){
+ finish()
+ }
+ }
+
+ /*
+ * Static methods
+ * */
+ companion object {
+
+ /*
+ * Contains the activity shown
+ * */
+ private var currentActivity: Activity? = null
+
+ /*
+ * Flag to validate if the window has to finish or not
+ * */
+ private var destroyWindow:Boolean? = false
+
+ /*
+ * Listener when the loading window is closed
+ * */
+ private var onLoadingClosed:LoadingClosed? = null
+
+ /*
+ * Listener when the loading window is resume
+ * */
+ private var onLoadingReady:LoadingReady? = null
+
+ /*
+ * Contains the seconds to finish the window in case of timer
+ * */
+ private var seconds:Int = -1
+
+ /*
+ * Contains the icon loading size
+ * */
+ private var loadingIconWidth:Int = -1
+ private var loadingIconHeigt:Int = -1
+ private var loadinIconChangeSize:Boolean = false
+
+
+
+
+ /*
+ * Show the loading activity
+ * */
+ @JvmStatic
+ open fun show(activity: Activity) {
+
+ if(activity!=null){
+
+ /*
+ * If it is not visible
+ * */
+ if(currentActivity==null){
+
+ /*
+ * Reset flags
+ * */
+ destroyWindow = false
+
+ /*
+ * Show the loading activity
+ * */
+ val intent = Intent(activity, LoadingActivity::class.java)
+ activity.startActivity(intent)
+ }
+ }
+ }
+
+ /*
+ * Dismiss the loading activity
+ * */
+ @JvmStatic
+ open fun dismiss() {
+
+ if(currentActivity!=null){
+
+ /*
+ * Close the activity
+ * */
+ currentActivity?.finish()
+
+ /*
+ * Reset flags
+ * */
+ loadinIconChangeSize = false
+ currentActivity = null
+ destroyWindow = true
+ }
+ }
+
+ /*
+ * Change the loading icon size
+ * */
+ @JvmStatic
+ open fun loadingIconSize(width:Int,heigth:Int) {
+
+ /*
+ * The loading icon size wil change
+ * */
+ loadinIconChangeSize = true
+
+ /*
+ * Save the sizes
+ * */
+ loadingIconWidth = width
+ loadingIconHeigt = heigth
+ }
+
+ /*
+ * When the loading window is closed
+ * */
+ @JvmStatic
+ open fun onLoadingClosed(onLoadingClose: LoadingClosed) {
+ this.onLoadingClosed = onLoadingClose
+ }
+
+ /*
+ * When the loading window is up and visible
+ * */
+ @JvmStatic
+ open fun onLoadingReady(onLoadingResume:LoadingReady) {
+ this.onLoadingReady = onLoadingResume
+ }
+
+
+ /*
+ * Timer to close the window
+ * */
+ @JvmStatic
+ open fun closeOnTime(seconds:Int) {
+ LoadingActivity.seconds = seconds
+ }
+ }
+
+
+ /*
+ * Interface for all the events
+ * */
+ interface LoadingClosed{
+ fun onLoadingClosed()
+ }
+ interface LoadingReady{
+ fun onLoadingReady()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/cy/agorise/crystalwallet/activities/PinRequestActivity.java b/app/src/main/java/cy/agorise/crystalwallet/activities/PinRequestActivity.java
index a4f4a5a..289d899 100644
--- a/app/src/main/java/cy/agorise/crystalwallet/activities/PinRequestActivity.java
+++ b/app/src/main/java/cy/agorise/crystalwallet/activities/PinRequestActivity.java
@@ -7,22 +7,18 @@ import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.text.Editable;
-import android.widget.Button;
import android.widget.EditText;
-import android.widget.TextView;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
-import butterknife.OnClick;
import butterknife.OnTextChanged;
import cy.agorise.crystalwallet.R;
import cy.agorise.crystalwallet.application.CrystalSecurityMonitor;
import cy.agorise.crystalwallet.models.AccountSeed;
import cy.agorise.crystalwallet.models.GeneralSetting;
import cy.agorise.crystalwallet.util.PasswordManager;
-import cy.agorise.crystalwallet.viewmodels.AccountSeedViewModel;
import cy.agorise.crystalwallet.viewmodels.GeneralSettingListViewModel;
public class PinRequestActivity extends AppCompatActivity {
diff --git a/app/src/main/java/cy/agorise/crystalwallet/apigenerator/GrapheneApiGenerator.java b/app/src/main/java/cy/agorise/crystalwallet/apigenerator/GrapheneApiGenerator.java
index d1bfc00..9d781fd 100644
--- a/app/src/main/java/cy/agorise/crystalwallet/apigenerator/GrapheneApiGenerator.java
+++ b/app/src/main/java/cy/agorise/crystalwallet/apigenerator/GrapheneApiGenerator.java
@@ -1,5 +1,6 @@
package cy.agorise.crystalwallet.apigenerator;
+import android.app.Activity;
import android.content.Context;
import java.io.Serializable;
@@ -81,6 +82,30 @@ public abstract class GrapheneApiGenerator {
*/
private static HashMap currentBitsharesListener = new HashMap<>();
+ /*
+ *
+ * To present erros to user
+ * */
+ private static Activity activity;
+
+
+ /*
+ *
+ * Interface to catch only errors in connection with sockets
+ * */
+ private static OnErrorWebSocket onErrorWebSocket;
+
+ /*
+ *
+ * Interface to catch both errors and success in connection with sockets
+ * */
+ private static OnResponsesWebSocket onResponsesWebSocker;
+
+
+
+
+
+
/**
* Retrieves the data of an account searching by it's id
*
@@ -221,6 +246,8 @@ public abstract class GrapheneApiGenerator {
request.getListener().fail(request.getId());
}
}), CryptoNetManager.getURL(CryptoNet.BITSHARES));
+ thread.setActivity(activity); //To catch websocket errors to user interface
+ thread.setOnErrorWebSocker(onErrorWebSocket); //To deliver websocket errors to user interface
thread.start();
}
@@ -703,4 +730,35 @@ public abstract class GrapheneApiGenerator {
}
}
+
+ public static void setActivity(Activity activity) {
+ GrapheneApiGenerator.activity = activity;
+ }
+
+
+ public static void setOnResponsesWebSocker(OnResponsesWebSocket onResponsesWebSocker) {
+ GrapheneApiGenerator.onResponsesWebSocker = onResponsesWebSocker;
+ }
+
+ public static void setOnErrorWebSocket(OnErrorWebSocket onErrorWebSocket) {
+ GrapheneApiGenerator.onErrorWebSocket = onErrorWebSocket;
+ }
+
+ /*
+ *
+ * Interface to catch errors in connection with sockets
+ * */
+ public interface OnErrorWebSocket {
+ void onError(Exception exception);
+ }
+
+ /*
+ *
+ * Interface to catch succesfully connection with sockets
+ * */
+ public interface OnResponsesWebSocket {
+ void onSuccess();
+ void onError(Exception exception);
+ }
+
}
diff --git a/app/src/main/java/cy/agorise/crystalwallet/application/CrystalApplication.java b/app/src/main/java/cy/agorise/crystalwallet/application/CrystalApplication.java
index b7776d1..d6dad49 100644
--- a/app/src/main/java/cy/agorise/crystalwallet/application/CrystalApplication.java
+++ b/app/src/main/java/cy/agorise/crystalwallet/application/CrystalApplication.java
@@ -1,5 +1,6 @@
package cy.agorise.crystalwallet.application;
+import android.app.Activity;
import android.app.Application;
import android.content.Intent;
import android.content.res.Configuration;
@@ -11,6 +12,7 @@ import com.idescout.sql.SqlScoutServer;
import java.util.Locale;
import cy.agorise.crystalwallet.R;
+import cy.agorise.crystalwallet.apigenerator.GrapheneApiGenerator;
import cy.agorise.crystalwallet.dao.CrystalDatabase;
import cy.agorise.crystalwallet.enums.CryptoNet;
import cy.agorise.crystalwallet.models.BitsharesAsset;
diff --git a/app/src/main/java/cy/agorise/crystalwallet/dialogs/material/CrystalDialog.kt b/app/src/main/java/cy/agorise/crystalwallet/dialogs/material/CrystalDialog.kt
new file mode 100644
index 0000000..415beb5
--- /dev/null
+++ b/app/src/main/java/cy/agorise/crystalwallet/dialogs/material/CrystalDialog.kt
@@ -0,0 +1,31 @@
+package cy.agorise.crystalwallet.dialogs.material
+
+import android.app.Activity
+import cy.agorise.crystalwallet.R
+import kotlinx.android.synthetic.main.account_seed_list.view.*
+
+
+/*
+* Dialog material that shows loading gif and and explicit message
+* */
+open class CrystalDialog : DialogMaterial{
+
+ constructor(activity: Activity) : super(activity) {
+
+ /*
+ * Prepare the dialog
+ * */
+ this.builder.title("")
+ this.builder.content("")
+ }
+}
+
+/*
+* Internal interfaces
+* */
+interface PositiveResponse{
+ fun onPositive()
+}
+interface NegativeResponse{
+ fun onNegative()
+}
\ No newline at end of file
diff --git a/app/src/main/java/cy/agorise/crystalwallet/dialogs/material/DialogMaterial.kt b/app/src/main/java/cy/agorise/crystalwallet/dialogs/material/DialogMaterial.kt
new file mode 100644
index 0000000..7082a12
--- /dev/null
+++ b/app/src/main/java/cy/agorise/crystalwallet/dialogs/material/DialogMaterial.kt
@@ -0,0 +1,154 @@
+package cy.agorise.crystalwallet.dialogs.material
+
+import android.app.Activity
+import com.afollestad.materialdialogs.MaterialDialog
+import cy.agorise.crystalwallet.R
+
+/*
+*
+* Controls the custom implementarion for all kind of material dialogs
+* Reference in: https://github.com/afollestad/material-dialogs
+*
+* */
+open abstract class DialogMaterial{
+
+ protected var builder: MaterialDialog.Builder //Contains the builder
+ protected lateinit var materialDialog: MaterialDialog //Contains the controller for the dialog
+
+ /*
+ * Contains the activity
+ * */
+ protected var activity:Activity;
+
+
+ /*
+ * Contains the response for positive button click
+ * */
+ var positiveResponse:PositiveResponse? = null
+
+ /*
+ * Contains the response for negative button click
+ * */
+ var negativeResponse:NegativeResponse? = null
+
+
+
+
+ constructor(activity: Activity) {
+
+ /*
+ * Save the activity
+ * */
+ this.activity = activity
+
+ /*
+ * Init the builder
+ * */
+ builder = MaterialDialog.Builder(activity)
+ }
+
+
+ /*
+ * Show the dialog
+ * */
+ fun show() {
+
+ /*
+ * If user wants positive and negative
+ * */
+ if(positiveResponse != null && negativeResponse != null){
+
+ /*
+ * Add positve
+ * */
+ builder.positiveText(activity.resources.getString(R.string.ok))
+ builder.onPositive { dialog, which ->
+
+ /*
+ * If response is not null deliver response
+ * */
+ if(positiveResponse != null){
+ positiveResponse!!.onPositive()
+ }
+ }
+
+ /*
+ * Add negative
+ * */
+ builder.negativeText(activity.resources.getString(R.string.cancel))
+ builder.onNegative { dialog, which ->
+
+ /*
+ * If response is not null deliver response
+ * */
+ if(negativeResponse != null){
+ negativeResponse!!.onNegative()
+ }
+ }
+ }
+
+ /*
+ * If user wants positive button
+ * */
+ if(positiveResponse != null){
+ builder.positiveText(activity.resources.getString(R.string.ok))
+ builder.onPositive { dialog, which ->
+
+ /*
+ * If response is not null deliver response
+ * */
+ if(positiveResponse != null){
+ positiveResponse!!.onPositive()
+ }
+ }
+ }
+
+ /*
+ * Build internal material dialog, this lets to show it
+ * */
+ this.build()
+
+ /*
+ * Show the dialog
+ * */
+ materialDialog.show()
+ }
+
+ /*
+ * Close the dialog
+ * */
+ fun dismiss() {
+ this.materialDialog.dismiss()
+ }
+
+ /*
+ * After the class is completed as needed, we need to call this method to join all together after show the
+ * childs implementations
+ * */
+ open fun build() {
+ this.materialDialog = this.builder.build()
+ }
+
+
+ /*
+ * Set indeterminate progress
+ *
+ * */
+ open fun progress(){
+ this.builder.progress(true, 0)
+ }
+
+ /*
+ * Setters and getters
+ * */
+ fun setText(message: String) {
+ this.builder.content(message)
+ }
+
+ fun setTitle(title: String) {
+ this.builder.title(title)
+ }
+ /*
+ * End of setters and getters
+ * */
+}
\ No newline at end of file
diff --git a/app/src/main/java/cy/agorise/crystalwallet/dialogs/material/ToastIt.kt b/app/src/main/java/cy/agorise/crystalwallet/dialogs/material/ToastIt.kt
new file mode 100644
index 0000000..1c9fc9a
--- /dev/null
+++ b/app/src/main/java/cy/agorise/crystalwallet/dialogs/material/ToastIt.kt
@@ -0,0 +1,31 @@
+package cy.agorise.crystalwallet.dialogs.material
+
+import android.app.Activity
+import android.widget.Toast
+
+
+/*
+* This class is an implementation of toast
+* */
+class ToastIt {
+
+ /*
+ * Satitic methods
+ * */
+ companion object {
+
+ /*
+ * Show long toast
+ * */
+ @JvmStatic fun showLongToast(activity: Activity, message:String) {
+ Toast.makeText(activity, message, Toast.LENGTH_LONG).show()
+ }
+
+ /*
+ * Show short toast
+ * */
+ @JvmStatic fun showShortToast(activity: Activity, message:String) {
+ Toast.makeText(activity, message, Toast.LENGTH_SHORT).show()
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/cy/agorise/crystalwallet/fragments/PinSecurityFragment.java b/app/src/main/java/cy/agorise/crystalwallet/fragments/PinSecurityFragment.java
index edfaea9..c5d298c 100644
--- a/app/src/main/java/cy/agorise/crystalwallet/fragments/PinSecurityFragment.java
+++ b/app/src/main/java/cy/agorise/crystalwallet/fragments/PinSecurityFragment.java
@@ -1,16 +1,13 @@
package cy.agorise.crystalwallet.fragments;
import android.arch.lifecycle.LiveData;
-import android.arch.lifecycle.Observer;
import android.arch.lifecycle.ViewModelProviders;
import android.os.Bundle;
-import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.text.Editable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
@@ -21,9 +18,7 @@ import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnTextChanged;
import cy.agorise.crystalwallet.R;
-import cy.agorise.crystalwallet.activities.CreateSeedActivity;
import cy.agorise.crystalwallet.application.CrystalSecurityMonitor;
-import cy.agorise.crystalwallet.dao.CrystalDatabase;
import cy.agorise.crystalwallet.models.GeneralSetting;
import cy.agorise.crystalwallet.util.PasswordManager;
import cy.agorise.crystalwallet.viewmodels.GeneralSettingListViewModel;
diff --git a/app/src/main/java/cy/agorise/crystalwallet/fragments/SendTransactionFragment.java b/app/src/main/java/cy/agorise/crystalwallet/fragments/SendTransactionFragment.java
index e6d96e1..5a89378 100644
--- a/app/src/main/java/cy/agorise/crystalwallet/fragments/SendTransactionFragment.java
+++ b/app/src/main/java/cy/agorise/crystalwallet/fragments/SendTransactionFragment.java
@@ -32,6 +32,7 @@ import android.widget.Spinner;
import android.widget.TextView;
import com.google.zxing.Result;
+import com.jaredrummler.materialspinner.MaterialSpinner;
import java.io.File;
import java.math.RoundingMode;
@@ -73,7 +74,7 @@ public class SendTransactionFragment extends DialogFragment implements UIValidat
SendTransactionValidator sendTransactionValidator;
@BindView(R.id.spFrom)
- Spinner spFrom;
+ MaterialSpinner spFrom;
@BindView(R.id.tvFromError)
TextView tvFromError;
@BindView(R.id.etTo)
@@ -176,8 +177,27 @@ public class SendTransactionFragment extends DialogFragment implements UIValidat
CryptoNetAccountListViewModel cryptoNetAccountListViewModel = ViewModelProviders.of(this).get(CryptoNetAccountListViewModel.class);
List cryptoNetAccounts = cryptoNetAccountListViewModel.getCryptoNetAccountList();
CryptoNetAccountAdapter fromSpinnerAdapter = new CryptoNetAccountAdapter(this.getContext(), android.R.layout.simple_spinner_item, cryptoNetAccounts);
- spFrom.setAdapter(fromSpinnerAdapter);
- spFrom.setSelection(0);
+
+ //spFrom.setAdapter(fromSpinnerAdapter);
+ //spFrom.setSelection(0);
+
+ /*
+ * Custom material spinner implementation
+ * */
+ spFrom.setItems(cryptoNetAccounts);
+ spFrom.setSelectedIndex(0);
+ spFrom.setOnItemSelectedListener(new MaterialSpinner.OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(MaterialSpinner view, int position, long id, CryptoNetAccount item) {
+ sendTransactionValidator.validate();
+ }
+ });
+ spFrom.setOnNothingSelectedListener(new MaterialSpinner.OnNothingSelectedListener() {
+
+ @Override public void onNothingSelected(MaterialSpinner spinner) {
+
+ }
+ });
// etFrom.setText(this.grapheneAccount.getName());
}
@@ -230,10 +250,10 @@ public class SendTransactionFragment extends DialogFragment implements UIValidat
}
}
- @OnItemSelected(R.id.spFrom)
+ /*@OnItemSelected(R.id.spFrom)
public void afterFromSelected(Spinner spinner, int position) {
this.sendTransactionValidator.validate();
- }
+ }*/
@OnTextChanged(value = R.id.etTo,
callback = OnTextChanged.Callback.AFTER_TEXT_CHANGED)
@@ -311,7 +331,7 @@ public class SendTransactionFragment extends DialogFragment implements UIValidat
@OnClick(R.id.btnSend)
public void sendTransaction(){
if (this.sendTransactionValidator.isValid()) {
- CryptoNetAccount fromAccountSelected = (CryptoNetAccount) spFrom.getSelectedItem();
+ CryptoNetAccount fromAccountSelected = (CryptoNetAccount) spFrom.getItems().get(spFrom.getSelectedIndex());
/*
diff --git a/app/src/main/java/cy/agorise/crystalwallet/models/FieldValidatorModel.java b/app/src/main/java/cy/agorise/crystalwallet/models/FieldValidatorModel.java
new file mode 100644
index 0000000..36409ea
--- /dev/null
+++ b/app/src/main/java/cy/agorise/crystalwallet/models/FieldValidatorModel.java
@@ -0,0 +1,56 @@
+package cy.agorise.crystalwallet.models;
+
+import android.view.View;
+
+public class FieldValidatorModel {
+
+ /*
+ * Determine if the field is valid
+ * */
+ private boolean valid;
+
+ /*
+ * Contains the message of the error
+ * */
+ private String message;
+
+
+
+ /*
+ * Setters and getters
+ * */
+ public boolean isValid() {
+ return valid;
+ }
+
+ public void setValid(boolean valid) {
+ this.valid = valid;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+ /*
+ * End of setters and getters
+ * */
+
+
+ /*
+ * Set tha the field is invalid
+ * */
+ final public void setInvalid(){
+ this.valid = false;
+ }
+
+
+ /*
+ * Set tha the field is valid
+ * */
+ final public void setValid(){
+ this.valid = true;
+ }
+}
diff --git a/app/src/main/java/cy/agorise/crystalwallet/network/BitsharesCryptoNetVerifier.java b/app/src/main/java/cy/agorise/crystalwallet/network/BitsharesCryptoNetVerifier.java
index 8a47bce..e90758f 100644
--- a/app/src/main/java/cy/agorise/crystalwallet/network/BitsharesCryptoNetVerifier.java
+++ b/app/src/main/java/cy/agorise/crystalwallet/network/BitsharesCryptoNetVerifier.java
@@ -1,5 +1,6 @@
package cy.agorise.crystalwallet.network;
+import cy.agorise.crystalwallet.apigenerator.GrapheneApiGenerator;
import cy.agorise.crystalwallet.enums.CryptoNet;
import cy.agorise.graphenej.interfaces.WitnessResponseListener;
import cy.agorise.graphenej.models.BaseResponse;
@@ -23,15 +24,21 @@ public class BitsharesCryptoNetVerifier extends CryptoNetVerifier {
private final String CHAIN_ID = "9cf6f255a208100d2bb275a3c52f4b1589b7ec9c9bfc2cb2a5fe6411295106d8";//testnet
//private final String CHAIN_ID = "4018d7844c78f6a6c41c6a552b898022310fc5dec06da467ee7905a8dad512c8";//mainnet
- @Override
- public void checkURL(final String url) {
+
+
+
+
+
+ public BitsharesCryptoNetVerifier(){
+
+ /**/
final long startTime = System.currentTimeMillis();
- WebSocketThread thread = new WebSocketThread(new GetChainId(new WitnessResponseListener() {
+ thread = new WebSocketThread(new GetChainId(new WitnessResponseListener() {
@Override
public void onSuccess(WitnessResponse response) {
if(response.result instanceof String) {
if(response.result.equals(CHAIN_ID)) {
- CryptoNetManager.verifiedCryptoNetURL(cryptoNet, url, System.currentTimeMillis() - startTime);
+ CryptoNetManager.verifiedCryptoNetURL(cryptoNet, null, System.currentTimeMillis() - startTime);
}else{
System.out.println(" BitsharesCryptoNetVerifier Error we are not in the net current chain id " + response.result + " excepted " + CHAIN_ID);
//TODO handle error bad chain
@@ -43,8 +50,15 @@ public class BitsharesCryptoNetVerifier extends CryptoNetVerifier {
public void onError(BaseResponse.Error error) {
//TODO handle error
}
- }),url);
- thread.start();
+ }),null);
+
+ }
+
+
+ @Override
+ public void checkURL(final String url) {
+ thread.setmUrl(url); //Set the url
+ thread.start(); //Run the thread connection
}
@Override
diff --git a/app/src/main/java/cy/agorise/crystalwallet/network/CryptoNetManager.java b/app/src/main/java/cy/agorise/crystalwallet/network/CryptoNetManager.java
index d424cc8..8084096 100644
--- a/app/src/main/java/cy/agorise/crystalwallet/network/CryptoNetManager.java
+++ b/app/src/main/java/cy/agorise/crystalwallet/network/CryptoNetManager.java
@@ -1,14 +1,14 @@
package cy.agorise.crystalwallet.network;
+import android.app.Activity;
import android.support.annotation.NonNull;
-import android.util.Log;
import java.util.ArrayList;
import java.util.Collections;
-import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
+import cy.agorise.crystalwallet.apigenerator.GrapheneApiGenerator;
import cy.agorise.crystalwallet.enums.CryptoNet;
/**
@@ -61,20 +61,63 @@ public abstract class CryptoNetManager {
}
}
- public static void addCryptoNetURL(CryptoNet crypto, String[] urls){
- if(!CryptoNetURLs.containsKey(crypto)){
- CryptoNetURLs.put(crypto,new HashSet());
- }
- CryptoNetVerifier verifier = CryptoNetVerifier.getNetworkVerify(crypto);
- for(String url : urls) {
+ /*
+ * Add url with listener on error only for sockets
+ * */
+ public static void addCryptoNetURL(CryptoNet crypto,
+ String[] urls,
+ final Activity activity,
+ final GrapheneApiGenerator.OnErrorWebSocket onErrorWebSocker,
+ final boolean showNormalError){
+ addCryptoNetURL(crypto,urls,activity,onErrorWebSocker,null,showNormalError);
+ }
+
+
+ /*
+ * Add url with listener on error and response for sockets
+ * */
+ public static void addCryptoNetURL(CryptoNet crypto,
+ String[] urls,
+ final Activity activity,
+ final GrapheneApiGenerator.OnResponsesWebSocket onResponsesWebSocket,
+ final boolean showNormalError){
+ addCryptoNetURL(crypto,urls,activity,null,onResponsesWebSocket,showNormalError);
+ }
+
+
+ /*
+ * Utility for above methods
+ *
+ * */
+ public static void addCryptoNetURL(CryptoNet crypto,
+ String[] urls,
+ final Activity activity,
+ final GrapheneApiGenerator.OnErrorWebSocket onErrorWebSocker,
+ final GrapheneApiGenerator.OnResponsesWebSocket onResponsesWebSocket,
+ final boolean showNormalError) {
+
+ if (!CryptoNetURLs.containsKey(crypto)) {
+ CryptoNetURLs.put(crypto, new HashSet());
+ }
+
+ CryptoNetVerifier verifier = CryptoNetVerifier.getNetworkVerify(crypto);
+ verifier.getThread().setActivity(activity); //Logical connection to ui
+ verifier.getThread().setOnErrorWebSocker(onErrorWebSocker); //Connect response web socket error to ui response
+ verifier.getThread().setOnResponsesWebSocket(onResponsesWebSocket); //Connect response and error web socket error to ui response
+ verifier.getThread().setShowNormalMessage(showNormalError); //Not show native message error, we handle it
+
+ for (String url : urls) {
CryptoNetURLs.get(crypto).add(url);
- if(verifier != null) {
+ if (verifier != null) {
verifier.checkURL(url);
}
}
+
}
+
+
public static void removeCryptoNetURL(CryptoNet crypto, String url){
if(CryptoNetURLs.containsKey(crypto)){
CryptoNetURLs.get(crypto).remove(url);
@@ -145,5 +188,4 @@ public abstract class CryptoNetManager {
return (int) (this.getTime() - testedURL.getTime());
}
}
-
}
diff --git a/app/src/main/java/cy/agorise/crystalwallet/network/CryptoNetVerifier.java b/app/src/main/java/cy/agorise/crystalwallet/network/CryptoNetVerifier.java
index 7364b79..832d2f0 100644
--- a/app/src/main/java/cy/agorise/crystalwallet/network/CryptoNetVerifier.java
+++ b/app/src/main/java/cy/agorise/crystalwallet/network/CryptoNetVerifier.java
@@ -1,5 +1,8 @@
package cy.agorise.crystalwallet.network;
+import android.app.Activity;
+
+import cy.agorise.crystalwallet.apigenerator.GrapheneApiGenerator;
import cy.agorise.crystalwallet.enums.CryptoNet;
/**
@@ -12,6 +15,14 @@ import cy.agorise.crystalwallet.enums.CryptoNet;
public abstract class CryptoNetVerifier {
+ /*
+ * Contains the worker connection thread
+ */
+ protected WebSocketThread thread;
+
+
+
+
static CryptoNetVerifier getNetworkVerify(CryptoNet cryptoNet){
if(cryptoNet.getLabel().equals(CryptoNet.BITSHARES.getLabel())){
return new BitsharesCryptoNetVerifier();
@@ -22,4 +33,9 @@ public abstract class CryptoNetVerifier {
public abstract void checkURL(final String url);
public abstract String getChainId();
+
+
+ public WebSocketThread getThread() {
+ return thread;
+ }
}
diff --git a/app/src/main/java/cy/agorise/crystalwallet/network/WebSocketThread.java b/app/src/main/java/cy/agorise/crystalwallet/network/WebSocketThread.java
index 8f90654..3009f2e 100644
--- a/app/src/main/java/cy/agorise/crystalwallet/network/WebSocketThread.java
+++ b/app/src/main/java/cy/agorise/crystalwallet/network/WebSocketThread.java
@@ -1,15 +1,19 @@
package cy.agorise.crystalwallet.network;
+import android.app.Activity;
import android.util.Log;
+import android.widget.Toast;
import com.neovisionaries.ws.client.WebSocket;
-import com.neovisionaries.ws.client.WebSocketException;
import com.neovisionaries.ws.client.WebSocketFactory;
import com.neovisionaries.ws.client.WebSocketListener;
import java.io.IOException;
import java.util.HashMap;
+import cy.agorise.crystalwallet.activities.LoadingActivity;
+import cy.agorise.crystalwallet.apigenerator.GrapheneApiGenerator;
+
/**
* Created by henry on 8/10/2017.
*/
@@ -33,6 +37,34 @@ public class WebSocketThread extends Thread {
// If the parameters of this class can be change
private boolean canChange = true;
+ /*
+ *
+ * Interface to catch only errors in connection with sockets
+ * */
+ private GrapheneApiGenerator.OnErrorWebSocket onErrorWebSocker;
+
+ /*
+ *
+ * Interface to catch errors and success responses in connection with sockets
+ * */
+ private GrapheneApiGenerator.OnResponsesWebSocket onResponsesWebSocket;
+
+
+ /*
+ * To catch websocket errors
+ * */
+ private Activity activity;
+
+ /*
+ * To show normal error message or not
+ * */
+ private boolean showNormalMessage = true;
+
+
+ /*
+ * Object needed for socket connection
+ * */
+ private WebSocketFactory factory;
/**
* Basic constructor,
@@ -43,16 +75,27 @@ public class WebSocketThread extends Thread {
* @param url The url to connect
*/
public WebSocketThread(WebSocketListener webSocketListener, String url) {
- try {
- WebSocketFactory factory = new WebSocketFactory().setConnectionTimeout(5000);
- this.mUrl = url;
- this.mWebSocketListener = webSocketListener;
- this.mWebSocket = factory.createSocket(this.mUrl);
- this.mWebSocket.addListener(this.mWebSocketListener);
- } catch (IOException e) {
- Log.e(TAG, "IOException. Msg: "+e.getMessage());
- } catch(NullPointerException e){
- Log.e(TAG, "NullPointerException at WebsocketWorkerThreas. Msg: "+e.getMessage());
+
+ /*
+ * The listener always can be setted
+ * */
+ this.mWebSocketListener = webSocketListener;
+
+ /*
+ *
+ * If at this point the url is not defined, this will be set after
+ * */
+ if(url!=null){
+ try {
+ factory = new WebSocketFactory().setConnectionTimeout(5000);
+ this.mUrl = url;
+ this.mWebSocket = factory.createSocket(this.mUrl);
+ this.mWebSocket.addListener(this.mWebSocketListener);
+ } catch (IOException e) {
+ Log.e(TAG, "IOException. Msg: "+e.getMessage());
+ } catch(NullPointerException e){
+ Log.e(TAG, "NullPointerException at WebsocketWorkerThreas. Msg: "+e.getMessage());
+ }
}
}
@@ -110,16 +153,62 @@ public class WebSocketThread extends Thread {
@Override
public void run() {
+
canChange = false;
+
// Moves the current Thread into the background
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND);
+
try {
+
+ /*
+ * If the initialization of the socket comes after
+ * */
+ if(factory==null){
+ factory = new WebSocketFactory().setConnectionTimeout(5000);
+ this.mWebSocket = factory.createSocket(this.mUrl);
+ this.mWebSocket.addListener(this.mWebSocketListener);
+ }
+
WebSocketThread.currentThreads.put(this.getId(),this);
mWebSocket.connect();
- } catch (WebSocketException e) {
+
+ /*
+ *
+ * Websocket success response
+ * */
+ if(onResponsesWebSocket!=null){
+ onResponsesWebSocket.onSuccess();
+ }
+
+ } catch (final Exception e) {
Log.e(TAG, "WebSocketException. Msg: "+e.getMessage());
- } catch(NullPointerException e){
- Log.e(TAG, "NullPointerException. Msg: "+e.getMessage());
+
+ //Deliver error to user
+ if(activity!=null){
+
+ /*
+ * Show error to user if aplies
+ * */
+ activity.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+
+ if(showNormalMessage){
+ Toast.makeText(activity, e.getMessage(), Toast.LENGTH_LONG).show();
+ }
+ }
+ });
+
+ /*Deliver response in the listeners*/
+ if(onErrorWebSocker!=null){
+ onErrorWebSocker.onError(e);
+ }
+ else if(onResponsesWebSocket!=null){
+ onResponsesWebSocket.onError(e);
+ }
+ }
+
}
WebSocketThread.currentThreads.remove(this.getId());
}
@@ -127,4 +216,25 @@ public class WebSocketThread extends Thread {
public boolean isConnected(){
return mWebSocket.isOpen();
}
+
+
+ public void setOnErrorWebSocker(GrapheneApiGenerator.OnErrorWebSocket onErrorWebSocker) {
+ this.onErrorWebSocker = onErrorWebSocker;
+ }
+
+ public void setActivity(Activity activity) {
+ this.activity = activity;
+ }
+
+ public void setShowNormalMessage(boolean showNormalMessage) {
+ this.showNormalMessage = showNormalMessage;
+ }
+
+ public void setmUrl(String mUrl) {
+ this.mUrl = mUrl;
+ }
+
+ public void setOnResponsesWebSocket(GrapheneApiGenerator.OnResponsesWebSocket onResponsesWebSocket) {
+ this.onResponsesWebSocket = onResponsesWebSocket;
+ }
}
diff --git a/app/src/main/java/cy/agorise/crystalwallet/requestmanagers/CryptoNetInfoRequest.java b/app/src/main/java/cy/agorise/crystalwallet/requestmanagers/CryptoNetInfoRequest.java
index 103411b..bdeecbc 100644
--- a/app/src/main/java/cy/agorise/crystalwallet/requestmanagers/CryptoNetInfoRequest.java
+++ b/app/src/main/java/cy/agorise/crystalwallet/requestmanagers/CryptoNetInfoRequest.java
@@ -1,5 +1,7 @@
package cy.agorise.crystalwallet.requestmanagers;
+import android.app.Activity;
+
import cy.agorise.crystalwallet.enums.CryptoCoin;
/**
@@ -19,6 +21,13 @@ public abstract class CryptoNetInfoRequest {
*/
protected CryptoNetInfoRequestListener listener;
+
+
+
+
+
+
+
protected CryptoNetInfoRequest(CryptoCoin coin){
this.coin = coin;
}
@@ -31,4 +40,5 @@ public abstract class CryptoNetInfoRequest {
listener.onCarryOut();
CryptoNetInfoRequests.getInstance().removeRequest(this);
}
+
}
diff --git a/app/src/main/java/cy/agorise/crystalwallet/tests/activities/dialogs/Test_CrystalDialogActivity.kt b/app/src/main/java/cy/agorise/crystalwallet/tests/activities/dialogs/Test_CrystalDialogActivity.kt
new file mode 100644
index 0000000..c1d2138
--- /dev/null
+++ b/app/src/main/java/cy/agorise/crystalwallet/tests/activities/dialogs/Test_CrystalDialogActivity.kt
@@ -0,0 +1,94 @@
+package cy.agorise.crystalwallet.tests.activities.dialogs
+
+import android.os.Bundle
+import android.widget.Toast
+import cy.agorise.crystalwallet.R
+import cy.agorise.crystalwallet.activities.CustomActivity
+import cy.agorise.crystalwallet.dialogs.material.CrystalDialog
+import cy.agorise.crystalwallet.dialogs.material.NegativeResponse
+import cy.agorise.crystalwallet.dialogs.material.PositiveResponse
+
+/*
+* Class to test CrystalDialog
+* */
+class Test_CrystalDialogActivity : CustomActivity() {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ setContentView(R.layout.empty_activity)
+
+ //show()
+ //showOKDialog()
+ //showOKCancelDialog()
+ //showProgressIndeterminate()
+ }
+
+ /*
+ *
+ * Show the simplest dialog
+ *
+ * */
+ fun show(){
+
+ var crytalDialog:CrystalDialog = CrystalDialog(this)
+ crytalDialog.setTitle("Title")
+ crytalDialog.setText("Text")
+ crytalDialog.show()
+ //crytalDialog.dismiss()
+ }
+
+ /*
+ *
+ * Show the accept dialog
+ *
+ * */
+ fun showOKDialog(){
+
+ var crytalDialog:CrystalDialog = CrystalDialog(this)
+ crytalDialog.setTitle("Title")
+ crytalDialog.setText("Text")
+ crytalDialog.positiveResponse = object:PositiveResponse{
+ override fun onPositive() {
+ Toast.makeText(globalActivity, "CrystalDialog Positive clicked", Toast.LENGTH_LONG).show()
+ }
+ }
+ crytalDialog.show()
+ }
+
+ /*
+ *
+ * Show the accept and cancel dialog
+ *
+ * */
+ fun showOKCancelDialog(){
+
+ var crytalDialog:CrystalDialog = CrystalDialog(this)
+ crytalDialog.setTitle("Title")
+ crytalDialog.setText("Text")
+ crytalDialog.positiveResponse = object:PositiveResponse{
+ override fun onPositive() {
+ Toast.makeText(globalActivity, "CrystalDialog Positive clicked", Toast.LENGTH_LONG).show()
+ }
+ }
+ crytalDialog.negativeResponse = object:NegativeResponse{
+ override fun onNegative() {
+ Toast.makeText(globalActivity, "CrystalDialog Negative clicked", Toast.LENGTH_LONG).show()
+ }
+ }
+ crytalDialog.show()
+ }
+
+ /*
+ *
+ * Show the indeterminate dialog with text
+ *
+ * */
+ fun showProgressIndeterminate(){
+
+ var crytalDialog:CrystalDialog = CrystalDialog(this)
+ crytalDialog.setText("Loading...")
+ crytalDialog.progress()
+ crytalDialog.show()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/cy/agorise/crystalwallet/tests/activities/dialogs/Test_DialogMaterialActivity.kt b/app/src/main/java/cy/agorise/crystalwallet/tests/activities/dialogs/Test_DialogMaterialActivity.kt
new file mode 100644
index 0000000..89af0bc
--- /dev/null
+++ b/app/src/main/java/cy/agorise/crystalwallet/tests/activities/dialogs/Test_DialogMaterialActivity.kt
@@ -0,0 +1,38 @@
+package cy.agorise.crystalwallet.tests.activities.dialogs
+
+import android.os.Bundle
+import cy.agorise.crystalwallet.R
+import cy.agorise.crystalwallet.activities.CustomActivity
+import cy.agorise.crystalwallet.dialogs.material.DialogMaterial
+
+
+/*
+* Class to test DialogMaterial.kt
+* */
+class Test_DialogMaterialActivity : CustomActivity() {
+
+ /*
+ * Object to be tested
+ * */
+ lateinit var dialogMaterial: DialogMaterial;
+
+
+
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ setContentView(R.layout.empty_activity)
+ }
+
+
+ /*
+ * This class can not be instantiate,
+ * this methos is commented to prevent compilation error, if uncommented it should
+ * throw error compilations and based on this this assertion is complete
+ *
+ * */
+ fun instiantiation(){
+ //dialogMaterial = DialogMaterial(this)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/cy/agorise/crystalwallet/tests/activities/dialogs/Test_GIFActivity.kt b/app/src/main/java/cy/agorise/crystalwallet/tests/activities/dialogs/Test_GIFActivity.kt
new file mode 100644
index 0000000..81c732c
--- /dev/null
+++ b/app/src/main/java/cy/agorise/crystalwallet/tests/activities/dialogs/Test_GIFActivity.kt
@@ -0,0 +1,44 @@
+package cy.agorise.crystalwallet.tests.activities.dialogs
+
+import android.os.Bundle
+import android.view.View
+import cy.agorise.crystalwallet.R
+import cy.agorise.crystalwallet.activities.CustomActivity
+import kotlinx.android.synthetic.main.empty_activity.*
+
+
+/*
+* Unit test for class GIFView
+* */
+class Test_GIFActivity : CustomActivity() {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ setContentView(R.layout.empty_activity)
+
+ /*
+ * For testings purpouses
+ * */
+ gifView.visibility = View.VISIBLE
+
+ load()
+ //loadWithContainer()
+ }
+
+
+ /*
+ * Load normaly the gif
+ * */
+ fun load(){
+ gifView.load(R.raw.burbujas)
+ }
+
+ /*
+ * Load with fit into container
+ * */
+ fun loadWithContainer(){
+ gifView.centerCrop()
+ gifView.load(R.raw.burbujas)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/cy/agorise/crystalwallet/tests/activities/dialogs/Test_LoadingActivity.kt b/app/src/main/java/cy/agorise/crystalwallet/tests/activities/dialogs/Test_LoadingActivity.kt
new file mode 100644
index 0000000..e3d95c0
--- /dev/null
+++ b/app/src/main/java/cy/agorise/crystalwallet/tests/activities/dialogs/Test_LoadingActivity.kt
@@ -0,0 +1,78 @@
+package cy.agorise.crystalwallet.tests.activities.dialogs
+
+import android.os.Bundle
+import android.widget.Toast
+import cy.agorise.crystalwallet.activities.CustomActivity
+import cy.agorise.crystalwallet.activities.LoadingActivity
+
+
+/*
+* Class to test LoadingActivity
+* */
+class Test_LoadingActivity : CustomActivity(){
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ show()
+ //withTimer()
+ //onLoadingClose()
+ //onLoadingReady()
+ //sizeInLoadingIcon()
+ }
+
+
+ /*
+ * Show the simple loading graphic
+ * */
+ fun show(){
+ LoadingActivity.show(globalActivity)
+ //LoadingActivity.dismiss() //For testing porpouse
+ }
+
+
+ /*
+ * Loading with timer
+ * */
+ fun withTimer(){
+ LoadingActivity.closeOnTime(3)
+ LoadingActivity.show(globalActivity)
+ }
+
+
+ /*
+ * Listener when the loading window is closed
+ * */
+ fun onLoadingClose(){
+ LoadingActivity.closeOnTime(3)
+ LoadingActivity.onLoadingClosed(object : LoadingActivity.LoadingClosed{
+ override fun onLoadingClosed() {
+ Toast.makeText(globalActivity, "onLoadingClosed event fired", Toast.LENGTH_LONG).show()
+ }
+
+ })
+ LoadingActivity.show(globalActivity)
+ }
+
+
+ /*
+ * Listener when the loading window is resume
+ * */
+ fun onLoadingReady(){
+ LoadingActivity.onLoadingReady(object : LoadingActivity.LoadingReady{
+ override fun onLoadingReady() {
+ Toast.makeText(globalActivity, "onLoadingReady event fired", Toast.LENGTH_LONG).show()
+ }
+
+ })
+ LoadingActivity.show(globalActivity)
+ }
+
+ /*
+ * Set specified size to the loading icon
+ * */
+ fun sizeInLoadingIcon(){
+ LoadingActivity.loadingIconSize(30,30)
+ LoadingActivity.show(globalActivity)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/cy/agorise/crystalwallet/tests/activities/dialogs/Test_NetworkActivity.kt b/app/src/main/java/cy/agorise/crystalwallet/tests/activities/dialogs/Test_NetworkActivity.kt
new file mode 100644
index 0000000..43d7d42
--- /dev/null
+++ b/app/src/main/java/cy/agorise/crystalwallet/tests/activities/dialogs/Test_NetworkActivity.kt
@@ -0,0 +1,25 @@
+package cy.agorise.crystalwallet.tests.activities.dialogs
+
+import android.os.Bundle
+import cy.agorise.crystalwallet.activities.CustomActivity
+
+
+
+
+/*
+* Class to test all network implementation
+* */
+class Test_NetworkActivity:CustomActivity(){
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+
+ }
+
+
+ fun testServerConnection(){
+
+
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/cy/agorise/crystalwallet/tests/activities/dialogs/Test_ToastActivity.kt b/app/src/main/java/cy/agorise/crystalwallet/tests/activities/dialogs/Test_ToastActivity.kt
new file mode 100644
index 0000000..b8566e5
--- /dev/null
+++ b/app/src/main/java/cy/agorise/crystalwallet/tests/activities/dialogs/Test_ToastActivity.kt
@@ -0,0 +1,34 @@
+package cy.agorise.crystalwallet.tests.activities.dialogs
+
+import android.os.Bundle
+import cy.agorise.crystalwallet.R
+import cy.agorise.crystalwallet.activities.CustomActivity
+import cy.agorise.crystalwallet.dialogs.material.ToastIt
+
+class Test_ToastActivity : CustomActivity() {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ setContentView(R.layout.empty_activity)
+
+ //showShort()
+ showLongShort()
+ }
+
+
+ /*
+ * Show simple short toast
+ * */
+ fun showShort(){
+ ToastIt.showShortToast(this,"showShortToast")
+ }
+
+
+ /*
+ * Show simple short toast
+ * */
+ fun showLongShort(){
+ ToastIt.showShortToast(this,"showLongShort")
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/cy/agorise/crystalwallet/tests/activities/dialogs/Test_VideoActivity.kt b/app/src/main/java/cy/agorise/crystalwallet/tests/activities/dialogs/Test_VideoActivity.kt
new file mode 100644
index 0000000..45d7a59
--- /dev/null
+++ b/app/src/main/java/cy/agorise/crystalwallet/tests/activities/dialogs/Test_VideoActivity.kt
@@ -0,0 +1,53 @@
+package cy.agorise.crystalwallet.tests.activities.dialogs
+
+import android.net.Uri
+import android.os.Bundle
+import android.view.View
+import cy.agorise.crystalwallet.R
+import cy.agorise.crystalwallet.activities.CustomActivity
+import kotlinx.android.synthetic.main.empty_activity.*
+
+
+/*
+* Class for test VideoExView
+* */
+class Test_VideoActivity : CustomActivity() {
+
+ /*
+ * cy.agorise.crystalwallet.views.natives.VideoViewEx
+ * should be used as view to get the new implementations
+ * */
+
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ setContentView(R.layout.empty_activity)
+
+ /*
+ * For testing purpouses
+ * */
+ video.visibility = View.VISIBLE
+
+ //play()
+ playIndeterminate()
+ }
+
+
+ /*
+ * Just one time play
+ * */
+ fun play(){
+ video.setVideoRaw(R.raw.appbar_background)
+ video.start()
+ }
+
+
+ /*
+ * Just one time play
+ * */
+ fun playIndeterminate(){
+ video.setVideoRaw(R.raw.appbar_background)
+ video.playContinius()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/cy/agorise/crystalwallet/util/FieldsValidator.kt b/app/src/main/java/cy/agorise/crystalwallet/util/FieldsValidator.kt
new file mode 100644
index 0000000..c6e76d5
--- /dev/null
+++ b/app/src/main/java/cy/agorise/crystalwallet/util/FieldsValidator.kt
@@ -0,0 +1,38 @@
+package cy.agorise.crystalwallet.util
+
+import cy.agorise.crystalwallet.viewmodels.validators.customImpl.interfaces.UIValidator
+import java.util.ArrayList
+
+class FieldsValidator {
+
+ /*
+ * Contains the fields to validate
+ * */
+ private var fields: MutableList = ArrayList()
+
+ /*
+ * Setters and getters
+ * */
+ fun setFields(fields: List) {
+ this.fields = fields as MutableList
+ }
+ /*
+ * Endo of setters and getters
+ * */
+
+ /*
+ * Validate all the fields
+ * */
+ fun validate() {
+ for (uiValidator in fields) {
+ uiValidator.validate()
+ }
+ }
+
+ /*
+ * Add component to the list
+ * */
+ fun add(uiValidator: UIValidator) {
+ this.fields.add(uiValidator)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/cy/agorise/crystalwallet/util/NetworkUtility.kt b/app/src/main/java/cy/agorise/crystalwallet/util/NetworkUtility.kt
new file mode 100644
index 0000000..45b0cf1
--- /dev/null
+++ b/app/src/main/java/cy/agorise/crystalwallet/util/NetworkUtility.kt
@@ -0,0 +1,72 @@
+package cy.agorise.crystalwallet.util
+
+import android.app.Activity
+import android.widget.Toast
+import cy.agorise.crystalwallet.R
+import cy.agorise.crystalwallet.apigenerator.GrapheneApiGenerator
+import cy.agorise.crystalwallet.application.CrystalApplication
+import cy.agorise.crystalwallet.enums.CryptoNet
+import cy.agorise.crystalwallet.network.CryptoNetManager
+
+/*
+*
+* Static methods for network utility
+* */
+class NetworkUtility {
+
+ /*
+ * Satitic methods
+ * */
+ companion object {
+
+ /*
+ * Test connection with server
+ * */
+ @JvmStatic fun testServerConnnection(activity:Activity){
+
+ val onErrorWebSocker = GrapheneApiGenerator.OnErrorWebSocket {
+ /*
+ * Show message to client
+ * */
+ activity.runOnUiThread(Runnable { Toast.makeText(activity, activity.getResources().getString(R.string.network_err_no_server_connection), Toast.LENGTH_LONG).show() })
+ }
+ CryptoNetManager.addCryptoNetURL(CryptoNet.BITSHARES, CrystalApplication.BITSHARES_TESTNET_URL, activity, onErrorWebSocker, false)
+
+ }
+
+ /*
+ * Test connection with server and custom implementation callback
+ * */
+ @JvmStatic fun testServerConnnection(activity:Activity, onResponseWebSocket: GrapheneApiGenerator.OnResponsesWebSocket){
+ CryptoNetManager.addCryptoNetURL(CryptoNet.BITSHARES, CrystalApplication.BITSHARES_TESTNET_URL, activity, onResponseWebSocket, false)
+ }
+
+ /*
+ * Test connection with server and custom implementation callback and with normal error
+ * */
+ @JvmStatic fun testServerConnnectionNormalError(activity:Activity, onResponseWebSocket: GrapheneApiGenerator.OnResponsesWebSocket){
+
+ /*
+ *
+ * Listener to catch the error and show the normal user error message
+ *
+ * */
+ val onErrorWebSocker = GrapheneApiGenerator.OnErrorWebSocket {
+ /*
+ * Show message to client
+ * */
+ activity.runOnUiThread(Runnable { Toast.makeText(activity, activity.getResources().getString(R.string.network_err_no_server_connection), Toast.LENGTH_LONG).show() })
+ }
+
+ /*
+ * Request
+ * */
+ CryptoNetManager.addCryptoNetURL( CryptoNet.BITSHARES,
+ CrystalApplication.BITSHARES_TESTNET_URL,
+ activity,
+ onErrorWebSocker,
+ onResponseWebSocket,
+ false)
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/cy/agorise/crystalwallet/viewmodels/AccountSeedViewModel.java b/app/src/main/java/cy/agorise/crystalwallet/viewmodels/AccountSeedViewModel.java
deleted file mode 100644
index bb546a4..0000000
--- a/app/src/main/java/cy/agorise/crystalwallet/viewmodels/AccountSeedViewModel.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package cy.agorise.crystalwallet.viewmodels;
-
-import android.app.Application;
-import android.arch.lifecycle.AndroidViewModel;
-import android.arch.lifecycle.LiveData;
-
-import cy.agorise.crystalwallet.dao.CrystalDatabase;
-import cy.agorise.crystalwallet.models.AccountSeed;
-
-/**
- * Created by Henry Varona on 27/9/2017.
- */
-
-public class AccountSeedViewModel extends AndroidViewModel {
-
- private LiveData accountSeed;
- private CrystalDatabase db;
- private Application app;
-
- public AccountSeedViewModel(Application application) {
- super(application);
- this.db = CrystalDatabase.getAppDatabase(application.getApplicationContext());
- this.app = application;
- }
-
- public void loadSeed(long seedId){
- this.accountSeed = this.db.accountSeedDao().findByIdLiveData(seedId);
- }
-
- public void addSeed(AccountSeed seed){
- long newId = this.db.accountSeedDao().insertAccountSeed(seed);
- seed.setId(newId);
- }
-
- public LiveData getAccountSeed(){
- return this.accountSeed;
- }
-
-}
diff --git a/app/src/main/java/cy/agorise/crystalwallet/viewmodels/AccountSeedViewModel.kt b/app/src/main/java/cy/agorise/crystalwallet/viewmodels/AccountSeedViewModel.kt
new file mode 100644
index 0000000..5118b71
--- /dev/null
+++ b/app/src/main/java/cy/agorise/crystalwallet/viewmodels/AccountSeedViewModel.kt
@@ -0,0 +1,39 @@
+package cy.agorise.crystalwallet.viewmodels
+
+import android.app.Application
+import android.arch.lifecycle.AndroidViewModel
+import android.arch.lifecycle.LiveData
+import cy.agorise.crystalwallet.dao.CrystalDatabase
+import cy.agorise.crystalwallet.models.AccountSeed
+
+
+
+
+class AccountSeedViewModel : AndroidViewModel {
+
+ private var accountSeed: LiveData? = null
+ private val db: CrystalDatabase
+ private val app: Application
+
+
+
+
+ constructor(application: Application,db:CrystalDatabase): super(application) {
+ this.app = application;
+ this.db = db;
+ }
+
+
+ fun loadSeed(seedId: Long) {
+ this.accountSeed = this.db.accountSeedDao().findByIdLiveData(seedId)
+ }
+
+ fun addSeed(seed: AccountSeed) {
+ val newId = this.db.accountSeedDao().insertAccountSeed(seed)
+ seed.id = newId
+ }
+
+ fun getAccountSeed(): LiveData? {
+ return this.accountSeed
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/cy/agorise/crystalwallet/viewmodels/validators/SendTransactionValidator.java b/app/src/main/java/cy/agorise/crystalwallet/viewmodels/validators/SendTransactionValidator.java
index 66565a7..3cd67d9 100644
--- a/app/src/main/java/cy/agorise/crystalwallet/viewmodels/validators/SendTransactionValidator.java
+++ b/app/src/main/java/cy/agorise/crystalwallet/viewmodels/validators/SendTransactionValidator.java
@@ -4,6 +4,8 @@ import android.content.Context;
import android.widget.EditText;
import android.widget.Spinner;
+import com.jaredrummler.materialspinner.MaterialSpinner;
+
import cy.agorise.crystalwallet.models.CryptoNetAccount;
import cy.agorise.crystalwallet.viewmodels.validators.validationfields.AmountValidationField;
import cy.agorise.crystalwallet.viewmodels.validators.validationfields.AssetValidationField;
@@ -20,7 +22,7 @@ public class SendTransactionValidator extends UIValidator {
private CryptoNetAccount account;
- public SendTransactionValidator(Context context, CryptoNetAccount account, Spinner fromEdit, EditText toEdit, Spinner assetSpinner, EditText amountEdit, EditText memoEdit){
+ public SendTransactionValidator(Context context, CryptoNetAccount account, MaterialSpinner fromEdit, EditText toEdit, Spinner assetSpinner, EditText amountEdit, EditText memoEdit){
super(context);
this.account = account;
this.addField(new FromValidationField(fromEdit));
diff --git a/app/src/main/java/cy/agorise/crystalwallet/viewmodels/validators/customImpl/interfaces/UIValidator.kt b/app/src/main/java/cy/agorise/crystalwallet/viewmodels/validators/customImpl/interfaces/UIValidator.kt
new file mode 100644
index 0000000..2fc915e
--- /dev/null
+++ b/app/src/main/java/cy/agorise/crystalwallet/viewmodels/validators/customImpl/interfaces/UIValidator.kt
@@ -0,0 +1,10 @@
+package cy.agorise.crystalwallet.viewmodels.validators.customImpl.interfaces
+
+
+/*
+* Interface that all the views that need validation can use
+* */
+interface UIValidator {
+
+ fun validate()
+}
\ No newline at end of file
diff --git a/app/src/main/java/cy/agorise/crystalwallet/viewmodels/validators/customImpl/interfaces/UIValidatorListener.kt b/app/src/main/java/cy/agorise/crystalwallet/viewmodels/validators/customImpl/interfaces/UIValidatorListener.kt
new file mode 100644
index 0000000..bd638fe
--- /dev/null
+++ b/app/src/main/java/cy/agorise/crystalwallet/viewmodels/validators/customImpl/interfaces/UIValidatorListener.kt
@@ -0,0 +1,14 @@
+package cy.agorise.crystalwallet.viewmodels.validators.customImpl.interfaces
+
+import cy.agorise.crystalwallet.viewmodels.validators.customImpl.validationFields.CustomValidationField
+
+
+/*
+* Listener to deliver response to controls from inner validations
+* */
+interface UIValidatorListener {
+
+
+ fun onValidationFailed(customValidationField: CustomValidationField)
+ fun onValidationSucceeded(customValidationField: CustomValidationField)
+}
\ No newline at end of file
diff --git a/app/src/main/java/cy/agorise/crystalwallet/viewmodels/validators/customImpl/validationFields/BitsharesAccountNameValidation.kt b/app/src/main/java/cy/agorise/crystalwallet/viewmodels/validators/customImpl/validationFields/BitsharesAccountNameValidation.kt
new file mode 100644
index 0000000..c482f87
--- /dev/null
+++ b/app/src/main/java/cy/agorise/crystalwallet/viewmodels/validators/customImpl/validationFields/BitsharesAccountNameValidation.kt
@@ -0,0 +1,265 @@
+package cy.agorise.crystalwallet.viewmodels.validators.customImpl.validationFields
+
+import android.app.Activity
+import cy.agorise.crystalwallet.R
+import cy.agorise.crystalwallet.apigenerator.GrapheneApiGenerator
+import cy.agorise.crystalwallet.dialogs.material.CrystalDialog
+import cy.agorise.crystalwallet.requestmanagers.CryptoNetInfoRequests
+import cy.agorise.crystalwallet.requestmanagers.ValidateExistBitsharesAccountRequest
+import cy.agorise.crystalwallet.viewmodels.validators.customImpl.interfaces.UIValidator
+import cy.agorise.crystalwallet.viewmodels.validators.customImpl.interfaces.UIValidatorListener
+import cy.agorise.crystalwallet.views.natives.CustomTextInputEditText
+
+
+/*
+*
+* Validation layer for Account Name
+* */
+class BitsharesAccountNameValidation : CustomValidationField, UIValidator {
+
+ /*
+ * Contains the field to validate
+ * */
+ private val accountNameField: CustomTextInputEditText
+
+ /*
+ * Interface to validate when an account exist an take over control it
+ * */
+ private var onAccountExist: OnAccountExist? = null
+
+
+
+
+
+ constructor ( activity: Activity,
+ accountNameField: CustomTextInputEditText,
+ uiValidatorListener: UIValidatorListener) : super(activity) {
+
+ this.accountNameField = accountNameField
+ this.uiValidatorListener = uiValidatorListener
+
+ /*
+ * The current view for errors will be this
+ * */
+ this.currentView = this.accountNameField
+ }
+
+ override fun validate() {
+
+ val newValue = accountNameField.text.toString()
+
+ /*
+ Contains the validation result
+ */
+ var result = true
+
+ /*
+ * Validate empty field
+ * */
+ if (newValue == "") {
+
+ /*
+ * Validation not passed
+ * */
+ result = false
+ accountNameField.fieldValidatorModel.setInvalid()
+ accountNameField.fieldValidatorModel.message = this.accountNameField.resources.getString(R.string.create_account_window_err_account_empty)
+ } else {
+
+ /*
+ * Remove error
+ * */
+ accountNameField.error = null
+
+ /*
+ Validate at least min length
+ */
+ if (newValue.length < 10) {
+
+ /*
+ * Validation not passed
+ * */
+ result = false
+ accountNameField.fieldValidatorModel.setInvalid()
+ accountNameField.fieldValidatorModel.message = this.accountNameField.resources.getString(R.string.create_account_window_err_min_account_name_len)
+ } else {
+
+ /*
+ * Remove error
+ * */
+ accountNameField.error = null
+
+ /*
+ Validate at least one character
+ */
+ if (!newValue.matches(".*[a-zA-Z]+.*".toRegex())) {
+
+ /*
+ * Validation not passed
+ * */
+ result = false
+ accountNameField.fieldValidatorModel.setInvalid()
+ accountNameField.fieldValidatorModel.message = this.accountNameField.resources.getString(R.string.create_account_window_err_at_least_one_character)
+ } else {
+
+ /*
+ * Remove error
+ * */
+ accountNameField.error = null
+
+ /*
+ Validate at least one number for the account string
+ */
+ if (!newValue.matches(".*\\d+.*".toRegex())) {
+
+ /*
+ * Validation not passed
+ * */
+ result = false
+ accountNameField.fieldValidatorModel.setInvalid()
+ accountNameField.fieldValidatorModel.message = this.accountNameField.resources.getString(R.string.create_account_window_err_at_least_one_number)
+ } else {
+
+ /*
+ * Remove error
+ * */
+ accountNameField.error = null
+
+
+ /*
+ Validate at least one middle script
+ */
+ if (!newValue.contains("-")) {
+
+ /*
+ * Validation not passed
+ * */
+ result = false
+ accountNameField.fieldValidatorModel.setInvalid()
+ accountNameField.fieldValidatorModel.message = this.accountNameField.resources.getString(R.string.create_account_window_err_at_least_one_script)
+ } else {
+
+ /*
+ * Remove error
+ * */
+ accountNameField.error = null
+ }
+ }
+ }
+ }
+ }
+
+ /*
+ * If passed first validations
+ * */
+ if (!result) {
+
+ /*
+ * Deliver result
+ * */
+ if (uiValidatorListener != null) {
+ uiValidatorListener.onValidationFailed(this)
+ }
+ } else {
+
+ /*
+ * Show the dialog for connection with the server
+ * */
+ val creatingAccountMaterialDialog = CrystalDialog(activity)
+ creatingAccountMaterialDialog.setText(activity.resources.getString(R.string.window_create_seed_Server_validation))
+ creatingAccountMaterialDialog.build()
+ creatingAccountMaterialDialog.show()
+
+
+ val request = ValidateExistBitsharesAccountRequest(newValue)
+ request.setListener {
+ /*
+ * Dismiss the dialog of loading
+ * */
+ creatingAccountMaterialDialog.dismiss()
+
+ if (request.accountExists) {
+
+ /*
+ * The account exists and is not valid
+ * */
+ accountNameField.fieldValidatorModel.setInvalid()
+ accountNameField.fieldValidatorModel.message = accountNameField.resources.getString(R.string.account_name_already_exist)
+
+ /*
+ * Deliver the response
+ * */
+ if (uiValidatorListener != null) {
+ uiValidatorListener.onValidationFailed(globalCustomValidationField)
+ }
+
+ /*
+ * Deliver response to local callback
+ * */
+ if (onAccountExist != null) {
+ onAccountExist!!.onAccountExists()
+ }
+
+ } else {
+
+ /*
+ * Passed all validations
+ * */
+ accountNameField.fieldValidatorModel.setValid()
+
+ /*
+ * Deliver the response
+ * */
+ if (uiValidatorListener != null) {
+ uiValidatorListener.onValidationSucceeded(globalCustomValidationField)
+ }
+ }
+ }
+
+ /*
+ * Listener for websocket error
+ * */
+ GrapheneApiGenerator.setActivity(activity); //Set the activity to catch errors
+ val onErrorWebSocker = object : GrapheneApiGenerator.OnErrorWebSocket {
+ override fun onError(exception: java.lang.Exception?) {
+
+ /*
+ *
+ * Hide loading dialog
+ *
+ * */
+ creatingAccountMaterialDialog.dismiss();
+
+ }
+
+ }
+ GrapheneApiGenerator.setOnErrorWebSocket(onErrorWebSocker); //Set the activity to catch errors
+
+
+ /*
+ *
+ * Run thread*/
+ CryptoNetInfoRequests.getInstance().addRequest(request)
+ }/*
+ * Passed initial validations, next final validations
+ * */
+ }
+
+
+ /*
+ * Setters and getters
+ * */
+ fun setOnAccountExist(onAccountExist: OnAccountExist) {
+ this.onAccountExist = onAccountExist
+ }
+ /*
+ * End of setters and getters
+ * */
+
+ /*
+ * Interface to validate when an account exist an take over control it
+ * */
+ open interface OnAccountExist {
+ fun onAccountExists()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/cy/agorise/crystalwallet/viewmodels/validators/customImpl/validationFields/CustomValidationField.kt b/app/src/main/java/cy/agorise/crystalwallet/viewmodels/validators/customImpl/validationFields/CustomValidationField.kt
new file mode 100644
index 0000000..e45393c
--- /dev/null
+++ b/app/src/main/java/cy/agorise/crystalwallet/viewmodels/validators/customImpl/validationFields/CustomValidationField.kt
@@ -0,0 +1,46 @@
+package cy.agorise.crystalwallet.viewmodels.validators.customImpl.validationFields
+
+import android.app.Activity
+import android.view.View
+import cy.agorise.crystalwallet.viewmodels.validators.customImpl.interfaces.UIValidatorListener
+
+open class CustomValidationField {
+
+ /*
+ * Listener to deliver response to controller
+ * */
+ protected lateinit var uiValidatorListener: UIValidatorListener
+
+ /*
+ * Contains the field to validate
+ * */
+ @JvmField var currentView : View? = null
+
+
+ /*
+ * Contains a handler to my self
+ * */
+ @JvmField protected var globalCustomValidationField: CustomValidationField
+
+ /*
+ * Contains the acivity for utility
+ * */
+ @JvmField protected var activity: Activity
+
+
+
+
+
+ constructor(activity:Activity){
+
+ /*
+ * Save the activity
+ * */
+ this.activity = activity
+
+ /*
+ * Init the custom field for later references
+ * */
+ this.globalCustomValidationField = this
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/cy/agorise/crystalwallet/viewmodels/validators/customImpl/validationFields/PinDoubleConfirmationValidationField.kt b/app/src/main/java/cy/agorise/crystalwallet/viewmodels/validators/customImpl/validationFields/PinDoubleConfirmationValidationField.kt
new file mode 100644
index 0000000..9fa7493
--- /dev/null
+++ b/app/src/main/java/cy/agorise/crystalwallet/viewmodels/validators/customImpl/validationFields/PinDoubleConfirmationValidationField.kt
@@ -0,0 +1,135 @@
+package cy.agorise.crystalwallet.viewmodels.validators.customImpl.validationFields
+
+import android.app.Activity
+import cy.agorise.crystalwallet.R
+import cy.agorise.crystalwallet.viewmodels.validators.customImpl.interfaces.UIValidator
+import cy.agorise.crystalwallet.viewmodels.validators.customImpl.interfaces.UIValidatorListener
+import cy.agorise.crystalwallet.views.natives.CustomTextInputEditText
+
+
+/*
+* Validate PIN and PIN confirmation
+* */
+class PinDoubleConfirmationValidationField : CustomValidationField, UIValidator {
+
+ /*
+ * Contain the fields to validate
+ * */
+ private val pinField: CustomTextInputEditText
+ private val pinConfirmationField: CustomTextInputEditText
+
+
+
+
+ constructor(activity: Activity,
+ pinField: CustomTextInputEditText,
+ pinConfirmationField: CustomTextInputEditText,
+ pinDoubleConfirmationInterface: UIValidatorListener) : super(activity) {
+
+ this.pinField = pinField
+ this.pinConfirmationField = pinConfirmationField
+ this.uiValidatorListener = pinDoubleConfirmationInterface
+ }
+
+
+ override fun validate() {
+
+ val pin = pinField.text.toString().trim { it <= ' ' }
+ val pinConfirmation = pinConfirmationField.text.toString().trim { it <= ' ' }
+
+ /*
+ * Contains the result for the validations
+ * */
+ var result = true
+
+ /*
+ Check if the two fields are equals theme selfs
+ * */
+ if (pin.length < 5) {
+
+ /*
+ *
+ * False validation
+ * */
+ pinField.fieldValidatorModel.message = this.pinField.context.resources.getString(R.string.create_account_window_err_at_least_pin_characters)
+ result = false
+
+ /*
+ * The current view for error
+ * */
+ this.currentView = pinField
+ } else {
+
+ /*Remove the error*/
+ pinField.error = null
+
+ /*
+ * Same validation for PIN Confirmation
+ * */
+ if (pinConfirmation.length < 5) {
+
+ /*
+ *
+ * False validation
+ * */
+ pinConfirmationField.fieldValidatorModel.message = this.pinField.context.resources.getString(R.string.create_account_window_err_at_least_pin_characters)
+ result = false
+
+ /*
+ * The current view for error
+ * */
+ this.currentView = pinConfirmationField
+ } else {
+
+ /*Remove the error*/
+ pinField.error = null
+
+ /*
+ * Final validation, check if the PINs are equals
+ *
+ * */
+ if (!pin.isEmpty() && !pinConfirmation.isEmpty() && pinConfirmation.compareTo(pin) != 0) {
+
+ /*
+ *
+ * False validation
+ * */
+ pinField.fieldValidatorModel.message = this.pinField.context.resources.getString(R.string.mismatch_pin)
+ pinConfirmationField.fieldValidatorModel.message = this.pinField.context.resources.getString(R.string.mismatch_pin)
+ result = false
+
+ /*
+ * The current view for error
+ * */
+ this.currentView = pinConfirmationField
+ }
+ }
+ }
+
+ /*
+ * Passed validations
+ * */
+ if (result) {
+
+ pinField.fieldValidatorModel.setValid()
+ pinConfirmationField.fieldValidatorModel.setValid()
+
+ /*
+ * Connect response to controller
+ * */
+ if (uiValidatorListener != null) {
+ uiValidatorListener.onValidationSucceeded(this)
+ }
+ } else {
+
+ /*
+ * Connect response to controller
+ * */
+ if (uiValidatorListener != null) {
+ uiValidatorListener.onValidationFailed(this)
+ }
+ }/*
+ * Not passed validations
+ * */
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/cy/agorise/crystalwallet/viewmodels/validators/validationfields/BitsharesAccountNameDoesntExistsValidationField.java b/app/src/main/java/cy/agorise/crystalwallet/viewmodels/validators/validationfields/BitsharesAccountNameDoesntExistsValidationField.java
index e7a4d87..4b79eb1 100644
--- a/app/src/main/java/cy/agorise/crystalwallet/viewmodels/validators/validationfields/BitsharesAccountNameDoesntExistsValidationField.java
+++ b/app/src/main/java/cy/agorise/crystalwallet/viewmodels/validators/validationfields/BitsharesAccountNameDoesntExistsValidationField.java
@@ -21,15 +21,47 @@ public class BitsharesAccountNameDoesntExistsValidationField extends ValidationF
}
public void validate(){
+
final String newValue = accountNameField.getText().toString();
this.setLastValue(newValue);
this.startValidating();
+ /*
+ * Validate empty field
+ * */
if (newValue.equals("")){
setValidForValue("", false);
setMessageForValue("","");
validator.validationFailed(this);
- } else {
+ }
+ /*
+ Validate at least min length
+ */
+ else if(newValue.length()<10){
+ setValidForValue("", false);
+ setMessageForValue(validator.getContext().getResources().getString(R.string.create_account_window_err_min_account_name_len),"");
+ validator.validationFailed(this);
+ }
+ /*
+ Validate at least one number for the account string
+ */
+ else if(!newValue.matches(".*\\\\d+.*")){
+ setValidForValue("", false);
+ setMessageForValue(validator.getContext().getResources().getString(R.string.create_account_window_err_at_least_one_number),"");
+ validator.validationFailed(this);
+ }
+ /*
+ Validate at least one middle script
+ */
+ else if(!newValue.contains("-")){
+ setValidForValue("", false);
+ setMessageForValue(accountNameField.getContext().getResources().getString(R.string.create_account_window_err_at_least_one_number),"");
+ validator.validationFailed(this);
+ }
+ /*
+ * Passed all primary validations
+ * */
+ else {
final ValidationField field = this;
@@ -37,11 +69,17 @@ public class BitsharesAccountNameDoesntExistsValidationField extends ValidationF
request.setListener(new CryptoNetInfoRequestListener() {
@Override
public void onCarryOut() {
+
if (request.getAccountExists()) {
+
+ /*
+ * The account exists and is not valid
+ * */
setMessageForValue(newValue,validator.getContext().getResources().getString(R.string.account_name_already_exist,"'"+newValue+"'"));
setValidForValue(newValue, false);
+
} else {
- setValidForValue(newValue, true);
+ setValidForValue(newValue, true);
}
}
});
diff --git a/app/src/main/java/cy/agorise/crystalwallet/viewmodels/validators/validationfields/FromValidationField.java b/app/src/main/java/cy/agorise/crystalwallet/viewmodels/validators/validationfields/FromValidationField.java
index a693ba9..4f18033 100644
--- a/app/src/main/java/cy/agorise/crystalwallet/viewmodels/validators/validationfields/FromValidationField.java
+++ b/app/src/main/java/cy/agorise/crystalwallet/viewmodels/validators/validationfields/FromValidationField.java
@@ -2,7 +2,10 @@ package cy.agorise.crystalwallet.viewmodels.validators.validationfields;
import android.widget.Spinner;
+import com.jaredrummler.materialspinner.MaterialSpinner;
+
import cy.agorise.crystalwallet.R;
+import cy.agorise.crystalwallet.models.CryptoNetAccount;
import cy.agorise.crystalwallet.requestmanagers.CryptoNetInfoRequestListener;
import cy.agorise.crystalwallet.requestmanagers.CryptoNetInfoRequests;
import cy.agorise.crystalwallet.requestmanagers.ValidateExistBitsharesAccountRequest;
@@ -14,9 +17,9 @@ import cy.agorise.crystalwallet.requestmanagers.ValidateExistBitsharesAccountReq
public class FromValidationField extends ValidationField {
//private EditText fromField;
- private Spinner fromField;
+ private MaterialSpinner fromField;
- public FromValidationField(Spinner fromField){
+ public FromValidationField(MaterialSpinner fromField){
super(fromField);
this.fromField = fromField;
}
@@ -24,8 +27,9 @@ public class FromValidationField extends ValidationField {
public void validate(){
final String newValue;
- if (fromField.getSelectedItem() != null) {
- newValue = fromField.getSelectedItem().toString();
+ if (fromField.getSelectedIndex() != -1) {
+ final CryptoNetAccount cryptoNetAccount = (CryptoNetAccount) fromField.getItems().get(fromField.getSelectedIndex());
+ newValue = cryptoNetAccount.getName();
} else {
newValue = "";
}
diff --git a/app/src/main/java/cy/agorise/crystalwallet/viewmodels/validators/validationfields/PinValidationField_.java b/app/src/main/java/cy/agorise/crystalwallet/viewmodels/validators/validationfields/PinValidationField_.java
new file mode 100644
index 0000000..cb2c211
--- /dev/null
+++ b/app/src/main/java/cy/agorise/crystalwallet/viewmodels/validators/validationfields/PinValidationField_.java
@@ -0,0 +1,11 @@
+package cy.agorise.crystalwallet.viewmodels.validators.validationfields;
+
+import cy.agorise.crystalwallet.viewmodels.validators.customImpl.interfaces.UIValidator;
+
+public class PinValidationField_ implements UIValidator {
+
+ @Override
+ public void validate() {
+
+ }
+}
diff --git a/app/src/main/java/cy/agorise/crystalwallet/viewmodels/validators/validationfields/ToValidationField.java b/app/src/main/java/cy/agorise/crystalwallet/viewmodels/validators/validationfields/ToValidationField.java
index f2e8702..9c06402 100644
--- a/app/src/main/java/cy/agorise/crystalwallet/viewmodels/validators/validationfields/ToValidationField.java
+++ b/app/src/main/java/cy/agorise/crystalwallet/viewmodels/validators/validationfields/ToValidationField.java
@@ -3,7 +3,10 @@ package cy.agorise.crystalwallet.viewmodels.validators.validationfields;
import android.widget.EditText;
import android.widget.Spinner;
+import com.jaredrummler.materialspinner.MaterialSpinner;
+
import cy.agorise.crystalwallet.R;
+import cy.agorise.crystalwallet.models.CryptoNetAccount;
import cy.agorise.crystalwallet.requestmanagers.CryptoNetInfoRequestListener;
import cy.agorise.crystalwallet.requestmanagers.CryptoNetInfoRequests;
import cy.agorise.crystalwallet.requestmanagers.ValidateExistBitsharesAccountRequest;
@@ -14,10 +17,10 @@ import cy.agorise.crystalwallet.requestmanagers.ValidateExistBitsharesAccountReq
public class ToValidationField extends ValidationField {
- private Spinner fromField;
+ private MaterialSpinner fromField;
private EditText toField;
- public ToValidationField(Spinner fromField, EditText toField){
+ public ToValidationField(MaterialSpinner fromField, EditText toField){
super(toField);
this.fromField = fromField;
this.toField = toField;
@@ -25,8 +28,9 @@ public class ToValidationField extends ValidationField {
public void validate(){
final String fromNewValue;
- if (fromField.getSelectedItem() != null) {
- fromNewValue = fromField.getSelectedItem().toString();
+ if (fromField.getSelectedIndex() != -1) {
+ final CryptoNetAccount cryptoNetAccount = (CryptoNetAccount) fromField.getItems().get(fromField.getSelectedIndex());
+ fromNewValue = cryptoNetAccount.getName();
} else {
fromNewValue = "";
}
diff --git a/app/src/main/java/cy/agorise/crystalwallet/viewmodels/validators/validationfields/ValidationField.java b/app/src/main/java/cy/agorise/crystalwallet/viewmodels/validators/validationfields/ValidationField.java
index 0884c19..dff7085 100644
--- a/app/src/main/java/cy/agorise/crystalwallet/viewmodels/validators/validationfields/ValidationField.java
+++ b/app/src/main/java/cy/agorise/crystalwallet/viewmodels/validators/validationfields/ValidationField.java
@@ -18,6 +18,10 @@ public abstract class ValidationField {
protected UIValidator validator;
protected View view;
+
+
+
+
public ValidationField(View view){
this.lastValue = "";
this.message = "";
diff --git a/app/src/main/java/cy/agorise/crystalwallet/views/CryptoNetBalanceViewHolder.java b/app/src/main/java/cy/agorise/crystalwallet/views/CryptoNetBalanceViewHolder.java
index bf1d66e..4a2043c 100644
--- a/app/src/main/java/cy/agorise/crystalwallet/views/CryptoNetBalanceViewHolder.java
+++ b/app/src/main/java/cy/agorise/crystalwallet/views/CryptoNetBalanceViewHolder.java
@@ -192,7 +192,14 @@ public class CryptoNetBalanceViewHolder extends RecyclerView.ViewHolder {
} else {
final CryptoNetBalanceViewHolder thisViewHolder = this;
this.cryptoNetAccountId = balance.getAccountId();
- cryptoNetName.setText(balance.getCryptoNet().getLabel());
+
+ /*
+ * The first letter should be in mayus
+ * */
+ final String crypto = balance.getCryptoNet().getLabel().toString().toLowerCase();
+ final String upperString = crypto.substring(0,1).toUpperCase() + crypto.substring(1);
+
+ cryptoNetName.setText(upperString);
//Loads the crypto coin balance list of this account using a ViewModel and retrieving a LiveData List
CryptoCoinBalanceListViewModel cryptoCoinBalanceListViewModel = ViewModelProviders.of(this.fragment).get(CryptoCoinBalanceListViewModel.class);
diff --git a/app/src/main/java/cy/agorise/crystalwallet/views/natives/CustomTextInputEditText.java b/app/src/main/java/cy/agorise/crystalwallet/views/natives/CustomTextInputEditText.java
new file mode 100644
index 0000000..950b4fb
--- /dev/null
+++ b/app/src/main/java/cy/agorise/crystalwallet/views/natives/CustomTextInputEditText.java
@@ -0,0 +1,78 @@
+package cy.agorise.crystalwallet.views.natives;
+
+import android.content.Context;
+import android.support.design.widget.TextInputEditText;
+import android.util.AttributeSet;
+import android.view.View;
+
+import cy.agorise.crystalwallet.models.FieldValidatorModel;
+import cy.agorise.crystalwallet.viewmodels.validators.customImpl.interfaces.UIValidator;
+
+
+/*
+* Custom implementation of the native control to get more over control it
+* */
+public class CustomTextInputEditText extends TextInputEditText implements UIValidator {
+
+ /*
+ * Contains the field validator, this aid to validate the field
+ * */
+ private FieldValidatorModel fieldValidatorModel = new FieldValidatorModel();
+
+ /*
+ * Interface to validate the field
+ * */
+ private UIValidator uiValidator;
+
+ /*
+ * Contains the last input value
+ * */
+ private String lastValue;
+
+
+
+
+ public CustomTextInputEditText(Context context, AttributeSet attrs) {
+ super(context, attrs);
+
+ /*
+ * Set listener to get the last value of the control
+ * */
+ this.setOnFocusChangeListener(new OnFocusChangeListener() {
+ @Override
+ public void onFocusChange(View v, boolean hasFocus) {
+
+ if(!hasFocus){
+ lastValue = getText().toString();
+ }
+ }
+ });
+ }
+
+
+
+ public void setFieldValidatorModel(FieldValidatorModel fieldValidatorModel) {
+ this.fieldValidatorModel = fieldValidatorModel;
+ }
+ public void setUiValidator(UIValidator uiValidator) {
+ this.uiValidator = uiValidator;
+ }
+ public FieldValidatorModel getFieldValidatorModel() {
+ return fieldValidatorModel;
+ }
+
+ public String getLastValue() {
+ return lastValue;
+ }
+ /*
+ * End of setters and getters
+ * */
+
+ @Override
+ public void validate() {
+ uiValidator.validate();
+ }
+
+
+
+}
diff --git a/app/src/main/java/cy/agorise/crystalwallet/views/natives/GIFView.kt b/app/src/main/java/cy/agorise/crystalwallet/views/natives/GIFView.kt
new file mode 100644
index 0000000..d98c7f9
--- /dev/null
+++ b/app/src/main/java/cy/agorise/crystalwallet/views/natives/GIFView.kt
@@ -0,0 +1,40 @@
+package cy.agorise.crystalwallet.views.natives
+
+import android.content.Context
+import android.util.AttributeSet
+import android.widget.ImageView
+import com.bumptech.glide.Glide
+import com.bumptech.glide.request.RequestOptions
+import cy.agorise.crystalwallet.R
+
+
+/*
+* GIF implementation based on existing imageview class
+* */
+class GIFView : ImageView {
+
+ /*
+ * Contains aditional options for the gif
+ * */
+ private var options: RequestOptions? = RequestOptions()
+
+
+
+
+ constructor(context:Context,attrs: AttributeSet?) : super(context,attrs) {
+ }
+
+ /*
+ * Load the gif
+ * */
+ fun load(rawID:Int){
+ Glide.with(this).asGif().load(rawID).apply(options!!).into(this)
+ }
+
+ /*
+ * Option to fit the gif in the container
+ * */
+ fun centerCrop(){
+ options!!.centerCrop()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/cy/agorise/crystalwallet/views/natives/VideoExView.kt b/app/src/main/java/cy/agorise/crystalwallet/views/natives/VideoExView.kt
new file mode 100644
index 0000000..c018d33
--- /dev/null
+++ b/app/src/main/java/cy/agorise/crystalwallet/views/natives/VideoExView.kt
@@ -0,0 +1,36 @@
+package cy.agorise.crystalwallet.views.natives
+
+import android.content.Context
+import android.net.Uri
+import android.util.AttributeSet
+import android.widget.VideoView
+import cy.agorise.crystalwallet.R
+import kotlinx.android.synthetic.main.empty_activity.*
+
+
+/*
+* Extensión for videoview
+* */
+class VideoExView(context: Context?, attrs: AttributeSet?) : VideoView(context, attrs) {
+
+ /*
+ * Set the path based on raw, this should be called first to set the video path
+ * */
+ fun setVideoRaw(rawID:Int){
+ val uriPath = "android.resource://" + context.packageName + "/" + R.raw.appbar_background
+ val uri = Uri.parse(uriPath)
+ this.setVideoURI(uri)
+ }
+
+
+ /*
+ * With this method the video play continues
+ * */
+ fun playContinius(){
+
+ start()
+ this.setOnCompletionListener {
+ start()
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/res/anim/rotate360.xml b/app/src/main/res/anim/rotate360.xml
index 0efcc73..c582275 100644
--- a/app/src/main/res/anim/rotate360.xml
+++ b/app/src/main/res/anim/rotate360.xml
@@ -1,13 +1,17 @@
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/disable_style.xml b/app/src/main/res/drawable/disable_style.xml
new file mode 100644
index 0000000..f780d52
--- /dev/null
+++ b/app/src/main/res/drawable/disable_style.xml
@@ -0,0 +1,24 @@
+
+
+ -
+
+
-
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/loading.png b/app/src/main/res/drawable/loading.png
new file mode 100644
index 0000000..f98e21c
Binary files /dev/null and b/app/src/main/res/drawable/loading.png differ
diff --git a/app/src/main/res/drawable/ok.png b/app/src/main/res/drawable/ok.png
new file mode 100644
index 0000000..5fa675e
Binary files /dev/null and b/app/src/main/res/drawable/ok.png differ
diff --git a/app/src/main/res/drawable/warning.png b/app/src/main/res/drawable/warning.png
new file mode 100644
index 0000000..b73afa1
Binary files /dev/null and b/app/src/main/res/drawable/warning.png differ
diff --git a/app/src/main/res/layout/backup_seed.xml b/app/src/main/res/layout/backup_seed.xml
index 9166b1c..0a50ef8 100644
--- a/app/src/main/res/layout/backup_seed.xml
+++ b/app/src/main/res/layout/backup_seed.xml
@@ -1,52 +1,91 @@
-
-
+ android:layout_centerInParent="true">
-
-
-
-
-
-
-
+ android:layout_marginLeft="@dimen/activity_horizontal_margin"
+ android:layout_marginRight="@dimen/activity_horizontal_margin"
+ android:layout_marginTop="10dp"
+ android:layout_marginBottom="20dp"
+ android:text="@string/window_seed_backup"
+ android:layout_centerHorizontal="true"
+ android:textSize="20dp"
+ android:textStyle="bold" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/balance_list_item.xml b/app/src/main/res/layout/balance_list_item.xml
index 997394a..0c65a38 100644
--- a/app/src/main/res/layout/balance_list_item.xml
+++ b/app/src/main/res/layout/balance_list_item.xml
@@ -25,8 +25,8 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
- android:maxHeight="32dp"
- android:maxWidth="32dp"
+ android:maxHeight="28dp"
+ android:maxWidth="28dp"
app:srcCompat="@drawable/bts" />
diff --git a/app/src/main/res/layout/board.xml b/app/src/main/res/layout/board.xml
index 8e0b8e4..2cfab65 100644
--- a/app/src/main/res/layout/board.xml
+++ b/app/src/main/res/layout/board.xml
@@ -21,6 +21,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
+ android:background="@color/red"
app:contentScrim="@color/transparent"
app:layout_scrollFlags="scroll|exitUntilCollapsed"
app:toolbarId="@+id/toolbar">
@@ -30,10 +31,11 @@
android:layout_width="match_parent"
android:layout_height="match_parent" />
-
+ />
diff --git a/app/src/main/res/layout/create_seed.xml b/app/src/main/res/layout/create_seed.xml
index d7eecca..0012c10 100644
--- a/app/src/main/res/layout/create_seed.xml
+++ b/app/src/main/res/layout/create_seed.xml
@@ -6,13 +6,23 @@
android:layout_height="match_parent"
tools:context=".activities.CreateSeedActivity">
+
+
-
+
-
+
-
+
-