Update Navigation and Lifecycle libraries.
- Updated the Navigation architecture component library to the latest stable version, with no big changes required. - Updated the Lifecycle architecture component library to the latest stable version, along with a bunch of changes related to the deprecation of some methods and the addition of others.
This commit is contained in:
parent
fd68b8bb96
commit
be5c9bcea7
15 changed files with 312 additions and 308 deletions
|
@ -63,7 +63,7 @@ android {
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
def lifecycle_version = "2.2.0"
|
def lifecycle_version = "2.3.0"
|
||||||
def arch_version = "2.1.0"
|
def arch_version = "2.1.0"
|
||||||
def room_version = "2.2.6"
|
def room_version = "2.2.6"
|
||||||
def rx_bindings_version = '3.0.0'
|
def rx_bindings_version = '3.0.0'
|
||||||
|
@ -83,8 +83,8 @@ dependencies {
|
||||||
implementation 'com.google.android.gms:play-services-maps:17.0.0'
|
implementation 'com.google.android.gms:play-services-maps:17.0.0'
|
||||||
implementation 'com.google.maps.android:android-maps-utils:0.5'
|
implementation 'com.google.maps.android:android-maps-utils:0.5'
|
||||||
// AAC Lifecycle
|
// AAC Lifecycle
|
||||||
implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"
|
implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"
|
||||||
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version" // viewModelScope
|
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
|
||||||
implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version"
|
implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version"
|
||||||
// AAC Room
|
// AAC Room
|
||||||
implementation "androidx.room:room-runtime:$room_version"
|
implementation "androidx.room:room-runtime:$room_version"
|
||||||
|
|
|
@ -7,10 +7,9 @@ import android.os.Handler
|
||||||
import android.preference.PreferenceManager
|
import android.preference.PreferenceManager
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
|
import androidx.activity.viewModels
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.core.content.pm.PackageInfoCompat
|
import androidx.core.content.pm.PackageInfoCompat
|
||||||
import androidx.lifecycle.Observer
|
|
||||||
import androidx.lifecycle.ViewModelProviders
|
|
||||||
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
||||||
import cy.agorise.bitsybitshareswallet.database.entities.Balance
|
import cy.agorise.bitsybitshareswallet.database.entities.Balance
|
||||||
import cy.agorise.bitsybitshareswallet.database.entities.Transfer
|
import cy.agorise.bitsybitshareswallet.database.entities.Transfer
|
||||||
|
@ -69,10 +68,11 @@ abstract class ConnectedActivity : AppCompatActivity() {
|
||||||
private const val RESPONSE_GET_MARKET_HISTORY = 6
|
private const val RESPONSE_GET_MARKET_HISTORY = 6
|
||||||
}
|
}
|
||||||
|
|
||||||
private lateinit var mUserAccountViewModel: UserAccountViewModel
|
// TODO consolidate ViewModels
|
||||||
private lateinit var mBalanceViewModel: BalanceViewModel
|
private val userAccountViewModel: UserAccountViewModel by viewModels()
|
||||||
private lateinit var mTransferViewModel: TransferViewModel
|
private val balanceViewModel: BalanceViewModel by viewModels()
|
||||||
private lateinit var mConnectedActivityViewModel: ConnectedActivityViewModel
|
private val transferViewModel: TransferViewModel by viewModels()
|
||||||
|
private val connectedActivityViewModel: ConnectedActivityViewModel by viewModels()
|
||||||
|
|
||||||
private lateinit var mAssetRepository: AssetRepository
|
private lateinit var mAssetRepository: AssetRepository
|
||||||
|
|
||||||
|
@ -114,42 +114,38 @@ abstract class ConnectedActivity : AppCompatActivity() {
|
||||||
mAssetRepository = AssetRepository(this)
|
mAssetRepository = AssetRepository(this)
|
||||||
|
|
||||||
// Configure ConnectedActivityViewModel to obtain missing equivalent values
|
// Configure ConnectedActivityViewModel to obtain missing equivalent values
|
||||||
mConnectedActivityViewModel = ViewModelProviders.of(this).get(ConnectedActivityViewModel::class.java)
|
|
||||||
|
|
||||||
val currencyCode = Helper.getCoingeckoSupportedCurrency(Locale.getDefault())
|
val currencyCode = Helper.getCoingeckoSupportedCurrency(Locale.getDefault())
|
||||||
Log.d(TAG, "Using currency: ${currencyCode.toUpperCase(Locale.ROOT)}")
|
Log.d(TAG, "Using currency: ${currencyCode.toUpperCase(Locale.ROOT)}")
|
||||||
mConnectedActivityViewModel.observeMissingEquivalentValuesIn(currencyCode)
|
connectedActivityViewModel.observeMissingEquivalentValuesIn(currencyCode)
|
||||||
|
|
||||||
// Configure UserAccountViewModel to obtain the missing account ids
|
// Configure UserAccountViewModel to obtain the missing account ids
|
||||||
mUserAccountViewModel = ViewModelProviders.of(this).get(UserAccountViewModel::class.java)
|
userAccountViewModel.getMissingUserAccountIds().observe(this, { userAccountIds ->
|
||||||
|
|
||||||
mUserAccountViewModel.getMissingUserAccountIds().observe(this, Observer<List<String>>{ userAccountIds ->
|
|
||||||
if (userAccountIds.isNotEmpty()) {
|
if (userAccountIds.isNotEmpty()) {
|
||||||
missingUserAccounts.clear()
|
missingUserAccounts.clear()
|
||||||
for (userAccountId in userAccountIds)
|
for (userAccountId in userAccountIds)
|
||||||
missingUserAccounts.add(UserAccount(userAccountId))
|
missingUserAccounts.add(UserAccount(userAccountId))
|
||||||
|
|
||||||
mHandler.postDelayed(mRequestMissingUserAccountsTask, Constants.NETWORK_SERVICE_RETRY_PERIOD)
|
mHandler.postDelayed(
|
||||||
|
mRequestMissingUserAccountsTask,
|
||||||
|
Constants.NETWORK_SERVICE_RETRY_PERIOD
|
||||||
|
)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// Configure UserAccountViewModel to obtain the missing account ids
|
// Configure UserAccountViewModel to obtain the missing account ids
|
||||||
mBalanceViewModel = ViewModelProviders.of(this).get(BalanceViewModel::class.java)
|
balanceViewModel.getMissingAssetIds().observe(this, { assetIds ->
|
||||||
|
|
||||||
mBalanceViewModel.getMissingAssetIds().observe(this, Observer<List<String>>{ assetIds ->
|
|
||||||
if (assetIds.isNotEmpty()) {
|
if (assetIds.isNotEmpty()) {
|
||||||
missingAssets.clear()
|
missingAssets.clear()
|
||||||
for (assetId in assetIds)
|
for (assetId in assetIds)
|
||||||
missingAssets.add(Asset(assetId))
|
missingAssets.add(Asset(assetId))
|
||||||
|
|
||||||
mHandler.postDelayed(mRequestMissingAssetsTask, Constants.NETWORK_SERVICE_RETRY_PERIOD)
|
mHandler
|
||||||
|
.postDelayed(mRequestMissingAssetsTask, Constants.NETWORK_SERVICE_RETRY_PERIOD)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
//Configure TransferViewModel to obtain the Transfer's block numbers with missing time information, one by one
|
//Configure TransferViewModel to obtain the Transfer's block numbers with missing time information, one by one
|
||||||
mTransferViewModel = ViewModelProviders.of(this).get(TransferViewModel::class.java)
|
transferViewModel.getTransferBlockNumberWithMissingTime().observe(this, { blockNumber ->
|
||||||
|
|
||||||
mTransferViewModel.getTransferBlockNumberWithMissingTime().observe(this, Observer<Long>{ blockNumber ->
|
|
||||||
if (blockNumber != null && blockNumber != blockNumberWithMissingTime) {
|
if (blockNumber != null && blockNumber != blockNumberWithMissingTime) {
|
||||||
blockNumberWithMissingTime = blockNumber
|
blockNumberWithMissingTime = blockNumber
|
||||||
mHandler.post(mRequestBlockMissingTimeTask)
|
mHandler.post(mRequestBlockMissingTimeTask)
|
||||||
|
@ -167,13 +163,14 @@ abstract class ConnectedActivity : AppCompatActivity() {
|
||||||
mCompositeDisposable.add(disposable)
|
mCompositeDisposable.add(disposable)
|
||||||
|
|
||||||
|
|
||||||
val info = this.packageManager.getPackageInfo(this.packageName, PackageManager.GET_ACTIVITIES)
|
val info =
|
||||||
|
this.packageManager.getPackageInfo(this.packageName, PackageManager.GET_ACTIVITIES)
|
||||||
val versionCode = PackageInfoCompat.getLongVersionCode(info)
|
val versionCode = PackageInfoCompat.getLongVersionCode(info)
|
||||||
val hasPurgedEquivalentValues = PreferenceManager.getDefaultSharedPreferences(this)
|
val hasPurgedEquivalentValues = PreferenceManager.getDefaultSharedPreferences(this)
|
||||||
.getBoolean(Constants.KEY_HAS_PURGED_EQUIVALENT_VALUES, false)
|
.getBoolean(Constants.KEY_HAS_PURGED_EQUIVALENT_VALUES, false)
|
||||||
if(versionCode > 11 && !hasPurgedEquivalentValues) {
|
if (versionCode > 11 && !hasPurgedEquivalentValues) {
|
||||||
thread {
|
thread {
|
||||||
mConnectedActivityViewModel.purgeEquivalentValues()
|
connectedActivityViewModel.purgeEquivalentValues()
|
||||||
PreferenceManager.getDefaultSharedPreferences(this)
|
PreferenceManager.getDefaultSharedPreferences(this)
|
||||||
.edit()
|
.edit()
|
||||||
.putBoolean(Constants.KEY_HAS_PURGED_EQUIVALENT_VALUES, true)
|
.putBoolean(Constants.KEY_HAS_PURGED_EQUIVALENT_VALUES, true)
|
||||||
|
@ -201,7 +198,7 @@ abstract class ConnectedActivity : AppCompatActivity() {
|
||||||
* Error consumer used to handle potential errors caused by the NetworkService while processing
|
* Error consumer used to handle potential errors caused by the NetworkService while processing
|
||||||
* incoming data.
|
* incoming data.
|
||||||
*/
|
*/
|
||||||
private fun handleError(throwable: Throwable){
|
private fun handleError(throwable: Throwable) {
|
||||||
Log.e(TAG, "Error while processing received message. Msg: " + throwable.message)
|
Log.e(TAG, "Error while processing received message. Msg: " + throwable.message)
|
||||||
val stack = throwable.stackTrace
|
val stack = throwable.stackTrace
|
||||||
for (e in stack) {
|
for (e in stack) {
|
||||||
|
@ -217,24 +214,24 @@ abstract class ConnectedActivity : AppCompatActivity() {
|
||||||
if (message.error == null) {
|
if (message.error == null) {
|
||||||
if (responseMap.containsKey(message.id)) {
|
if (responseMap.containsKey(message.id)) {
|
||||||
when (responseMap[message.id]) {
|
when (responseMap[message.id]) {
|
||||||
RESPONSE_GET_FULL_ACCOUNTS ->
|
RESPONSE_GET_FULL_ACCOUNTS ->
|
||||||
handleAccountDetails((message.result as List<*>)[0] as FullAccountDetails)
|
handleAccountDetails((message.result as List<*>)[0] as FullAccountDetails)
|
||||||
|
|
||||||
RESPONSE_GET_ACCOUNTS ->
|
RESPONSE_GET_ACCOUNTS ->
|
||||||
handleAccountProperties(message.result as List<AccountProperties>)
|
handleAccountProperties(message.result as List<AccountProperties>)
|
||||||
|
|
||||||
RESPONSE_GET_ACCOUNT_BALANCES ->
|
RESPONSE_GET_ACCOUNT_BALANCES ->
|
||||||
handleBalanceUpdate(message.result as List<AssetAmount>)
|
handleBalanceUpdate(message.result as List<AssetAmount>)
|
||||||
|
|
||||||
RESPONSE_GET_ASSETS ->
|
RESPONSE_GET_ASSETS ->
|
||||||
handleAssets(message.result as List<Asset>)
|
handleAssets(message.result as List<Asset>)
|
||||||
|
|
||||||
RESPONSE_GET_BLOCK_HEADER -> {
|
RESPONSE_GET_BLOCK_HEADER -> {
|
||||||
val blockNumber = requestIdToBlockNumberMap[message.id] ?: 0L
|
val blockNumber = requestIdToBlockNumberMap[message.id] ?: 0L
|
||||||
handleBlockHeader(message.result as BlockHeader, blockNumber)
|
handleBlockHeader(message.result as BlockHeader, blockNumber)
|
||||||
requestIdToBlockNumberMap.remove(message.id)
|
requestIdToBlockNumberMap.remove(message.id)
|
||||||
}
|
}
|
||||||
RESPONSE_GET_MARKET_HISTORY -> handleMarketData(message.result as List<BucketObject>)
|
RESPONSE_GET_MARKET_HISTORY -> handleMarketData(message.result as List<BucketObject>)
|
||||||
}
|
}
|
||||||
responseMap.remove(message.id)
|
responseMap.remove(message.id)
|
||||||
}
|
}
|
||||||
|
@ -259,11 +256,11 @@ abstract class ConnectedActivity : AppCompatActivity() {
|
||||||
responseMap.clear()
|
responseMap.clear()
|
||||||
} else if (message.updateCode == ConnectionStatusUpdate.API_UPDATE) {
|
} else if (message.updateCode == ConnectionStatusUpdate.API_UPDATE) {
|
||||||
// If we got an API update
|
// If we got an API update
|
||||||
if(message.api == ApiAccess.API_HISTORY) {
|
if (message.api == ApiAccess.API_HISTORY) {
|
||||||
// Starts the procedure that will obtain the missing equivalent values
|
// Starts the procedure that will obtain the missing equivalent values
|
||||||
mTransferViewModel
|
transferViewModel
|
||||||
.getTransfersWithMissingBtsValue().observe(this, Observer<Transfer> {
|
.getTransfersWithMissingBtsValue().observe(this, {
|
||||||
if(it != null) handleTransfersWithMissingBtsValue(it)
|
if (it != null) handleTransfersWithMissingBtsValue(it)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -274,13 +271,16 @@ abstract class ConnectedActivity : AppCompatActivity() {
|
||||||
* Method called whenever we get a list of transfers with their bts value missing.
|
* Method called whenever we get a list of transfers with their bts value missing.
|
||||||
*/
|
*/
|
||||||
private fun handleTransfersWithMissingBtsValue(transfer: Transfer) {
|
private fun handleTransfersWithMissingBtsValue(transfer: Transfer) {
|
||||||
if(mNetworkService?.isConnected == true){
|
if (mNetworkService?.isConnected == true) {
|
||||||
val base = Asset(transfer.transferAssetId)
|
val base = Asset(transfer.transferAssetId)
|
||||||
val quote = Asset("1.3.0")
|
val quote = Asset("1.3.0")
|
||||||
val bucket: Long = TimeUnit.SECONDS.convert(1, TimeUnit.DAYS)
|
val bucket: Long = TimeUnit.SECONDS.convert(1, TimeUnit.DAYS)
|
||||||
val end: Long = transfer.timestamp * 1000L
|
val end: Long = transfer.timestamp * 1000L
|
||||||
val start: Long = (transfer.timestamp - bucket) * 1000L
|
val start: Long = (transfer.timestamp - bucket) * 1000L
|
||||||
val id = mNetworkService!!.sendMessage(GetMarketHistory(base, quote, bucket, start, end), GetMarketHistory.REQUIRED_API)
|
val id = mNetworkService!!.sendMessage(
|
||||||
|
GetMarketHistory(base, quote, bucket, start, end),
|
||||||
|
GetMarketHistory.REQUIRED_API
|
||||||
|
)
|
||||||
responseMap[id] = RESPONSE_GET_MARKET_HISTORY
|
responseMap[id] = RESPONSE_GET_MARKET_HISTORY
|
||||||
this.transfer = transfer
|
this.transfer = transfer
|
||||||
}
|
}
|
||||||
|
@ -292,11 +292,17 @@ abstract class ConnectedActivity : AppCompatActivity() {
|
||||||
*/
|
*/
|
||||||
private fun handleAccountDetails(accountDetails: FullAccountDetails) {
|
private fun handleAccountDetails(accountDetails: FullAccountDetails) {
|
||||||
val latestOpCount = accountDetails.statistics.total_ops
|
val latestOpCount = accountDetails.statistics.total_ops
|
||||||
Log.d(TAG, "handleAccountDetails. prev count: $storedOpCount, current count: $latestOpCount")
|
Log.d(
|
||||||
|
TAG,
|
||||||
|
"handleAccountDetails. prev count: $storedOpCount, current count: $latestOpCount"
|
||||||
|
)
|
||||||
|
|
||||||
if (latestOpCount == 0L) {
|
if (latestOpCount == 0L) {
|
||||||
Log.d(TAG, "The node returned 0 total_ops for current account and may not have installed the history plugin. " +
|
Log.d(
|
||||||
"\nAsk the NetworkService to remove the node from the list and connect to another one.")
|
TAG,
|
||||||
|
"The node returned 0 total_ops for current account and may not have installed the history plugin. " +
|
||||||
|
"\nAsk the NetworkService to remove the node from the list and connect to another one."
|
||||||
|
)
|
||||||
mNetworkService?.reconnectNode()
|
mNetworkService?.reconnectNode()
|
||||||
} else if (storedOpCount == -1L) {
|
} else if (storedOpCount == -1L) {
|
||||||
// Initial case when the app starts
|
// Initial case when the app starts
|
||||||
|
@ -317,7 +323,8 @@ abstract class ConnectedActivity : AppCompatActivity() {
|
||||||
* create a list of BiTSy's UserAccount objects and stores them into the database
|
* create a list of BiTSy's UserAccount objects and stores them into the database
|
||||||
*/
|
*/
|
||||||
private fun handleAccountProperties(accountPropertiesList: List<AccountProperties>) {
|
private fun handleAccountProperties(accountPropertiesList: List<AccountProperties>) {
|
||||||
val userAccounts = ArrayList<cy.agorise.bitsybitshareswallet.database.entities.UserAccount>()
|
val userAccounts =
|
||||||
|
ArrayList<cy.agorise.bitsybitshareswallet.database.entities.UserAccount>()
|
||||||
|
|
||||||
for (accountProperties in accountPropertiesList) {
|
for (accountProperties in accountPropertiesList) {
|
||||||
val userAccount = cy.agorise.bitsybitshareswallet.database.entities.UserAccount(
|
val userAccount = cy.agorise.bitsybitshareswallet.database.entities.UserAccount(
|
||||||
|
@ -329,7 +336,7 @@ abstract class ConnectedActivity : AppCompatActivity() {
|
||||||
userAccounts.add(userAccount)
|
userAccounts.add(userAccount)
|
||||||
}
|
}
|
||||||
|
|
||||||
mUserAccountViewModel.insertAll(userAccounts)
|
userAccountViewModel.insertAll(userAccounts)
|
||||||
missingUserAccounts.clear()
|
missingUserAccounts.clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -346,7 +353,7 @@ abstract class ConnectedActivity : AppCompatActivity() {
|
||||||
balances.add(balance)
|
balances.add(balance)
|
||||||
}
|
}
|
||||||
|
|
||||||
mBalanceViewModel.insertAll(balances)
|
balanceViewModel.insertAll(balances)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -382,35 +389,38 @@ abstract class ConnectedActivity : AppCompatActivity() {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val date = dateFormat.parse(blockHeader.timestamp)
|
val date = dateFormat.parse(blockHeader.timestamp)
|
||||||
mTransferViewModel.setBlockTime(blockNumber, date.time / 1000)
|
transferViewModel.setBlockTime(blockNumber, date.time / 1000)
|
||||||
} catch (e: ParseException) {
|
} catch (e: ParseException) {
|
||||||
Log.e(TAG, "ParseException. Msg: " + e.message)
|
Log.e(TAG, "ParseException. Msg: " + e.message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleMarketData(buckets: List<BucketObject>) {
|
private fun handleMarketData(buckets: List<BucketObject>) {
|
||||||
if(buckets.isNotEmpty()){
|
if (buckets.isNotEmpty()) {
|
||||||
Log.d(TAG,"handleMarketData. Bucket is not empty")
|
Log.d(TAG, "handleMarketData. Bucket is not empty")
|
||||||
val bucket = buckets[0]
|
val bucket = buckets[0]
|
||||||
val pair = Pair(transfer, bucket)
|
val pair = Pair(transfer, bucket)
|
||||||
val disposable = Observable.just(pair)
|
val disposable = Observable.just(pair)
|
||||||
.subscribeOn(Schedulers.computation())
|
.subscribeOn(Schedulers.computation())
|
||||||
.map { mTransferViewModel.updateBtsValue(it.first!!, it.second) }
|
.map { transferViewModel.updateBtsValue(it.first!!, it.second) }
|
||||||
.subscribe({},{
|
.subscribe({}, {
|
||||||
Log.e(TAG,"Error at updateBtsValue. Msg: ${it.message}")
|
Log.e(TAG, "Error at updateBtsValue. Msg: ${it.message}")
|
||||||
for(line in it.stackTrace) Log.e(TAG, "${line.className}#${line.methodName}:${line.lineNumber}")
|
for (line in it.stackTrace)
|
||||||
|
Log.e(TAG, "${line.className}#${line.methodName}:${line.lineNumber}")
|
||||||
})
|
})
|
||||||
mCompositeDisposable.add(disposable)
|
mCompositeDisposable.add(disposable)
|
||||||
}else{
|
} else {
|
||||||
Log.i(TAG,"handleMarketData. Bucket IS empty")
|
Log.i(TAG, "handleMarketData. Bucket IS empty")
|
||||||
AsyncTask.execute { mTransferViewModel.updateBtsValue(transfer!!, Transfer.ERROR) }
|
AsyncTask.execute { transferViewModel.updateBtsValue(transfer!!, Transfer.ERROR) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateBalances() {
|
private fun updateBalances() {
|
||||||
if (mNetworkService?.isConnected == true) {
|
if (mNetworkService?.isConnected == true) {
|
||||||
val id = mNetworkService!!.sendMessage(GetAccountBalances(mCurrentAccount, ArrayList()),
|
val id = mNetworkService!!.sendMessage(
|
||||||
GetAccountBalances.REQUIRED_API)
|
GetAccountBalances(mCurrentAccount, ArrayList()),
|
||||||
|
GetAccountBalances.REQUIRED_API
|
||||||
|
)
|
||||||
|
|
||||||
responseMap[id] = RESPONSE_GET_ACCOUNT_BALANCES
|
responseMap[id] = RESPONSE_GET_ACCOUNT_BALANCES
|
||||||
}
|
}
|
||||||
|
@ -447,10 +457,13 @@ abstract class ConnectedActivity : AppCompatActivity() {
|
||||||
private val mRequestMissingUserAccountsTask = object : Runnable {
|
private val mRequestMissingUserAccountsTask = object : Runnable {
|
||||||
override fun run() {
|
override fun run() {
|
||||||
if (mNetworkService?.isConnected == true) {
|
if (mNetworkService?.isConnected == true) {
|
||||||
val id = mNetworkService!!.sendMessage(GetAccounts(missingUserAccounts), GetAccounts.REQUIRED_API)
|
val id = mNetworkService!!.sendMessage(
|
||||||
|
GetAccounts(missingUserAccounts),
|
||||||
|
GetAccounts.REQUIRED_API
|
||||||
|
)
|
||||||
|
|
||||||
responseMap[id] = RESPONSE_GET_ACCOUNTS
|
responseMap[id] = RESPONSE_GET_ACCOUNTS
|
||||||
} else if (missingUserAccounts.isNotEmpty()){
|
} else if (missingUserAccounts.isNotEmpty()) {
|
||||||
mHandler.postDelayed(this, Constants.NETWORK_SERVICE_RETRY_PERIOD)
|
mHandler.postDelayed(this, Constants.NETWORK_SERVICE_RETRY_PERIOD)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -462,10 +475,11 @@ abstract class ConnectedActivity : AppCompatActivity() {
|
||||||
private val mRequestMissingAssetsTask = object : Runnable {
|
private val mRequestMissingAssetsTask = object : Runnable {
|
||||||
override fun run() {
|
override fun run() {
|
||||||
if (mNetworkService?.isConnected == true) {
|
if (mNetworkService?.isConnected == true) {
|
||||||
val id = mNetworkService!!.sendMessage(GetAssets(missingAssets), GetAssets.REQUIRED_API)
|
val id =
|
||||||
|
mNetworkService!!.sendMessage(GetAssets(missingAssets), GetAssets.REQUIRED_API)
|
||||||
|
|
||||||
responseMap[id] = RESPONSE_GET_ASSETS
|
responseMap[id] = RESPONSE_GET_ASSETS
|
||||||
} else if (missingAssets.isNotEmpty()){
|
} else if (missingAssets.isNotEmpty()) {
|
||||||
mHandler.postDelayed(this, Constants.NETWORK_SERVICE_RETRY_PERIOD)
|
mHandler.postDelayed(this, Constants.NETWORK_SERVICE_RETRY_PERIOD)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -480,13 +494,17 @@ abstract class ConnectedActivity : AppCompatActivity() {
|
||||||
if (mCurrentAccount != null) {
|
if (mCurrentAccount != null) {
|
||||||
val userAccounts = ArrayList<String>()
|
val userAccounts = ArrayList<String>()
|
||||||
userAccounts.add(mCurrentAccount!!.objectId)
|
userAccounts.add(mCurrentAccount!!.objectId)
|
||||||
val id = mNetworkService!!.sendMessage(GetFullAccounts(userAccounts, false),
|
val id = mNetworkService!!.sendMessage(
|
||||||
GetFullAccounts.REQUIRED_API)
|
GetFullAccounts(userAccounts, false),
|
||||||
|
GetFullAccounts.REQUIRED_API
|
||||||
|
)
|
||||||
|
|
||||||
responseMap[id] = RESPONSE_GET_FULL_ACCOUNTS
|
responseMap[id] = RESPONSE_GET_FULL_ACCOUNTS
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Log.w(TAG, "NetworkService is null or is not connected. mNetworkService: $mNetworkService")
|
val msg = "NetworkService is null or is not connected. " +
|
||||||
|
"mNetworkService: $mNetworkService"
|
||||||
|
Log.w(TAG, msg)
|
||||||
}
|
}
|
||||||
mHandler.postDelayed(this, Constants.MISSING_PAYMENT_CHECK_PERIOD)
|
mHandler.postDelayed(this, Constants.MISSING_PAYMENT_CHECK_PERIOD)
|
||||||
|
|
||||||
|
@ -500,8 +518,10 @@ abstract class ConnectedActivity : AppCompatActivity() {
|
||||||
override fun run() {
|
override fun run() {
|
||||||
|
|
||||||
if (mNetworkService?.isConnected == true) {
|
if (mNetworkService?.isConnected == true) {
|
||||||
val id = mNetworkService!!.sendMessage(GetBlockHeader(blockNumberWithMissingTime),
|
val id = mNetworkService!!.sendMessage(
|
||||||
GetBlockHeader.REQUIRED_API)
|
GetBlockHeader(blockNumberWithMissingTime),
|
||||||
|
GetBlockHeader.REQUIRED_API
|
||||||
|
)
|
||||||
|
|
||||||
responseMap[id] = RESPONSE_GET_BLOCK_HEADER
|
responseMap[id] = RESPONSE_GET_BLOCK_HEADER
|
||||||
requestIdToBlockNumberMap[id] = blockNumberWithMissingTime
|
requestIdToBlockNumberMap[id] = blockNumberWithMissingTime
|
||||||
|
@ -521,7 +541,7 @@ abstract class ConnectedActivity : AppCompatActivity() {
|
||||||
override fun onPause() {
|
override fun onPause() {
|
||||||
super.onPause()
|
super.onPause()
|
||||||
mNetworkService?.nodeLatencyVerifier?.nodeList?.let { nodes ->
|
mNetworkService?.nodeLatencyVerifier?.nodeList?.let { nodes ->
|
||||||
mConnectedActivityViewModel.updateNodeLatencies(nodes as List<FullNode>)
|
connectedActivityViewModel.updateNodeLatencies(nodes as List<FullNode>)
|
||||||
}
|
}
|
||||||
|
|
||||||
mHandler.removeCallbacks(mCheckMissingPaymentsTask)
|
mHandler.removeCallbacks(mCheckMissingPaymentsTask)
|
||||||
|
@ -532,6 +552,6 @@ abstract class ConnectedActivity : AppCompatActivity() {
|
||||||
|
|
||||||
override fun onDestroy() {
|
override fun onDestroy() {
|
||||||
super.onDestroy()
|
super.onDestroy()
|
||||||
if(!mCompositeDisposable.isDisposed) mCompositeDisposable.dispose()
|
if (!mCompositeDisposable.isDisposed) mCompositeDisposable.dispose()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,22 +5,20 @@ import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.lifecycle.Observer
|
import androidx.fragment.app.viewModels
|
||||||
import androidx.lifecycle.ViewModelProviders
|
|
||||||
import androidx.recyclerview.widget.DividerItemDecoration
|
import androidx.recyclerview.widget.DividerItemDecoration
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import cy.agorise.bitsybitshareswallet.adapters.BalancesAdapter
|
import cy.agorise.bitsybitshareswallet.adapters.BalancesAdapter
|
||||||
import cy.agorise.bitsybitshareswallet.database.joins.BalanceDetail
|
|
||||||
import cy.agorise.bitsybitshareswallet.databinding.FragmentBalancesBinding
|
import cy.agorise.bitsybitshareswallet.databinding.FragmentBalancesBinding
|
||||||
import cy.agorise.bitsybitshareswallet.viewmodels.BalanceDetailViewModel
|
import cy.agorise.bitsybitshareswallet.viewmodels.BalanceDetailViewModel
|
||||||
|
|
||||||
class BalancesFragment : Fragment() {
|
class BalancesFragment : Fragment() {
|
||||||
|
|
||||||
|
private val viewModel: BalanceDetailViewModel by viewModels()
|
||||||
|
|
||||||
private var _binding: FragmentBalancesBinding? = null
|
private var _binding: FragmentBalancesBinding? = null
|
||||||
private val binding get() = _binding!!
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
private lateinit var mBalanceDetailViewModel: BalanceDetailViewModel
|
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
inflater: LayoutInflater, container: ViewGroup?,
|
inflater: LayoutInflater, container: ViewGroup?,
|
||||||
savedInstanceState: Bundle?
|
savedInstanceState: Bundle?
|
||||||
|
@ -40,19 +38,15 @@ class BalancesFragment : Fragment() {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
||||||
// Configure BalanceDetailViewModel to show the current balances
|
// Configure BalanceDetailViewModel to show the current balances
|
||||||
mBalanceDetailViewModel =
|
val balancesAdapter = BalancesAdapter(requireContext())
|
||||||
ViewModelProviders.of(this).get(BalanceDetailViewModel::class.java)
|
|
||||||
|
|
||||||
val balancesAdapter = BalancesAdapter(context!!)
|
|
||||||
binding.rvBalances.adapter = balancesAdapter
|
binding.rvBalances.adapter = balancesAdapter
|
||||||
binding.rvBalances.layoutManager = LinearLayoutManager(context!!)
|
binding.rvBalances.layoutManager = LinearLayoutManager(requireContext())
|
||||||
binding.rvBalances.addItemDecoration(
|
binding.rvBalances.addItemDecoration(
|
||||||
DividerItemDecoration(context!!, DividerItemDecoration.VERTICAL)
|
DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL)
|
||||||
)
|
)
|
||||||
|
|
||||||
mBalanceDetailViewModel.getAll()
|
viewModel.getAll().observe(viewLifecycleOwner, { balancesDetails ->
|
||||||
.observe(this, Observer<List<BalanceDetail>> { balancesDetails ->
|
balancesAdapter.replaceAll(balancesDetails)
|
||||||
balancesAdapter.replaceAll(balancesDetails)
|
})
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package cy.agorise.bitsybitshareswallet.fragments
|
||||||
import android.preference.PreferenceManager
|
import android.preference.PreferenceManager
|
||||||
import androidx.navigation.fragment.findNavController
|
import androidx.navigation.fragment.findNavController
|
||||||
import cy.agorise.bitsybitshareswallet.R
|
import cy.agorise.bitsybitshareswallet.R
|
||||||
|
import cy.agorise.bitsybitshareswallet.activities.ConnectedActivity
|
||||||
import cy.agorise.bitsybitshareswallet.database.entities.Authority
|
import cy.agorise.bitsybitshareswallet.database.entities.Authority
|
||||||
import cy.agorise.bitsybitshareswallet.repositories.AuthorityRepository
|
import cy.agorise.bitsybitshareswallet.repositories.AuthorityRepository
|
||||||
import cy.agorise.bitsybitshareswallet.repositories.UserAccountRepository
|
import cy.agorise.bitsybitshareswallet.repositories.UserAccountRepository
|
||||||
|
@ -13,7 +14,6 @@ import cy.agorise.graphenej.BrainKey
|
||||||
import cy.agorise.graphenej.PublicKey
|
import cy.agorise.graphenej.PublicKey
|
||||||
import cy.agorise.graphenej.models.AccountProperties
|
import cy.agorise.graphenej.models.AccountProperties
|
||||||
import org.bitcoinj.core.ECKey
|
import org.bitcoinj.core.ECKey
|
||||||
import cy.agorise.bitsybitshareswallet.activities.ConnectedActivity
|
|
||||||
|
|
||||||
|
|
||||||
abstract class BaseAccountFragment : ConnectedFragment() {
|
abstract class BaseAccountFragment : ConnectedFragment() {
|
||||||
|
@ -36,7 +36,7 @@ abstract class BaseAccountFragment : ConnectedFragment() {
|
||||||
val hashedPIN = CryptoUtils.createSHA256Hash(salt + pin)
|
val hashedPIN = CryptoUtils.createSHA256Hash(salt + pin)
|
||||||
|
|
||||||
// Stores the user selected PIN, hashed
|
// Stores the user selected PIN, hashed
|
||||||
PreferenceManager.getDefaultSharedPreferences(context!!).edit()
|
PreferenceManager.getDefaultSharedPreferences(requireContext()).edit()
|
||||||
.putString(Constants.KEY_HASHED_PIN_PATTERN, hashedPIN)
|
.putString(Constants.KEY_HASHED_PIN_PATTERN, hashedPIN)
|
||||||
.putString(Constants.KEY_PIN_PATTERN_SALT, salt)
|
.putString(Constants.KEY_PIN_PATTERN_SALT, salt)
|
||||||
.putInt(Constants.KEY_SECURITY_LOCK_SELECTED, 1).apply() // 1 -> PIN
|
.putInt(Constants.KEY_SECURITY_LOCK_SELECTED, 1).apply() // 1 -> PIN
|
||||||
|
@ -44,15 +44,17 @@ abstract class BaseAccountFragment : ConnectedFragment() {
|
||||||
// Stores the accounts this key refers to
|
// Stores the accounts this key refers to
|
||||||
val id = accountProperties.id
|
val id = accountProperties.id
|
||||||
val name = accountProperties.name
|
val name = accountProperties.name
|
||||||
val isLTM = accountProperties.membership_expiration_date == Constants.LIFETIME_EXPIRATION_DATE
|
val isLTM =
|
||||||
|
accountProperties.membership_expiration_date == Constants.LIFETIME_EXPIRATION_DATE
|
||||||
|
|
||||||
val userAccount = cy.agorise.bitsybitshareswallet.database.entities.UserAccount(id, name, isLTM)
|
val userAccount =
|
||||||
|
cy.agorise.bitsybitshareswallet.database.entities.UserAccount(id, name, isLTM)
|
||||||
|
|
||||||
val userAccountRepository = UserAccountRepository(context!!.applicationContext)
|
val userAccountRepository = UserAccountRepository(requireContext().applicationContext)
|
||||||
userAccountRepository.insert(userAccount)
|
userAccountRepository.insert(userAccount)
|
||||||
|
|
||||||
// Stores the id of the currently active user account
|
// Stores the id of the currently active user account
|
||||||
PreferenceManager.getDefaultSharedPreferences(context!!).edit()
|
PreferenceManager.getDefaultSharedPreferences(requireContext()).edit()
|
||||||
.putString(Constants.KEY_CURRENT_ACCOUNT_ID, accountProperties.id).apply()
|
.putString(Constants.KEY_CURRENT_ACCOUNT_ID, accountProperties.id).apply()
|
||||||
|
|
||||||
// Trying to store all possible authorities (owner, active and memo) into the database
|
// Trying to store all possible authorities (owner, active and memo) into the database
|
||||||
|
@ -65,13 +67,25 @@ abstract class BaseAccountFragment : ConnectedFragment() {
|
||||||
val publicKey = PublicKey(ECKey.fromPublicOnly(mBrainKey!!.privateKey.pubKey))
|
val publicKey = PublicKey(ECKey.fromPublicOnly(mBrainKey!!.privateKey.pubKey))
|
||||||
|
|
||||||
if (ownerAuthority.keyAuths.keys.contains(publicKey)) {
|
if (ownerAuthority.keyAuths.keys.contains(publicKey)) {
|
||||||
addAuthorityToDatabase(accountProperties.id, AuthorityType.OWNER.ordinal, mBrainKey!!)
|
addAuthorityToDatabase(
|
||||||
|
accountProperties.id,
|
||||||
|
AuthorityType.OWNER.ordinal,
|
||||||
|
mBrainKey!!
|
||||||
|
)
|
||||||
}
|
}
|
||||||
if (activeAuthority.keyAuths.keys.contains(publicKey)) {
|
if (activeAuthority.keyAuths.keys.contains(publicKey)) {
|
||||||
addAuthorityToDatabase(accountProperties.id, AuthorityType.ACTIVE.ordinal, mBrainKey!!)
|
addAuthorityToDatabase(
|
||||||
|
accountProperties.id,
|
||||||
|
AuthorityType.ACTIVE.ordinal,
|
||||||
|
mBrainKey!!
|
||||||
|
)
|
||||||
}
|
}
|
||||||
if (options.memoKey == publicKey) {
|
if (options.memoKey == publicKey) {
|
||||||
addAuthorityToDatabase(accountProperties.id, AuthorityType.MEMO.ordinal, mBrainKey!!)
|
addAuthorityToDatabase(
|
||||||
|
accountProperties.id,
|
||||||
|
AuthorityType.MEMO.ordinal,
|
||||||
|
mBrainKey!!
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,13 +105,21 @@ abstract class BaseAccountFragment : ConnectedFragment() {
|
||||||
val wif = brainKey.walletImportFormat
|
val wif = brainKey.walletImportFormat
|
||||||
val sequenceNumber = brainKey.sequenceNumber
|
val sequenceNumber = brainKey.sequenceNumber
|
||||||
|
|
||||||
val encryptedBrainKey = CryptoUtils.encrypt(context!!, brainKeyWords)
|
val encryptedBrainKey = CryptoUtils.encrypt(requireContext(), brainKeyWords)
|
||||||
val encryptedSequenceNumber = CryptoUtils.encrypt(context!!, sequenceNumber.toString())
|
val encryptedSequenceNumber =
|
||||||
val encryptedWIF = CryptoUtils.encrypt(context!!, wif)
|
CryptoUtils.encrypt(requireContext(), sequenceNumber.toString())
|
||||||
|
val encryptedWIF = CryptoUtils.encrypt(requireContext(), wif)
|
||||||
|
|
||||||
val authority = Authority(0, userId, authorityType, encryptedWIF, encryptedBrainKey, encryptedSequenceNumber)
|
val authority = Authority(
|
||||||
|
0,
|
||||||
|
userId,
|
||||||
|
authorityType,
|
||||||
|
encryptedWIF,
|
||||||
|
encryptedBrainKey,
|
||||||
|
encryptedSequenceNumber
|
||||||
|
)
|
||||||
|
|
||||||
val authorityRepository = AuthorityRepository(context!!)
|
val authorityRepository = AuthorityRepository(requireContext())
|
||||||
authorityRepository.insert(authority)
|
authorityRepository.insert(authority)
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -362,8 +362,9 @@ class CreateAccountFragment : BaseAccountFragment() {
|
||||||
var reader: BufferedReader? = null
|
var reader: BufferedReader? = null
|
||||||
val dictionary: String
|
val dictionary: String
|
||||||
try {
|
try {
|
||||||
reader =
|
reader = BufferedReader(
|
||||||
BufferedReader(InputStreamReader(context!!.assets.open(BRAINKEY_FILE), "UTF-8"))
|
InputStreamReader(requireContext().assets.open(BRAINKEY_FILE), "UTF-8")
|
||||||
|
)
|
||||||
dictionary = reader.readLine()
|
dictionary = reader.readLine()
|
||||||
|
|
||||||
val brainKeySuggestion = BrainKey.suggest(dictionary)
|
val brainKeySuggestion = BrainKey.suggest(dictionary)
|
||||||
|
|
|
@ -12,8 +12,7 @@ import android.view.*
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.os.ConfigurationCompat
|
import androidx.core.os.ConfigurationCompat
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.lifecycle.Observer
|
import androidx.fragment.app.viewModels
|
||||||
import androidx.lifecycle.ViewModelProviders
|
|
||||||
import androidx.navigation.fragment.navArgs
|
import androidx.navigation.fragment.navArgs
|
||||||
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
||||||
import cy.agorise.bitsybitshareswallet.R
|
import cy.agorise.bitsybitshareswallet.R
|
||||||
|
@ -38,12 +37,13 @@ class EReceiptFragment : Fragment() {
|
||||||
private const val REQUEST_WRITE_EXTERNAL_STORAGE_PERMISSION = 100
|
private const val REQUEST_WRITE_EXTERNAL_STORAGE_PERMISSION = 100
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val args: EReceiptFragmentArgs by navArgs()
|
||||||
|
|
||||||
|
private val viewModel: EReceiptViewModel by viewModels()
|
||||||
|
|
||||||
private var _binding: FragmentEReceiptBinding? = null
|
private var _binding: FragmentEReceiptBinding? = null
|
||||||
private val binding get() = _binding!!
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
private val args: EReceiptFragmentArgs by navArgs()
|
|
||||||
|
|
||||||
private lateinit var mEReceiptViewModel: EReceiptViewModel
|
|
||||||
private lateinit var mLocale: Locale
|
private lateinit var mLocale: Locale
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
|
@ -75,12 +75,9 @@ class EReceiptFragment : Fragment() {
|
||||||
|
|
||||||
val transferId = args.transferId
|
val transferId = args.transferId
|
||||||
|
|
||||||
mEReceiptViewModel = ViewModelProviders.of(this).get(EReceiptViewModel::class.java)
|
viewModel.get(userId, transferId).observe(viewLifecycleOwner, { transferDetail ->
|
||||||
|
bindTransferDetail(transferDetail)
|
||||||
mEReceiptViewModel.get(userId, transferId)
|
})
|
||||||
.observe(this, Observer<TransferDetail> { transferDetail ->
|
|
||||||
bindTransferDetail(transferDetail)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun bindTransferDetail(transferDetail: TransferDetail) {
|
private fun bindTransferDetail(transferDetail: TransferDetail) {
|
||||||
|
@ -165,7 +162,7 @@ class EReceiptFragment : Fragment() {
|
||||||
* shares it but if it is not then it asks the user for that permission */
|
* shares it but if it is not then it asks the user for that permission */
|
||||||
private fun verifyStoragePermission() {
|
private fun verifyStoragePermission() {
|
||||||
if (ContextCompat
|
if (ContextCompat
|
||||||
.checkSelfPermission(activity!!, Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
.checkSelfPermission(requireActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
||||||
!= PackageManager.PERMISSION_GRANTED
|
!= PackageManager.PERMISSION_GRANTED
|
||||||
) {
|
) {
|
||||||
// Permission is not already granted
|
// Permission is not already granted
|
||||||
|
|
|
@ -10,8 +10,7 @@ import android.widget.TextView
|
||||||
import androidx.core.os.ConfigurationCompat
|
import androidx.core.os.ConfigurationCompat
|
||||||
import androidx.fragment.app.DialogFragment
|
import androidx.fragment.app.DialogFragment
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.lifecycle.Observer
|
import androidx.fragment.app.viewModels
|
||||||
import androidx.lifecycle.ViewModelProviders
|
|
||||||
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
||||||
import cy.agorise.bitsybitshareswallet.R
|
import cy.agorise.bitsybitshareswallet.R
|
||||||
import cy.agorise.bitsybitshareswallet.adapters.BalancesDetailsAdapter
|
import cy.agorise.bitsybitshareswallet.adapters.BalancesDetailsAdapter
|
||||||
|
@ -42,6 +41,8 @@ class FilterOptionsDialog : DialogFragment(), DatePickerFragment.OnDateSetListen
|
||||||
const val END_DATE_PICKER = 1
|
const val END_DATE_PICKER = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val viewModel: BalanceDetailViewModel by viewModels()
|
||||||
|
|
||||||
private var _binding: DialogFilterOptionsBinding? = null
|
private var _binding: DialogFilterOptionsBinding? = null
|
||||||
private val binding get() = _binding!!
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
|
@ -56,8 +57,6 @@ class FilterOptionsDialog : DialogFragment(), DatePickerFragment.OnDateSetListen
|
||||||
|
|
||||||
private var mBalanceDetails = ArrayList<BalanceDetail>()
|
private var mBalanceDetails = ArrayList<BalanceDetail>()
|
||||||
|
|
||||||
private lateinit var mBalanceDetailViewModel: BalanceDetailViewModel
|
|
||||||
|
|
||||||
private var mBalancesDetailsAdapter: BalancesDetailsAdapter? = null
|
private var mBalancesDetailsAdapter: BalancesDetailsAdapter? = null
|
||||||
|
|
||||||
private lateinit var mCurrency: Currency
|
private lateinit var mCurrency: Currency
|
||||||
|
@ -117,7 +116,7 @@ class FilterOptionsDialog : DialogFragment(), DatePickerFragment.OnDateSetListen
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
||||||
onAttachToParentFragment(parentFragment!!)
|
onAttachToParentFragment(requireParentFragment())
|
||||||
|
|
||||||
val crashlytics = FirebaseCrashlytics.getInstance()
|
val crashlytics = FirebaseCrashlytics.getInstance()
|
||||||
crashlytics.setCustomKey(Constants.CRASHLYTICS_KEY_LAST_SCREEN, TAG)
|
crashlytics.setCustomKey(Constants.CRASHLYTICS_KEY_LAST_SCREEN, TAG)
|
||||||
|
@ -150,31 +149,25 @@ class FilterOptionsDialog : DialogFragment(), DatePickerFragment.OnDateSetListen
|
||||||
binding.cbAsset.isChecked = mFilterOptions.assetAll
|
binding.cbAsset.isChecked = mFilterOptions.assetAll
|
||||||
|
|
||||||
// Configure BalanceDetailViewModel to obtain the user's Balances
|
// Configure BalanceDetailViewModel to obtain the user's Balances
|
||||||
mBalanceDetailViewModel =
|
viewModel.getAll().observe(viewLifecycleOwner, { balancesDetails ->
|
||||||
ViewModelProviders.of(this).get(BalanceDetailViewModel::class.java)
|
mBalanceDetails.clear()
|
||||||
|
mBalanceDetails.addAll(balancesDetails)
|
||||||
|
mBalanceDetails.sortWith { a, b -> a.toString().compareTo(b.toString(), true) }
|
||||||
|
mBalancesDetailsAdapter = BalancesDetailsAdapter(
|
||||||
|
requireContext(),
|
||||||
|
android.R.layout.simple_spinner_item,
|
||||||
|
mBalanceDetails
|
||||||
|
)
|
||||||
|
binding.sAsset.adapter = mBalancesDetailsAdapter
|
||||||
|
|
||||||
mBalanceDetailViewModel.getAll()
|
// Try to select the selectedAssetSymbol
|
||||||
.observe(this, Observer<List<BalanceDetail>> { balancesDetails ->
|
for (i in 0 until mBalancesDetailsAdapter!!.count) {
|
||||||
mBalanceDetails.clear()
|
if (mBalancesDetailsAdapter!!.getItem(i)!!.symbol == mFilterOptions.asset) {
|
||||||
mBalanceDetails.addAll(balancesDetails)
|
binding.sAsset.setSelection(i)
|
||||||
mBalanceDetails.sortWith(
|
break
|
||||||
Comparator { a, b -> a.toString().compareTo(b.toString(), true) }
|
|
||||||
)
|
|
||||||
mBalancesDetailsAdapter = BalancesDetailsAdapter(
|
|
||||||
context!!,
|
|
||||||
android.R.layout.simple_spinner_item,
|
|
||||||
mBalanceDetails
|
|
||||||
)
|
|
||||||
binding.sAsset.adapter = mBalancesDetailsAdapter
|
|
||||||
|
|
||||||
// Try to select the selectedAssetSymbol
|
|
||||||
for (i in 0 until mBalancesDetailsAdapter!!.count) {
|
|
||||||
if (mBalancesDetailsAdapter!!.getItem(i)!!.symbol == mFilterOptions.asset) {
|
|
||||||
binding.sAsset.setSelection(i)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
})
|
||||||
|
|
||||||
// Initialize Equivalent Value
|
// Initialize Equivalent Value
|
||||||
binding.cbEquivalentValue.setOnCheckedChangeListener { _, isChecked ->
|
binding.cbEquivalentValue.setOnCheckedChangeListener { _, isChecked ->
|
||||||
|
|
|
@ -6,16 +6,15 @@ import android.view.*
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.appcompat.widget.Toolbar
|
import androidx.appcompat.widget.Toolbar
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
|
import androidx.core.content.res.ResourcesCompat
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.fragment.app.FragmentManager
|
import androidx.fragment.app.FragmentManager
|
||||||
import androidx.fragment.app.FragmentPagerAdapter
|
import androidx.fragment.app.FragmentPagerAdapter
|
||||||
import androidx.lifecycle.Observer
|
import androidx.fragment.app.viewModels
|
||||||
import androidx.lifecycle.ViewModelProviders
|
|
||||||
import androidx.navigation.Navigation
|
import androidx.navigation.Navigation
|
||||||
import androidx.navigation.fragment.findNavController
|
import androidx.navigation.fragment.findNavController
|
||||||
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
||||||
import cy.agorise.bitsybitshareswallet.R
|
import cy.agorise.bitsybitshareswallet.R
|
||||||
import cy.agorise.bitsybitshareswallet.database.entities.UserAccount
|
|
||||||
import cy.agorise.bitsybitshareswallet.databinding.FragmentHomeBinding
|
import cy.agorise.bitsybitshareswallet.databinding.FragmentHomeBinding
|
||||||
import cy.agorise.bitsybitshareswallet.utils.Constants
|
import cy.agorise.bitsybitshareswallet.utils.Constants
|
||||||
import cy.agorise.bitsybitshareswallet.viewmodels.UserAccountViewModel
|
import cy.agorise.bitsybitshareswallet.viewmodels.UserAccountViewModel
|
||||||
|
@ -27,11 +26,11 @@ class HomeFragment : Fragment() {
|
||||||
private const val TAG = "HomeFragment"
|
private const val TAG = "HomeFragment"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val viewModel: UserAccountViewModel by viewModels()
|
||||||
|
|
||||||
private var _binding: FragmentHomeBinding? = null
|
private var _binding: FragmentHomeBinding? = null
|
||||||
private val binding get() = _binding!!
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
private lateinit var mUserAccountViewModel: UserAccountViewModel
|
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
inflater: LayoutInflater,
|
inflater: LayoutInflater,
|
||||||
container: ViewGroup?,
|
container: ViewGroup?,
|
||||||
|
@ -47,7 +46,8 @@ class HomeFragment : Fragment() {
|
||||||
// MerchantsFragment (visibility)
|
// MerchantsFragment (visibility)
|
||||||
val toolbar: Toolbar? = activity?.findViewById(R.id.toolbar)
|
val toolbar: Toolbar? = activity?.findViewById(R.id.toolbar)
|
||||||
(activity as AppCompatActivity).setSupportActionBar(toolbar)
|
(activity as AppCompatActivity).setSupportActionBar(toolbar)
|
||||||
toolbar?.navigationIcon = resources.getDrawable(R.drawable.ic_bitsy_logo_2, null)
|
toolbar?.navigationIcon =
|
||||||
|
ResourcesCompat.getDrawable(resources, R.drawable.ic_bitsy_logo_2, null)
|
||||||
toolbar?.setBackgroundResource(if (!nightMode) R.color.colorPrimary else R.color.colorToolbarDark)
|
toolbar?.setBackgroundResource(if (!nightMode) R.color.colorPrimary else R.color.colorToolbarDark)
|
||||||
toolbar?.visibility = View.VISIBLE
|
toolbar?.visibility = View.VISIBLE
|
||||||
toolbar?.title = getString(R.string.app_name)
|
toolbar?.title = getString(R.string.app_name)
|
||||||
|
@ -94,22 +94,19 @@ class HomeFragment : Fragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Configure UserAccountViewModel to show the current account
|
// Configure UserAccountViewModel to show the current account
|
||||||
mUserAccountViewModel = ViewModelProviders.of(this).get(UserAccountViewModel::class.java)
|
viewModel.getUserAccount(userId).observe(viewLifecycleOwner, { userAccount ->
|
||||||
|
if (userAccount != null) {
|
||||||
mUserAccountViewModel.getUserAccount(userId)
|
binding.tvAccountName.text = userAccount.name
|
||||||
.observe(this, Observer<UserAccount> { userAccount ->
|
if (userAccount.isLtm) {
|
||||||
if (userAccount != null) {
|
// Add the lightning bolt to the start of the account name if it is LTM
|
||||||
binding.tvAccountName.text = userAccount.name
|
binding.tvAccountName.setCompoundDrawablesWithIntrinsicBounds(
|
||||||
if (userAccount.isLtm) {
|
R.drawable.ic_ltm_account, 0, 0, 0
|
||||||
// Add the lightning bolt to the start of the account name if it is LTM
|
)
|
||||||
binding.tvAccountName.setCompoundDrawablesWithIntrinsicBounds(
|
// Add some padding so that the lightning bolt icon is not too close to the account name text
|
||||||
R.drawable.ic_ltm_account, 0, 0, 0
|
binding.tvAccountName.compoundDrawablePadding = 12
|
||||||
)
|
|
||||||
// Add some padding so that the lightning bolt icon is not too close to the account name text
|
|
||||||
binding.tvAccountName.compoundDrawablePadding = 12
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
})
|
||||||
|
|
||||||
// Navigate to the Receive Transaction Fragment
|
// Navigate to the Receive Transaction Fragment
|
||||||
binding.fabReceiveTransaction.setOnClickListener(
|
binding.fabReceiveTransaction.setOnClickListener(
|
||||||
|
@ -149,11 +146,11 @@ class HomeFragment : Fragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getPageTitle(position: Int): CharSequence {
|
override fun getPageTitle(position: Int): CharSequence {
|
||||||
return listOf(
|
return when (position) {
|
||||||
getString(R.string.title_balances),
|
0 -> getString(R.string.title_balances)
|
||||||
getString(R.string.title_net_worth),
|
1 -> getString(R.string.title_net_worth)
|
||||||
""
|
else -> ""
|
||||||
)[position]
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getCount(): Int {
|
override fun getCount(): Int {
|
||||||
|
|
|
@ -402,7 +402,7 @@ class ImportBrainkeyFragment : BaseAccountFragment() {
|
||||||
for (accountProperties in accountPropertiesList) {
|
for (accountProperties in accountPropertiesList) {
|
||||||
candidates.add(accountProperties.name)
|
candidates.add(accountProperties.name)
|
||||||
}
|
}
|
||||||
MaterialDialog(context!!)
|
MaterialDialog(requireContext())
|
||||||
.title(R.string.dialog__account_candidates_title)
|
.title(R.string.dialog__account_candidates_title)
|
||||||
.message(R.string.dialog__account_candidates_content)
|
.message(R.string.dialog__account_candidates_content)
|
||||||
.listItemsSingleChoice(
|
.listItemsSingleChoice(
|
||||||
|
|
|
@ -18,8 +18,7 @@ import androidx.appcompat.widget.Toolbar
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.cursoradapter.widget.SimpleCursorAdapter
|
import androidx.cursoradapter.widget.SimpleCursorAdapter
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.lifecycle.Observer
|
import androidx.fragment.app.viewModels
|
||||||
import androidx.lifecycle.ViewModelProviders
|
|
||||||
import com.afollestad.materialdialogs.MaterialDialog
|
import com.afollestad.materialdialogs.MaterialDialog
|
||||||
import com.afollestad.materialdialogs.customview.customView
|
import com.afollestad.materialdialogs.customview.customView
|
||||||
import com.google.android.gms.maps.CameraUpdateFactory
|
import com.google.android.gms.maps.CameraUpdateFactory
|
||||||
|
@ -73,13 +72,13 @@ class MerchantsFragment : Fragment(), OnMapReadyCallback, SearchView.OnSuggestio
|
||||||
private const val SUGGEST_COLUMN_IMAGE_RESOURCE = "suggest_image_resource"
|
private const val SUGGEST_COLUMN_IMAGE_RESOURCE = "suggest_image_resource"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val viewModel: MerchantViewModel by viewModels()
|
||||||
|
|
||||||
private var _binding: FragmentMerchantsBinding? = null
|
private var _binding: FragmentMerchantsBinding? = null
|
||||||
private val binding get() = _binding!!
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
private var mMap: GoogleMap? = null
|
private var mMap: GoogleMap? = null
|
||||||
|
|
||||||
private lateinit var mMerchantViewModel: MerchantViewModel
|
|
||||||
|
|
||||||
private var mMarkerManager: MarkerManager? = null
|
private var mMarkerManager: MarkerManager? = null
|
||||||
|
|
||||||
/** Keeps track of all RxJava disposables, to make sure they are all disposed when the fragment is destroyed */
|
/** Keeps track of all RxJava disposables, to make sure they are all disposed when the fragment is destroyed */
|
||||||
|
@ -166,8 +165,6 @@ class MerchantsFragment : Fragment(), OnMapReadyCallback, SearchView.OnSuggestio
|
||||||
val mapFragment = childFragmentManager.findFragmentById(R.id.map) as SupportMapFragment
|
val mapFragment = childFragmentManager.findFragmentById(R.id.map) as SupportMapFragment
|
||||||
mapFragment.getMapAsync(this)
|
mapFragment.getMapAsync(this)
|
||||||
|
|
||||||
mMerchantViewModel = ViewModelProviders.of(this).get(MerchantViewModel::class.java)
|
|
||||||
|
|
||||||
setupPopupWindow()
|
setupPopupWindow()
|
||||||
|
|
||||||
// Gets the screen width to correctly place the merchants and tellers popup menu
|
// Gets the screen width to correctly place the merchants and tellers popup menu
|
||||||
|
@ -245,12 +242,12 @@ class MerchantsFragment : Fragment(), OnMapReadyCallback, SearchView.OnSuggestio
|
||||||
|
|
||||||
private fun updateSearchViewSuggestions(query: String) {
|
private fun updateSearchViewSuggestions(query: String) {
|
||||||
// Obtain observable of the list of merchants matching the query
|
// Obtain observable of the list of merchants matching the query
|
||||||
val merchantsObs = mMerchantViewModel.queryMerchants(query)
|
val merchantsObs = viewModel.queryMerchants(query)
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.observeOn(AndroidSchedulers.mainThread()).toObservable()
|
.observeOn(AndroidSchedulers.mainThread()).toObservable()
|
||||||
|
|
||||||
// Obtain observable of the list of tellers matching the query
|
// Obtain observable of the list of tellers matching the query
|
||||||
val tellerObs = mMerchantViewModel.queryTellers(query)
|
val tellerObs = viewModel.queryTellers(query)
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.observeOn(AndroidSchedulers.mainThread()).toObservable()
|
.observeOn(AndroidSchedulers.mainThread()).toObservable()
|
||||||
|
|
||||||
|
@ -449,7 +446,10 @@ class MerchantsFragment : Fragment(), OnMapReadyCallback, SearchView.OnSuggestio
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun verifyLocationPermission() {
|
private fun verifyLocationPermission() {
|
||||||
if (ContextCompat.checkSelfPermission(activity!!, Manifest.permission.ACCESS_FINE_LOCATION)
|
if (ContextCompat.checkSelfPermission(
|
||||||
|
requireActivity(),
|
||||||
|
Manifest.permission.ACCESS_FINE_LOCATION
|
||||||
|
)
|
||||||
!= PackageManager.PERMISSION_GRANTED
|
!= PackageManager.PERMISSION_GRANTED
|
||||||
) {
|
) {
|
||||||
// Permission is not already granted
|
// Permission is not already granted
|
||||||
|
@ -482,7 +482,7 @@ class MerchantsFragment : Fragment(), OnMapReadyCallback, SearchView.OnSuggestio
|
||||||
// Force marker to use a custom info window
|
// Force marker to use a custom info window
|
||||||
mMerchantClusterManager?.markerCollection?.setOnInfoWindowAdapter(MerchantInfoWindowAdapter())
|
mMerchantClusterManager?.markerCollection?.setOnInfoWindowAdapter(MerchantInfoWindowAdapter())
|
||||||
|
|
||||||
mMerchantViewModel.getAllMerchants().observe(this, Observer<List<Merchant>> { merchants ->
|
viewModel.getAllMerchants().observe(viewLifecycleOwner, { merchants ->
|
||||||
this.merchants.clear()
|
this.merchants.clear()
|
||||||
this.merchants.addAll(merchants)
|
this.merchants.addAll(merchants)
|
||||||
showHideMerchantsMarkers()
|
showHideMerchantsMarkers()
|
||||||
|
@ -508,7 +508,7 @@ class MerchantsFragment : Fragment(), OnMapReadyCallback, SearchView.OnSuggestio
|
||||||
// Force marker to use a custom info window
|
// Force marker to use a custom info window
|
||||||
mTellerClusterManager?.markerCollection?.setOnInfoWindowAdapter(TellerInfoWindowAdapter())
|
mTellerClusterManager?.markerCollection?.setOnInfoWindowAdapter(TellerInfoWindowAdapter())
|
||||||
|
|
||||||
mMerchantViewModel.getAllTellers().observe(this, Observer<List<Teller>> { tellers ->
|
viewModel.getAllTellers().observe(viewLifecycleOwner, { tellers ->
|
||||||
this.tellers.clear()
|
this.tellers.clear()
|
||||||
this.tellers.addAll(tellers)
|
this.tellers.addAll(tellers)
|
||||||
showHideTellersMarkers()
|
showHideTellersMarkers()
|
||||||
|
|
|
@ -11,8 +11,7 @@ import android.widget.AdapterView
|
||||||
import androidx.appcompat.widget.Toolbar
|
import androidx.appcompat.widget.Toolbar
|
||||||
import androidx.collection.LongSparseArray
|
import androidx.collection.LongSparseArray
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.lifecycle.Observer
|
import androidx.fragment.app.viewModels
|
||||||
import androidx.lifecycle.ViewModelProviders
|
|
||||||
import com.google.common.primitives.UnsignedLong
|
import com.google.common.primitives.UnsignedLong
|
||||||
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
||||||
import com.jakewharton.rxbinding3.widget.textChanges
|
import com.jakewharton.rxbinding3.widget.textChanges
|
||||||
|
@ -52,11 +51,11 @@ class ReceiveTransactionFragment : ConnectedFragment() {
|
||||||
private const val OTHER_ASSET = "other_asset"
|
private const val OTHER_ASSET = "other_asset"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val viewModel: ReceiveTransactionViewModel by viewModels()
|
||||||
|
|
||||||
private var _binding: FragmentReceiveTransactionBinding? = null
|
private var _binding: FragmentReceiveTransactionBinding? = null
|
||||||
private val binding get() = _binding!!
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
private lateinit var mViewModel: ReceiveTransactionViewModel
|
|
||||||
|
|
||||||
/** Current user account */
|
/** Current user account */
|
||||||
private var mUserAccount: UserAccount? = null
|
private var mUserAccount: UserAccount? = null
|
||||||
|
|
||||||
|
@ -118,53 +117,49 @@ class ReceiveTransactionFragment : ConnectedFragment() {
|
||||||
crashlytics.setCustomKey(Constants.CRASHLYTICS_KEY_LAST_SCREEN, TAG)
|
crashlytics.setCustomKey(Constants.CRASHLYTICS_KEY_LAST_SCREEN, TAG)
|
||||||
|
|
||||||
// Configure ViewModel
|
// Configure ViewModel
|
||||||
mViewModel = ViewModelProviders.of(this).get(ReceiveTransactionViewModel::class.java)
|
|
||||||
|
|
||||||
val userId = PreferenceManager.getDefaultSharedPreferences(context)
|
val userId = PreferenceManager.getDefaultSharedPreferences(context)
|
||||||
.getString(Constants.KEY_CURRENT_ACCOUNT_ID, "")
|
.getString(Constants.KEY_CURRENT_ACCOUNT_ID, "")
|
||||||
|
|
||||||
mViewModel.getUserAccount(userId!!).observe(this,
|
viewModel.getUserAccount(userId!!).observe(viewLifecycleOwner, { user ->
|
||||||
Observer<cy.agorise.bitsybitshareswallet.database.entities.UserAccount> { user ->
|
mUserAccount = UserAccount(user.id, user.name)
|
||||||
mUserAccount = UserAccount(user.id, user.name)
|
})
|
||||||
})
|
|
||||||
|
|
||||||
mViewModel.getAllNonZero().observe(this,
|
viewModel.getAllNonZero().observe(viewLifecycleOwner, { assets ->
|
||||||
Observer<List<cy.agorise.bitsybitshareswallet.database.entities.Asset>> { assets ->
|
mAssets.clear()
|
||||||
mAssets.clear()
|
mAssets.addAll(assets)
|
||||||
mAssets.addAll(assets)
|
|
||||||
|
|
||||||
// Add BTS to always show a QR
|
// Add BTS to always show a QR
|
||||||
if (mAssets.isEmpty())
|
if (mAssets.isEmpty())
|
||||||
mAssets.add(
|
mAssets.add(
|
||||||
cy.agorise.bitsybitshareswallet.database.entities.Asset(
|
cy.agorise.bitsybitshareswallet.database.entities.Asset(
|
||||||
"1.3.0", "BTS", 5, "", ""
|
"1.3.0", "BTS", 5, "", ""
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
mAssets.sortWith(
|
|
||||||
Comparator { a, b -> a.toString().compareTo(b.toString(), true) }
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Add an option at the end so the user can search for an asset other than the ones saved in the db
|
mAssets.sortWith(
|
||||||
val asset = cy.agorise.bitsybitshareswallet.database.entities.Asset(
|
Comparator { a, b -> a.toString().compareTo(b.toString(), true) }
|
||||||
OTHER_ASSET, getString(R.string.text__other), 0, "", ""
|
)
|
||||||
)
|
|
||||||
mAssets.add(asset)
|
|
||||||
|
|
||||||
mAssetsAdapter =
|
// Add an option at the end so the user can search for an asset other than the ones saved in the db
|
||||||
AssetsAdapter(context!!, android.R.layout.simple_spinner_item, mAssets)
|
val asset = cy.agorise.bitsybitshareswallet.database.entities.Asset(
|
||||||
binding.spAsset.adapter = mAssetsAdapter
|
OTHER_ASSET, getString(R.string.text__other), 0, "", ""
|
||||||
|
)
|
||||||
|
mAssets.add(asset)
|
||||||
|
|
||||||
// Try to select the selectedAssetSymbol
|
mAssetsAdapter =
|
||||||
for (i in 0 until mAssetsAdapter!!.count) {
|
AssetsAdapter(requireContext(), android.R.layout.simple_spinner_item, mAssets)
|
||||||
if (mAssetsAdapter!!.getItem(i)!!.symbol == selectedAssetSymbol) {
|
binding.spAsset.adapter = mAssetsAdapter
|
||||||
binding.spAsset.setSelection(i)
|
|
||||||
break
|
// Try to select the selectedAssetSymbol
|
||||||
}
|
for (i in 0 until mAssetsAdapter!!.count) {
|
||||||
|
if (mAssetsAdapter!!.getItem(i)!!.symbol == selectedAssetSymbol) {
|
||||||
|
binding.spAsset.setSelection(i)
|
||||||
|
break
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
})
|
||||||
|
|
||||||
mViewModel.qrCodeBitmap.observe(this, Observer { bitmap ->
|
viewModel.qrCodeBitmap.observe(viewLifecycleOwner, { bitmap ->
|
||||||
binding.ivQR.setImageBitmap(bitmap)
|
binding.ivQR.setImageBitmap(bitmap)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -204,7 +199,7 @@ class ReceiveTransactionFragment : ConnectedFragment() {
|
||||||
|
|
||||||
// Add adapter to the Assets AutoCompleteTextView
|
// Add adapter to the Assets AutoCompleteTextView
|
||||||
mAutoSuggestAssetAdapter =
|
mAutoSuggestAssetAdapter =
|
||||||
AutoSuggestAssetAdapter(context!!, android.R.layout.simple_dropdown_item_1line)
|
AutoSuggestAssetAdapter(requireContext(), android.R.layout.simple_dropdown_item_1line)
|
||||||
binding.actvAsset.setAdapter(mAutoSuggestAssetAdapter)
|
binding.actvAsset.setAdapter(mAutoSuggestAssetAdapter)
|
||||||
|
|
||||||
// Use RxJava Debounce to avoid making calls to the NetworkService on every text change event and also avoid
|
// Use RxJava Debounce to avoid making calls to the NetworkService on every text change event and also avoid
|
||||||
|
@ -311,7 +306,7 @@ class ReceiveTransactionFragment : ConnectedFragment() {
|
||||||
)
|
)
|
||||||
Log.d(TAG, "invoice: " + invoice.toJsonString())
|
Log.d(TAG, "invoice: " + invoice.toJsonString())
|
||||||
try {
|
try {
|
||||||
mViewModel.updateInvoice(invoice, min(binding.ivQR.width, binding.ivQR.height))
|
viewModel.updateInvoice(invoice, min(binding.ivQR.width, binding.ivQR.height))
|
||||||
updateAmountAddressUI(amount, asset.symbol, asset.precision, mUserAccount!!.name)
|
updateAmountAddressUI(amount, asset.symbol, asset.precision, mUserAccount!!.name)
|
||||||
} catch (e: NullPointerException) {
|
} catch (e: NullPointerException) {
|
||||||
Log.e(TAG, "NullPointerException. Msg: " + e.message)
|
Log.e(TAG, "NullPointerException. Msg: " + e.message)
|
||||||
|
@ -366,7 +361,7 @@ class ReceiveTransactionFragment : ConnectedFragment() {
|
||||||
|
|
||||||
private fun verifyStoragePermission() {
|
private fun verifyStoragePermission() {
|
||||||
if (ContextCompat.checkSelfPermission(
|
if (ContextCompat.checkSelfPermission(
|
||||||
activity!!,
|
requireActivity(),
|
||||||
android.Manifest.permission.WRITE_EXTERNAL_STORAGE
|
android.Manifest.permission.WRITE_EXTERNAL_STORAGE
|
||||||
)
|
)
|
||||||
!= PackageManager.PERMISSION_GRANTED
|
!= PackageManager.PERMISSION_GRANTED
|
||||||
|
@ -411,7 +406,7 @@ class ReceiveTransactionFragment : ConnectedFragment() {
|
||||||
|
|
||||||
// Get Screenshot
|
// Get Screenshot
|
||||||
val screenshot = Helper.loadBitmapFromView(binding.container)
|
val screenshot = Helper.loadBitmapFromView(binding.container)
|
||||||
val imageUri = Helper.saveTemporalBitmap(context!!, screenshot)
|
val imageUri = Helper.saveTemporalBitmap(requireContext(), screenshot)
|
||||||
|
|
||||||
// Prepare information for share intent
|
// Prepare information for share intent
|
||||||
val subject = getString(R.string.msg__invoice_subject, mUserAccount?.name)
|
val subject = getString(R.string.msg__invoice_subject, mUserAccount?.name)
|
||||||
|
@ -428,4 +423,4 @@ class ReceiveTransactionFragment : ConnectedFragment() {
|
||||||
shareIntent.type = "*/*"
|
shareIntent.type = "*/*"
|
||||||
startActivity(Intent.createChooser(shareIntent, getString(R.string.text__share_with)))
|
startActivity(Intent.createChooser(shareIntent, getString(R.string.text__share_with)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,8 +12,7 @@ import android.widget.Toast
|
||||||
import androidx.appcompat.widget.Toolbar
|
import androidx.appcompat.widget.Toolbar
|
||||||
import androidx.collection.LongSparseArray
|
import androidx.collection.LongSparseArray
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.lifecycle.Observer
|
import androidx.fragment.app.viewModels
|
||||||
import androidx.lifecycle.ViewModelProviders
|
|
||||||
import androidx.navigation.fragment.findNavController
|
import androidx.navigation.fragment.findNavController
|
||||||
import androidx.navigation.fragment.navArgs
|
import androidx.navigation.fragment.navArgs
|
||||||
import com.afollestad.materialdialogs.MaterialDialog
|
import com.afollestad.materialdialogs.MaterialDialog
|
||||||
|
@ -74,13 +73,15 @@ class SendTransactionFragment : ConnectedFragment(), ZXingScannerView.ResultHand
|
||||||
private const val ACTION_SEND_TRANSFER = 1
|
private const val ACTION_SEND_TRANSFER = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
private var _binding: FragmentSendTransactionBinding? = null
|
|
||||||
private val binding get() = _binding!!
|
|
||||||
|
|
||||||
// Navigation AAC Safe Args
|
|
||||||
private val args: SendTransactionFragmentArgs by navArgs()
|
private val args: SendTransactionFragmentArgs by navArgs()
|
||||||
|
|
||||||
private lateinit var mViewModel: SendTransactionViewModel
|
// TODO consolidate ViewModels
|
||||||
|
private val viewModel: SendTransactionViewModel by viewModels()
|
||||||
|
|
||||||
|
private val balanceDetailViewModel: BalanceDetailViewModel by viewModels()
|
||||||
|
|
||||||
|
private var _binding: FragmentSendTransactionBinding? = null
|
||||||
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
/** Variables used in field's validation */
|
/** Variables used in field's validation */
|
||||||
private var isCameraPreviewVisible = false
|
private var isCameraPreviewVisible = false
|
||||||
|
@ -90,8 +91,6 @@ class SendTransactionFragment : ConnectedFragment(), ZXingScannerView.ResultHand
|
||||||
|
|
||||||
private var mBalancesDetails = ArrayList<BalanceDetail>()
|
private var mBalancesDetails = ArrayList<BalanceDetail>()
|
||||||
|
|
||||||
private lateinit var mBalanceDetailViewModel: BalanceDetailViewModel
|
|
||||||
|
|
||||||
private var mBalancesDetailsAdapter: BalancesDetailsAdapter? = null
|
private var mBalancesDetailsAdapter: BalancesDetailsAdapter? = null
|
||||||
|
|
||||||
/** Keeps track of the asset's symbol selected in the Asset spinner */
|
/** Keeps track of the asset's symbol selected in the Asset spinner */
|
||||||
|
@ -162,10 +161,8 @@ class SendTransactionFragment : ConnectedFragment(), ZXingScannerView.ResultHand
|
||||||
mUserAccount = UserAccount(userId)
|
mUserAccount = UserAccount(userId)
|
||||||
|
|
||||||
// Configure ViewModel
|
// Configure ViewModel
|
||||||
mViewModel = ViewModelProviders.of(this).get(SendTransactionViewModel::class.java)
|
viewModel.getWIF(userId, AuthorityType.ACTIVE.ordinal)
|
||||||
|
.observe(viewLifecycleOwner, { encryptedWIF ->
|
||||||
mViewModel.getWIF(userId, AuthorityType.ACTIVE.ordinal).observe(this,
|
|
||||||
Observer<String> { encryptedWIF ->
|
|
||||||
context?.let {
|
context?.let {
|
||||||
try {
|
try {
|
||||||
wifKey = CryptoUtils.decrypt(it, encryptedWIF)
|
wifKey = CryptoUtils.decrypt(it, encryptedWIF)
|
||||||
|
@ -186,31 +183,27 @@ class SendTransactionFragment : ConnectedFragment(), ZXingScannerView.ResultHand
|
||||||
binding.fabOpenCamera.setOnClickListener { if (isCameraPreviewVisible) stopCameraPreview() else verifyCameraPermission() }
|
binding.fabOpenCamera.setOnClickListener { if (isCameraPreviewVisible) stopCameraPreview() else verifyCameraPermission() }
|
||||||
|
|
||||||
// Configure BalanceDetailViewModel to show the current balances
|
// Configure BalanceDetailViewModel to show the current balances
|
||||||
mBalanceDetailViewModel =
|
balanceDetailViewModel.getAll().observe(viewLifecycleOwner, { balancesDetails ->
|
||||||
ViewModelProviders.of(this).get(BalanceDetailViewModel::class.java)
|
mBalancesDetails.clear()
|
||||||
|
mBalancesDetails.addAll(balancesDetails)
|
||||||
|
mBalancesDetails.sortWith(
|
||||||
|
Comparator { a, b -> a.toString().compareTo(b.toString(), true) }
|
||||||
|
)
|
||||||
|
mBalancesDetailsAdapter = BalancesDetailsAdapter(
|
||||||
|
requireContext(),
|
||||||
|
android.R.layout.simple_spinner_item,
|
||||||
|
mBalancesDetails
|
||||||
|
)
|
||||||
|
binding.spAsset.adapter = mBalancesDetailsAdapter
|
||||||
|
|
||||||
mBalanceDetailViewModel.getAll()
|
// Try to select the selectedAssetSymbol
|
||||||
.observe(this, Observer<List<BalanceDetail>> { balancesDetails ->
|
for (i in 0 until mBalancesDetailsAdapter!!.count) {
|
||||||
mBalancesDetails.clear()
|
if (mBalancesDetailsAdapter!!.getItem(i)!!.symbol == selectedAssetSymbol) {
|
||||||
mBalancesDetails.addAll(balancesDetails)
|
binding.spAsset.setSelection(i)
|
||||||
mBalancesDetails.sortWith(
|
break
|
||||||
Comparator { a, b -> a.toString().compareTo(b.toString(), true) }
|
|
||||||
)
|
|
||||||
mBalancesDetailsAdapter = BalancesDetailsAdapter(
|
|
||||||
context!!,
|
|
||||||
android.R.layout.simple_spinner_item,
|
|
||||||
mBalancesDetails
|
|
||||||
)
|
|
||||||
binding.spAsset.adapter = mBalancesDetailsAdapter
|
|
||||||
|
|
||||||
// Try to select the selectedAssetSymbol
|
|
||||||
for (i in 0 until mBalancesDetailsAdapter!!.count) {
|
|
||||||
if (mBalancesDetailsAdapter!!.getItem(i)!!.symbol == selectedAssetSymbol) {
|
|
||||||
binding.spAsset.setSelection(i)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
})
|
||||||
|
|
||||||
binding.spAsset.onItemSelectedListener = assetItemSelectedListener
|
binding.spAsset.onItemSelectedListener = assetItemSelectedListener
|
||||||
|
|
||||||
|
@ -387,7 +380,7 @@ class SendTransactionFragment : ConnectedFragment(), ZXingScannerView.ResultHand
|
||||||
|
|
||||||
/** Verifies if the user has already granted the Camera permission, if not the asks for it */
|
/** Verifies if the user has already granted the Camera permission, if not the asks for it */
|
||||||
private fun verifyCameraPermission() {
|
private fun verifyCameraPermission() {
|
||||||
if (ContextCompat.checkSelfPermission(activity!!, android.Manifest.permission.CAMERA)
|
if (ContextCompat.checkSelfPermission(requireActivity(), android.Manifest.permission.CAMERA)
|
||||||
!= PackageManager.PERMISSION_GRANTED
|
!= PackageManager.PERMISSION_GRANTED
|
||||||
) {
|
) {
|
||||||
// Permission is not already granted
|
// Permission is not already granted
|
||||||
|
@ -711,7 +704,7 @@ class SendTransactionFragment : ConnectedFragment(), ZXingScannerView.ResultHand
|
||||||
|
|
||||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
if (item.itemId == R.id.menu_info) {
|
if (item.itemId == R.id.menu_info) {
|
||||||
MaterialDialog(context!!).show {
|
MaterialDialog(requireContext()).show {
|
||||||
customView(R.layout.dialog_send_transaction_info, scrollable = true)
|
customView(R.layout.dialog_send_transaction_info, scrollable = true)
|
||||||
positiveButton(android.R.string.ok) { dismiss() }
|
positiveButton(android.R.string.ok) { dismiss() }
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ import android.view.ViewGroup
|
||||||
import androidx.appcompat.widget.Toolbar
|
import androidx.appcompat.widget.Toolbar
|
||||||
import androidx.collection.LongSparseArray
|
import androidx.collection.LongSparseArray
|
||||||
import androidx.core.content.res.ResourcesCompat
|
import androidx.core.content.res.ResourcesCompat
|
||||||
import androidx.lifecycle.ViewModelProviders
|
import androidx.fragment.app.viewModels
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import com.afollestad.materialdialogs.MaterialDialog
|
import com.afollestad.materialdialogs.MaterialDialog
|
||||||
import com.afollestad.materialdialogs.callbacks.onDismiss
|
import com.afollestad.materialdialogs.callbacks.onDismiss
|
||||||
|
@ -60,11 +60,11 @@ class SettingsFragment : ConnectedFragment(), BaseSecurityLockDialog.OnPINPatter
|
||||||
private const val RESPONSE_BROADCAST_TRANSACTION = 3
|
private const val RESPONSE_BROADCAST_TRANSACTION = 3
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val viewModel: SettingsFragmentViewModel by viewModels()
|
||||||
|
|
||||||
private var _binding: FragmentSettingsBinding? = null
|
private var _binding: FragmentSettingsBinding? = null
|
||||||
private val binding get() = _binding!!
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
private lateinit var mViewModel: SettingsFragmentViewModel
|
|
||||||
|
|
||||||
private var mUserAccount: UserAccount? = null
|
private var mUserAccount: UserAccount? = null
|
||||||
|
|
||||||
private var privateKey: String? = null
|
private var privateKey: String? = null
|
||||||
|
@ -119,19 +119,16 @@ class SettingsFragment : ConnectedFragment(), BaseSecurityLockDialog.OnPINPatter
|
||||||
.getString(Constants.KEY_CURRENT_ACCOUNT_ID, "") ?: ""
|
.getString(Constants.KEY_CURRENT_ACCOUNT_ID, "") ?: ""
|
||||||
|
|
||||||
// Configure ViewModel
|
// Configure ViewModel
|
||||||
mViewModel = ViewModelProviders.of(this).get(SettingsFragmentViewModel::class.java)
|
viewModel.getUserAccount(userId).observe(viewLifecycleOwner, { userAccount ->
|
||||||
|
if (userAccount != null) {
|
||||||
|
mUserAccount = UserAccount(userAccount.id, userAccount.name)
|
||||||
|
binding.btnUpgradeToLTM.isEnabled =
|
||||||
|
!userAccount.isLtm // Disable button if already LTM
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
mViewModel.getUserAccount(userId).observe(this,
|
viewModel.getWIF(userId, AuthorityType.ACTIVE.ordinal)
|
||||||
androidx.lifecycle.Observer<cy.agorise.bitsybitshareswallet.database.entities.UserAccount> { userAccount ->
|
.observe(viewLifecycleOwner, { encryptedWIF ->
|
||||||
if (userAccount != null) {
|
|
||||||
mUserAccount = UserAccount(userAccount.id, userAccount.name)
|
|
||||||
binding.btnUpgradeToLTM.isEnabled =
|
|
||||||
!userAccount.isLtm // Disable button if already LTM
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
mViewModel.getWIF(userId, AuthorityType.ACTIVE.ordinal).observe(this,
|
|
||||||
androidx.lifecycle.Observer<String> { encryptedWIF ->
|
|
||||||
context?.let {
|
context?.let {
|
||||||
try {
|
try {
|
||||||
privateKey = CryptoUtils.decrypt(it, encryptedWIF)
|
privateKey = CryptoUtils.decrypt(it, encryptedWIF)
|
||||||
|
@ -624,7 +621,7 @@ class SettingsFragment : ConnectedFragment(), BaseSecurityLockDialog.OnPINPatter
|
||||||
|
|
||||||
private fun removeAccount(context: Context) {
|
private fun removeAccount(context: Context) {
|
||||||
// Clears the database.
|
// Clears the database.
|
||||||
mViewModel.clearDatabase(context)
|
viewModel.clearDatabase(context)
|
||||||
|
|
||||||
// Clears the shared preferences.
|
// Clears the shared preferences.
|
||||||
val pref = PreferenceManager.getDefaultSharedPreferences(context)
|
val pref = PreferenceManager.getDefaultSharedPreferences(context)
|
||||||
|
|
|
@ -11,8 +11,7 @@ import androidx.appcompat.widget.SearchView
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.fragment.app.FragmentActivity
|
import androidx.fragment.app.FragmentActivity
|
||||||
import androidx.lifecycle.Observer
|
import androidx.fragment.app.viewModels
|
||||||
import androidx.lifecycle.ViewModelProviders
|
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import com.afollestad.materialdialogs.MaterialDialog
|
import com.afollestad.materialdialogs.MaterialDialog
|
||||||
import com.afollestad.materialdialogs.list.listItemsMultiChoice
|
import com.afollestad.materialdialogs.list.listItemsMultiChoice
|
||||||
|
@ -20,7 +19,6 @@ import com.google.firebase.crashlytics.FirebaseCrashlytics
|
||||||
import com.jakewharton.rxbinding3.appcompat.queryTextChangeEvents
|
import com.jakewharton.rxbinding3.appcompat.queryTextChangeEvents
|
||||||
import cy.agorise.bitsybitshareswallet.R
|
import cy.agorise.bitsybitshareswallet.R
|
||||||
import cy.agorise.bitsybitshareswallet.adapters.TransfersDetailsAdapter
|
import cy.agorise.bitsybitshareswallet.adapters.TransfersDetailsAdapter
|
||||||
import cy.agorise.bitsybitshareswallet.database.joins.TransferDetail
|
|
||||||
import cy.agorise.bitsybitshareswallet.databinding.FragmentTransactionsBinding
|
import cy.agorise.bitsybitshareswallet.databinding.FragmentTransactionsBinding
|
||||||
import cy.agorise.bitsybitshareswallet.models.FilterOptions
|
import cy.agorise.bitsybitshareswallet.models.FilterOptions
|
||||||
import cy.agorise.bitsybitshareswallet.utils.*
|
import cy.agorise.bitsybitshareswallet.utils.*
|
||||||
|
@ -42,11 +40,11 @@ class TransactionsFragment : Fragment(), FilterOptionsDialog.OnFilterOptionsSele
|
||||||
private const val REQUEST_WRITE_EXTERNAL_STORAGE_PERMISSION = 100
|
private const val REQUEST_WRITE_EXTERNAL_STORAGE_PERMISSION = 100
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val viewModel: TransactionsViewModel by viewModels()
|
||||||
|
|
||||||
private var _binding: FragmentTransactionsBinding? = null
|
private var _binding: FragmentTransactionsBinding? = null
|
||||||
private val binding get() = _binding!!
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
private lateinit var mViewModel: TransactionsViewModel
|
|
||||||
|
|
||||||
private var mDisposables = CompositeDisposable()
|
private var mDisposables = CompositeDisposable()
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
|
@ -74,31 +72,28 @@ class TransactionsFragment : Fragment(), FilterOptionsDialog.OnFilterOptionsSele
|
||||||
val userId = PreferenceManager.getDefaultSharedPreferences(context)
|
val userId = PreferenceManager.getDefaultSharedPreferences(context)
|
||||||
.getString(Constants.KEY_CURRENT_ACCOUNT_ID, "") ?: ""
|
.getString(Constants.KEY_CURRENT_ACCOUNT_ID, "") ?: ""
|
||||||
|
|
||||||
val transfersDetailsAdapter = TransfersDetailsAdapter(context!!)
|
val transfersDetailsAdapter = TransfersDetailsAdapter(requireContext())
|
||||||
binding.rvTransactions.adapter = transfersDetailsAdapter
|
binding.rvTransactions.adapter = transfersDetailsAdapter
|
||||||
binding.rvTransactions.layoutManager = LinearLayoutManager(context)
|
binding.rvTransactions.layoutManager = LinearLayoutManager(context)
|
||||||
|
|
||||||
// Configure TransactionsViewModel to fetch the transaction history
|
// Configure TransactionsViewModel to fetch the transaction history
|
||||||
mViewModel = ViewModelProviders.of(this).get(TransactionsViewModel::class.java)
|
viewModel.getFilteredTransactions(userId).observe(viewLifecycleOwner, { transactions ->
|
||||||
|
if (transactions.isEmpty()) {
|
||||||
|
binding.rvTransactions.visibility = View.GONE
|
||||||
|
binding.tvEmpty.visibility = View.VISIBLE
|
||||||
|
} else {
|
||||||
|
binding.rvTransactions.visibility = View.VISIBLE
|
||||||
|
binding.tvEmpty.visibility = View.GONE
|
||||||
|
|
||||||
mViewModel.getFilteredTransactions(userId).observe(this,
|
val shouldScrollUp = transactions.size - transfersDetailsAdapter.itemCount == 1
|
||||||
Observer<List<TransferDetail>> { transactions ->
|
transfersDetailsAdapter.replaceAll(transactions)
|
||||||
if (transactions.isEmpty()) {
|
|
||||||
binding.rvTransactions.visibility = View.GONE
|
|
||||||
binding.tvEmpty.visibility = View.VISIBLE
|
|
||||||
} else {
|
|
||||||
binding.rvTransactions.visibility = View.VISIBLE
|
|
||||||
binding.tvEmpty.visibility = View.GONE
|
|
||||||
|
|
||||||
val shouldScrollUp = transactions.size - transfersDetailsAdapter.itemCount == 1
|
// Scroll to the top only if the difference between old and new items is 1
|
||||||
transfersDetailsAdapter.replaceAll(transactions)
|
// which most likely means a new transaction was received/sent.
|
||||||
|
if (shouldScrollUp)
|
||||||
// Scroll to the top only if the difference between old and new items is 1
|
binding.rvTransactions.scrollToPosition(0)
|
||||||
// which most likely means a new transaction was received/sent.
|
}
|
||||||
if (shouldScrollUp)
|
})
|
||||||
binding.rvTransactions.scrollToPosition(0)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// Set custom touch listener to handle bounce/stretch effect
|
// Set custom touch listener to handle bounce/stretch effect
|
||||||
val bounceTouchListener = BounceTouchListener(binding.rvTransactions)
|
val bounceTouchListener = BounceTouchListener(binding.rvTransactions)
|
||||||
|
@ -118,7 +113,7 @@ class TransactionsFragment : Fragment(), FilterOptionsDialog.OnFilterOptionsSele
|
||||||
.map { it.queryText.toString().toLowerCase() }
|
.map { it.queryText.toString().toLowerCase() }
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.subscribe {
|
.subscribe {
|
||||||
mViewModel.setFilterQuery(it)
|
viewModel.setFilterQuery(it)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -133,7 +128,7 @@ class TransactionsFragment : Fragment(), FilterOptionsDialog.OnFilterOptionsSele
|
||||||
val args = Bundle()
|
val args = Bundle()
|
||||||
args.putParcelable(
|
args.putParcelable(
|
||||||
FilterOptionsDialog.KEY_FILTER_OPTIONS,
|
FilterOptionsDialog.KEY_FILTER_OPTIONS,
|
||||||
mViewModel.getFilterOptions()
|
viewModel.getFilterOptions()
|
||||||
)
|
)
|
||||||
filterOptionsDialog.arguments = args
|
filterOptionsDialog.arguments = args
|
||||||
filterOptionsDialog.show(childFragmentManager, "filter-options-tag")
|
filterOptionsDialog.show(childFragmentManager, "filter-options-tag")
|
||||||
|
@ -163,13 +158,13 @@ class TransactionsFragment : Fragment(), FilterOptionsDialog.OnFilterOptionsSele
|
||||||
* Gets called when the user selects some filter options in the [FilterOptionsDialog] and wants to apply them.
|
* Gets called when the user selects some filter options in the [FilterOptionsDialog] and wants to apply them.
|
||||||
*/
|
*/
|
||||||
override fun onFilterOptionsSelected(filterOptions: FilterOptions) {
|
override fun onFilterOptionsSelected(filterOptions: FilterOptions) {
|
||||||
mViewModel.applyFilterOptions(filterOptions)
|
viewModel.applyFilterOptions(filterOptions)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Verifies that the storage permission has been granted before attempting to generate the export options */
|
/** Verifies that the storage permission has been granted before attempting to generate the export options */
|
||||||
private fun verifyStoragePermission() {
|
private fun verifyStoragePermission() {
|
||||||
if (ContextCompat.checkSelfPermission(
|
if (ContextCompat.checkSelfPermission(
|
||||||
activity!!,
|
requireActivity(),
|
||||||
Manifest.permission.WRITE_EXTERNAL_STORAGE
|
Manifest.permission.WRITE_EXTERNAL_STORAGE
|
||||||
)
|
)
|
||||||
!= PackageManager.PERMISSION_GRANTED
|
!= PackageManager.PERMISSION_GRANTED
|
||||||
|
@ -205,7 +200,7 @@ class TransactionsFragment : Fragment(), FilterOptionsDialog.OnFilterOptionsSele
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showExportOptionsDialog() {
|
private fun showExportOptionsDialog() {
|
||||||
MaterialDialog(context!!).show {
|
MaterialDialog(requireContext()).show {
|
||||||
title(R.string.title_export_transactions)
|
title(R.string.title_export_transactions)
|
||||||
listItemsMultiChoice(
|
listItemsMultiChoice(
|
||||||
R.array.export_options,
|
R.array.export_options,
|
||||||
|
@ -228,7 +223,7 @@ class TransactionsFragment : Fragment(), FilterOptionsDialog.OnFilterOptionsSele
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
mViewModel.getFilteredTransactionsOnce()?.let { filteredTransactions ->
|
viewModel.getFilteredTransactionsOnce()?.let { filteredTransactions ->
|
||||||
if (exportPDF)
|
if (exportPDF)
|
||||||
activity?.let { PDFGeneratorTask(it).execute(filteredTransactions) }
|
activity?.let { PDFGeneratorTask(it).execute(filteredTransactions) }
|
||||||
|
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
buildscript {
|
buildscript {
|
||||||
|
|
||||||
ext {
|
ext {
|
||||||
kotlin_version = '1.4.30'
|
kotlin_version = '1.4.31'
|
||||||
nav_version = '2.1.0'
|
nav_version = '2.3.4'
|
||||||
}
|
}
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
|
|
Loading…
Reference in a new issue