Skip to content

Commit

Permalink
UI Fixes #79, #81: Back button, Small screen layouts (#84)
Browse files Browse the repository at this point in the history
* - Nav: Back button generalization

* - layout improvements: consistent, better padding across screens; tested in small screen devices; BisqTextField improvements

* Swipe back navigation for IOS

* Fix: Back button whilte screen issue; isIOS() moved to presenter
  • Loading branch information
nostrbuddha authored Dec 1, 2024
1 parent 2c3bbe2 commit 5af44e6
Show file tree
Hide file tree
Showing 17 changed files with 247 additions and 85 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import network.bisq.mobile.android.node.BuildNodeConfig
import network.bisq.mobile.client.shared.BuildConfig
import network.bisq.mobile.domain.getPlatform
import network.bisq.mobile.presentation.ui.AppPresenter


Expand Down Expand Up @@ -48,5 +49,10 @@ open class MainPresenter() :
_isContentVisible.value = !_isContentVisible.value
}

override fun isIOS(): Boolean {
val platform = getPlatform()
val isIOS = platform.name.lowercase().contains("ios")
return isIOS
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,24 @@ import org.jetbrains.compose.ui.tooling.preview.Preview

import kotlinx.coroutines.flow.StateFlow
import network.bisq.mobile.presentation.ViewPresenter
import network.bisq.mobile.presentation.ui.components.SwipeBackIOSNavigationHandler
import org.koin.compose.koinInject
import network.bisq.mobile.presentation.ui.navigation.Routes

import network.bisq.mobile.presentation.ui.navigation.graph.RootNavGraph
import network.bisq.mobile.presentation.ui.theme.BisqTheme
import org.koin.mp.KoinPlatform.getKoin

interface AppPresenter: ViewPresenter {
interface AppPresenter : ViewPresenter {
fun setNavController(controller: NavHostController)
// Observables for state

// Observables for state
val isContentVisible: StateFlow<Boolean>

// Actions
fun toggleContentVisibility()

fun isIOS(): Boolean
}

/**
Expand Down Expand Up @@ -57,7 +61,9 @@ fun App() {
BisqTheme(darkTheme = true) {
ProvideStrings(lyricist) {
if (isNavControllerSet) {
RootNavGraph()
SwipeBackIOSNavigationHandler(rootNavController) {
RootNavGraph()
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ fun CurrencyProfileCard(
horizontalArrangement = Arrangement.SpaceBetween,
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 14.dp, vertical = 4.dp)
.padding(vertical = 4.dp)
.clickable(
interactionSource = interactionSource,
indication = null,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package network.bisq.mobile.presentation.ui.components

import androidx.compose.foundation.gestures.detectHorizontalDragGestures
import androidx.compose.foundation.layout.Box
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.dp
import androidx.navigation.NavController
import network.bisq.mobile.presentation.ui.AppPresenter
import org.koin.compose.koinInject

// TODO:
// Patch work to handle horizontal swipe in iOS and pop back
// Will remove this once compose officially has this support for iOS
// Ref links:
// - https://github.com/adrielcafe/voyager/issues/144
// - https://trycatchdebug.net/news/1426361/native-ios-swipe-back-gesture-in-compose
@Composable
fun SwipeBackIOSNavigationHandler(
navController: NavController,
content: @Composable () -> Unit
) {
val presenter: AppPresenter = koinInject()

// TODO: Find the right way to get screenWidth in KMP way.
// This is not right.
val screenWidthDp = remember { 360.dp }
val density = LocalDensity.current

val screenWidthPx = with(density) { screenWidthDp.toPx() }
val threshold = screenWidthPx / 3

var cumulativeDrag by remember { mutableStateOf(0f) }

Box(
modifier = if (presenter.isIOS()) {
Modifier.pointerInput(Unit) {
detectHorizontalDragGestures(
onDragStart = {
cumulativeDrag = 0f
},
onDragEnd = {
cumulativeDrag = 0f
},
onDragCancel = {
},
onHorizontalDrag = { change, dragAmount ->
cumulativeDrag += dragAmount.takeIf { it > 0 } ?: 0f

if (cumulativeDrag >= threshold) {
if (navController.currentBackStackEntry != null) navController.popBackStack()
cumulativeDrag = 0f
}
}
)
}
} else {
Modifier
}
) {
content()
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,24 @@
package network.bisq.mobile.presentation.ui.components.atoms

import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.TextField
import androidx.compose.material3.TextFieldDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import network.bisq.mobile.components.MaterialTextField
import androidx.compose.ui.draw.clip
import androidx.compose.ui.focus.onFocusChanged
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import network.bisq.mobile.presentation.ui.theme.BisqTheme

@Composable
Expand All @@ -15,24 +29,66 @@ fun BisqTextField(
placeholder: String?,
labelRightSuffix: (@Composable () -> Unit)? = null,
modifier: Modifier = Modifier,
) {
) {
var isFocused by remember { mutableStateOf(false) }
Column(modifier = modifier) {
Row (
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
if (label.isNotEmpty()) {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
BisqText.baseRegular(
text = label,
color = BisqTheme.colors.light2,
)
if (labelRightSuffix != null) {
labelRightSuffix()
}
}
}
Box(
modifier = Modifier
.fillMaxWidth()
.clip(shape = RoundedCornerShape(6.dp))
.background(color = BisqTheme.colors.secondary)
) {
BisqText.baseRegular(
text = label,
color = BisqTheme.colors.light2,
TextField(
value = value,
singleLine = true,
modifier = Modifier.fillMaxWidth().clickable { isFocused = true }
.onFocusChanged { focusState ->
isFocused = focusState.isFocused
},
textStyle = TextStyle(fontSize = 22.sp),
onValueChange = onValueChanged,
colors = TextFieldDefaults.colors(
focusedTextColor = BisqTheme.colors.light3,
unfocusedTextColor = BisqTheme.colors.secondaryHover,
unfocusedIndicatorColor = BisqTheme.colors.secondary,
focusedIndicatorColor = Color.Transparent,
focusedContainerColor = BisqTheme.colors.secondary,
cursorColor = Color.Blue,
unfocusedContainerColor = BisqTheme.colors.secondary
),
placeholder = {
if (placeholder != null) {
BisqText.h5Regular(
text = placeholder,
color = BisqTheme.colors.secondaryHover,
)
}
}
)
if (isFocused) {
Box(
modifier = Modifier
.fillMaxWidth()
.height(2.dp)
.align(Alignment.BottomCenter)
.background(BisqTheme.colors.primary)
)
if (labelRightSuffix != null) {
labelRightSuffix()
}
}
MaterialTextField(
text = value,
placeholder = placeholder ?: "",
onValueChanged = { onValueChanged(it) })
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import network.bisq.mobile.presentation.ui.theme.BisqTheme
import network.bisq.mobile.presentation.ui.theme.BisqUIConstants

@Composable
fun BisqScrollLayout(
innerPadding: PaddingValues = PaddingValues(top = 48.dp, bottom = 12.dp, start = 12.dp, end = 12.dp),
padding: PaddingValues = PaddingValues(all = BisqUIConstants.ScreenPadding),
verticalArrangement: Arrangement.Vertical = Arrangement.Top,
content: @Composable ColumnScope.() -> Unit
) {
Expand All @@ -23,7 +24,7 @@ fun BisqScrollLayout(
modifier = Modifier
.fillMaxSize()
.background(color = BisqTheme.colors.backgroundColor)
.padding(innerPadding)
.padding(padding)
.verticalScroll(rememberScrollState())
) {
content()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,26 @@ import androidx.compose.material3.Scaffold
import androidx.compose.runtime.Composable
import androidx.compose.ui.unit.dp
import network.bisq.mobile.presentation.ui.theme.BisqTheme
import network.bisq.mobile.presentation.ui.theme.BisqUIConstants

@Composable
fun BisqScrollScaffold(
innerPadding: PaddingValues = PaddingValues(top = 48.dp, bottom = 12.dp, start = 12.dp, end = 12.dp),
topBar: @Composable () -> Unit = {},
bottomBar: @Composable () -> Unit = {},
padding: PaddingValues = PaddingValues(
top = BisqUIConstants.ScrollTopPadding,
bottom = BisqUIConstants.ScreenPadding,
start = BisqUIConstants.ScreenPadding,
end = BisqUIConstants.ScreenPadding
),
topBar: @Composable (() -> Unit)? = null,
bottomBar: @Composable (() -> Unit)? = null,
content: @Composable ColumnScope.() -> Unit
) {
Scaffold(
containerColor = BisqTheme.colors.backgroundColor,
topBar = topBar,
bottomBar = bottomBar,
topBar = topBar ?: {},
bottomBar = bottomBar ?: {},
content = {
BisqScrollLayout {
content()
}
BisqScrollLayout(padding = if (topBar != null) it else padding) { content() }
},
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import network.bisq.mobile.presentation.ui.theme.BisqTheme
import network.bisq.mobile.presentation.ui.theme.BisqUIConstants

@Composable
fun BisqStaticLayout(
innerPadding: PaddingValues = PaddingValues(top = 48.dp, bottom = 12.dp, start = 12.dp, end = 12.dp),
padding: PaddingValues = PaddingValues(all = BisqUIConstants.ScreenPadding),
verticalArrangement: Arrangement.Vertical = Arrangement.SpaceBetween,
content: @Composable ColumnScope.() -> Unit
) {
Expand All @@ -21,7 +22,7 @@ fun BisqStaticLayout(
modifier = Modifier
.fillMaxSize()
.background(color = BisqTheme.colors.backgroundColor)
.padding(innerPadding)
.padding(padding)
) {
content()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,29 @@ package network.bisq.mobile.presentation.ui.components.layout

import androidx.compose.foundation.layout.*
import androidx.compose.material3.Scaffold
import androidx.compose.material3.TopAppBar
import androidx.compose.runtime.Composable
import androidx.compose.ui.unit.dp
import network.bisq.mobile.presentation.ui.theme.BisqTheme
import network.bisq.mobile.presentation.ui.theme.BisqUIConstants

@Composable
fun BisqStaticScaffold(
innerPadding: PaddingValues = PaddingValues(top = 96.dp, bottom = 12.dp, start = 12.dp, end = 12.dp),
topBar: @Composable () -> Unit = {},
bottomBar: @Composable () -> Unit = {},
padding: PaddingValues = PaddingValues(
top = BisqUIConstants.StaticTopPadding,
bottom = BisqUIConstants.ScreenPadding,
start = BisqUIConstants.ScreenPadding,
end = BisqUIConstants.ScreenPadding
),
topBar: @Composable (() -> Unit)? = null,
bottomBar: @Composable (() -> Unit)? = null,
content: @Composable ColumnScope.() -> Unit
) {
Scaffold(
containerColor = BisqTheme.colors.backgroundColor,
topBar = topBar,
bottomBar = bottomBar,
topBar = topBar ?: {},
bottomBar = bottomBar ?: {},
content = {
BisqStaticLayout(innerPadding = innerPadding) { content() }
BisqStaticLayout(padding = if (topBar != null) it else padding) { content() }
}
)
}
Loading

0 comments on commit 5af44e6

Please sign in to comment.