Skip to content

Commit

Permalink
push
Browse files Browse the repository at this point in the history
  • Loading branch information
gmulhearn committed Sep 18, 2023
1 parent d7aabec commit 339f7ec
Show file tree
Hide file tree
Showing 5 changed files with 142 additions and 113 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
package org.hyperledger.ariesvcx

import android.util.Log
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import okhttp3.OkHttpClient
import okhttp3.Request
import org.hyperledger.ariesvcx.utils.await

data class AppUiState(
val profileReady: Boolean = false,
val connectionInvitationReceived: Boolean = false,
val connectionCompleted: Boolean = false
)

class AppDemoController : ViewModel() {
private val httpClient = OkHttpClient()

private var profile: ProfileHolder? = null
private var connection: Connection? = null

private var onConnectionComplete: (connection: Connection) -> Unit = {}

// Expose screen UI state
private val _state = MutableStateFlow(AppUiState())
val states: StateFlow<AppUiState> = _state.asStateFlow()

private val walletConfig = WalletConfig(
walletName = "test_create_wallet_add_uuid_here",
walletKey = "8dvfYSt5d1taSd6yJdpjq4emkwsPDDLYxkNFysFD2cZY",
walletKeyDerivation = "RAW",
walletType = null,
storageConfig = null,
storageCredentials = null,
rekey = null,
rekeyDerivationMethod = null
)

suspend fun setupProfile() {
withContext(Dispatchers.IO) {
val newProfile = newIndyProfile(walletConfig)
profile = newProfile
connection = createInvitee(newProfile)
}
_state.update { current ->
current.copy(profileReady = true)
}
}

suspend fun acceptConnectionInvitation(invitation: String) {
if (connection == null || profile == null) {
throw Exception("Connection or Profile is null")
}
withContext(Dispatchers.IO) {
connection!!.acceptInvitation(
profile = profile!!,
invitation = invitation
)
_state.update { it.copy(connectionInvitationReceived = true) }

connection!!.sendRequest(
profile!!,
"$BASE_RELAY_ENDPOINT/send_user_message/demo-user-1",
emptyList()
)

// use viewmodel scope to finish off this work
viewModelScope.launch(Dispatchers.IO) {
awaitConnectionCompletion()
}
}
}

private suspend fun awaitConnectionCompletion() {
val pollRelayRequest = Request.Builder()
.url("$BASE_RELAY_ENDPOINT/pop_user_message/demo-user-1")
.build()
while (true) {
delay(500)
val relayResponse = httpClient.newCall(pollRelayRequest).await()
if (relayResponse.code == 200) {
val message = relayResponse.body!!.string()

val unpackedMessage = unpackMessage(
profile!!,
message
)

Log.d("AppDemoController", unpackedMessage.message)
connection!!.handleResponse(profile!!, unpackedMessage.message)
connection!!.sendAck(profile!!)

Log.d("AppDemoController", "connection state: ${connection!!.getState()}")

_state.update { it.copy(connectionCompleted = true) }
onConnectionComplete(connection!!)
break
}
}
}

fun subscribeToConnectionComplete(onComplete: (connection: Connection) -> Unit) {
onConnectionComplete = onComplete
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package org.hyperledger.ariesvcx

// Set your public IP address here, this endpoint will be used while communicating with the peer(agent).
const val BASE_RELAY_ENDPOINT = "https://b199-27-57-116-96.ngrok-free.app";
const val BASE_RELAY_ENDPOINT = "https://0f6d-144-48-39-12.ngrok-free.app"
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
Expand All @@ -29,46 +30,22 @@ import org.hyperledger.ariesvcx.utils.await

@Composable
fun HomeScreen(
demoController: AppDemoController,
navController: NavHostController,
setProfileHolder: (ProfileHolder) -> Unit,
profileHolder: ProfileHolder?,
connection: Connection?,
walletConfig: WalletConfig,
connectionRequestState: Boolean,
httpClient: OkHttpClient
) {

val demoState by demoController.states.collectAsState()

val scope = rememberCoroutineScope()
val context = LocalContext.current

var flagKeepFetching by remember {
mutableStateOf(true)
}

val request = Request.Builder()
.url("$BASE_RELAY_ENDPOINT/pop_user_message/${walletConfig.walletKey}")
.build()


LaunchedEffect(true) {
scope.launch(Dispatchers.IO) {
while (flagKeepFetching && connectionRequestState) {
delay(500)
val response = httpClient.newCall(request).await()
if (response.code == 200) {
val message = response.body!!.string()

val unpackedMessage = unpackMessage(
profileHolder!!,
message
)

Log.d("HOMESCREEN", "HomeScreen: ${unpackedMessage.message}")
connection?.handleResponse(profileHolder, unpackedMessage.message)
flagKeepFetching = false
connection?.sendAck(profileHolder)
}
}
demoController.subscribeToConnectionComplete { newConn ->
scope.launch(Dispatchers.Main) {
Toast.makeText(
context,
"New Connection Created",
Toast.LENGTH_SHORT
).show()
}
}

Expand All @@ -78,27 +55,31 @@ fun HomeScreen(
verticalArrangement = Arrangement.Center
) {
Button(
enabled = (connection == null),
enabled = (!demoState.profileReady),
onClick = {
scope.launch(Dispatchers.IO) {
val profile = newIndyProfile(walletConfig)
setProfileHolder(profile)
scope.launch {
demoController.setupProfile()
withContext(Dispatchers.Main) {
Toast.makeText(
context,
"New Profile Created: $profile",
"New Profile Created",
Toast.LENGTH_SHORT
).show()
}
}
}) {
Text(text = "New Indy Profile")
}
Button(enabled = (profileHolder != null && connection != null),
Button(enabled = (demoState.profileReady && !demoState.connectionInvitationReceived),
onClick = {
navController.navigate(Destination.QRScan.route)
}) {
Text(text = "Scan QR Code")
}
Button(enabled = (demoState.connectionCompleted),
onClick = {
}) {
Text(text = "Receive a credential")
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,32 +26,6 @@ sealed class Destination(val route: String) {
}

class MainActivity : ComponentActivity() {
private var profile by mutableStateOf<ProfileHolder?>(null)
private var connection by mutableStateOf<Connection?>(null)
private var connectionRequestState by mutableStateOf(false)
private var httpClient = OkHttpClient()

private val walletConfig = WalletConfig(
walletName = "test_create_wallet_add_uuid_here",
walletKey = "8dvfYSt5d1taSd6yJdpjq4emkwsPDDLYxkNFysFD2cZY",
walletKeyDerivation = "RAW",
walletType = null,
storageConfig = null,
storageCredentials = null,
rekey = null,
rekeyDerivationMethod = null
)

private fun setProfileHolder(profileHolder: ProfileHolder) {
profile = profileHolder
connection = createInvitee(profileHolder)
}

private fun setConnectionRequestState() {
connectionRequestState = true
}


override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Os.setenv("EXTERNAL_STORAGE", this.filesDir.absolutePath, true)
Expand All @@ -63,14 +37,8 @@ class MainActivity : ComponentActivity() {
) {
val navController = rememberNavController()
NavigationAppHost(
demoController = AppDemoController(),
navController = navController,
setProfileHolder = { setProfileHolder(it) },
connection = connection,
profileHolder = profile,
walletConfig = walletConfig,
connectionRequestState = connectionRequestState,
setConnectionRequestState = { setConnectionRequestState() },
httpClient = httpClient
)
}
}
Expand All @@ -80,35 +48,21 @@ class MainActivity : ComponentActivity() {

@Composable
fun NavigationAppHost(
demoController: AppDemoController,
navController: NavHostController,
setProfileHolder: (ProfileHolder) -> Unit,
connection: Connection?,
profileHolder: ProfileHolder?,
walletConfig: WalletConfig,
connectionRequestState: Boolean,
setConnectionRequestState: () -> Unit,
httpClient: OkHttpClient,
) {
NavHost(navController = navController, startDestination = "home") {
composable(Destination.Home.route) {
HomeScreen(
demoController = demoController,
navController = navController,
setProfileHolder = setProfileHolder,
profileHolder = profileHolder,
connection = connection,
walletConfig = walletConfig,
connectionRequestState = connectionRequestState,
httpClient = httpClient
)
}

composable(Destination.QRScan.route) {
ScanScreen(
connection = connection!!,
profileHolder = profileHolder!!,
demoController = demoController,
navController = navController,
walletConfig = walletConfig,
setConnectionRequestState = setConnectionRequestState
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package org.hyperledger.ariesvcx
import android.Manifest
import android.content.pm.PackageManager
import android.net.Uri
import android.util.Size
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.camera.core.CameraSelector
Expand Down Expand Up @@ -40,11 +39,8 @@ import kotlinx.coroutines.withContext

@Composable
fun ScanScreen(
connection: Connection,
profileHolder: ProfileHolder,
demoController: AppDemoController,
navController: NavHostController,
walletConfig: WalletConfig,
setConnectionRequestState: () -> Unit
) {
var scannedQRCodeText by remember {
mutableStateOf<String?>(null)
Expand All @@ -67,18 +63,9 @@ fun ScanScreen(
text = { Text(decoded) },
confirmButton = {
TextButton(onClick = {
scope.launch(Dispatchers.IO) {
connection.acceptInvitation(
profile = profileHolder,
invitation = decoded
)
connection.sendRequest(
profileHolder,
"$BASE_RELAY_ENDPOINT/send_user_message/${walletConfig.walletKey}",
emptyList()
)
scope.launch {
demoController.acceptConnectionInvitation(decoded)
withContext(Dispatchers.Main) {
setConnectionRequestState()
navController.navigate("home")
}
}
Expand Down Expand Up @@ -130,12 +117,6 @@ fun ScanScreen(
.build()
preview.setSurfaceProvider(previewView.surfaceProvider)
val imageAnalysis = ImageAnalysis.Builder()
.setTargetResolution(
Size(
320,
480
)
)
.setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
.build()
imageAnalysis.setAnalyzer(
Expand Down

0 comments on commit 339f7ec

Please sign in to comment.