Skip to content

Commit

Permalink
UI branch cleanup (#69)
Browse files Browse the repository at this point in the history
* UI Fixes and code cleanup

 - Android full screen issue (#61) - Made the system bar transparent, so it takes up current screen's BG color

 - Improved docs (README.md) for /components and /navigation

 - Component improvements: Button, TextField, Icons, PagerView

 - Code cleanup: Create profile, Onboarding, TrustedNodeSetup

* Handled most TODOs (Tech debts)

 - Clean, separate RootNavGraph and TabNavGraph

 - Component improvements: Button, TextField, Icons, Layout components

 - TopBar for Tab pages - Moved to TabContainerHome (added comments on why?)

* - Different onboarding page content in androidNode and xClient (facing some other issue in androidNode

* - fix lint issue with node main presenter

* - removing unnecessary libs added in node for merge

---------

Co-authored-by: Rodrigo Varela <[email protected]>
  • Loading branch information
nostrbuddha and rodvar authored Nov 23, 2024
1 parent 7f0c1ee commit 54d277c
Show file tree
Hide file tree
Showing 31 changed files with 878 additions and 709 deletions.
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
package network.bisq.mobile.client

import android.graphics.Color
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.SystemBarStyle
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.runtime.Composable
import androidx.compose.ui.tooling.preview.Preview
import network.bisq.mobile.presentation.MainPresenter
Expand All @@ -15,6 +18,7 @@ class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
presenter.attachView(this)
enableEdgeToEdge(SystemBarStyle.dark(Color.TRANSPARENT), SystemBarStyle.dark(Color.TRANSPARENT))

setContent {
App()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@ import network.bisq.mobile.android.node.domain.bootstrap.NodeApplicationBootstra
import network.bisq.mobile.android.node.domain.data.repository.NodeGreetingRepository
import network.bisq.mobile.android.node.domain.user_profile.NodeUserProfileServiceFacade
import network.bisq.mobile.android.node.presentation.NodeMainPresenter
import network.bisq.mobile.android.node.presentation.OnBoardingNodePresenter
import network.bisq.mobile.android.node.service.AndroidMemoryReportService
import network.bisq.mobile.domain.data.repository.main.bootstrap.ApplicationBootstrapFacade
import network.bisq.mobile.domain.user_profile.UserProfileServiceFacade
import network.bisq.mobile.presentation.MainPresenter
import network.bisq.mobile.presentation.ui.AppPresenter
import network.bisq.mobile.presentation.ui.uicases.startup.IOnboardingPresenter
import org.koin.android.ext.koin.androidContext
import org.koin.dsl.bind
import org.koin.dsl.module
Expand All @@ -32,4 +34,6 @@ val androidNodeModule = module {
// this line showcases both, the possibility to change behaviour of the app by changing one definition
// and binding the same obj to 2 different abstractions
single<MainPresenter> { NodeMainPresenter(get(), get(), get()) } bind AppPresenter::class

single<IOnboardingPresenter> { OnBoardingNodePresenter(get()) } bind IOnboardingPresenter::class
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,16 @@ import network.bisq.mobile.presentation.MainPresenter
class NodeMainPresenter(
private val supplier: AndroidApplicationService.Supplier,
private val androidMemoryReportService: AndroidMemoryReportService,
private val applicationBootstrapFacade: ApplicationBootstrapFacade
applicationBootstrapFacade: ApplicationBootstrapFacade
) : MainPresenter(applicationBootstrapFacade) {

var applicationServiceInited = false
override fun onViewAttached() {
// full override
// super.onViewAttached()

if (!applicationServiceInited) {
applicationServiceInited = true
val context = (view as Activity).applicationContext
val filesDirsPath = (view as Activity).filesDir.toPath()
supplier.applicationService =
AndroidApplicationService(androidMemoryReportService, filesDirsPath)
applicationBootstrapFacade.initialize()
supplier.applicationService.initialize()
}
override fun initializeServices() {
val context = (view as Activity).applicationContext
val filesDirsPath = (view as Activity).filesDir.toPath()
supplier.applicationService =
AndroidApplicationService(androidMemoryReportService, filesDirsPath)
supplier.applicationService.initialize()
super.initializeServices()
}

override fun onDestroying() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package network.bisq.mobile.android.node.presentation

import network.bisq.mobile.presentation.MainPresenter
import network.bisq.mobile.presentation.ui.uicases.startup.IOnboardingPresenter
import network.bisq.mobile.presentation.ui.uicases.startup.OnBoardingPresenter

class OnBoardingNodePresenter(
mainPresenter: MainPresenter
) : OnBoardingPresenter(mainPresenter), IOnboardingPresenter {
override val indexesToShow = listOf(1, 2)
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import network.bisq.mobile.presentation.ui.AppPresenter
*/
open class MainPresenter(private val applicationBootstrapFacade: ApplicationBootstrapFacade) : BasePresenter(null), AppPresenter {
lateinit var navController: NavHostController
private set
private set

override fun setNavController(controller: NavHostController) {
navController = controller
Expand All @@ -24,32 +24,37 @@ open class MainPresenter(private val applicationBootstrapFacade: ApplicationBoot
private val _isContentVisible = MutableStateFlow(false)
override val isContentVisible: StateFlow<Boolean> = _isContentVisible

private var applicationServiceInited = false
override fun onViewAttached() {
super.onViewAttached()

if (!applicationServiceInited) {
applicationServiceInited = true
applicationBootstrapFacade.initialize()
}
}
private var applicationServiceInited = false

// passthrough example
// private val _greetingText: StateFlow<String> = stateFlowFromRepository(
// repositoryFlow = greetingRepository.data,
// transform = { it?.greet() ?: "" },
// initialValue = "Welcome!"
// )
// override val greetingText: StateFlow<String> = _greetingText
// private val _greetingText: StateFlow<String> = stateFlowFromRepository(
// repositoryFlow = greetingRepository.data,
// transform = { it?.greet() ?: "" },
// initialValue = "Welcome!"
// )
// override val greetingText: StateFlow<String> = _greetingText

init {
log.i { "Shared Version: ${BuildConfig.SHARED_LIBS_VERSION}" }
log.i { "iOS Client Version: ${BuildConfig.IOS_APP_VERSION}" }
log.i { "Android Client Version: ${BuildConfig.IOS_APP_VERSION}" }
log.i { "Android Node Version: ${BuildNodeConfig.APP_VERSION}" }
// CoroutineScope(BackgroundDispatcher).launch {
// greetingRepository.create(Greeting())
// }
// CoroutineScope(BackgroundDispatcher).launch {
// greetingRepository.create(Greeting())
// }
}

override fun onViewAttached() {
super.onViewAttached()

if (!applicationServiceInited) {
initializeServices()
applicationServiceInited = true
}
}

protected open fun initializeServices() {
applicationBootstrapFacade.initialize()
}

// Toggle action
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,11 @@ fun App() {
}

val lyricist = rememberStrings()
// lyricist.languageTag = Locales.FR

BisqTheme(darkTheme = true) {
ProvideStrings(lyricist) {
if (isNavControllerSet) {
RootNavGraph(
startDestination = Routes.Splash.name
)
RootNavGraph()
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Components

This folder has all components that can be (re)used across the application

### Atoms
- This are very simplistic controls, that shows / does just one simple thing.
- They are mostly extensions of basic Compose components like text, button, etc.,, that are customized with Bisq look and feel.
- They are not aware of Presenter or any state management classes.

### Molecules
[TODO]

### Organisms
[TODO]

### Layout
- Container layout components
Original file line number Diff line number Diff line change
@@ -1,47 +1,63 @@
package network.bisq.mobile.presentation.ui.components.atoms

import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonColors
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import network.bisq.mobile.presentation.ui.theme.BisqTheme

// TODO:
// leftIcon, rightIcon -> Not happening right
/**
* Either pass
* - text for regular button (or)
* - iconOnly for Icon only button.
* If both are given, iconOnly takes precedence
*/
@Composable
fun BisqButton(
text: String,
text: String? = "Button",
onClick: () -> Unit,
color: Color = BisqTheme.colors.light1,
backgroundColor: Color = BisqTheme.colors.primary,
padding: PaddingValues = PaddingValues(horizontal = 48.dp, vertical = 4.dp),
leftIcon: Unit? = null,
rightIcon: Unit? = null,
modifier: Modifier = Modifier
iconOnly: (@Composable () -> Unit)? = null,
leftIcon: (@Composable () -> Unit)? = null,
rightIcon: (@Composable () -> Unit)? = null,
modifier: Modifier = Modifier,
cornerRadius: Dp = 8.dp
) {

// Apply proper rounded corner
Button(
onClick = { onClick() },
contentPadding = padding,
contentPadding = if(iconOnly != null) PaddingValues(horizontal = 0.dp, vertical = 0.dp) else padding,
colors = ButtonColors(
containerColor = backgroundColor,
disabledContainerColor = backgroundColor,
contentColor = color,
disabledContentColor = color)
disabledContentColor = color),
shape = RoundedCornerShape(cornerRadius),
) {
Row {
if(leftIcon != null) leftIcon
if(leftIcon != null) Spacer(modifier = Modifier.width(10.dp))
BisqText.baseMedium(
text = text,
color = BisqTheme.colors.light1,
)
if(rightIcon != null) Spacer(modifier = Modifier.width(10.dp))
if(rightIcon != null) rightIcon
if (iconOnly == null && text == null) {
BisqText.baseMedium("Error: Pass either text or icon")
}

if (iconOnly != null) {
iconOnly()
} else if (text != null) {
Row {
if(leftIcon != null) leftIcon()
if(leftIcon != null) Spacer(modifier = Modifier.width(10.dp))
BisqText.baseMedium(
text = text,
color = BisqTheme.colors.light1,
)
if(rightIcon != null) Spacer(modifier = Modifier.width(10.dp))
if(rightIcon != null) rightIcon()
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package network.bisq.mobile.presentation.ui.components.atoms

import androidx.compose.foundation.layout.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import network.bisq.mobile.components.MaterialTextField
import network.bisq.mobile.presentation.ui.theme.BisqTheme

@Composable
fun BisqTextField(
label: String,
value: String,
onValueChanged: (String) -> Unit,
placeholder: String?,
labelRightSuffix: (@Composable () -> Unit)? = null,
modifier: Modifier = Modifier,
) {
Column(modifier = modifier) {
Row (
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
BisqText.baseRegular(
text = label,
color = BisqTheme.colors.light2,
)
if (labelRightSuffix != null) {
labelRightSuffix()
}
}
MaterialTextField(
text = value,
placeholder = placeholder ?: "",
onValueChanged = { onValueChanged(it) })
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,26 @@ fun BellIcon(modifier: Modifier = Modifier) {
}

@Composable
fun UserIcon(modifier: Modifier = Modifier) {
Image(painterResource(Res.drawable.img_bot_image), "User icon", modifier = modifier)
fun CopyIcon(modifier: Modifier = Modifier) {
Image(painterResource(Res.drawable.icon_copy), "Copy icon", modifier = modifier)
}

@Composable
fun QuestionIcon(modifier: Modifier = Modifier) {
Image(painterResource(Res.drawable.icon_question_mark), "Question icon", modifier = modifier)
}

@Composable
fun ScanIcon(modifier: Modifier = Modifier) {
Image(painterResource(Res.drawable.icon_qr), "Scan icon", modifier = modifier)
}

@Composable
fun SortIcon(modifier: Modifier = Modifier) {
Image(painterResource(Res.drawable.icon_sort), "Sort icon", modifier = modifier)
}

@Composable
fun UserIcon(modifier: Modifier = Modifier) {
Image(painterResource(Res.drawable.img_bot_image), "User icon", modifier = modifier)
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,19 @@ import network.bisq.mobile.presentation.ui.theme.BisqTheme

@Composable
fun BisqScrollLayout(
innerPadding: PaddingValues = PaddingValues(top = 24.dp, bottom = 12.dp, start = 12.dp, end = 12.dp),
innerPadding: PaddingValues = PaddingValues(top = 48.dp, bottom = 12.dp, start = 12.dp, end = 12.dp),
verticalArrangement: Arrangement.Vertical = Arrangement.Top,
content: @Composable ColumnScope.() -> Unit
) {
Scaffold(
containerColor = BisqTheme.colors.backgroundColor,
Column(
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = verticalArrangement ?: Arrangement.Top,
modifier = Modifier
.fillMaxSize()
.background(color = BisqTheme.colors.backgroundColor)
.padding(innerPadding)
.verticalScroll(rememberScrollState())
) {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
.fillMaxSize()
.background(color = BisqTheme.colors.backgroundColor)
.padding(innerPadding)
.verticalScroll(rememberScrollState())
) {
content()
}
content()
}
}
Loading

0 comments on commit 54d277c

Please sign in to comment.