Skip to content

Commit

Permalink
refactor: bump uniffi, metadata direct fetch, etc (#9)
Browse files Browse the repository at this point in the history
* refactor: bump uniffi, metadata direct fetch, etc

* chore: make uniffi compilable again

* refactor: remove workspace

* fix: conform android to refactored uniffi types

* fix: it launches

* chore: default chains, temporarily block parallel stuff

* feat: minimal rpc address input

* feat: separate screen for network manager

* feat: separate screen for network manager

* chore: constructor for Key

* fix: network manager screen crash on key

* fix: parallel stuff properly, changed jsonrpsee to tungstenite

* feat: mwp siltti with bg network fetch

* chore: bump rustls library; no wss for now, only ws

---------

Co-authored-by: Slesarev <[email protected]>
  • Loading branch information
varovainen and Slesarew authored Jul 24, 2024
1 parent 1beab55 commit 491b7fb
Show file tree
Hide file tree
Showing 39 changed files with 3,031 additions and 1,577 deletions.
28 changes: 15 additions & 13 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -53,15 +53,16 @@ android {
pickFirsts += ['lib/arm64-v8a/libc++_shared.so', 'lib/x86_64/libc++_shared.so']
}
}
ndkVersion '24.0.8215888'
ndkVersion '27.0.12077973'
namespace 'fi.zymologia.siltti'
}

android.applicationVariants.configureEach { variant ->
def t = tasks.register("generate${variant.name.capitalize()}UniFFIBindings", Exec) {
workingDir "${project.projectDir}/../rust"
// Runs the bindings generation, note that you must have uniffi-bindgen installed and in your PATH environment variable
commandLine 'cargo', 'run', '--bin', 'uniffi-bindgen', 'generate', "${workingDir}/siltti/src/siltti.udl", '--language', 'kotlin', '--out-dir', "${buildDir}/generated/source/uniffi/${variant.name}/java"
commandLine 'cargo', 'build', '--release'
commandLine 'cargo', 'run', '--bin', 'uniffi-bindgen', 'generate', '--library', "${cargo.getTargetDirectory()}/aarch64-linux-android/release/libsiltti.so", '--language', 'kotlin', '--out-dir', "${buildDir}/generated/source/uniffi/${variant.name}/java"

}
variant.javaCompileProvider.get().dependsOn(t)
def sourceSet = variant.sourceSets.find { it.name == variant.name }
Expand All @@ -72,47 +73,48 @@ android.applicationVariants.configureEach { variant ->
apply plugin: 'org.mozilla.rust-android-gradle.rust-android'

cargo {
module = "../rust/siltti"
module = "../rust"
targetDirectory = "../rust/target"
libname = "siltti"
targets = ["arm64", "x86_64"]
apiLevel = 21
profile = 'release'
extraCargoBuildArguments = ["--locked"]
pythonCommand = "python3"
}

dependencies {

implementation 'androidx.core:core-ktx:1.10.1'
implementation 'androidx.core:core-ktx:1.12.0'
implementation "androidx.compose.ui:ui:$compose_version"
implementation "androidx.compose.material:material:$compose_version"
implementation "androidx.compose.ui:ui-tooling-preview:$compose_version"
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.6.1'
implementation 'androidx.activity:activity-compose:1.7.2'
implementation 'androidx.compose.runtime:runtime-livedata:1.5.0'
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.7.0'
implementation 'androidx.activity:activity-compose:1.8.2'
implementation 'androidx.compose.runtime:runtime-livedata:1.6.3'
implementation 'com.google.android.gms:play-services-mlkit-barcode-scanning:18.3.0'
implementation 'com.google.mlkit:barcode-scanning-common:17.0.0'
implementation 'com.google.mlkit:barcode-scanning:17.2.0'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3'
implementation 'androidx.work:work-runtime-ktx:2.8.1'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.8.0'
implementation 'androidx.work:work-runtime-ktx:2.9.0'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_version"
debugImplementation "androidx.compose.ui:ui-tooling:$compose_version"
debugImplementation "androidx.compose.ui:ui-test-manifest:$compose_version"
debugImplementation "androidx.compose.ui:ui-test-manifest:1.6.3"



def camerax_version = '1.3.0-rc01'
def camerax_version = '1.3.2'
implementation "androidx.camera:camera-core:${camerax_version}"
implementation "androidx.camera:camera-camera2:${camerax_version}"
implementation "androidx.camera:camera-lifecycle:${camerax_version}"
implementation "androidx.camera:camera-video:${camerax_version}"

implementation "androidx.camera:camera-view:${camerax_version}"
implementation "androidx.camera:camera-extensions:${camerax_version}"
implementation 'net.java.dev.jna:jna:5.13.0@aar'
implementation 'net.java.dev.jna:jna:5.14.0@aar'
}

preBuild.dependsOn "cargoBuild"
3 changes: 3 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,16 @@
<uses-feature android:name="android.hardware.nfc" android:required="true" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.NFC" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:networkSecurityConfig="@xml/network_security_config"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.Siltti">
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/java/fi/zymologia/siltti/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ class MainActivity : ComponentActivity() {
try {
action.makePacket()?.let {
Log.d("======> ", it.toString())
tech.transceive(it.toUByteArray().toByteArray())
tech.transceive(it)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
mainExecutor.execute { packagesSent.inc() }
}
Expand Down
55 changes: 30 additions & 25 deletions app/src/main/java/fi/zymologia/siltti/ScreenScaffold.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import androidx.compose.foundation.layout.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import fi.zymologia.siltti.screens.NetworkManager
import fi.zymologia.siltti.screens.ScanScreen
import fi.zymologia.siltti.screens.TXScreen
import fi.zymologia.siltti.uniffi.*
Expand All @@ -24,35 +25,37 @@ fun ScreenScaffold(
dbName: String,
count: State<Int?>,
counterReset: () -> Unit,
transmitCallback: (Action?) -> Unit
transmitCallback: (Action?) -> Unit,
) {
var appState by remember { mutableStateOf(Mode.Scan) }

val setAppState = { mode: Mode -> appState = mode }

Column(
Modifier
.fillMaxSize()
.fillMaxSize(),
) {
Box(
Modifier.padding(8.dp)
Modifier.padding(8.dp),
) {
// TODO: use all the cores needed to make this smooth
when (appState) {
Mode.Address -> {
fi.zymologia.siltti.screens.NewAddress(
setAppState,
transmitCallback,
dbName
dbName,
)
}
Mode.Scan -> {
ScanScreen(
dbName,
transmitCallback,
setAppState
setAppState,
)
}
Mode.Networks -> {
NetworkManager(dbName, setAppState)
}
Mode.TX -> {
TXScreen(transmitCallback, setAppState, count, counterReset)
}
Expand All @@ -64,44 +67,46 @@ fun ScreenScaffold(
enum class Mode {
Scan,
Address,
TX;
Networks,
TX,
}

class Signer : SignByCompanion {
@OptIn(ExperimentalUnsignedTypes::class)
override fun makeSignature(data: List<UByte>): List<UByte> {
val ks = KeyStore.getInstance("AndroidKeyStore").apply {
load(null)
}
override fun makeSignature(data: ByteArray): ByteArray {
val ks =
KeyStore.getInstance("AndroidKeyStore").apply {
load(null)
}

val ke = ks.getEntry("AndroidKeyStore", null)

if (ke !is KeyStore.PrivateKeyEntry) {
Log.w("", "Not an instance of a PrivateKeyEntry")
return emptyList()
return ByteArray(0)
}

val s = Signature.getInstance("SHA256withECDSA").apply {
initSign(ke.privateKey)
update(data.toUByteArray().toByteArray())
}
val s =
Signature.getInstance("SHA256withECDSA").apply {
initSign(ke.privateKey)
update(data)
}

val signature: ByteArray = s.sign()
return signature.toUByteArray().toList()
return s.sign()
}

@OptIn(ExperimentalUnsignedTypes::class)
override fun exportPublicKey(): List<UByte> {
val ks = KeyStore.getInstance("AndroidKeyStore").apply {
load(null)
}
override fun exportPublicKey(): ByteArray {
val ks =
KeyStore.getInstance("AndroidKeyStore").apply {
load(null)
}

val ke = ks.getEntry("AndroidKeyStore", null)

if (ke !is KeyStore.PrivateKeyEntry) {
Log.w("", "Not an instance of a PrivateKeyEntry")
return emptyList()
return ByteArray(0)
}
return ke.certificate.publicKey.encoded.toUByteArray().toList()
return ke.certificate.publicKey.encoded
}
}
7 changes: 7 additions & 0 deletions app/src/main/java/fi/zymologia/siltti/Utils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import fi.zymologia.siltti.screens.allPermissionsGranted
import fi.zymologia.siltti.uniffi.ChainKey
import fi.zymologia.siltti.uniffi.getAllKeys

fun Context.getActivity(): Activity = when (this) {
is Activity -> this
Expand Down Expand Up @@ -40,4 +42,9 @@ class PackagesSent : ViewModel() {
fun disable() {
_count.value = null
}
}

class Networks(dbPath: String) : ViewModel() {
private val _keys = MutableLiveData(getAllKeys(dbPath))
val keys: LiveData<List<ChainKey>> = _keys
}
37 changes: 18 additions & 19 deletions app/src/main/java/fi/zymologia/siltti/components/NetworkCard.kt
Original file line number Diff line number Diff line change
@@ -1,43 +1,42 @@
package fi.zymologia.siltti.components

import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.layout.*
import androidx.compose.material.Icon
import androidx.compose.material.Button
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Surface
import androidx.compose.material.Text
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.AddCircle
import androidx.compose.material.icons.filled.CheckCircle
import androidx.compose.material.icons.filled.Delete
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import fi.zymologia.siltti.uniffi.SpecsDisplay
import fi.zymologia.siltti.uniffi.SpecsKey

import fi.zymologia.siltti.uniffi.ChainKey
import fi.zymologia.siltti.uniffi.deleteByKey
import fi.zymologia.siltti.uniffi.requestUpdateByKey

@OptIn(ExperimentalFoundationApi::class)
@Composable
fun NetworkCard(
networks: MutableState<SpecsDisplay>,
key: SpecsKey
key: ChainKey,
dbName: String,
) {
Surface(
color = MaterialTheme.colors.primary,
modifier = Modifier
.fillMaxWidth()
.padding(10.dp)
modifier =
Modifier
.fillMaxWidth()
.padding(10.dp),
) {
Row(
horizontalArrangement = Arrangement.SpaceBetween,
modifier = Modifier.padding(10.dp)
modifier = Modifier.padding(10.dp),
) {
Text(
networks.value.title(key) ?: "unknown",
color = MaterialTheme.colors.onPrimary
key.substring(0, 64),
color = MaterialTheme.colors.onPrimary,
modifier = Modifier.combinedClickable(onClick = { requestUpdateByKey(key, dbName) }, onLongClick = { deleteByKey(key, dbName) }),
)
Text("Version: " + (networks.value.version(key) ?: "metadata unknown"))
// Text("Version: " + "PUT NETWORK VERSION HERE")
}
}
}
86 changes: 86 additions & 0 deletions app/src/main/java/fi/zymologia/siltti/screens/NetworkManager.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package fi.zymologia.siltti.screens

import android.annotation.SuppressLint
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material.Button
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.material.TextField
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.lifecycle.LiveData
import androidx.lifecycle.Observer
import fi.zymologia.siltti.Mode
import fi.zymologia.siltti.components.NetworkCard
import fi.zymologia.siltti.uniffi.ChainKey
import fi.zymologia.siltti.uniffi.getAllKeys
import fi.zymologia.siltti.uniffi.isUpdated
import fi.zymologia.siltti.uniffi.requestDefaults
import fi.zymologia.siltti.uniffi.requestFullFetch
import kotlinx.coroutines.delay

@SuppressLint("UnrememberedMutableState")
@Composable
fun NetworkManager(
dbName: String,
setAppState: (Mode) -> Unit,
) {
val rpcServer = remember { mutableStateOf("") }

val chainKeys = mutableStateOf(getAllKeys(dbName)) // Yes, I want it recomposed every time for now

val updated = remember { mutableStateOf(false) }

LaunchedEffect(updated.value) {
while (!isUpdated(dbName)) {
delay(1000)
}
chainKeys.value = getAllKeys(dbName)
updated.value = !updated.value
}
LazyColumn {
item {
Button(
onClick = {
requestDefaults();
},
) {
Text("Add defaults!")
}
}
item{
Text("Available networks", style = MaterialTheme.typography.h4)
}
this.items(
items = chainKeys.value,
key = { it },
) { key ->
NetworkCard(key, dbName)
}
item {
TextField(value = rpcServer.value, onValueChange = { rpcServer.value = it })
}
item {
Button(
onClick = {
requestFullFetch(rpcServer.value)
},
) {
Text("Add new network")
}
}
item {
Button(
onClick = {
setAppState(Mode.Scan)
},
) {
Text("Back to scan")
}
}
}
}
Loading

0 comments on commit 491b7fb

Please sign in to comment.