Skip to content

Commit

Permalink
Move AndroidCatHashService creation to AndroidApplicationService as w…
Browse files Browse the repository at this point in the history
…e need the application base directory.

Pass context to AndroidApplicationService.
Fix package names.

Add image to generateKeyPair as type Any.
This is just preliminary due KMP issues with BitMap or related image formats.
  • Loading branch information
HenrikJannsen authored and rodvar committed Nov 29, 2024
1 parent 13df7ee commit 2de6dd7
Show file tree
Hide file tree
Showing 11 changed files with 64 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
*/
package network.bisq.mobile.android.node

import android.content.Context
import androidx.core.util.Supplier
import bisq.account.AccountService
import bisq.application.ApplicationService
Expand All @@ -42,6 +43,7 @@ import bisq.user.UserService
import lombok.Getter
import lombok.Setter
import lombok.extern.slf4j.Slf4j
import network.bisq.mobile.android.node.service.AndroidCatHashService
import network.bisq.mobile.android.node.service.AndroidMemoryReportService
import network.bisq.mobile.utils.Logging
import java.nio.file.Path
Expand All @@ -59,6 +61,7 @@ import java.util.concurrent.TimeUnit
@Getter
class AndroidApplicationService(
androidMemoryReportService: AndroidMemoryReportService,
context: Context,
userDataDir: Path?
) :
ApplicationService("android", arrayOf<String>(), userDataDir), Logging {
Expand All @@ -69,6 +72,8 @@ class AndroidApplicationService(
lateinit var applicationService: AndroidApplicationService
var state: Supplier<Observable<State>> =
Supplier { applicationService.state }
var androidCatHashService: Supplier<AndroidCatHashService> =
Supplier { applicationService.androidCatHashService }
var securityService: Supplier<SecurityService> =
Supplier { applicationService.securityService }
var networkService: Supplier<NetworkService> =
Expand Down Expand Up @@ -113,6 +118,8 @@ class AndroidApplicationService(
private val shutDownErrorMessage = Observable<String>()
private val startupErrorMessage = Observable<String>()

val androidCatHashService = AndroidCatHashService(context, config.baseDir)

val securityService =
SecurityService(persistenceService, SecurityService.Config.from(getConfig("security")))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,6 @@ val androidNodeModule = module {
AndroidMemoryReportService(androidContext())
}

single<AndroidCatHashService> {
val context = androidContext()
AndroidCatHashService(context, context.filesDir.toPath())
}

single { AndroidApplicationService.Provider() }

single<ApplicationBootstrapFacade> { NodeApplicationBootstrapFacade(get()) }
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package network.bisq.mobile.android.node.domain.user_profile

import android.graphics.Bitmap
import androidx.compose.ui.graphics.asImageBitmap
import bisq.common.encoding.Hex
import bisq.security.DigestUtil
import bisq.security.SecurityService
Expand All @@ -8,6 +10,7 @@ import bisq.user.UserService
import bisq.user.identity.NymIdGenerator
import bisq.user.profile.UserProfile
import network.bisq.mobile.android.node.AndroidApplicationService
import network.bisq.mobile.android.node.service.AndroidCatHashService
import network.bisq.mobile.domain.service.user_profile.UserProfileServiceFacade
import network.bisq.mobile.utils.Logging
import java.security.KeyPair
Expand Down Expand Up @@ -35,6 +38,9 @@ class NodeUserProfileServiceFacade(private val applicationService: AndroidApplic
private val userService: UserService by lazy {
applicationService.userService.get()
}
private val catHashService: AndroidCatHashService by lazy {
applicationService.androidCatHashService.get()
}

// Misc
private var pubKeyHash: ByteArray? = null
Expand All @@ -47,7 +53,7 @@ class NodeUserProfileServiceFacade(private val applicationService: AndroidApplic
return userService.userIdentityService.userIdentities.isNotEmpty()
}

override suspend fun generateKeyPair(result: (String, String) -> Unit) {
override suspend fun generateKeyPair(result: (String, String, Any?) -> Unit) {
keyPair = securityService.keyBundleService.generateKeyPair()
pubKeyHash = DigestUtil.hash(keyPair!!.public.encoded)

Expand All @@ -58,15 +64,16 @@ class NodeUserProfileServiceFacade(private val applicationService: AndroidApplic
createSimulatedDelay(powDuration)

val id = Hex.encode(pubKeyHash)
val nym = NymIdGenerator.generate(pubKeyHash, proofOfWork!!.solution)

// CatHash is in desktop, needs to be reimplemented or the javafx part extracted and refactored into a non javafx lib
// Image image = CatHash.getImage(pubKeyHash,
// powSolution,
// CURRENT_AVATARS_VERSION,
// CreateProfileModel.CAT_HASH_IMAGE_SIZE);

result(id!!, nym!!)
val solution = proofOfWork!!.solution
val nym = NymIdGenerator.generate(pubKeyHash, solution)
val profileIcon: Bitmap = catHashService.getImage(
pubKeyHash,
solution,
0,
120.0
)
val imageBitmap = profileIcon.asImageBitmap()
result(id!!, nym!!, imageBitmap)
}

override suspend fun createAndPublishNewUserProfile(nickName: String) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,13 @@ class NodeMainPresenter(
if (!applicationServiceCreated) {
applicationServiceCreated = true
val filesDirsPath = (view as Activity).filesDir.toPath()
val applicationContext = (view as Activity).applicationContext
val applicationService =
AndroidApplicationService(androidMemoryReportService, filesDirsPath)
AndroidApplicationService(
androidMemoryReportService,
applicationContext,
filesDirsPath
)
provider.applicationService = applicationService

applicationBootstrapFacade.activate()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ import network.bisq.mobile.client.market.ClientMarketPriceServiceFacade
import network.bisq.mobile.client.market.MarketPriceApiGateway
import network.bisq.mobile.client.offerbook.ClientOfferbookServiceFacade
import network.bisq.mobile.client.service.ApiRequestService
import network.bisq.mobile.domain.client.main.user_profile.ClientUserProfileServiceFacade
import network.bisq.mobile.client.user_profile.ClientUserProfileServiceFacade
import network.bisq.mobile.client.offerbook.offer.OfferbookApiGateway
import network.bisq.mobile.domain.client.main.user_profile.UserProfileApiGateway
import network.bisq.mobile.client.user_profile.UserProfileApiGateway
import network.bisq.mobile.domain.data.repository.main.bootstrap.ApplicationBootstrapFacade
import network.bisq.mobile.domain.service.market_price.MarketPriceServiceFacade
import network.bisq.mobile.domain.service.offerbook.OfferbookServiceFacade
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
package network.bisq.mobile.domain.client.main.user_profile
package network.bisq.mobile.client.user_profile

import kotlinx.coroutines.delay
import kotlinx.datetime.Clock
import network.bisq.mobile.client.replicated_model.user.identity.PreparedData
import network.bisq.mobile.client.replicated_model.user.profile.UserProfile
import network.bisq.mobile.client.user_profile.UserProfileResponse
import network.bisq.mobile.domain.service.user_profile.UserProfileServiceFacade
import network.bisq.mobile.utils.Logging
import kotlin.math.max
Expand All @@ -22,12 +21,13 @@ class ClientUserProfileServiceFacade(private val apiGateway: UserProfileApiGatew
return getUserIdentityIds().isNotEmpty()
}

override suspend fun generateKeyPair(result: (String, String) -> Unit) {
override suspend fun generateKeyPair(result: (String, String, Any?) -> Unit) {
try {
val ts = Clock.System.now().toEpochMilliseconds()
val preparedData = apiGateway.requestPreparedData()
createSimulatedDelay(Clock.System.now().toEpochMilliseconds() - ts)
result(preparedData.id, preparedData.nym)
//todo not impl yet
result(preparedData.id, preparedData.nym, null)
this.preparedData = preparedData
} catch (e: Exception) {
log.e { e.toString() }
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package network.bisq.mobile.domain.client.main.user_profile
package network.bisq.mobile.client.user_profile

import kotlinx.serialization.Serializable
import network.bisq.mobile.client.replicated_model.user.identity.PreparedData
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
package network.bisq.mobile.domain.client.main.user_profile
package network.bisq.mobile.client.user_profile

import network.bisq.mobile.client.replicated_model.user.identity.PreparedData
import network.bisq.mobile.client.replicated_model.user.profile.UserProfile
import network.bisq.mobile.client.service.ApiRequestService
import network.bisq.mobile.client.user_profile.UserProfileResponse

class UserProfileApiGateway(
private val apiRequestService: ApiRequestService
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ interface UserProfileServiceFacade {
* the proof of work solution.
* The CatHash image is also created based on that hash and the proof of work solution.
*/
suspend fun generateKeyPair(result: (String, String) -> Unit)
suspend fun generateKeyPair(result: (String, String, Any?) -> Unit)

/**
* Once the user clicks the `create` button we create a user identity and publish the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ open class CreateProfilePresenter(
_nym.value = value
}

private val _profileIcon = MutableStateFlow<Any?>(null)
val profileIcon: StateFlow<Any?> get() = _profileIcon
private fun setProfileIcon(value: Any?) {
_profileIcon.value = value
}

private val _nickName = MutableStateFlow("")
val nickName: StateFlow<String> get() = _nickName
fun setNickname(value: String) {
Expand Down Expand Up @@ -99,10 +105,10 @@ open class CreateProfilePresenter(
setGenerateKeyPairInProgress(true)
log.i { "Show busy animation for generateKeyPair" }
// takes 200 -1000 ms
userProfileService.generateKeyPair { id, nym ->
userProfileService.generateKeyPair { id, nym, profileIcon ->
setId(id)
setNym(nym)
//todo show new profile image
setProfileIcon(profileIcon)
}
setGenerateKeyPairInProgress(false)
log.i { "Hide busy animation for generateKeyPair" }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,17 @@ package network.bisq.mobile.presentation.ui.uicases.startup
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.navigation.NavHostController
import bisqapps.shared.presentation.generated.resources.Res
import bisqapps.shared.presentation.generated.resources.img_bot_image
import cafe.adriel.lyricist.LocalStrings
import network.bisq.mobile.presentation.ui.components.atoms.BisqButton
import network.bisq.mobile.presentation.ui.components.atoms.BisqText
Expand All @@ -21,10 +22,10 @@ import network.bisq.mobile.presentation.ui.components.atoms.icons.BisqLogo
import network.bisq.mobile.presentation.ui.components.layout.BisqScrollScaffold
import network.bisq.mobile.presentation.ui.helpers.RememberPresenterLifecycle
import network.bisq.mobile.presentation.ui.theme.BisqTheme
import org.jetbrains.compose.resources.painterResource
import org.koin.compose.koinInject
import org.koin.core.parameter.parametersOf
import org.koin.core.qualifier.named
import kotlin.math.log

@Composable
fun CreateProfileScreen(
Expand Down Expand Up @@ -57,10 +58,19 @@ fun CreateProfileScreen(
placeholder = strings.onboarding_createProfile_nickName_prompt
)
Spacer(modifier = Modifier.height(36.dp))
Image(
painterResource(Res.drawable.img_bot_image),
"User profile icon generated from the hash of the public key"
) // TODO: Translation

presenter.profileIcon.collectAsState().value?.let { profileIcon ->
// how can i convert a coil3.Bitmap to androidx.compose.ui.graphics.ImageBitmap in KMP
val imageBitmap: ImageBitmap? = profileIcon as ImageBitmap
if (imageBitmap != null) {
Image(
bitmap = imageBitmap,
contentDescription = "User profile icon generated from the hash of the public key",
modifier = Modifier.height(60.dp).width(60.dp)
)
}
}

Spacer(modifier = Modifier.height(32.dp))
BisqText.baseRegular(
text = presenter.nym.collectAsState().value,
Expand Down

0 comments on commit 2de6dd7

Please sign in to comment.