Add basic WebSocket connectivity with Dero node.
- Created a new stargate module that will contain the code to connect with the Dero nodes. This stargate module will use the ktor library, which is a multiplatform networking library that works on both Android and iOS. - Added a bassic connectivity with a Dero node. It just connects with the node, listens for messages, and prints them out to the standard output. - Introduced the ScreenModel library and created a basic ImportAccountScreenModel. ScreenModel classes serve to host all the logic for their corresponding screens. - Added the Internet permssion to the Android app, to be able to connect with the internet. - Removed the Desktop target. After discussing with Ken, we decided that investing on a Desktop app does not make sense. We will focus on Android and iOS only.
This commit is contained in:
parent
34c82ba8f6
commit
8b9727082a
11 changed files with 141 additions and 65 deletions
|
@ -1,5 +1,3 @@
|
|||
import org.jetbrains.compose.desktop.application.dsl.TargetFormat
|
||||
|
||||
plugins {
|
||||
alias(libs.plugins.kotlinMultiplatform)
|
||||
alias(libs.plugins.androidApplication)
|
||||
|
@ -15,8 +13,6 @@ kotlin {
|
|||
}
|
||||
}
|
||||
|
||||
jvm("desktop")
|
||||
|
||||
listOf(
|
||||
iosX64(),
|
||||
iosArm64(),
|
||||
|
@ -29,26 +25,39 @@ kotlin {
|
|||
}
|
||||
|
||||
sourceSets {
|
||||
val desktopMain by getting
|
||||
|
||||
androidMain.dependencies {
|
||||
implementation(libs.compose.ui.tooling.preview)
|
||||
implementation(libs.androidx.activity.compose)
|
||||
val androidMain by getting {
|
||||
dependencies {
|
||||
implementation(libs.compose.ui.tooling.preview)
|
||||
implementation(libs.androidx.activity.compose)
|
||||
}
|
||||
}
|
||||
commonMain.dependencies {
|
||||
implementation(projects.shared.preferences)
|
||||
|
||||
implementation(compose.components.resources)
|
||||
implementation(compose.components.uiToolingPreview)
|
||||
implementation(compose.foundation)
|
||||
implementation(compose.material3)
|
||||
implementation(compose.runtime)
|
||||
implementation(compose.ui)
|
||||
implementation(libs.voyager.navigator)
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.4.1")
|
||||
val commonMain by getting {
|
||||
commonMain.dependencies {
|
||||
implementation(projects.shared.preferences)
|
||||
implementation(projects.shared.stargate)
|
||||
|
||||
implementation(compose.components.resources)
|
||||
implementation(compose.components.uiToolingPreview)
|
||||
implementation(compose.foundation)
|
||||
implementation(compose.material3)
|
||||
implementation(compose.runtime)
|
||||
implementation(compose.ui)
|
||||
implementation(libs.coroutines.core)
|
||||
implementation(libs.voyager.navigator)
|
||||
implementation(libs.voyager.screenmodel)
|
||||
}
|
||||
}
|
||||
desktopMain.dependencies {
|
||||
implementation(compose.desktop.currentOs)
|
||||
|
||||
val iosX64Main by getting
|
||||
val iosArm64Main by getting
|
||||
val iosSimulatorArm64Main by getting
|
||||
val iosMain by creating {
|
||||
dependsOn(commonMain)
|
||||
iosX64Main.dependsOn(this)
|
||||
iosArm64Main.dependsOn(this)
|
||||
iosSimulatorArm64Main.dependsOn(this)
|
||||
dependencies {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -86,15 +95,3 @@ android {
|
|||
debugImplementation(libs.compose.ui.tooling)
|
||||
}
|
||||
}
|
||||
|
||||
compose.desktop {
|
||||
application {
|
||||
mainClass = "MainKt"
|
||||
|
||||
nativeDistributions {
|
||||
targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb)
|
||||
packageName = "net.agorise.kee"
|
||||
packageVersion = "1.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
|
|
|
@ -7,6 +7,7 @@ import androidx.compose.ui.Alignment
|
|||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import cafe.adriel.voyager.core.model.rememberScreenModel
|
||||
import cafe.adriel.voyager.core.screen.Screen
|
||||
import cafe.adriel.voyager.navigator.LocalNavigator
|
||||
import kee.composeapp.generated.resources.Res
|
||||
|
@ -22,9 +23,10 @@ import ui.theme.KeeTheme
|
|||
private const val RECOVERY_WORDS_COUNT = 25
|
||||
|
||||
class ImportAccountScreen : Screen {
|
||||
|
||||
@Composable
|
||||
override fun Content() = KeeTheme {
|
||||
val screenModel = rememberScreenModel { ImportAccountScreenModel() }
|
||||
|
||||
ImportAccountScreenContent()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
package net.agorise.kee.ui.screen.importaccount
|
||||
|
||||
import cafe.adriel.voyager.core.model.ScreenModel
|
||||
import cafe.adriel.voyager.core.model.screenModelScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.IO
|
||||
import kotlinx.coroutines.launch
|
||||
import net.agorise.shared.stargate.Bridge
|
||||
|
||||
class ImportAccountScreenModel : ScreenModel {
|
||||
private val bridge = Bridge()
|
||||
|
||||
init {
|
||||
screenModelScope.launch(Dispatchers.IO) {
|
||||
bridge.start()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDispose() {
|
||||
super.onDispose()
|
||||
bridge.stop()
|
||||
}
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
package net.agorise.kee
|
||||
|
||||
class JVMPlatform: Platform {
|
||||
override val name: String = "Java ${System.getProperty("java.version")}"
|
||||
}
|
||||
|
||||
actual fun getPlatform(): Platform = JVMPlatform()
|
|
@ -1,20 +0,0 @@
|
|||
package net.agorise.kee
|
||||
|
||||
import androidx.compose.ui.unit.DpSize
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.window.Window
|
||||
import androidx.compose.ui.window.WindowPosition
|
||||
import androidx.compose.ui.window.application
|
||||
import androidx.compose.ui.window.rememberWindowState
|
||||
import cafe.adriel.voyager.navigator.Navigator
|
||||
import net.agorise.kee.ui.screen.home.HomeScreen
|
||||
|
||||
fun main() = application {
|
||||
val state = rememberWindowState(
|
||||
size = DpSize(420.dp, 880.dp),
|
||||
position = WindowPosition(300.dp, 300.dp)
|
||||
)
|
||||
Window(title = "Kee", onCloseRequest = ::exitApplication, state = state) {
|
||||
Navigator(HomeScreen())
|
||||
}
|
||||
}
|
|
@ -4,9 +4,11 @@ android-compileSdk = "34"
|
|||
android-minSdk = "26"
|
||||
android-targetSdk = "34"
|
||||
androidx-activityCompose = "1.8.2"
|
||||
compose = "1.6.2"
|
||||
compose = "1.6.4"
|
||||
compose-plugin = "1.6.0"
|
||||
coroutines = "1.8.0"
|
||||
kotlin = "1.9.22"
|
||||
ktor = "2.3.9"
|
||||
multiplatform-settings = "1.1.1"
|
||||
voyager = "1.0.0"
|
||||
|
||||
|
@ -14,8 +16,13 @@ voyager = "1.0.0"
|
|||
androidx-activity-compose = { group = "androidx.activity", name ="activity-compose", version.ref = "androidx-activityCompose" }
|
||||
compose-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling", version.ref = "compose" }
|
||||
compose-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview", version.ref = "compose" }
|
||||
coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "coroutines" }
|
||||
ktor-client-cio = { group = "io.ktor", name = "ktor-client-cio", version.ref = "ktor" }
|
||||
ktor-client-core = { group = "io.ktor", name = "ktor-client-core", version.ref = "ktor" }
|
||||
ktor-client-websockets = { group = "io.ktor", name = "ktor-client-websockets", version.ref = "ktor" }
|
||||
multiplatform-settings = { group="com.russhwolf", name = "multiplatform-settings-no-arg", version.ref = "multiplatform-settings" }
|
||||
voyager-navigator = { group = "cafe.adriel.voyager", name = "voyager-navigator", version.ref = "voyager" }
|
||||
voyager-screenmodel = { group = "cafe.adriel.voyager", name = "voyager-screenmodel", version.ref = "voyager" }
|
||||
|
||||
[plugins]
|
||||
androidApplication = { id = "com.android.application", version.ref = "agp" }
|
||||
|
|
|
@ -20,3 +20,4 @@ dependencyResolutionManagement {
|
|||
|
||||
include(":composeApp")
|
||||
include(":shared:preferences")
|
||||
include(":shared:stargate")
|
||||
|
|
|
@ -12,8 +12,6 @@ kotlin {
|
|||
}
|
||||
}
|
||||
|
||||
jvm()
|
||||
|
||||
iosX64()
|
||||
iosArm64()
|
||||
iosSimulatorArm64()
|
||||
|
|
40
shared/stargate/build.gradle.kts
Normal file
40
shared/stargate/build.gradle.kts
Normal file
|
@ -0,0 +1,40 @@
|
|||
plugins {
|
||||
alias(libs.plugins.kotlinMultiplatform)
|
||||
alias(libs.plugins.androidLibrary)
|
||||
}
|
||||
|
||||
kotlin {
|
||||
androidTarget {
|
||||
compilations.all {
|
||||
kotlinOptions {
|
||||
jvmTarget = "11"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
iosX64()
|
||||
iosArm64()
|
||||
iosSimulatorArm64()
|
||||
|
||||
sourceSets {
|
||||
commonMain.dependencies {
|
||||
implementation(libs.ktor.client.cio)
|
||||
implementation(libs.ktor.client.core)
|
||||
implementation(libs.ktor.client.websockets)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "net.agorise.shared.stargate"
|
||||
compileSdk = libs.versions.android.compileSdk.get().toInt()
|
||||
|
||||
defaultConfig {
|
||||
minSdk = libs.versions.android.minSdk.get().toInt()
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility = JavaVersion.VERSION_11
|
||||
targetCompatibility = JavaVersion.VERSION_11
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package net.agorise.shared.stargate
|
||||
|
||||
import io.ktor.client.HttpClient
|
||||
import io.ktor.client.engine.cio.CIO
|
||||
import io.ktor.client.plugins.websocket.DefaultClientWebSocketSession
|
||||
import io.ktor.client.plugins.websocket.WebSockets
|
||||
import io.ktor.client.plugins.websocket.webSocket
|
||||
import io.ktor.http.HttpMethod
|
||||
import io.ktor.websocket.Frame
|
||||
import io.ktor.websocket.readText
|
||||
import kotlinx.coroutines.flow.receiveAsFlow
|
||||
|
||||
class Bridge {
|
||||
private val client: HttpClient = HttpClient(CIO) { install(WebSockets) }
|
||||
|
||||
suspend fun start() {
|
||||
client.webSocket(method = HttpMethod.Get, host = "node.derofoundation.org", port = 11012, path = "/ws") {
|
||||
outputMessages()
|
||||
}
|
||||
}
|
||||
|
||||
fun stop() {
|
||||
client.close()
|
||||
}
|
||||
|
||||
private suspend fun DefaultClientWebSocketSession.outputMessages() {
|
||||
incoming.receiveAsFlow().collect { message ->
|
||||
(message as? Frame.Text)?.let { textFrame ->
|
||||
println(textFrame.readText())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue