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 a81d557..4b35668 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -17,7 +17,7 @@ android:supportsRtl="true" android:configChanges="locale" android:theme="@style/AppTheme"> - + @@ -100,8 +100,8 @@ - - + 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/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/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/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/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.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/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/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/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/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/empty_activity.xml b/app/src/main/res/layout/empty_activity.xml new file mode 100644 index 0000000..35dd716 --- /dev/null +++ b/app/src/main/res/layout/empty_activity.xml @@ -0,0 +1,20 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/loading_activity.xml b/app/src/main/res/layout/loading_activity.xml new file mode 100644 index 0000000..12b24a6 --- /dev/null +++ b/app/src/main/res/layout/loading_activity.xml @@ -0,0 +1,16 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/raw/burbujas.gif b/app/src/main/res/raw/burbujas.gif new file mode 100644 index 0000000..bd39504 Binary files /dev/null and b/app/src/main/res/raw/burbujas.gif differ diff --git a/app/src/main/res/values/strings_errors.xml b/app/src/main/res/values/strings_errors.xml new file mode 100644 index 0000000..29a6737 --- /dev/null +++ b/app/src/main/res/values/strings_errors.xml @@ -0,0 +1,15 @@ + + + The Account Name should contains at least one number + The Account Name should contains at least 10 characters length + PIN is emtpy + PIN is emtpy + Account Name is emtpy + The Account Name should contains at least one character + The PIN should contains at least 6 digits + The Account Name should contain at least one \'-\' + + No server connection + + + diff --git a/build.gradle b/build.gradle index 217e861..c6ac57d 100644 --- a/build.gradle +++ b/build.gradle @@ -1,13 +1,15 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { + ext.kotlinVersion = '1.1.51' repositories { jcenter() google() } dependencies { - classpath 'com.android.tools.build:gradle:3.1.3' + classpath 'com.android.tools.build:gradle:3.1.4' classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion" // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files }