Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UI Fixes #79, #81: Back button, Small screen layouts #84

Merged
merged 4 commits into from
Dec 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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(
rodvar marked this conversation as resolved.
Show resolved Hide resolved
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
Loading