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.

439 lines
17 KiB

// Copyright 2019 The Hush developers
package org.myhush.silentdragon
6 years ago
import android.annotation.SuppressLint
import android.app.Activity
import android.app.AlertDialog
import android.content.*
import android.net.Uri
6 years ago
import android.os.Bundle
6 years ago
import android.os.Handler
import android.os.StrictMode
import android.support.constraint.ConstraintLayout
import android.support.design.widget.Snackbar
import android.support.v7.app.AppCompatActivity
import android.util.Log
6 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
6 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.chat.ChatActivity
import org.myhush.silentdragon.chat.Message
5 years ago
import org.myhush.silentdragon.chat.MessageType
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.
}
6 years ago
override fun onCreate(savedInstanceState: Bundle?) {
//StrictMode.setThreadPolicy(StrictMode.ThreadPolicy.Builder().detectAll().penaltyLog().build()) // TESTING
6 years ago
super.onCreate(savedInstanceState)
5 years ago
title = getString(R.string.app_name)
6 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
)
6 years ago
}
btnReconnect.setOnClickListener {
ConnectionManager.refreshAllData()
}
6 years ago
swiperefresh.setOnRefreshListener {
ConnectionManager.refreshAllData()
6 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()
}
6 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
5 years ago
R.id.action_chat -> {
val intent = Intent(this, ChatActivity::class.java)
6 years ago
startActivity(intent)
return@setOnNavigationItemSelectedListener true
}
5 years ago
R.id.action_recieve -> {
val intent = Intent(this, ReceiveActivity::class.java)
startActivity(intent)
return@setOnNavigationItemSelectedListener true
}
6 years ago
else -> {
return@setOnNavigationItemSelectedListener false
}
}
}
loadSharedPref()
updateUI(false)
/*///////////////////////////
// CREATE SAMPLE CONTACTS //
Addressbook.clear()
Addressbook.addContact("", "N1CK145", "zN1CK145")
Addressbook.addContact("", "Denio", "zDenio")
Addressbook.addContact("", "Max Mustermann", "zMaxMust")
// //
/////////////////////////// */
}
private fun loadSharedPref() {
var ref: SharedPreferences = getSharedPreferences("MainFile", 0)
DataModel.selectedCurrency = ref.getString("currency", "USD")!!
}
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")
6 years ago
bottomNav.itemIconTintList = null
bottomNav.menu.findItem(R.id.action_bal)?.isChecked = true
when (connStatus) {
ConnectionStatus.DISCONNECTED -> {
setMainStatus("No Connection")
5 years ago
scrollViewTxns.visibility = ScrollView.GONE
layoutConnect.visibility = ConstraintLayout.VISIBLE
6 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) {
5 years ago
btnReconnect.visibility = Button.GONE
lblConnectionOr.visibility = TextView.GONE
} else {
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)
}
6 years ago
}
}
}
ConnectionStatus.CONNECTING -> {
setMainStatus("Connecting...")
6 years ago
scrollViewTxns.visibility = ScrollView.GONE
layoutConnect.visibility = ConstraintLayout.GONE
6 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("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 = "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
6 years ago
}
if (updateTxns) {
Handler().post {
run {
addPastTransactions(DataModel.transactions)
}
6 years ago
}
} else {
swiperefresh.isRefreshing = false
}
}
}
}
}
private fun addPastTransactions(txns: List<DataModel.TransactionItem>?) {
6 years ago
runOnUiThread {
val fragTx = supportFragmentManager.beginTransaction()
// clear past messages
txns?.forEach {
5 years ago
Addressbook.findContactByInAddress(it.addr)?.messageList?.clear()
}
6 years ago
for (fr in supportFragmentManager.fragments) {
fragTx.remove(fr)
}
6 years ago
6 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()
6 years ago
swiperefresh.isRefreshing = false
return@runOnUiThread
}
5 years ago
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
val fixAdd= "zs12ehfu3pzj23z88up5wefn2psl5akc3m3ctpnmxmyxm4qx3vghlnq98dnu7sv0hdqgn3e20jq2rr"
val fixName = "Netterdon"
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6 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) {
if(tx.memo?.length == 0){
fragTx.add(
txList.id ,
UnconfirmedTxItemFragment.newInstance(
Klaxon().toJsonString(tx),
""
),
"tag1"
)
} else {
// test if contact exists
5 years ago
if(Addressbook.findContactByInAddress(tx.addr) == null)
Addressbook.addContact(fixName, tx.addr, fixAdd)
// add message
5 years ago
if(tx.type == "send")
Addressbook.findContactByInAddress(tx.addr)!!.messageList.add(Message(tx.addr, tx, MessageType.SEND))
else
Addressbook.findContactByInAddress(tx.addr)!!.messageList.add(Message(tx.addr, tx, MessageType.RECIEVE))
}
6 years ago
}
}
6 years ago
// Add all confirmed transactions
val confirmed = txns.filter { t -> t.confirmations > 0L }
if (confirmed.isNotEmpty()) {
var oddeven = "odd"
for (tx in confirmed) {
if(tx.memo?.length == 0){
fragTx.add(
txList.id,
TransactionItemFragment.newInstance(
Klaxon().toJsonString(tx),
oddeven
),
"tag1"
)
oddeven = if (oddeven == "odd") "even" else "odd"
} else {
// test if contact exists
5 years ago
if(Addressbook.findContactByInAddress(tx.addr) == null)
Addressbook.addContact(fixName, tx.addr, fixAdd)
// add message
5 years ago
if(tx.type == "send")
Addressbook.findContactByInAddress(tx.addr)!!.messageList.add(Message(tx.addr, tx, MessageType.SEND))
else
Addressbook.findContactByInAddress(tx.addr)!!.messageList.add(Message(tx.addr, tx, MessageType.RECIEVE))
}
6 years ago
}
6 years ago
}
6 years ago
fragTx.commitAllowingStateLoss()
6 years ago
swiperefresh.isRefreshing = false
}
}
6 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
}
6 years ago
R.id.action_refresh -> {
swiperefresh.isRefreshing = true
ConnectionManager.refreshAllData()
6 years ago
return true
}
6 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()
}
}
}
6 years ago
}
}
6 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}")
6 years ago
// Check to make sure that the result is an actual address
if (!(data?.dataString ?: "").startsWith("ws")) {
Toast.makeText(applicationContext,
5 years ago
"${data?.dataString} is not a valid connection string!", Toast.LENGTH_SHORT).show()
6 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,
5 years ago
"${data?.dataString} is not a valid connection string!", 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() {
6 years ago
Log.i(TAG, "Disconnected")
connStatus = ConnectionStatus.DISCONNECTED
println("Connstatus = Disconnected")
DataModel.clear()
swiperefresh.isRefreshing = false
updateUI(true)
}
private val TAG = "MainActivity"
6 years ago
}