diff --git a/app/build.gradle b/app/build.gradle index 520e84f..59f1e89 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -15,6 +15,9 @@ android { arguments = ["room.schemaLocation": "$projectDir/schemas".toString()] } } + vectorDrawables { + useSupportLibrary true + } multiDexEnabled true } buildTypes { @@ -32,7 +35,7 @@ dependencies { exclude group: 'com.android.support', module: 'support-annotations' }) //testCompile 'com.android.support.test:runner:1.0.1' - compile 'com.android.support:appcompat-v7:26.1.0' + compile 'com.android.support:appcompat-v7:26.1.0' compile 'com.android.support:support-v4:26.1.0' compile 'com.android.support:design:26.1.0' compile 'com.android.support.constraint:constraint-layout:1.0.2' @@ -49,7 +52,7 @@ dependencies { compile 'org.tukaani:xz:1.6' compile 'com.jakewharton:butterknife:8.8.1' compile 'com.github.bilthon:graphenej:0.4.6-alpha1' - compile 'com.google.zxing:core:3.3.1'; + compile 'com.google.zxing:core:3.3.1' compile 'me.dm7.barcodescanner:zxing:1.9.8'; testCompile 'junit:junit:4.12' diff --git a/app/schemas/cy.agorise.crystalwallet.dao.CrystalDatabase/2.json b/app/schemas/cy.agorise.crystalwallet.dao.CrystalDatabase/2.json new file mode 100644 index 0000000..dfdbc9d --- /dev/null +++ b/app/schemas/cy.agorise.crystalwallet.dao.CrystalDatabase/2.json @@ -0,0 +1,573 @@ +{ + "formatVersion": 1, + "database": { + "version": 2, + "identityHash": "6dd1ca39bdde9af2cba2b35413c4975e", + "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, 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 + } + ], + "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": "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, 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 + } + ], + "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, \"6dd1ca39bdde9af2cba2b35413c4975e\")" + ] + } +} \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index fea7cf2..240a2e3 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -8,10 +8,10 @@ android:name="cy.agorise.crystalwallet.application.CrystalApplication" android:allowBackup="true" android:icon="@mipmap/ic_launcher" - android:label="@string/app_name" + android:label="Crystal" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" - android:theme="@style/Theme.AppCompat"> + android:theme="@style/AppTheme"> @@ -19,7 +19,8 @@ - + @@ -31,6 +32,10 @@ + + + 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 cf6ac67..1ee48f5 100644 --- a/app/src/main/java/cy/agorise/crystalwallet/activities/BoardActivity.java +++ b/app/src/main/java/cy/agorise/crystalwallet/activities/BoardActivity.java @@ -1,21 +1,39 @@ package cy.agorise.crystalwallet.activities; import android.content.Intent; +import android.content.res.Resources; +import android.graphics.drawable.AnimationDrawable; +import android.media.MediaPlayer; import android.os.Bundle; +import android.support.design.widget.AppBarLayout; +import android.support.design.widget.FloatingActionButton; +import android.support.design.widget.TabLayout; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentStatePagerAdapter; +import android.support.v4.app.FragmentTransaction; import android.support.v4.view.PagerAdapter; import android.support.v4.view.ViewPager; import android.support.v7.app.AppCompatActivity; +import android.support.v7.widget.Toolbar; +import android.util.Log; +import android.view.SurfaceHolder; +import android.view.SurfaceView; +import android.view.View; +import android.view.animation.LinearInterpolator; import android.widget.ImageButton; +import android.widget.ImageView; +import butterknife.BindColor; import butterknife.BindView; import butterknife.ButterKnife; import butterknife.OnClick; import cy.agorise.crystalwallet.R; +import cy.agorise.crystalwallet.fragments.AccountsFragment; import cy.agorise.crystalwallet.fragments.BalanceFragment; import cy.agorise.crystalwallet.fragments.ContactsFragment; +import cy.agorise.crystalwallet.fragments.ReceiveTransactionFragment; +import cy.agorise.crystalwallet.fragments.SendTransactionFragment; import cy.agorise.crystalwallet.fragments.TransactionsFragment; /** @@ -27,25 +45,180 @@ public class BoardActivity extends AppCompatActivity { @BindView(R.id.pager) public ViewPager mPager; - @BindView(R.id.btnGeneralSettings) - public ImageButton btnGeneralSettings; + //@BindView(R.id.btnGeneralSettings) + //public ImageButton btnGeneralSettings; + + @BindView(R.id.fabSend) + public FloatingActionButton fabSend; + + @BindView(R.id.fabReceive) + public FloatingActionButton fabReceive; + + @BindView(R.id.fabAddContact) + public FloatingActionButton fabAddContact; public BoardPagerAdapter boardAdapter; + /* + * the id of the account of this crypto net balance. It will be loaded + * when the element is bounded. + */ + long cryptoNetAccountId; + + @BindView(R.id.surface_view) + public SurfaceView mSurfaceView; + + @BindView(R.id.toolbar_user_img) + public ImageView userImage; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.board); ButterKnife.bind(this); + //-1 represents a crypto net account not loaded yet + this.cryptoNetAccountId = -1; + + Toolbar toolbar = findViewById(R.id.toolbar); + setSupportActionBar(toolbar); + + // Appbar animation + mSurfaceView.getHolder().addCallback(new SurfaceHolder.Callback() { + @Override + public void surfaceCreated(SurfaceHolder surfaceHolder) { + //Log.d(TAG,"surfaceCreated"); + MediaPlayer mediaPlayer = MediaPlayer.create(BoardActivity.this, R.raw.appbar_background); + mediaPlayer.setDisplay(mSurfaceView.getHolder()); + mediaPlayer.setLooping(true); + mediaPlayer.start(); + } + + @Override + public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) { + //Log.d(TAG,"surfaceChanged"); + } + + @Override + public void surfaceDestroyed(SurfaceHolder surfaceHolder) { + //Log.d(TAG,"surfaceDestroyed"); + } + }); + boardAdapter = new BoardPagerAdapter(getSupportFragmentManager()); mPager.setAdapter(boardAdapter); + + TabLayout tabLayout = findViewById(R.id.tabs); + + mPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout)); + tabLayout.addOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(mPager)); + + fabReceive.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + receiveToThisAccount(); + } + }); + fabSend.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + sendFromThisAccount(); + } + }); + + // Hide Add Contact fab, it won't hide until first page changed... + // Convert 72dp to pixels (fab is 56dp in diameter + 16dp margin) + final int fabDistanceToHide = (int) (72 * Resources.getSystem().getDisplayMetrics().density);; + fabAddContact.animate().translationY(fabDistanceToHide) + .setInterpolator(new LinearInterpolator()).start(); + + // Hide and show respective fabs when convenient + mPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + } + + @Override + public void onPageSelected(int position) { + + switch (position) { + case 0: + fabReceive.show(); + fabSend.show(); + fabAddContact.animate().translationY(fabDistanceToHide) + .setInterpolator(new LinearInterpolator()).start(); + break; + + case 1: + fabReceive.show(); + fabSend.show(); + fabAddContact.animate().translationY(fabDistanceToHide) + .setInterpolator(new LinearInterpolator()).start(); + break; + + default: + fabReceive.hide(); + fabSend.hide(); + fabAddContact.animate().translationY(0) + .setInterpolator(new LinearInterpolator()).start(); + break; + } + } + + @Override + public void onPageScrollStateChanged(int state) { + + } + }); } - @OnClick(R.id.btnGeneralSettings) - public void onBtnGeneralSettingsClick(){ - Intent intent = new Intent(this, GeneralSettingsActivity.class); - startActivity(intent); + /* + * dispatch the user to the accounts fragment + */ + @OnClick(R.id.toolbar_user_img) + public void accounts() { + FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); + Fragment prev = getSupportFragmentManager().findFragmentByTag("AccountsDialog"); + if (prev != null) { + ft.remove(prev); + } + ft.addToBackStack(null); + + // Create and show the dialog. + AccountsFragment newFragment = AccountsFragment.newInstance(this.cryptoNetAccountId); + newFragment.show(ft, "AccountsDialog"); + } + + /* + * dispatch the user to the receive fragment using this account + */ + public void receiveToThisAccount(){ + FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); + Fragment prev = getSupportFragmentManager().findFragmentByTag("ReceiveDialog"); + if (prev != null) { + ft.remove(prev); + } + ft.addToBackStack(null); + + // Create and show the dialog. + ReceiveTransactionFragment newFragment = ReceiveTransactionFragment.newInstance(this.cryptoNetAccountId); + newFragment.show(ft, "ReceiveDialog"); + } + + /* + * dispatch the user to the send fragment using this account + */ + public void sendFromThisAccount(){ + FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); + Fragment prev = getSupportFragmentManager().findFragmentByTag("SendDialog"); + if (prev != null) { + ft.remove(prev); + } + ft.addToBackStack(null); + + // Create and show the dialog. + SendTransactionFragment newFragment = SendTransactionFragment.newInstance(this.cryptoNetAccountId); + newFragment.show(ft, "SendDialog"); } private class BoardPagerAdapter extends FragmentStatePagerAdapter { diff --git a/app/src/main/java/cy/agorise/crystalwallet/activities/SendTransactionActivity.java b/app/src/main/java/cy/agorise/crystalwallet/activities/SendTransactionActivity.java index e2d7c9f..c2f6aec 100644 --- a/app/src/main/java/cy/agorise/crystalwallet/activities/SendTransactionActivity.java +++ b/app/src/main/java/cy/agorise/crystalwallet/activities/SendTransactionActivity.java @@ -44,8 +44,8 @@ public class SendTransactionActivity extends AppCompatActivity implements UIVali SendTransactionValidator sendTransactionValidator; - @BindView(R.id.etFrom) - EditText etFrom; + /*@BindView(R.id.etFrom) + EditText etFrom;*/ @BindView(R.id.tvFromError) TextView tvFromError; @BindView(R.id.etTo) @@ -111,18 +111,18 @@ public class SendTransactionActivity extends AppCompatActivity implements UIVali } }); - sendTransactionValidator = new SendTransactionValidator(this.getApplicationContext(), this.cryptoNetAccount, etFrom, etTo, spAsset, etAmount, etMemo); + //sendTransactionValidator = new SendTransactionValidator(this.getApplicationContext(), this.cryptoNetAccount, etFrom, etTo, spAsset, etAmount, etMemo); sendTransactionValidator.setListener(this); } else { this.finish(); } } - @OnTextChanged(value = R.id.etFrom, + /*@OnTextChanged(value = R.id.etFrom, callback = OnTextChanged.Callback.AFTER_TEXT_CHANGED) void afterFromChanged(Editable editable) { this.sendTransactionValidator.validate(); - } + }*/ @OnTextChanged(value = R.id.etTo, callback = OnTextChanged.Callback.AFTER_TEXT_CHANGED) @@ -177,9 +177,9 @@ public class SendTransactionActivity extends AppCompatActivity implements UIVali activity.runOnUiThread(new Runnable() { public void run() { - if (field.getView() == etFrom) { + /*if (field.getView() == etFrom) { tvFromError.setText(""); - } else if (field.getView() == etTo){ + } else*/ if (field.getView() == etTo){ tvToError.setText(""); } else if (field.getView() == etAmount){ tvAmountError.setText(""); @@ -201,9 +201,9 @@ public class SendTransactionActivity extends AppCompatActivity implements UIVali @Override public void onValidationFailed(ValidationField field) { - if (field.getView() == etFrom) { + /*if (field.getView() == etFrom) { tvFromError.setText(field.getMessage()); - } else if (field.getView() == etTo){ + } else*/ if (field.getView() == etTo){ tvToError.setText(field.getMessage()); } else if (field.getView() == spAsset){ tvAssetError.setText(field.getMessage()); diff --git a/app/src/main/java/cy/agorise/crystalwallet/activities/SettingsActivity.java b/app/src/main/java/cy/agorise/crystalwallet/activities/SettingsActivity.java new file mode 100644 index 0000000..54c7368 --- /dev/null +++ b/app/src/main/java/cy/agorise/crystalwallet/activities/SettingsActivity.java @@ -0,0 +1,115 @@ +package cy.agorise.crystalwallet.activities; + +import android.media.MediaPlayer; +import android.os.Bundle; +import android.support.design.widget.TabLayout; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.FragmentStatePagerAdapter; +import android.support.v4.view.ViewPager; +import android.support.v7.app.AppCompatActivity; +import android.support.v7.widget.Toolbar; +import android.view.SurfaceHolder; +import android.view.SurfaceView; +import android.widget.ImageView; + +import butterknife.BindView; +import butterknife.ButterKnife; +import butterknife.OnClick; +import cy.agorise.crystalwallet.R; +import cy.agorise.crystalwallet.fragments.BalanceFragment; +import cy.agorise.crystalwallet.fragments.GeneralSettingsFragment; + +/** + * Created by seven on 12/28/17. + * + */ + +public class SettingsActivity extends AppCompatActivity{ + + @BindView(R.id.ivGoBack) + public ImageView ivGoBack; + + @BindView(R.id.pager) + public ViewPager mPager; + + public SettingsPagerAdapter settingsPagerAdapter; + + @BindView(R.id.surface_view) + public SurfaceView mSurfaceView; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_settings); + ButterKnife.bind(this); + + Toolbar toolbar = findViewById(R.id.toolbar); + setSupportActionBar(toolbar); + + // Appbar animation + mSurfaceView.getHolder().addCallback(new SurfaceHolder.Callback() { + @Override + public void surfaceCreated(SurfaceHolder surfaceHolder) { + //Log.d(TAG,"surfaceCreated"); + MediaPlayer mediaPlayer = MediaPlayer.create(SettingsActivity.this, R.raw.appbar_background); + mediaPlayer.setDisplay(mSurfaceView.getHolder()); + mediaPlayer.setLooping(true); + mediaPlayer.start(); + } + + @Override + public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) { + //Log.d(TAG,"surfaceChanged"); + } + + @Override + public void surfaceDestroyed(SurfaceHolder surfaceHolder) { + //Log.d(TAG,"surfaceDestroyed"); + } + }); + + settingsPagerAdapter = new SettingsPagerAdapter(getSupportFragmentManager()); + mPager.setAdapter(settingsPagerAdapter); + + TabLayout tabLayout = findViewById(R.id.tabs); + + mPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout)); + tabLayout.addOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(mPager)); + } + + private class SettingsPagerAdapter extends FragmentStatePagerAdapter { + SettingsPagerAdapter(FragmentManager fm) { + super(fm); + } + + @Override + public Fragment getItem(int position) { + switch (position){ + case 0: + return new GeneralSettingsFragment(); + /*case 1: + return null; + case 2: + return null;*/ + case 1: + case 2: + case 3: + return new BalanceFragment(); + } + + + return null; //new OnConstructionFragment(); + } + + @Override + public int getCount() { + return 4; + } + } + + @OnClick(R.id.ivGoBack) + public void goBack(){ + onBackPressed(); + } +} diff --git a/app/src/main/java/cy/agorise/crystalwallet/fragments/AccountsFragment.java b/app/src/main/java/cy/agorise/crystalwallet/fragments/AccountsFragment.java new file mode 100644 index 0000000..f0e3ae4 --- /dev/null +++ b/app/src/main/java/cy/agorise/crystalwallet/fragments/AccountsFragment.java @@ -0,0 +1,86 @@ +package cy.agorise.crystalwallet.fragments; + +import android.app.Dialog; +import android.content.Intent; +import android.graphics.Color; +import android.graphics.drawable.ColorDrawable; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.v4.app.DialogFragment; +import android.support.v7.app.AlertDialog; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.Window; +import android.widget.ImageView; +import android.widget.TextView; + +import butterknife.BindView; +import butterknife.ButterKnife; +import butterknife.OnClick; +import cy.agorise.crystalwallet.R; +import cy.agorise.crystalwallet.activities.GeneralSettingsActivity; +import cy.agorise.crystalwallet.activities.SettingsActivity; + +public class AccountsFragment extends DialogFragment { + + @BindView(R.id.tvSettings) + TextView tvSettings; + + @BindView(R.id.tvClose) + TextView tvClose; + + public AccountsFragment() { + // Required empty public constructor + } + + public static AccountsFragment newInstance(long cryptoNetAccountId) { + AccountsFragment f = new AccountsFragment(); + + // Supply num input as an argument. + Bundle args = new Bundle(); + args.putLong("CRYPTO_NET_ACCOUNT_ID", cryptoNetAccountId); + f.setArguments(args); + + return f; + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + } + + @NonNull + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + AlertDialog.Builder builder = new AlertDialog.Builder(getActivity(), R.style.AccountsTheme); + + LayoutInflater inflater = getActivity().getLayoutInflater(); + View view = inflater.inflate(R.layout.fragment_accounts, null); + ButterKnife.bind(this, view); + + return builder.setView(view).create(); + } + + @Override + public void onResume() { + super.onResume(); + + // Force dialog fragment to use the full width of the screen + Window dialogWindow = getDialog().getWindow(); + assert dialogWindow != null; + dialogWindow.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); + } + + @OnClick(R.id.tvSettings) + public void onTvSettingsClick(){ + dismiss(); + Intent intent = new Intent(getActivity(), SettingsActivity.class); + startActivity(intent); + } + + @OnClick(R.id.tvClose) + public void cancel(){ + this.dismiss(); + } +} diff --git a/app/src/main/java/cy/agorise/crystalwallet/fragments/GeneralSettingsFragment.java b/app/src/main/java/cy/agorise/crystalwallet/fragments/GeneralSettingsFragment.java new file mode 100644 index 0000000..7be6e28 --- /dev/null +++ b/app/src/main/java/cy/agorise/crystalwallet/fragments/GeneralSettingsFragment.java @@ -0,0 +1,42 @@ +package cy.agorise.crystalwallet.fragments; + +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import butterknife.ButterKnife; +import cy.agorise.crystalwallet.R; + +/** + * Created by xd on 12/28/17. + */ + +public class GeneralSettingsFragment extends Fragment { + public GeneralSettingsFragment() { + // Required empty public constructor + } + + public static GeneralSettingsFragment newInstance() { + GeneralSettingsFragment fragment = new GeneralSettingsFragment(); + Bundle args = new Bundle(); + fragment.setArguments(args); + return fragment; + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + // Inflate the layout for this fragment + View v = inflater.inflate(R.layout.fragment_general_settings, container, false); + ButterKnife.bind(this, v); + + return v; + } +} diff --git a/app/src/main/java/cy/agorise/crystalwallet/fragments/ReceiveTransactionFragment.java b/app/src/main/java/cy/agorise/crystalwallet/fragments/ReceiveTransactionFragment.java index bb17cb6..3e26231 100644 --- a/app/src/main/java/cy/agorise/crystalwallet/fragments/ReceiveTransactionFragment.java +++ b/app/src/main/java/cy/agorise/crystalwallet/fragments/ReceiveTransactionFragment.java @@ -7,14 +7,18 @@ import android.arch.lifecycle.Observer; import android.content.DialogInterface; import android.graphics.Bitmap; import android.os.Bundle; +import android.os.Handler; import android.support.annotation.NonNull; import android.support.annotation.Nullable; +import android.support.design.widget.FloatingActionButton; import android.support.v4.app.DialogFragment; import android.support.v7.app.AlertDialog; import android.text.Editable; import android.util.Log; import android.view.LayoutInflater; import android.view.View; +import android.view.ViewGroup; +import android.view.Window; import android.widget.Button; import android.widget.EditText; import android.widget.ImageView; @@ -26,6 +30,7 @@ import com.google.zxing.MultiFormatWriter; import com.google.zxing.WriterException; import com.google.zxing.common.BitMatrix; +import butterknife.OnClick; import cy.agorise.graphenej.Invoice; import java.util.ArrayList; import java.util.List; @@ -62,6 +67,8 @@ public class ReceiveTransactionFragment extends DialogFragment implements UIVali TextView tvAssetError; @BindView(R.id.ivQrCode) ImageView ivQrCode; + @BindView(R.id.tvCancel) + TextView tvCancel; private Button btnShareQrCode; private Button btnClose; @@ -75,6 +82,8 @@ public class ReceiveTransactionFragment extends DialogFragment implements UIVali private Invoice invoice; private ArrayList invoiceItems; + private FloatingActionButton fabReceive; + public static ReceiveTransactionFragment newInstance(long cryptoNetAccountId) { ReceiveTransactionFragment f = new ReceiveTransactionFragment(); @@ -97,8 +106,10 @@ public class ReceiveTransactionFragment extends DialogFragment implements UIVali @NonNull @Override public Dialog onCreateDialog(Bundle savedInstanceState) { - AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); - builder.setTitle("Receive Assets"); + fabReceive = getActivity().findViewById(R.id.fabReceive); + fabReceive.hide(); + AlertDialog.Builder builder = new AlertDialog.Builder(getActivity(), R.style.ReceiveTransactionTheme); + //builder.setTitle("Receive Assets"); LayoutInflater inflater = getActivity().getLayoutInflater(); View view = inflater.inflate(R.layout.receive_transaction, null); @@ -138,18 +149,18 @@ public class ReceiveTransactionFragment extends DialogFragment implements UIVali builder.setView(view); - builder.setPositiveButton("Share this QR", new DialogInterface.OnClickListener() { + /*builder.setPositiveButton("Share this QR", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { shareQrCode(); } - }); - builder.setNegativeButton("Close", new DialogInterface.OnClickListener() { + });*/ + /*builder.setNegativeButton("Close", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } - }); + });*/ AlertDialog dialog = builder.create(); @@ -166,6 +177,28 @@ public class ReceiveTransactionFragment extends DialogFragment implements UIVali return dialog; } + @Override + public void onResume() { + super.onResume(); + + // Force dialog fragment to use the full width of the screen + Window dialogWindow = getDialog().getWindow(); + assert dialogWindow != null; + dialogWindow.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); + } + + @Override + public void onDestroy() { + super.onDestroy(); + + Handler handler = new Handler(); + handler.postDelayed(new Runnable() { + public void run() { + fabReceive.show(); + } + }, 400); + } + @OnTextChanged(value = R.id.etAmount, callback = OnTextChanged.Callback.AFTER_TEXT_CHANGED) void afterAmountChanged(Editable editable) { @@ -184,6 +217,11 @@ public class ReceiveTransactionFragment extends DialogFragment implements UIVali } } + @OnClick(R.id.tvCancel) + public void cancel(){ + this.dismiss(); + } + @Override public void onValidationSucceeded(final ValidationField field) { final ReceiveTransactionFragment fragment = this; 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 1525114..6c37d63 100644 --- a/app/src/main/java/cy/agorise/crystalwallet/fragments/SendTransactionFragment.java +++ b/app/src/main/java/cy/agorise/crystalwallet/fragments/SendTransactionFragment.java @@ -5,8 +5,10 @@ import android.arch.lifecycle.LiveData; import android.arch.lifecycle.Observer; import android.content.DialogInterface; import android.os.Bundle; +import android.os.Handler; import android.support.annotation.NonNull; import android.support.annotation.Nullable; +import android.support.design.widget.FloatingActionButton; import android.support.v4.app.DialogFragment; import android.support.v4.app.Fragment; import android.support.v7.app.AlertDialog; @@ -16,6 +18,8 @@ import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.view.Window; +import android.view.animation.LinearInterpolator; import android.widget.Button; import android.widget.EditText; import android.widget.Spinner; @@ -48,8 +52,8 @@ public class SendTransactionFragment extends DialogFragment implements UIValidat SendTransactionValidator sendTransactionValidator; - @BindView(R.id.etFrom) - EditText etFrom; + @BindView(R.id.spFrom) + Spinner spFrom; @BindView(R.id.tvFromError) TextView tvFromError; @BindView(R.id.etTo) @@ -68,10 +72,10 @@ public class SendTransactionFragment extends DialogFragment implements UIValidat EditText etMemo; @BindView(R.id.tvMemoError) TextView tvMemoError; - //@BindView(R.id.btnSend) - Button btnSend; - //@BindView(R.id.btnCancel) - Button btnCancel; + @BindView(R.id.btnSend) + FloatingActionButton btnSend; + @BindView(R.id.btnCancel) + TextView btnCancel; Button btnScanQrCode; @@ -79,6 +83,7 @@ public class SendTransactionFragment extends DialogFragment implements UIValidat private CryptoNetAccount cryptoNetAccount; private GrapheneAccount grapheneAccount; private CrystalDatabase db; + private FloatingActionButton fabSend; public static SendTransactionFragment newInstance(long cryptoNetAccountId) { SendTransactionFragment f = new SendTransactionFragment(); @@ -99,8 +104,11 @@ public class SendTransactionFragment extends DialogFragment implements UIValidat @NonNull @Override public Dialog onCreateDialog(Bundle savedInstanceState) { - AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); - builder.setTitle("Send"); + fabSend = getActivity().findViewById(R.id.fabSend); + fabSend.hide(); + + AlertDialog.Builder builder = new AlertDialog.Builder(getActivity(), R.style.SendTransactionTheme); + //builder.setTitle("Send"); LayoutInflater inflater = getActivity().getLayoutInflater(); View view = inflater.inflate(R.layout.send_transaction, null); @@ -133,26 +141,18 @@ public class SendTransactionFragment extends DialogFragment implements UIValidat spAsset.setAdapter(assetAdapter); } }); - - sendTransactionValidator = new SendTransactionValidator(this.getContext(), this.cryptoNetAccount, etFrom, etTo, spAsset, etAmount, etMemo); + // TODO SendTransactionValidator to accept spFrom + //sendTransactionValidator = new SendTransactionValidator(this.getContext(), this.cryptoNetAccount, spFrom, etTo, spAsset, etAmount, etMemo); sendTransactionValidator.setListener(this); - etFrom.setText(this.grapheneAccount.getName()); + // etFrom.setText(this.grapheneAccount.getName()); } - builder.setView(view); + return builder.setView(view).create(); + } - builder.setPositiveButton("Send", new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - sendTransaction(); - } - }); - builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - dialog.dismiss(); - } - }); + @Override + public void onResume() { + super.onResume(); builder.setNeutralButton("Scan QR Code", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { @@ -160,63 +160,26 @@ public class SendTransactionFragment extends DialogFragment implements UIValidat } }); - AlertDialog dialog = builder.create(); - - dialog.setOnShowListener(new DialogInterface.OnShowListener() { - @Override - public void onShow(DialogInterface dialog) { - btnSend = ((AlertDialog)dialog).getButton(AlertDialog.BUTTON_POSITIVE); - btnCancel = ((AlertDialog)dialog).getButton(AlertDialog.BUTTON_NEGATIVE); - btnScanQrCode = ((AlertDialog)dialog).getButton(AlertDialog.BUTTON_NEUTRAL); - btnSend.setEnabled(false); - } - }); - - return dialog; + // Force dialog fragment to use the full width of the screen + Window dialogWindow = getDialog().getWindow(); + assert dialogWindow != null; + dialogWindow.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); } - /*public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState){ - View view = inflater.inflate(R.layout.send_transaction, container, false); - ButterKnife.bind(this, view); + @Override + public void onDestroy() { + super.onDestroy(); + btnScanQrCode = ((AlertDialog)dialog).getButton(AlertDialog.BUTTON_NEUTRAL); + Handler handler = new Handler(); + handler.postDelayed(new Runnable() { + public void run() { + fabSend.show(); + } + }, 400); + } - btnSend.setEnabled(false); - - this.cryptoNetAccountId = getArguments().getLong("CRYPTO_NET_ACCOUNT_ID",-1); - - if (this.cryptoNetAccountId != -1) { - db = CrystalDatabase.getAppDatabase(this.getContext()); - this.cryptoNetAccount = db.cryptoNetAccountDao().getById(this.cryptoNetAccountId); - - this.grapheneAccount = new GrapheneAccount(this.cryptoNetAccount); - this.grapheneAccount.loadInfo(db.grapheneAccountInfoDao().getByAccountId(this.cryptoNetAccountId)); - - final LiveData> balancesList = db.cryptoCoinBalanceDao().getBalancesFromAccount(cryptoNetAccountId); - balancesList.observe(this, new Observer>() { - @Override - public void onChanged(@Nullable List cryptoCoinBalances) { - ArrayList assetIds = new ArrayList(); - for (CryptoCoinBalance nextBalance : balancesList.getValue()) { - assetIds.add(nextBalance.getCryptoCurrencyId()); - } - List cryptoCurrencyList = db.cryptoCurrencyDao().getByIds(assetIds); - - CryptoCurrencyAdapter assetAdapter = new CryptoCurrencyAdapter(getContext(), android.R.layout.simple_spinner_item, cryptoCurrencyList); - spAsset.setAdapter(assetAdapter); - } - }); - - sendTransactionValidator = new SendTransactionValidator(this.getContext(), this.cryptoNetAccount, etFrom, etTo, spAsset, etAmount, etMemo); - sendTransactionValidator.setListener(this); - etFrom.setText(this.grapheneAccount.getName()); - } - - return view; - }*/ - - @OnTextChanged(value = R.id.etFrom, - callback = OnTextChanged.Callback.AFTER_TEXT_CHANGED) - void afterFromChanged(Editable editable) { + @OnItemSelected(R.id.spFrom) + public void afterFromSelected(Spinner spinner, int position) { this.sendTransactionValidator.validate(); } @@ -244,10 +207,10 @@ public class SendTransactionFragment extends DialogFragment implements UIValidat this.sendTransactionValidator.validate(); } - //@OnClick(R.id.btnCancel) - //public void cancel(){ - // this.finish(); - //} + @OnClick(R.id.btnCancel) + public void cancel(){ + this.dismiss(); + } //@OnClick(R.id.btnSend) public void sendTransaction(){ @@ -277,7 +240,7 @@ public class SendTransactionFragment extends DialogFragment implements UIValidat final SendTransactionFragment fragment = this; - if (field.getView() == etFrom) { + if (field.getView() == spFrom) { tvFromError.setText(""); } else if (field.getView() == etTo){ tvToError.setText(""); @@ -300,7 +263,7 @@ public class SendTransactionFragment extends DialogFragment implements UIValidat @Override public void onValidationFailed(ValidationField field) { - if (field.getView() == etFrom) { + if (field.getView() == spFrom) { tvFromError.setText(field.getMessage()); } else if (field.getView() == etTo){ tvToError.setText(field.getMessage()); diff --git a/app/src/main/java/cy/agorise/crystalwallet/util/CircularImageView.java b/app/src/main/java/cy/agorise/crystalwallet/util/CircularImageView.java new file mode 100644 index 0000000..af8ddfb --- /dev/null +++ b/app/src/main/java/cy/agorise/crystalwallet/util/CircularImageView.java @@ -0,0 +1,450 @@ +package cy.agorise.crystalwallet.util; + +import android.annotation.TargetApi; +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Bitmap; +import android.graphics.BitmapShader; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.ColorFilter; +import android.graphics.Matrix; +import android.graphics.Paint; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; +import android.graphics.RectF; +import android.graphics.Shader; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; +import android.net.Uri; +import android.os.Build; +import android.util.AttributeSet; +import android.util.Log; +import android.view.MotionEvent; +import android.widget.ImageView; +import cy.agorise.crystalwallet.R; + +/** + * Custom ImageView for circular images in Android while maintaining the + * best draw performance and supporting custom borders & selectors. + */ +public class CircularImageView extends ImageView { + // For logging purposes + private static final String TAG = CircularImageView.class.getSimpleName(); + + // Default property values + private static final boolean SHADOW_ENABLED = false; + private static final float SHADOW_RADIUS = 4f; + private static final float SHADOW_DX = 0f; + private static final float SHADOW_DY = 2f; + private static final int SHADOW_COLOR = Color.BLACK; + + // Border & Selector configuration variables + private boolean hasBorder; + private boolean hasSelector; + private boolean isSelected; + private int borderWidth; + private int canvasSize; + private int selectorStrokeWidth; + + // Shadow properties + private boolean shadowEnabled; + private float shadowRadius; + private float shadowDx; + private float shadowDy; + private int shadowColor; + + // Objects used for the actual drawing + private BitmapShader shader; + private Bitmap image; + private Paint paint; + private Paint paintBorder; + private Paint paintSelectorBorder; + private ColorFilter selectorFilter; + + public CircularImageView(Context context) { + this(context, null, R.styleable.CircularImageViewStyle_circularImageViewDefault); + } + + public CircularImageView(Context context, AttributeSet attrs) { + this(context, attrs, R.styleable.CircularImageViewStyle_circularImageViewDefault); + } + + public CircularImageView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(context, attrs, defStyleAttr); + } + + @TargetApi(Build.VERSION_CODES.LOLLIPOP) + public CircularImageView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + init(context, attrs, defStyleAttr); + } + + /** + * Initializes paint objects and sets desired attributes. + * @param context Context + * @param attrs Attributes + * @param defStyle Default Style + */ + private void init(Context context, AttributeSet attrs, int defStyle) { + // Initialize paint objects + paint = new Paint(); + paint.setAntiAlias(true); + paintBorder = new Paint(); + paintBorder.setAntiAlias(true); + paintBorder.setStyle(Paint.Style.STROKE); + paintSelectorBorder = new Paint(); + paintSelectorBorder.setAntiAlias(true); + + // Enable software rendering on HoneyComb and up. (needed for shadow) + if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) + setLayerType(LAYER_TYPE_SOFTWARE, null); + + // Load the styled attributes and set their properties + TypedArray attributes = context.obtainStyledAttributes(attrs, R.styleable.CircularImageView, defStyle, 0); + + // Check for extra features being enabled + hasBorder = attributes.getBoolean(R.styleable.CircularImageView_civ_border, false); + hasSelector = attributes.getBoolean(R.styleable.CircularImageView_civ_selector, false); + shadowEnabled = attributes.getBoolean(R.styleable.CircularImageView_civ_shadow, SHADOW_ENABLED); + + // Set border properties, if enabled + if(hasBorder) { + int defaultBorderSize = (int) (2 * context.getResources().getDisplayMetrics().density + 0.5f); + setBorderWidth(attributes.getDimensionPixelOffset(R.styleable.CircularImageView_civ_borderWidth, defaultBorderSize)); + setBorderColor(attributes.getColor(R.styleable.CircularImageView_civ_borderColor, Color.WHITE)); + } + + // Set selector properties, if enabled + if(hasSelector) { + int defaultSelectorSize = (int) (2 * context.getResources().getDisplayMetrics().density + 0.5f); + setSelectorColor(attributes.getColor(R.styleable.CircularImageView_civ_selectorColor, Color.TRANSPARENT)); + setSelectorStrokeWidth(attributes.getDimensionPixelOffset(R.styleable.CircularImageView_civ_selectorStrokeWidth, defaultSelectorSize)); + setSelectorStrokeColor(attributes.getColor(R.styleable.CircularImageView_civ_selectorStrokeColor, Color.BLUE)); + } + + // Set shadow properties, if enabled + if(shadowEnabled) { + shadowRadius = attributes.getFloat(R.styleable.CircularImageView_civ_shadowRadius, SHADOW_RADIUS); + shadowDx = attributes.getFloat(R.styleable.CircularImageView_civ_shadowDx, SHADOW_DX); + shadowDy = attributes.getFloat(R.styleable.CircularImageView_civ_shadowDy, SHADOW_DY); + shadowColor = attributes.getColor(R.styleable.CircularImageView_civ_shadowColor, SHADOW_COLOR); + setShadowEnabled(true); + } + + // We no longer need our attributes TypedArray, give it back to cache + attributes.recycle(); + } + + /** + * Sets the CircularImageView's border width in pixels. + * @param borderWidth Width in pixels for the border. + */ + public void setBorderWidth(int borderWidth) { + this.borderWidth = borderWidth; + if(paintBorder != null) + paintBorder.setStrokeWidth(borderWidth); + requestLayout(); + invalidate(); + } + + /** + * Sets the CircularImageView's basic border color. + * @param borderColor The new color (including alpha) to set the border. + */ + public void setBorderColor(int borderColor) { + if (paintBorder != null) + paintBorder.setColor(borderColor); + this.invalidate(); + } + + /** + * Sets the color of the selector to be draw over the + * CircularImageView. Be sure to provide some opacity. + * @param selectorColor The color (including alpha) to set for the selector overlay. + */ + public void setSelectorColor(int selectorColor) { + this.selectorFilter = new PorterDuffColorFilter(selectorColor, PorterDuff.Mode.SRC_ATOP); + this.invalidate(); + } + + /** + * Sets the stroke width to be drawn around the CircularImageView + * during click events when the selector is enabled. + * @param selectorStrokeWidth Width in pixels for the selector stroke. + */ + public void setSelectorStrokeWidth(int selectorStrokeWidth) { + this.selectorStrokeWidth = selectorStrokeWidth; + this.requestLayout(); + this.invalidate(); + } + + /** + * Sets the stroke color to be drawn around the CircularImageView + * during click events when the selector is enabled. + * @param selectorStrokeColor The color (including alpha) to set for the selector stroke. + */ + public void setSelectorStrokeColor(int selectorStrokeColor) { + if (paintSelectorBorder != null) + paintSelectorBorder.setColor(selectorStrokeColor); + this.invalidate(); + } + + /** + * Enables a dark shadow for this CircularImageView. + * @param enabled Set to true to draw a shadow or false to disable it. + */ + public void setShadowEnabled(boolean enabled) { + shadowEnabled = enabled; + updateShadow(); + } + + /** + * Enables a dark shadow for this CircularImageView. + * If the radius is set to 0, the shadow is removed. + * @param radius Radius for the shadow to extend to. + * @param dx Horizontal shadow offset. + * @param dy Vertical shadow offset. + * @param color The color of the shadow to apply. + */ + public void setShadow(float radius, float dx, float dy, int color) { + shadowRadius = radius; + shadowDx = dx; + shadowDy = dy; + shadowColor = color; + updateShadow(); + } + + @Override + public void onDraw(Canvas canvas) { + // Don't draw anything without an image + if(image == null) + return; + + // Nothing to draw (Empty bounds) + if(image.getHeight() == 0 || image.getWidth() == 0) + return; + + // Update shader if canvas size has changed + int oldCanvasSize = canvasSize; + canvasSize = getWidth() < getHeight() ? getWidth() : getHeight(); + if(oldCanvasSize != canvasSize) + updateBitmapShader(); + + // Apply shader to paint + paint.setShader(shader); + + // Keep track of selectorStroke/border width + int outerWidth = 0; + + // Get the exact X/Y axis of the view + int center = canvasSize / 2; + + + if(hasSelector && isSelected) { // Draw the selector stroke & apply the selector filter, if applicable + outerWidth = selectorStrokeWidth; + center = (canvasSize - (outerWidth * 2)) / 2; + + paint.setColorFilter(selectorFilter); + canvas.drawCircle(center + outerWidth, center + outerWidth, ((canvasSize - (outerWidth * 2)) / 2) + outerWidth - 4.0f, paintSelectorBorder); + } + else if(hasBorder) { // If no selector was drawn, draw a border and clear the filter instead... if enabled + outerWidth = borderWidth; + center = (canvasSize - (outerWidth * 2)) / 2; + + paint.setColorFilter(null); + RectF rekt = new RectF(0 + outerWidth / 2, 0 + outerWidth / 2, canvasSize - outerWidth / 2, canvasSize - outerWidth / 2); + canvas.drawArc(rekt, 360, 360, false, paintBorder); + //canvas.drawCircle(center + outerWidth, center + outerWidth, ((canvasSize - (outerWidth * 2)) / 2) + outerWidth - 4.0f, paintBorder); + } + else // Clear the color filter if no selector nor border were drawn + paint.setColorFilter(null); + + // Draw the circular image itself + canvas.drawCircle(center + outerWidth, center + outerWidth, ((canvasSize - (outerWidth * 2)) / 2), paint); + } + + @Override + public boolean dispatchTouchEvent(MotionEvent event) { + // Check for clickable state and do nothing if disabled + if(!this.isClickable()) { + this.isSelected = false; + return super.onTouchEvent(event); + } + + // Set selected state based on Motion Event + switch(event.getAction()) { + case MotionEvent.ACTION_DOWN: + this.isSelected = true; + break; + case MotionEvent.ACTION_UP: + case MotionEvent.ACTION_SCROLL: + case MotionEvent.ACTION_OUTSIDE: + case MotionEvent.ACTION_CANCEL: + this.isSelected = false; + break; + } + + // Redraw image and return super type + this.invalidate(); + return super.dispatchTouchEvent(event); + } + + @Override + public void setImageURI(Uri uri) { + super.setImageURI(uri); + + // Extract a Bitmap out of the drawable & set it as the main shader + image = drawableToBitmap(getDrawable()); + if(canvasSize > 0) + updateBitmapShader(); + } + + @Override + public void setImageResource(int resId) { + super.setImageResource(resId); + + // Extract a Bitmap out of the drawable & set it as the main shader + image = drawableToBitmap(getDrawable()); + if(canvasSize > 0) + updateBitmapShader(); + } + + @Override + public void setImageDrawable(Drawable drawable) { + super.setImageDrawable(drawable); + + // Extract a Bitmap out of the drawable & set it as the main shader + image = drawableToBitmap(getDrawable()); + if(canvasSize > 0) + updateBitmapShader(); + } + + @Override + public void setImageBitmap(Bitmap bm) { + super.setImageBitmap(bm); + + // Extract a Bitmap out of the drawable & set it as the main shader + image = bm; + if(canvasSize > 0) + updateBitmapShader(); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int width = measureWidth(widthMeasureSpec); + int height = measureHeight(heightMeasureSpec); + setMeasuredDimension(width, height); + } + + private int measureWidth(int measureSpec) { + int result; + int specMode = MeasureSpec.getMode(measureSpec); + int specSize = MeasureSpec.getSize(measureSpec); + + if (specMode == MeasureSpec.EXACTLY) { + // The parent has determined an exact size for the child. + result = specSize; + } + else if (specMode == MeasureSpec.AT_MOST) { + // The child can be as large as it wants up to the specified size. + result = specSize; + } + else { + // The parent has not imposed any constraint on the child. + result = canvasSize; + } + + return result; + } + + private int measureHeight(int measureSpecHeight) { + int result; + int specMode = MeasureSpec.getMode(measureSpecHeight); + int specSize = MeasureSpec.getSize(measureSpecHeight); + + if (specMode == MeasureSpec.EXACTLY) { + // We were told how big to be + result = specSize; + } else if (specMode == MeasureSpec.AT_MOST) { + // The child can be as large as it wants up to the specified size. + result = specSize; + } else { + // Measure the text (beware: ascent is a negative number) + result = canvasSize; + } + + return (result + 2); + } + + // TODO: Update shadow layers based on border/selector state and visibility. + private void updateShadow() { + float radius = shadowEnabled ? shadowRadius : 0; + //paint.setShadowLayer(radius, shadowDx, shadowDy, shadowColor); + paintBorder.setShadowLayer(radius, shadowDx, shadowDy, shadowColor); + paintSelectorBorder.setShadowLayer(radius, shadowDx, shadowDy, shadowColor); + } + + /** + * Convert a drawable object into a Bitmap. + * @param drawable Drawable to extract a Bitmap from. + * @return A Bitmap created from the drawable parameter. + */ + public Bitmap drawableToBitmap(Drawable drawable) { + if (drawable == null) // Don't do anything without a proper drawable + return null; + else if (drawable instanceof BitmapDrawable) { // Use the getBitmap() method instead if BitmapDrawable + Log.i(TAG, "Bitmap drawable!"); + return ((BitmapDrawable) drawable).getBitmap(); + } + + int intrinsicWidth = drawable.getIntrinsicWidth(); + int intrinsicHeight = drawable.getIntrinsicHeight(); + + if (!(intrinsicWidth > 0 && intrinsicHeight > 0)) + return null; + + try { + // Create Bitmap object out of the drawable + Bitmap bitmap = Bitmap.createBitmap(intrinsicWidth, intrinsicHeight, Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(bitmap); + drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); + drawable.draw(canvas); + return bitmap; + } catch (OutOfMemoryError e) { + // Simply return null of failed bitmap creations + Log.e(TAG, "Encountered OutOfMemoryError while generating bitmap!"); + return null; + } + } + + // TODO TEST REMOVE + public void setIconModeEnabled(boolean e) {} + + /** + * Re-initializes the shader texture used to fill in + * the Circle upon drawing. + */ + public void updateBitmapShader() { + if (image == null) + return; + + shader = new BitmapShader(image, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); + + if(canvasSize != image.getWidth() || canvasSize != image.getHeight()) { + Matrix matrix = new Matrix(); + float scale = (float) canvasSize / (float) image.getWidth(); + matrix.setScale(scale, scale); + shader.setLocalMatrix(matrix); + } + } + + /** + * @return Whether or not this view is currently + * in its selected state. + */ + public boolean isSelected() { + return this.isSelected; + } +} diff --git a/app/src/main/java/cy/agorise/crystalwallet/views/CryptoNetBalanceListView.java b/app/src/main/java/cy/agorise/crystalwallet/views/CryptoNetBalanceListView.java index 1e7afa5..be10ebb 100644 --- a/app/src/main/java/cy/agorise/crystalwallet/views/CryptoNetBalanceListView.java +++ b/app/src/main/java/cy/agorise/crystalwallet/views/CryptoNetBalanceListView.java @@ -84,7 +84,7 @@ public class CryptoNetBalanceListView extends RelativeLayout { this.listView.setNestedScrollingEnabled(false); } - /* + /*main_content * Sets the data for the list of balances. * * @param data the list of crypto net balances that will be show to the user diff --git a/app/src/main/res/anim/accounts_in.xml b/app/src/main/res/anim/accounts_in.xml new file mode 100644 index 0000000..e229b12 --- /dev/null +++ b/app/src/main/res/anim/accounts_in.xml @@ -0,0 +1,15 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/accounts_out.xml b/app/src/main/res/anim/accounts_out.xml new file mode 100644 index 0000000..33f5797 --- /dev/null +++ b/app/src/main/res/anim/accounts_out.xml @@ -0,0 +1,17 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/receive_transaction_in.xml b/app/src/main/res/anim/receive_transaction_in.xml new file mode 100644 index 0000000..0f925b5 --- /dev/null +++ b/app/src/main/res/anim/receive_transaction_in.xml @@ -0,0 +1,16 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/receive_transaction_out.xml b/app/src/main/res/anim/receive_transaction_out.xml new file mode 100644 index 0000000..6ac9f7d --- /dev/null +++ b/app/src/main/res/anim/receive_transaction_out.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/send_transaction_in.xml b/app/src/main/res/anim/send_transaction_in.xml new file mode 100644 index 0000000..ef3a508 --- /dev/null +++ b/app/src/main/res/anim/send_transaction_in.xml @@ -0,0 +1,16 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/send_transaction_out.xml b/app/src/main/res/anim/send_transaction_out.xml new file mode 100644 index 0000000..34514b8 --- /dev/null +++ b/app/src/main/res/anim/send_transaction_out.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/add_contact_fab.png b/app/src/main/res/drawable/add_contact_fab.png new file mode 100644 index 0000000..95b9b88 Binary files /dev/null and b/app/src/main/res/drawable/add_contact_fab.png differ diff --git a/app/src/main/res/drawable/crystal_logo.png b/app/src/main/res/drawable/crystal_logo.png new file mode 100644 index 0000000..66af3f8 Binary files /dev/null and b/app/src/main/res/drawable/crystal_logo.png differ diff --git a/app/src/main/res/drawable/ic_add_24dp.xml b/app/src/main/res/drawable/ic_add_24dp.xml new file mode 100644 index 0000000..0ca2ede --- /dev/null +++ b/app/src/main/res/drawable/ic_add_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_arrow_24dp.xml b/app/src/main/res/drawable/ic_arrow_24dp.xml new file mode 100644 index 0000000..a8c49fb --- /dev/null +++ b/app/src/main/res/drawable/ic_arrow_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_arrow_back.xml b/app/src/main/res/drawable/ic_arrow_back.xml new file mode 100644 index 0000000..f6c7026 --- /dev/null +++ b/app/src/main/res/drawable/ic_arrow_back.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_arrow_forward.xml b/app/src/main/res/drawable/ic_arrow_forward.xml new file mode 100644 index 0000000..38f52cf --- /dev/null +++ b/app/src/main/res/drawable/ic_arrow_forward.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_close.xml b/app/src/main/res/drawable/ic_close.xml new file mode 100644 index 0000000..2b9c759 --- /dev/null +++ b/app/src/main/res/drawable/ic_close.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_info_outline.xml b/app/src/main/res/drawable/ic_info_outline.xml new file mode 100644 index 0000000..075d9be --- /dev/null +++ b/app/src/main/res/drawable/ic_info_outline.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_lightning_24dp.xml b/app/src/main/res/drawable/ic_lightning_24dp.xml new file mode 100644 index 0000000..f163184 --- /dev/null +++ b/app/src/main/res/drawable/ic_lightning_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_people.xml b/app/src/main/res/drawable/ic_people.xml new file mode 100644 index 0000000..d26694e --- /dev/null +++ b/app/src/main/res/drawable/ic_people.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_person_add.xml b/app/src/main/res/drawable/ic_person_add.xml new file mode 100644 index 0000000..e8c63ed --- /dev/null +++ b/app/src/main/res/drawable/ic_person_add.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_settings_24dp.xml b/app/src/main/res/drawable/ic_settings_24dp.xml new file mode 100644 index 0000000..d4255f1 --- /dev/null +++ b/app/src/main/res/drawable/ic_settings_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ken_code_gravatar.png b/app/src/main/res/drawable/ken_code_gravatar.png new file mode 100644 index 0000000..863bda2 Binary files /dev/null and b/app/src/main/res/drawable/ken_code_gravatar.png differ diff --git a/app/src/main/res/drawable/receive_icon.png b/app/src/main/res/drawable/receive_icon.png new file mode 100644 index 0000000..8ccf611 Binary files /dev/null and b/app/src/main/res/drawable/receive_icon.png differ diff --git a/app/src/main/res/drawable/receive_transaction_top_view.xml b/app/src/main/res/drawable/receive_transaction_top_view.xml new file mode 100644 index 0000000..32bc4d2 --- /dev/null +++ b/app/src/main/res/drawable/receive_transaction_top_view.xml @@ -0,0 +1,9 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/roundcorner.xml b/app/src/main/res/drawable/roundcorner.xml new file mode 100644 index 0000000..41081b5 --- /dev/null +++ b/app/src/main/res/drawable/roundcorner.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/send_icon.png b/app/src/main/res/drawable/send_icon.png new file mode 100644 index 0000000..7e6c965 Binary files /dev/null and b/app/src/main/res/drawable/send_icon.png differ diff --git a/app/src/main/res/drawable/send_transaction_send_view.xml b/app/src/main/res/drawable/send_transaction_send_view.xml new file mode 100644 index 0000000..50501fb --- /dev/null +++ b/app/src/main/res/drawable/send_transaction_send_view.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/send_transaction_top_view.xml b/app/src/main/res/drawable/send_transaction_top_view.xml new file mode 100644 index 0000000..d7ce80f --- /dev/null +++ b/app/src/main/res/drawable/send_transaction_top_view.xml @@ -0,0 +1,9 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/font/opensans.xml b/app/src/main/res/font/opensans.xml new file mode 100644 index 0000000..9df3e72 --- /dev/null +++ b/app/src/main/res/font/opensans.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/font/opensans_italic.ttf b/app/src/main/res/font/opensans_italic.ttf new file mode 100755 index 0000000..e6c5414 Binary files /dev/null and b/app/src/main/res/font/opensans_italic.ttf differ diff --git a/app/src/main/res/font/opensans_regular.ttf b/app/src/main/res/font/opensans_regular.ttf new file mode 100755 index 0000000..2e31d02 Binary files /dev/null and b/app/src/main/res/font/opensans_regular.ttf differ diff --git a/app/src/main/res/layout/activity_setting.xml b/app/src/main/res/layout/activity_setting.xml deleted file mode 100644 index 083c1bf..0000000 --- a/app/src/main/res/layout/activity_setting.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - diff --git a/app/src/main/res/layout/activity_settings.xml b/app/src/main/res/layout/activity_settings.xml new file mode 100644 index 0000000..f030f1a --- /dev/null +++ b/app/src/main/res/layout/activity_settings.xml @@ -0,0 +1,135 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/board.xml b/app/src/main/res/layout/board.xml index abb5e7b..31aa573 100644 --- a/app/src/main/res/layout/board.xml +++ b/app/src/main/res/layout/board.xml @@ -1,24 +1,162 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + android:layout_height="match_parent" - + + + + + + + android:layout_gravity="end|bottom" + android:layout_margin="@dimen/fab_margin" + app:backgroundTint="@color/colorPrimaryDark" + app:srcCompat="@drawable/ic_person_add" /> - - - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_accounts.xml b/app/src/main/res/layout/fragment_accounts.xml new file mode 100644 index 0000000..25dc617 --- /dev/null +++ b/app/src/main/res/layout/fragment_accounts.xml @@ -0,0 +1,144 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/fragment_general_settings.xml b/app/src/main/res/layout/fragment_general_settings.xml new file mode 100644 index 0000000..0a58521 --- /dev/null +++ b/app/src/main/res/layout/fragment_general_settings.xml @@ -0,0 +1,153 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_transactions.xml b/app/src/main/res/layout/fragment_transactions.xml index c847c93..c982fd9 100644 --- a/app/src/main/res/layout/fragment_transactions.xml +++ b/app/src/main/res/layout/fragment_transactions.xml @@ -1,4 +1,4 @@ - - + diff --git a/app/src/main/res/layout/receive_transaction.xml b/app/src/main/res/layout/receive_transaction.xml index 1ead746..ddcc678 100644 --- a/app/src/main/res/layout/receive_transaction.xml +++ b/app/src/main/res/layout/receive_transaction.xml @@ -1,33 +1,154 @@ - + android:layout_height="wrap_content" > + + + + + + + + + + + android:layout_width="150dp" + android:layout_height="wrap_content" + android:layout_marginTop="24dp" + android:layout_marginStart="24dp" + android:inputType="textMultiLine" + android:textColor="@color/white" + android:textSize="20sp" + android:hint="@string/amount" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@+id/gravatar" /> + + android:layout_width="0dp" + android:layout_height="wrap_content" + android:textColor="@color/red" + app:layout_constraintEnd_toEndOf="@+id/etAmount" + app:layout_constraintStart_toStartOf="@+id/etAmount" + app:layout_constraintTop_toBottomOf="@+id/etAmount" /> + + android:textColor="@color/white" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintTop_toTopOf="@+id/etAmount" /> + + + + android:layout_width="0dp" + android:layout_height="wrap_content" + android:textColor="@color/red" + app:layout_constraintBottom_toBottomOf="@+id/tvAmountError" + app:layout_constraintEnd_toEndOf="@+id/spAsset" + app:layout_constraintStart_toStartOf="@+id/spAsset" /> + + + - \ No newline at end of file + android:layout_marginBottom="24dp" + android:layout_marginStart="24dp" + android:layout_marginTop="24dp" + android:text="@string/share_this_qr" + android:textSize="18sp" + android:textStyle="bold" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@+id/ivQrCode" /> + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/send_transaction.xml b/app/src/main/res/layout/send_transaction.xml index 539c465..cf22d2f 100644 --- a/app/src/main/res/layout/send_transaction.xml +++ b/app/src/main/res/layout/send_transaction.xml @@ -1,105 +1,239 @@ - + android:layout_height="wrap_content"> + + - - - + android:layout_marginStart="24dp" + android:layout_marginTop="24dp" + android:text="@string/title_capital" + android:textColor="@color/white" + android:textSize="20sp" + android:textStyle="bold" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" /> + + + + + + + + android:textColor="@color/white" + android:textSize="20sp" + android:hint="@string/to_capital" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@+id/gravatar" /> + + + - - - - + android:textColor="@color/red" + app:layout_constraintEnd_toEndOf="@+id/etTo" + app:layout_constraintStart_toStartOf="@+id/etTo" + app:layout_constraintTop_toBottomOf="@+id/etTo" /> + + + + + + android:textColor="@color/white" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintTop_toTopOf="@+id/etAmount" /> + + + - + android:textColor="@color/red" + app:layout_constraintBottom_toBottomOf="@+id/tvAmountError" + app:layout_constraintEnd_toEndOf="@+id/spAsset" + app:layout_constraintStart_toStartOf="@+id/spAsset" /> + + android:textColor="@color/white" + android:hint="@string/memo_capital" + android:textSize="20sp" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@+id/tvAmountError" /> + - - \ No newline at end of file + android:layout_marginBottom="24dp" + android:layout_marginEnd="24dp" + android:text="@string/cancel_capital" + android:textStyle="bold" + android:textSize="18sp" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" /> + + \ No newline at end of file diff --git a/app/src/main/res/raw/appbar_background.mp4 b/app/src/main/res/raw/appbar_background.mp4 new file mode 100644 index 0000000..db5535e Binary files /dev/null and b/app/src/main/res/raw/appbar_background.mp4 differ diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml new file mode 100644 index 0000000..848e37e --- /dev/null +++ b/app/src/main/res/values/attrs.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index e2f6b22..dad7b53 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -5,8 +5,11 @@ #669900 #d3d3d3 #686767 + #E3E3E3 #ffffff #f0006b + #00ffffff + #330099d6 #147b00 @@ -38,4 +41,8 @@ #ff56a9c7 #000000 #ffffff + #FF7063 + #FF9269 + #52CE84 + #4EBB7F diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index 9cf8f0c..b81577a 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -6,7 +6,7 @@ 16dp 14sp 72dp - 70sp + 140sp 16dp 16dp 35sp @@ -15,6 +15,7 @@ 70dp 140dp 150dp + 8dp 13sp diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 4e91a18..84ccf5b 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -452,4 +452,25 @@ Hello blank fragment + Scan a QR or NFC signal + CANCEL + Send Assets + Receive Assets + Share this QR + CLOSE + user_name + My Accounts + You don\'t have multiple accounts at the moment + SETTINGS + QR code + Crystal Logo + Lightning icon + Small triangle icon + General + Security + Backups + Accounts + Go back arrow + Settings + Info icon diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index f7a00e7..be0ebc8 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -1,6 +1,5 @@ - - - - + + + + + + + + + + + + diff --git a/build.gradle b/build.gradle index aad8aaa..f0981d9 100644 --- a/build.gradle +++ b/build.gradle @@ -3,6 +3,7 @@ buildscript { repositories { jcenter() + google() } dependencies { classpath 'com.android.tools.build:gradle:3.0.0' @@ -23,6 +24,7 @@ allprojects { maven { url 'http://www.idescout.com/maven/repo/' } + google() } }