Skip to content

Commit

Permalink
UI branch - Draft PR (#36)
Browse files Browse the repository at this point in the history
* Attempts to load image in iOS

* [Splash] Animation

* Onboarding page

* Nav module

* Bottom Tab bar nav - with Placeholder screens

* Profile, Bisq URL screen - UI

* Exchange screen - UI

* Home screen

* Theme - Colors, Typography classes

* Implemented Theme colors, Typography classes across other screens

* Components: Layout, Button, Logo; Font adjustments in inital setup screens

* MVP pattern for Splash, Onboarding, GettingStarted screens

* i18n - Done in splash screen with lyricist package

* Resources - Cleanup

* All images converted to PNG, tested in both iOS, Android and removed coil3 lib dependency

* First code review corrections 1/2

* i18n Improvements

- Script to convert translation keys, values from bisq2 app to mobile app lyricist structure
- Translation strings in onboarding screens
- Key, Values updated for all strings used in bisq2's application module.

* Code review corrections 2/2
 - Made use of Koin DI in SplashScreen, OnboardingScreen, GettingStartedScreen
 - /screens to /uicases/*

* Code review corrections 3/n (This partial commit fails in android)

- Better data models and repositories in 'domain'
- Better DI usage with screens and presenters, by moving navControllers into DI (But having some issue now, which stops tab based nav from working. RootNavGraph, TabNavGraph probably need some refactor)
- Few other minor feedback corrections

* - fix compilation issue (in kotlin getters are not necessary, making fields public already generates those

* - fix runtime crashes by specifying which nav controller to get (to be reviewed by buddha)

* - fix compose example test compilation errors

* - upgrading gradle wrapper to 8.11 to get the gradle config cache fixes and improvements. This fixes the build issue on this branch

* - referencing new sub readme doc from main readme (navigation docs)

* - reverting cocoapods downgrade

* NetworkRepository improvement - Partial

* [added] CreateProfilePresenter

* [added] TrustedNodeSetupPresenter

* - i18n: revert to English

* - added presenter hierarchy to propagate lifecycle events to all presenters + small nits

* - using iOS notification center for a more precise onResume() behaviour

---------

Co-authored-by: Rodrigo Varela <[email protected]>
  • Loading branch information
nostrbuddha and rodvar authored Nov 17, 2024
1 parent 6415a67 commit d584cff
Show file tree
Hide file tree
Showing 88 changed files with 3,952 additions and 288 deletions.
9 changes: 8 additions & 1 deletion bisqapps/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,21 @@ Addicionally, for the `androidNode` module to build you need to have its depende

Done! Alternatively if you are interested only in contributing for the `xClients` you can just build them individually instead of building the whole project.

### UI Designs
### UI

**Designs**

androidNode + xClient screens are designed in Figma.
Yet to differentiate between which screens goes into which.

Figma link: https://www.figma.com/design/IPnuicxGKIZXq28gybxOgp/Xchange?node-id=7-759&t=LV9Gx9XgJRvXu5YQ-1

Though the figma design captures most of the functionality, it's an evolving document. It will be updated with new screens, flow updates, based on discussions happening in GH issues / matrix.

**Navigation Implementation**

Please refer to [this README](shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/navigation/README.md)

### Configuring dev env: known issues

- Some Apple M chips have trouble with cocoapods, follow [this guide](https://stackoverflow.com/questions/64901180/how-to-run-cocoapods-on-apple-silicon-m1/66556339#66556339) to fix it
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,7 @@ package network.bisq.mobile.android.node.presentation

import android.app.Activity
import android.os.Build
import network.bisq.mobile.presentation.MainPresenter
import bisq.common.facades.FacadeProvider
import bisq.common.facades.android.AndroidGuavaFacade
import bisq.common.facades.android.AndroidJdkFacade
import bisq.common.network.AndroidEmulatorLocalhostFacade
import org.bouncycastle.jce.provider.BouncyCastleProvider
import java.security.Security
import android.os.Process
import network.bisq.mobile.android.node.domain.model.UserProfileModel
import bisq.common.observable.Observable
import bisq.user.identity.UserIdentityService
import bisq.application.State
import bisq.bonded_roles.market_price.MarketPrice
import bisq.chat.ChatChannelDomain
Expand All @@ -21,8 +11,13 @@ import bisq.chat.common.CommonPublicChatMessage
import bisq.chat.two_party.TwoPartyPrivateChatChannel
import bisq.chat.two_party.TwoPartyPrivateChatMessage
import bisq.common.currency.MarketRepository
import bisq.common.facades.FacadeProvider
import bisq.common.facades.android.AndroidGuavaFacade
import bisq.common.facades.android.AndroidJdkFacade
import bisq.common.locale.LanguageRepository
import bisq.common.network.AndroidEmulatorLocalhostFacade
import bisq.common.network.TransportType
import bisq.common.observable.Observable
import bisq.common.observable.Pin
import bisq.common.observable.collection.CollectionObserver
import bisq.common.timer.Scheduler
Expand All @@ -34,16 +29,20 @@ import bisq.security.DigestUtil
import bisq.security.SecurityService
import bisq.user.identity.NymIdGenerator
import bisq.user.identity.UserIdentity
import bisq.user.identity.UserIdentityService
import bisq.user.profile.UserProfile
import kotlinx.coroutines.*
import network.bisq.mobile.android.node.AndroidNodeGreeting
import network.bisq.mobile.android.node.domain.data.repository.NodeGreetingRepository
import network.bisq.mobile.android.node.domain.model.UserProfileModel
import network.bisq.mobile.android.node.service.AndroidApplicationService
import network.bisq.mobile.android.node.service.AndroidMemoryReportService
import network.bisq.mobile.domain.data.model.Greeting
import network.bisq.mobile.domain.data.repository.GreetingRepository
import network.bisq.mobile.domain.data.repository.SingleObjectRepository
import java.util.Optional
import network.bisq.mobile.presentation.MainPresenter
import org.bouncycastle.jce.provider.BouncyCastleProvider
import java.security.Security
import java.util.*
import java.util.concurrent.CompletableFuture
import java.util.concurrent.TimeUnit
import java.util.concurrent.atomic.AtomicLong
Expand Down Expand Up @@ -105,9 +104,9 @@ class MainNodePresenter(greetingRepository: NodeGreetingRepository): MainPresent
launchServices()
}

override fun onDestroy() {
override fun onDestroying() {
applicationService.shutdown()
super.onDestroy()
super.onDestroying()
}

private fun log(message: String) {
Expand Down
2 changes: 1 addition & 1 deletion bisqapps/gradle.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#Gradle
org.gradle.jvmargs=-Xmx4096M -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 -Dkotlin.daemon.jvm.options\="-Xmx4096M"
org.gradle.jvmargs=-Xmx8g -XX:MaxMetaspaceSize=1g -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 -Dkotlin.daemon.jvm.options\="-Xmx8g"
org.gradle.caching=true
org.gradle.configuration-cache=true

Expand Down
109 changes: 59 additions & 50 deletions bisqapps/gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@ android-targetSdk = "34"
android-minSdk = "24"
android-node-minSdk = "31"
androidx-activityCompose = "1.9.2"

androidx-appcompat = "1.7.0"
androidx-constraintlayout = "2.1.4"
androidx-core-ktx = "1.13.1"
androidx-espresso-core = "3.6.1"
androidx-lifecycle = "2.8.2"
androidx-material = "1.12.0"
androidx-test-junit = "1.2.1"

androidx-lifecycle = "2.8.2"
androidx-test-compose-ver = "1.6.8"
androidx-multidex = "2.0.1"
bisq-core = "2.1.2"
Expand All @@ -23,52 +25,57 @@ kotlinTestJunit = "2.0.20"
kotlinx = "1.9.0"
kermit = "2.0.4"
buildconfig = "5.5.0"
navigationCompose = "2.7.0-alpha07"
protobuf = "0.9.4"
protob = "4.28.2"
ksp = "2.0.20-1.0.25"

chimp-jsocks-lib = { strictly = '567e1cd6' }
chimp-jtorctl-lib = { strictly = '9b5ba203' }
failsafe-lib = { strictly = '3.2.4' }

bouncycastle-lib = { strictly = '1.78.1' }

google-guava-lib = { strictly = '33.2.1-jre' }

apache-httpcomponents-httpclient-lib = { strictly = '4.5.14' } # 5.3.1 would be better but has lot of API changes

chimp-jtorctl-lib = { strictly = '9b5ba203' }
apache-commons-lang-lib = { strictly = '3.14.0' }
apache-httpcomponents-core-lib = { strictly = '4.4.16' }
apache-httpcomponents-httpclient-lib = { strictly = '4.5.14' } # 5.3.1 would be better but has lot of API changes
apache-tomcat-annotations-api = { strictly = '6.0.53' }

assertj-core-lib = { strictly = '3.22.0' }
bouncycastle-lib = { strictly = '1.78.1' }

glassfish-jersey-lib = { strictly = '3.1.8' }
glassfish-jaxb-runtime-lib = { strictly = '4.0.5' }

google-gson-lib = { strictly = '2.9.0' }
google-guava-lib = { strictly = '33.2.1-jre' }

grpc = { strictly = '1.61.0' }

i2p-lib = { strictly = '1.8.0' }
i2p-v2 = { strictly = '2.4.0' }
jackson-lib = { strictly = '2.17.2' }

lyricist = "1.7.0"

koin = "4.0.0"
lombok-lib = { strictly = '1.18.34' }
typesafe-config-lib = { strictly = '1.4.3' }

[libraries]
kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" }
kotlin-test-junit = { module = "org.jetbrains.kotlin:kotlin-test-junit", version.ref = "kotlin" }
kotlin-test-junit-v180 = { module = "org.jetbrains.kotlin:kotlin-test-junit", version.ref = "kotlinTestJunit" }
kotlinx-coroutines = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinx" }
mock-io = { module = "io.mockk:mockk", version.ref = "mockio" }
junit = { group = "junit", name = "junit", version.ref = "junit" }
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "androidx-core-ktx" }
androidx-test-junit = { group = "androidx.test.ext", name = "junit", version.ref = "androidx-test-junit" }
androidx-multidex = { group = "androidx.multidex", name = "multidex", version.ref = "androidx-multidex" }
androidx-test-compose = { group = "androidx.compose.ui", name = "ui-test-junit4-android", version.ref = "androidx-test-compose-ver" }
androidx-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest", version.ref = "androidx-test-compose-ver" }
androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "androidx-espresso-core" }
androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "androidx-appcompat" }
androidx-material = { group = "com.google.android.material", name = "material", version.ref = "androidx-material" }
androidx-constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "androidx-constraintlayout" }

#kotlin-test-junit = { module = "org.jetbrains.kotlin:kotlin-test-junit", version.ref = "kotlin" }
#androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "androidx-core-ktx" }
#androidx-test-junit = { group = "androidx.test.ext", name = "junit", version.ref = "androidx-test-junit" }
#androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "androidx-espresso-core" }
#androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "androidx-appcompat" }
#androidx-material = { group = "com.google.android.material", name = "material", version.ref = "androidx-material" }
#androidx-constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "androidx-constraintlayout" }

androidx-activity-compose = { module = "androidx.activity:activity-compose", version.ref = "androidx-activityCompose" }
androidx-lifecycle-viewmodel = { group = "org.jetbrains.androidx.lifecycle", name = "lifecycle-viewmodel", version.ref = "androidx-lifecycle" }
androidx-lifecycle-runtime-compose = { group = "org.jetbrains.androidx.lifecycle", name = "lifecycle-runtime-compose", version.ref = "androidx-lifecycle" }
Expand All @@ -82,11 +89,11 @@ typesafe-config = { module = 'com.typesafe:config', version.ref = 'typesafe-conf
bouncycastle = { module = 'org.bouncycastle:bcprov-jdk18on', version.ref = 'bouncycastle-lib' }
bouncycastle-pg = { module = 'org.bouncycastle:bcpg-jdk18on', version.ref = 'bouncycastle-lib' }

#protobuf-lite = { group ="com.google.protobuf", name = "protobuf-javalite", version.ref = "protoblite"}
lyricist = { module = "cafe.adriel.lyricist:lyricist", version.ref = "lyricist" }
navigation-compose = { module = "org.jetbrains.androidx.navigation:navigation-compose", version.ref = "navigationCompose" }
protobuf-gradle-plugin = { module = 'com.google.protobuf:protobuf-gradle-plugin', version.ref = 'protobuf' }
protoc = { module = "com.google.protobuf:protoc", version.ref = "protob" }


bisq-core-common = { module = "bisq:common", version.ref = "bisq-core" }
bisq-core-security = { module = "bisq:security", version.ref = "bisq-core" }
bisq-core-settings = { module = "bisq:settings", version.ref = "bisq-core" }
Expand All @@ -110,48 +117,49 @@ bisq-core-identity = { module = "bisq:identity", version.ref = "bisq-core" }

# bisq core transitive dependencies
chimp-jsocks = { module = 'com.github.chimp1984:jsocks', version.ref = 'chimp-jsocks-lib' }
chimp-jtorctl = { module = 'com.github.chimp1984:jtorctl', version.ref = 'chimp-jtorctl-lib' }
failsafe = { module = 'dev.failsafe:failsafe', version.ref = 'failsafe-lib' }
apache-commons-lang = { module = 'org.apache.commons:commons-lang3', version.ref = 'apache-commons-lang-lib' }
apache-httpcomponents-core = { module = 'org.apache.httpcomponents:httpcore', version.ref = 'apache-httpcomponents-core-lib' }
apache-httpcomponents-httpclient = { module = 'org.apache.httpcomponents:httpclient', version.ref = 'apache-httpcomponents-httpclient-lib' }
apache-tomcat-annotations-api = { module = 'org.apache.tomcat:annotations-api', version.ref = 'apache-tomcat-annotations-api' }
assertj-core = { module = 'org.assertj:assertj-core', version.ref = 'assertj-core-lib' }
glassfish-jersey-jdk-http = { module = 'org.glassfish.jersey.containers:jersey-container-jdk-http', version.ref = 'glassfish-jersey-lib' }
glassfish-jersey-json-jackson = { module = 'org.glassfish.jersey.media:jersey-media-json-jackson', version.ref = 'glassfish-jersey-lib' }
glassfish-jersey-inject-hk2 = { module = 'org.glassfish.jersey.inject:jersey-hk2', version.ref = 'glassfish-jersey-lib' }
glassfish-jaxb-runtime = { module = 'org.glassfish.jaxb:jaxb-runtime', version.ref = 'glassfish-jaxb-runtime-lib' }

google-gson = { module = 'com.google.code.gson:gson', version.ref = 'google-gson-lib' }
google-guava = { module = 'com.google.guava:guava', version.ref = 'google-guava-lib' }

grpc-netty-shaded = { module = 'io.grpc:grpc-netty-shaded', version.ref = 'grpc' }
grpc-protobuf = { module = 'io.grpc:grpc-protobuf', version.ref = 'grpc' }
grpc-services = { module = 'io.grpc:grpc-services', version.ref = 'grpc' }
grpc-stub = { module = 'io.grpc:grpc-stub', version.ref = 'grpc' }


i2p-core = { module = 'net.i2p:i2p', version.ref = 'i2p-lib' }
i2p-core-v2 = { module = 'net.i2p:i2p', version.ref = 'i2p-v2' }
i2p-streaming = { module = 'net.i2p.client:streaming', version.ref = 'i2p-lib' }
i2p-streaming-v2 = { module = 'net.i2p.client:streaming', version.ref = 'i2p-v2' }
i2p-router = { module = 'net.i2p:router', version.ref = 'i2p-lib' }

jackson-core = { module = 'com.fasterxml.jackson.core:jackson-core', version.ref = 'jackson-lib' }
jackson-annotations = { module = 'com.fasterxml.jackson.core:jackson-annotations', version.ref = 'jackson-lib' }
jackson-databind = { module = 'com.fasterxml.jackson.core:jackson-databind', version.ref = 'jackson-lib' }
#chimp-jtorctl = { module = 'com.github.chimp1984:jtorctl', version.ref = 'chimp-jtorctl-lib' }
#apache-commons-lang = { module = 'org.apache.commons:commons-lang3', version.ref = 'apache-commons-lang-lib' }
#apache-httpcomponents-core = { module = 'org.apache.httpcomponents:httpcore', version.ref = 'apache-httpcomponents-core-lib' }
#apache-tomcat-annotations-api = { module = 'org.apache.tomcat:annotations-api', version.ref = 'apache-tomcat-annotations-api' }
#assertj-core = { module = 'org.assertj:assertj-core', version.ref = 'assertj-core-lib' }
#glassfish-jersey-jdk-http = { module = 'org.glassfish.jersey.containers:jersey-container-jdk-http', version.ref = 'glassfish-jersey-lib' }
#glassfish-jersey-json-jackson = { module = 'org.glassfish.jersey.media:jersey-media-json-jackson', version.ref = 'glassfish-jersey-lib' }
#glassfish-jersey-inject-hk2 = { module = 'org.glassfish.jersey.inject:jersey-hk2', version.ref = 'glassfish-jersey-lib' }
#glassfish-jaxb-runtime = { module = 'org.glassfish.jaxb:jaxb-runtime', version.ref = 'glassfish-jaxb-runtime-lib' }
#
#google-gson = { module = 'com.google.code.gson:gson', version.ref = 'google-gson-lib' }

#grpc-netty-shaded = { module = 'io.grpc:grpc-netty-shaded', version.ref = 'grpc' }
#grpc-protobuf = { module = 'io.grpc:grpc-protobuf', version.ref = 'grpc' }
#grpc-services = { module = 'io.grpc:grpc-services', version.ref = 'grpc' }
#grpc-stub = { module = 'io.grpc:grpc-stub', version.ref = 'grpc' }
#
#
#i2p-core = { module = 'net.i2p:i2p', version.ref = 'i2p-lib' }
#i2p-core-v2 = { module = 'net.i2p:i2p', version.ref = 'i2p-v2' }
#i2p-streaming = { module = 'net.i2p.client:streaming', version.ref = 'i2p-lib' }
#i2p-streaming-v2 = { module = 'net.i2p.client:streaming', version.ref = 'i2p-v2' }
#i2p-router = { module = 'net.i2p:router', version.ref = 'i2p-lib' }
#
#jackson-core = { module = 'com.fasterxml.jackson.core:jackson-core', version.ref = 'jackson-lib' }
#jackson-annotations = { module = 'com.fasterxml.jackson.core:jackson-annotations', version.ref = 'jackson-lib' }
#jackson-databind = { module = 'com.fasterxml.jackson.core:jackson-databind', version.ref = 'jackson-lib' }

# koin
koin-core = { module = "io.insert-koin:koin-core", version.ref = "koin" }
koin-compose = { module = "io.insert-koin:koin-compose", version.ref = "koin" }
koin-android = { module = "io.insert-koin:koin-android", version.ref = "koin" }

[bundles]
glassfish-jersey = ['glassfish-jersey-jdk-http', 'glassfish-jersey-json-jackson', 'glassfish-jersey-inject-hk2', 'glassfish-jaxb-runtime']
grpc = ['grpc-protobuf', 'grpc-services', 'grpc-stub']
i2p = ['i2p-core', 'i2p-router', 'i2p-streaming']
i2p-v2 = ['i2p-core-v2', 'i2p-streaming-v2']
jackson = ['jackson-core', 'jackson-annotations', 'jackson-databind']
#glassfish-jersey = ['glassfish-jersey-jdk-http', 'glassfish-jersey-json-jackson', 'glassfish-jersey-inject-hk2', 'glassfish-jaxb-runtime']
#grpc = ['grpc-protobuf', 'grpc-services', 'grpc-stub']
#i2p = ['i2p-core', 'i2p-router', 'i2p-streaming']
#i2p-v2 = ['i2p-core-v2', 'i2p-streaming-v2']
#jackson = ['jackson-core', 'jackson-annotations', 'jackson-databind']

[plugins]
kotlinCocoapods = { id = "org.jetbrains.kotlin.native.cocoapods", version.ref = "kotlin" }
Expand All @@ -162,3 +170,4 @@ compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "
kotlinMultiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" }
buildconfig = { id = "com.github.gmazzo.buildconfig", version.ref = "buildconfig" }
protobuf = { id = "com.google.protobuf", version.ref = "protobuf" }
ksp = { id = "com.google.devtools.ksp", version.ref="ksp" }
Binary file modified bisqapps/gradle/wrapper/gradle-wrapper.jar
Binary file not shown.
2 changes: 1 addition & 1 deletion bisqapps/gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
Expand Down
Loading

0 comments on commit d584cff

Please sign in to comment.