diff --git a/app/src/main/java/cy/agorise/bitsybitshareswallet/activities/ConnectedActivity.kt b/app/src/main/java/cy/agorise/bitsybitshareswallet/activities/ConnectedActivity.kt index 54ff0e2..5eb1c4d 100644 --- a/app/src/main/java/cy/agorise/bitsybitshareswallet/activities/ConnectedActivity.kt +++ b/app/src/main/java/cy/agorise/bitsybitshareswallet/activities/ConnectedActivity.kt @@ -18,6 +18,7 @@ import cy.agorise.bitsybitshareswallet.processors.TransfersLoader import cy.agorise.bitsybitshareswallet.repositories.AssetRepository import cy.agorise.bitsybitshareswallet.utils.Constants import cy.agorise.bitsybitshareswallet.viewmodels.BalanceViewModel +import cy.agorise.bitsybitshareswallet.viewmodels.TransferViewModel import cy.agorise.bitsybitshareswallet.viewmodels.UserAccountViewModel import cy.agorise.graphenej.Asset import cy.agorise.graphenej.AssetAmount @@ -27,12 +28,16 @@ import cy.agorise.graphenej.api.android.NetworkService import cy.agorise.graphenej.api.android.RxBus import cy.agorise.graphenej.api.calls.* import cy.agorise.graphenej.models.AccountProperties +import cy.agorise.graphenej.models.BlockHeader import cy.agorise.graphenej.models.FullAccountDetails import cy.agorise.graphenej.models.JsonRpcResponse import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.disposables.Disposable -import java.util.HashMap +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* import kotlin.collections.ArrayList +import kotlin.collections.HashMap /** * Class in charge of managing the connection to graphenej's NetworkService @@ -44,9 +49,11 @@ abstract class ConnectedActivity : AppCompatActivity(), ServiceConnection { private val RESPONSE_GET_ACCOUNTS = 2 private val RESPONSE_GET_ACCOUNT_BALANCES = 3 private val RESPONSE_GET_ASSETS = 4 + private val RESPONSE_GET_BLOCK_HEADER = 5 private lateinit var mUserAccountViewModel: UserAccountViewModel private lateinit var mBalanceViewModel: BalanceViewModel + private lateinit var mTransferViewModel: TransferViewModel private lateinit var mAssetRepository: AssetRepository @@ -69,6 +76,11 @@ abstract class ConnectedActivity : AppCompatActivity(), ServiceConnection { // Map used to keep track of request and response id pairs private val responseMap = HashMap() + /** Map used to keep track of request id and block number pairs */ + private val requestIdToBlockNumberMap = HashMap() + + private var blockNumberWithMissingTime = 0L + /** * Flag used to keep track of the NetworkService binding state */ @@ -110,6 +122,17 @@ abstract class ConnectedActivity : AppCompatActivity(), ServiceConnection { } }) + //Configure TransferViewModel to obtain the Transfer's block numbers with missing time information, one by one + mTransferViewModel = ViewModelProviders.of(this).get(TransferViewModel::class.java) + + mTransferViewModel.getTransferBlockNumberWithMissingTime().observe(this, Observer{ blockNumber -> + if (blockNumber != null && blockNumber != blockNumberWithMissingTime) { + blockNumberWithMissingTime = blockNumber + Log.d(TAG, "Block number: $blockNumber, Time: ${System.currentTimeMillis()}") + mHandler.postDelayed(mRequestBlockMissingTimeTask, 10) + } + }) + mDisposable = RxBus.getBusInstance() .asFlowable() .observeOn(AndroidSchedulers.mainThread()) @@ -136,6 +159,12 @@ abstract class ConnectedActivity : AppCompatActivity(), ServiceConnection { RESPONSE_GET_ASSETS -> handleAssets(message.result as List) + + RESPONSE_GET_BLOCK_HEADER -> { + val blockNumber = requestIdToBlockNumberMap[message.id] ?: 0L + handleBlockHeader(message.result as BlockHeader, blockNumber) + requestIdToBlockNumberMap.remove(message.id) + } } responseMap.remove(message.id) } @@ -245,6 +274,22 @@ abstract class ConnectedActivity : AppCompatActivity(), ServiceConnection { missingAssets.clear() } + /** + * Receives the [BlockHeader] related to a Transfer's missing time and saves it into the database. + */ + private fun handleBlockHeader(blockHeader: BlockHeader, blockNumber: Long) { + + val dateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.US) + dateFormat.timeZone = TimeZone.getTimeZone("GMT") + + try { + val date = dateFormat.parse(blockHeader.timestamp) + mTransferViewModel.setBlockTime(blockNumber, date.time / 1000) + } catch (e: ParseException) { + Log.e(TAG, "ParseException. Msg: " + e.message) + } + } + private fun updateBalances() { if (mNetworkService!!.isConnected) { val id = mNetworkService!!.sendMessage(GetAccountBalances(mCurrentAccount, ArrayList()), @@ -299,9 +344,26 @@ abstract class ConnectedActivity : AppCompatActivity(), ServiceConnection { responseMap[id] = RESPONSE_GET_FULL_ACCOUNTS } } else { - Log.w(TAG, "NetworkService is null or is not connected. mNetworkService: $mNetworkService") + mHandler.postDelayed(this, Constants.MISSING_PAYMENT_CHECK_PERIOD) + } + } + } + + /** + * Task used to obtain the missing time from a block from Graphenej's NetworkService. + */ + private val mRequestBlockMissingTimeTask = object : Runnable { + override fun run() { + + if (mNetworkService != null && mNetworkService!!.isConnected) { + val id = mNetworkService!!.sendMessage(GetBlockHeader(blockNumberWithMissingTime), + GetBlockHeader.REQUIRED_API) + + responseMap[id] = RESPONSE_GET_BLOCK_HEADER + requestIdToBlockNumberMap[id] = blockNumberWithMissingTime + } else { + mHandler.postDelayed(this, Constants.MISSING_PAYMENT_CHECK_PERIOD) } - mHandler.postDelayed(this, Constants.MISSING_PAYMENT_CHECK_PERIOD) } } diff --git a/app/src/main/java/cy/agorise/bitsybitshareswallet/database/daos/TransferDao.kt b/app/src/main/java/cy/agorise/bitsybitshareswallet/database/daos/TransferDao.kt index f61a9e5..63aeaee 100644 --- a/app/src/main/java/cy/agorise/bitsybitshareswallet/database/daos/TransferDao.kt +++ b/app/src/main/java/cy/agorise/bitsybitshareswallet/database/daos/TransferDao.kt @@ -17,12 +17,18 @@ interface TransferDao { @Insert(onConflict = OnConflictStrategy.IGNORE) fun insertAll(transfers: List) - @Query("SELECT COUNT(*) FROM transfers") - fun getCount(): Single + @Query("UPDATE transfers SET timestamp=:timestamp WHERE block_number=:blockNumber") + fun setBlockTime(blockNumber: Long, timestamp: Long) @Query("SELECT * FROM transfers") fun getAll(): LiveData> + @Query("SELECT COUNT(*) FROM transfers") + fun getCount(): Single + + @Query("SELECT block_number FROM transfers WHERE timestamp='0' LIMIT 1") + fun getTransferBlockNumberWithMissingTime(): LiveData + @Query("DELETE FROM transfers") fun deleteAll() } \ No newline at end of file diff --git a/app/src/main/java/cy/agorise/bitsybitshareswallet/processors/TransfersLoader.kt b/app/src/main/java/cy/agorise/bitsybitshareswallet/processors/TransfersLoader.kt index 13255b7..b099c54 100644 --- a/app/src/main/java/cy/agorise/bitsybitshareswallet/processors/TransfersLoader.kt +++ b/app/src/main/java/cy/agorise/bitsybitshareswallet/processors/TransfersLoader.kt @@ -7,9 +7,6 @@ import android.content.ServiceConnection import android.os.IBinder import android.preference.PreferenceManager import android.util.Log -import androidx.lifecycle.Lifecycle -import androidx.lifecycle.LifecycleObserver -import androidx.lifecycle.OnLifecycleEvent import cy.agorise.bitsybitshareswallet.database.entities.Transfer import cy.agorise.bitsybitshareswallet.models.HistoricalOperationEntry import cy.agorise.bitsybitshareswallet.repositories.AuthorityRepository diff --git a/app/src/main/java/cy/agorise/bitsybitshareswallet/repositories/TransferRepository.kt b/app/src/main/java/cy/agorise/bitsybitshareswallet/repositories/TransferRepository.kt index 9c27bd2..7f328d5 100644 --- a/app/src/main/java/cy/agorise/bitsybitshareswallet/repositories/TransferRepository.kt +++ b/app/src/main/java/cy/agorise/bitsybitshareswallet/repositories/TransferRepository.kt @@ -21,6 +21,10 @@ class TransferRepository internal constructor(context: Context) { insertAllAsyncTask(mTransferDao).execute(transfers) } + fun setBlockTime(blockNumber: Long, timestamp: Long) { + setBlockTimeAsyncTask(mTransferDao).execute(Pair(blockNumber, timestamp)) + } + fun getAll(): LiveData> { return mTransferDao.getAll() } @@ -29,6 +33,10 @@ class TransferRepository internal constructor(context: Context) { return mTransferDao.getCount() } + fun getTransferBlockNumberWithMissingTime(): LiveData { + return mTransferDao.getTransferBlockNumberWithMissingTime() + } + fun deleteAll() { deleteAllAsyncTask(mTransferDao).execute() } @@ -42,6 +50,15 @@ class TransferRepository internal constructor(context: Context) { } } + private class setBlockTimeAsyncTask internal constructor(private val mAsyncTaskDao: TransferDao) : + AsyncTask, Void, Void>() { + + override fun doInBackground(vararg pair: Pair): Void? { + mAsyncTaskDao.setBlockTime(pair[0].first, pair[0].second) + return null + } + } + private class deleteAllAsyncTask internal constructor(private val mAsyncTaskDao: TransferDao) : AsyncTask() { diff --git a/app/src/main/java/cy/agorise/bitsybitshareswallet/viewmodels/TransferViewModel.kt b/app/src/main/java/cy/agorise/bitsybitshareswallet/viewmodels/TransferViewModel.kt new file mode 100644 index 0000000..484d72c --- /dev/null +++ b/app/src/main/java/cy/agorise/bitsybitshareswallet/viewmodels/TransferViewModel.kt @@ -0,0 +1,18 @@ +package cy.agorise.bitsybitshareswallet.viewmodels + +import android.app.Application +import androidx.lifecycle.AndroidViewModel +import androidx.lifecycle.LiveData +import cy.agorise.bitsybitshareswallet.repositories.TransferRepository + +class TransferViewModel(application: Application) : AndroidViewModel(application) { + private var mRepository = TransferRepository(application) + + internal fun setBlockTime(blockNumber: Long, timestamp: Long) { + mRepository.setBlockTime(blockNumber, timestamp) + } + + internal fun getTransferBlockNumberWithMissingTime(): LiveData { + return mRepository.getTransferBlockNumberWithMissingTime() + } +} \ No newline at end of file