import android.util.Base64
data class NtruUiState(
val isLoading: Boolean = false,
val error: Throwable? = null,
val message: String = "",
val encrypted: NtruData = NtruData(),
val decrypted: NtruData = NtruData(),
val qrCode: QRCode? = null
)
class EncryptedData(
val message: String,
val encrypted: ByteArray,
val qrCode: QRCode
)
@JvmInline
value class NtruData(val data: ByteArray = ByteArray(0)) {
fun text() = String(data)
fun base64Encoded(): String {
return Base64.encodeToString(data, Base64.DEFAULT)//.substring(0, 20)
}
}
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
class NtruUiStateHolder {
private var state = NtruUiState()
private val mutableUiState = MutableLiveData(state)
val uiState: LiveData<NtruUiState> get() = mutableUiState
fun encryptedBytes(): ByteArray {
return state.encrypted.data
}
fun postEncrypted(data: EncryptedData) {
postEncrypted(message = data.message, encrypted = data.encrypted, qrCode = data.qrCode)
}
private fun postEncrypted(message: String, encrypted: ByteArray, qrCode: QRCode) {
val newState = updatedState(
isLoading = false,
error = null,
message = message,
encrypted = encrypted,
decrypted = ByteArray(0),
qrCode = qrCode
)
mutableUiState.postValue(newState)
}
fun postDecrypted(decrypted: ByteArray) {
mutableUiState.postValue(
updatedState(
isLoading = false,
error = null,
decrypted = decrypted
)
)
}
private fun updatedState(
isLoading: Boolean = state.isLoading,
error: Throwable? = state.error,
message: String = state.message,
encrypted: ByteArray = state.encrypted.data,
decrypted: ByteArray = state.decrypted.data,
qrCode: QRCode? = state.qrCode
): NtruUiState {
return state.copy(
isLoading = isLoading,
error = error,
message = message,
encrypted = NtruData(encrypted),
decrypted = NtruData(decrypted),
qrCode = qrCode
).also {
state = it
}
}
fun postError(e: Throwable) {
mutableUiState.postValue(updatedState(error = e))
}
fun postLoading(isLoading: Boolean) {
mutableUiState.postValue(updatedState(isLoading = isLoading))
}
}
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.isVisible
import androidx.lifecycle.ViewModelProvider
import com.remind.sampleapp.databinding.ActivityNtruBinding
class NtruActivity : AppCompatActivity() {
private val viewModel: NtruViewModel by lazy { ViewModelProvider(this)[NtruViewModel::class.java] }
private val binding by lazy { ActivityNtruBinding.inflate(layoutInflater) }
private val msg: String
get() = binding.messageEdt.text.toString()
/** Called when the activity is first created. */
public override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
setupView()
observeUiState()
}
private fun setupView() {
binding.apply {
encryptBtn.setOnClickListener {
runEncryption()
}
decryptBtn.setOnClickListener {
runDecryption()
}
}
}
private fun observeUiState() {
viewModel.uiState.observe(this, ::updateUi)
}
private fun updateUi(state: NtruUiState) {
bindLoading(state.isLoading)
bindError(state.error)
bindEncryptedData(state)
}
private fun bindLoading(loading: Boolean) {
binding.progressBar.isVisible = loading
}
private fun bindError(error: Throwable?) {
error ?: return
binding.encryptTxt.text = error.localizedMessage
}
private fun bindEncryptedData(state: NtruUiState) {
if (state.message.isBlank()) return
binding.apply {
encryptTxt.text = state.encrypted.base64Encoded()
decryptTxt.text = state.decrypted.text()
}
bindQrCode(state.qrCode)
}
private fun bindQrCode(qrCode: QRCode?) {
qrCode ?: return
binding.qrcodeImg.setImageBitmap(qrCode.bitmap())
}
private fun runEncryption() {
viewModel.encrypt(msg)
}
private fun runDecryption() {
viewModel.decrypt()
}
}
도움이 되시길...