You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

396 lines
15 KiB

4 years ago
// Copyright 2019-2020 The Hush developers
// Released under the GPLv3
package org.myhush.silentdragon
5 years ago
import android.annotation.SuppressLint
import android.app.Activity
4 years ago
import android.app.AlertDialog
import android.content.*
import android.net.Uri
import android.os.Build
5 years ago
import android.os.Bundle
5 years ago
import android.os.Handler
import androidx.constraintlayout.widget.ConstraintLayout
import com.google.android.material.snackbar.Snackbar
import androidx.core.text.HtmlCompat
import androidx.appcompat.app.AppCompatActivity
import android.text.Html
import android.util.Log
5 years ago
import android.view.Menu
import android.view.MenuItem
5 years ago
import android.widget.Button
import android.widget.ScrollView
5 years ago
import android.widget.TextView
import android.widget.Toast
import com.beust.klaxon.Klaxon
5 years ago
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.android.synthetic.main.content_main.*
import org.myhush.silentdragon.DataModel.ConnectionStatus
import org.myhush.silentdragon.DataModel.connStatus
import org.myhush.silentdragon.ui.AboutActivity
import org.myhush.silentdragon.ui.SettingsActivity
import java.text.DecimalFormat
class MainActivity : AppCompatActivity(),
TransactionItemFragment.OnFragmentInteractionListener,
UnconfirmedTxItemFragment.OnFragmentInteractionListener {
override fun onFragmentInteraction(uri: Uri) {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
5 years ago
override fun onCreate(savedInstanceState: Bundle?) {
//StrictMode.setThreadPolicy(StrictMode.ThreadPolicy.Builder().detectAll().penaltyLog().build()) // TESTING
5 years ago
super.onCreate(savedInstanceState)
5 years ago
title = getString(R.string.app_name)
5 years ago
setContentView(R.layout.activity_main)
setSupportActionBar(toolbar)
// When creating, clear all the data first
setMainStatus("")
5 years ago
DataModel.init()
btnConnect.setOnClickListener {
val intent = Intent(this, QrReaderActivity::class.java)
intent.putExtra("REQUEST_CODE",
QrReaderActivity.REQUEST_CONNDATA
)
startActivityForResult(intent,
QrReaderActivity.REQUEST_CONNDATA
)
5 years ago
}
btnReconnect.setOnClickListener {
ConnectionManager.refreshAllData()
}
4 years ago
btnHelp.setOnClickListener {
val dialogBuilder = AlertDialog.Builder(this)
dialogBuilder.setMessage(if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) Html.fromHtml(resources.getString(R.string.help_text), HtmlCompat.FROM_HTML_MODE_LEGACY) else Html.fromHtml(resources.getString(R.string.help_text)))
4 years ago
.setNegativeButton(resources.getString(R.string.ok), DialogInterface.OnClickListener {
dialog, id -> dialog.cancel()
})
val alert = dialogBuilder.create()
alert.setTitle(resources.getString(R.string.help))
alert.show()
}
5 years ago
swiperefresh.setOnRefreshListener {
ConnectionManager.refreshAllData()
5 years ago
}
txtMainBalanceUSD.setOnClickListener {
if(DataModel.selectedCurrency == "BTC")
Toast.makeText(applicationContext, "1 HUSH = ${DataModel.currencySymbols[DataModel.selectedCurrency]}${DecimalFormat(" #,##0.00000000")
.format(DataModel.currencyValues[DataModel.selectedCurrency])}", Toast.LENGTH_LONG).show()
else(
Toast.makeText(applicationContext, "1 HUSH = ${DataModel.currencySymbols[DataModel.selectedCurrency]}${DecimalFormat("#,##0.00")
.format(DataModel.currencyValues[DataModel.selectedCurrency])}", Toast.LENGTH_LONG).show()
)
}
5 years ago
bottomNav.setOnNavigationItemSelectedListener {
when(it.itemId) {
R.id.action_send -> {
val intent = Intent(this, SendActivity::class.java)
startActivity(intent)
return@setOnNavigationItemSelectedListener true
}
R.id.action_bal -> true
R.id.action_recieve -> {
val intent = Intent(this, ReceiveActivity::class.java)
startActivity(intent)
return@setOnNavigationItemSelectedListener true
}
else -> {
return@setOnNavigationItemSelectedListener false
}
}
}
loadSharedPref()
updateUI(false)
}
private fun loadSharedPref() {
var ref: SharedPreferences = getSharedPreferences("MainFile", 0)
DataModel.selectedCurrency = ref.getString("currency", "BTC").toString()
}
private fun setMainStatus(status: String) {
lblBalance.text = ""
txtMainBalanceUSD.text = ""
txtMainBalance.text = status
}
@SuppressLint("SetTextI18n")
private fun updateUI(updateTxns: Boolean) {
runOnUiThread {
Log.i(TAG, "Updating UI $updateTxns")
5 years ago
bottomNav.itemIconTintList = null
bottomNav.menu.findItem(R.id.action_bal)?.isChecked = true
when (connStatus) {
ConnectionStatus.DISCONNECTED -> {
setMainStatus(resources.getString(R.string.no_connection))
5 years ago
scrollViewTxns.visibility = ScrollView.GONE
layoutConnect.visibility = ConstraintLayout.VISIBLE
5 years ago
swiperefresh.isRefreshing = false
5 years ago
// Hide the reconnect button if there is no connection string
if (DataModel.getConnString(SilentDragonApp.appContext!!).isNullOrBlank() ||
5 years ago
DataModel.getSecret() == null) {
4 years ago
btnHelp.visibility = Button.VISIBLE
5 years ago
btnReconnect.visibility = Button.GONE
lblConnectionOr.visibility = TextView.GONE
} else {
4 years ago
btnHelp.visibility = Button.GONE
5 years ago
btnReconnect.visibility = Button.VISIBLE
lblConnectionOr.visibility = TextView.VISIBLE
}
// Disable the send and recieve buttons
bottomNav.menu.findItem(R.id.action_recieve).isEnabled = false
bottomNav.menu.findItem(R.id.action_send).isEnabled = false
if (updateTxns) {
Handler().post {
run {
addPastTransactions(DataModel.transactions)
}
5 years ago
}
}
}
ConnectionStatus.CONNECTING -> {
setMainStatus(resources.getString(R.string.connecting))
5 years ago
scrollViewTxns.visibility = ScrollView.GONE
layoutConnect.visibility = ConstraintLayout.GONE
5 years ago
swiperefresh.isRefreshing = true
// Disable the send and recieve buttons
bottomNav.menu.findItem(R.id.action_recieve).isEnabled = false
bottomNav.menu.findItem(R.id.action_send).isEnabled = false
}
ConnectionStatus.CONNECTED -> {
scrollViewTxns.visibility = ScrollView.VISIBLE
layoutConnect.visibility = ConstraintLayout.GONE
ConnectionManager.initCurrencies()
if (DataModel.mainResponseData == null) {
setMainStatus(resources.getString(R.string.loading))
} else {
val cur = DataModel.selectedCurrency
val price = DataModel.currencyValues[cur]?: 0.0
val bal = DataModel.mainResponseData?.balance ?: 0.0
val balText = DecimalFormat("#0.00000000").format(bal)
lblBalance.text = resources.getString(R.string.balance)
txtMainBalance.text = balText + " ${DataModel.mainResponseData?.tokenName} "
if(cur == "BTC")
txtMainBalanceUSD.text = "${DataModel.currencySymbols[cur]} " + DecimalFormat("0.00000000").format(bal * price)
else
txtMainBalanceUSD.text = "${DataModel.currencySymbols[cur]} " + DecimalFormat("#,##0.00").format(bal * price)
// Enable the send and recieve buttons
bottomNav.menu.findItem(R.id.action_recieve).isEnabled = true
bottomNav.menu.findItem(R.id.action_send).isEnabled = true
5 years ago
}
if (updateTxns) {
Handler().post {
run {
addPastTransactions(DataModel.transactions)
}
5 years ago
}
} else {
swiperefresh.isRefreshing = false
}
}
}
}
}
private fun addPastTransactions(txns: List<DataModel.TransactionItem>?) {
5 years ago
runOnUiThread {
val fragTx = supportFragmentManager.beginTransaction()
5 years ago
for (fr in supportFragmentManager.fragments) {
fragTx.remove(fr)
}
5 years ago
5 years ago
// If there are no transactions, make sure to commit the Tx, so existing items are removed, and just return
if (txns.isNullOrEmpty()) {
fragTx.commitAllowingStateLoss()
5 years ago
swiperefresh.isRefreshing = false
return@runOnUiThread
}
5 years ago
// Split all the transactions into confirmations = 0 and confirmations > 0
// Unconfirmed first
val unconfirmed = txns.filter { t -> t.confirmations == 0L }
if (unconfirmed.isNotEmpty()) {
for (tx in unconfirmed) {
fragTx.add(
txList.id ,
UnconfirmedTxItemFragment.newInstance(
Klaxon().toJsonString(tx),
""
),
5 years ago
"tag1"
)
}
}
5 years ago
// Add all confirmed transactions
val confirmed = txns.filter { t -> t.confirmations > 0L }
if (confirmed.isNotEmpty()) {
var oddeven = "odd"
for (tx in confirmed) {
fragTx.add(
txList.id,
TransactionItemFragment.newInstance(
Klaxon().toJsonString(tx),
oddeven
),
5 years ago
"tag1"
)
oddeven = if (oddeven == "odd") "even" else "odd"
}
5 years ago
}
5 years ago
fragTx.commitAllowingStateLoss()
5 years ago
swiperefresh.isRefreshing = false
}
}
5 years ago
override fun onCreateOptionsMenu(menu: Menu): Boolean {
// Inflate the menu; this adds items to the action bar if it is present.
menuInflater.inflate(R.menu.menu_main, menu)
return true
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when (item.itemId) {
R.id.action_settings -> {
val intent = Intent(this, SettingsActivity::class.java)
startActivity(intent)
return true
}
5 years ago
R.id.action_about -> {
val intent = Intent(this, AboutActivity::class.java)
startActivity(intent)
return true
}
5 years ago
R.id.action_refresh -> {
swiperefresh.isRefreshing = true
ConnectionManager.refreshAllData()
5 years ago
return true
}
5 years ago
else -> super.onOptionsItemSelected(item)
}
}
var mReceiver: BroadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
// We've received a signal
when(intent.getStringExtra("action")) {
"refresh" -> {
swiperefresh.isRefreshing = !intent.getBooleanExtra("finished", true)
}
"newdata" -> {
val updateTxns = intent.getBooleanExtra("updateTxns", false)
updateUI(updateTxns)
}
"error" -> {
val msg = intent.getStringExtra("msg")
if (!msg.isNullOrEmpty()) {
Snackbar.make(layoutConnect, msg, Snackbar.LENGTH_LONG).show()
}
// Also check if we need to disconnect
if (intent.getBooleanExtra("doDisconnect", false)) {
disconnected()
}
}
}
5 years ago
}
}
5 years ago
override fun onResume() {
super.onResume()
registerReceiver(mReceiver, IntentFilter(ConnectionManager.DATA_SIGNAL))
// On resuming, refresh all data
ConnectionManager.refreshAllData()
}
override fun onDestroy() {
unregisterReceiver(mReceiver)
super.onDestroy()
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
when(requestCode) {
QrReaderActivity.REQUEST_CONNDATA -> {
if (resultCode == Activity.RESULT_OK) {
Log.i(TAG, "Main Activity got result for QrCode: ${data?.dataString}")
5 years ago
// Check to make sure that the result is an actual address
if (!(data?.dataString ?: "").startsWith("ws")) {
Toast.makeText(applicationContext,
getString(R.string.is_not_a_valid_connection_string, data?.dataString), Toast.LENGTH_SHORT).show()
5 years ago
return
}
5 years ago
val conComponents = data?.dataString?.split(",")
if (conComponents?.size ?: 0 < 2 || conComponents?.size ?: 0 > 3) {
5 years ago
Toast.makeText(applicationContext,
getString(R.string.is_not_a_valid_connection_string, data?.dataString), Toast.LENGTH_SHORT).show()
5 years ago
return
}
val conString = conComponents!![0]
5 years ago
val secretHex = conComponents[1]
val allowInternetConnections = if (conComponents.size == 3) conComponents[2] == "1" else false
5 years ago
DataModel.setSecretHex(secretHex)
DataModel.setConnString(
conString,
applicationContext
)
DataModel.setAllowInternet(
allowInternetConnections
)
ConnectionManager.refreshAllData()
}
}
}
}
private fun disconnected() {
5 years ago
Log.i(TAG, "Disconnected")
connStatus = ConnectionStatus.DISCONNECTED
println("Connstatus = Disconnected")
DataModel.clear()
swiperefresh.isRefreshing = false
updateUI(true)
}
private val TAG = "MainActivity"
5 years ago
}