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

Add a scaffold for all the screens that use a top app bar + sticky buttons at the bottom of the screen and some LargeButton component #23

Merged
merged 9 commits into from
Aug 16, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,17 @@ import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import com.infomaniak.swisstransfer.ui.screen.newtransfer.NewTransferScreen
import com.infomaniak.swisstransfer.ui.theme.SwissTransferTheme

class NewTransferActivity : ComponentActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
NewTransferScreen()
SwissTransferTheme {
NewTransferScreen()
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Infomaniak SwissTransfer - Android
* Copyright (C) 2024 Infomaniak Network SA
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package com.infomaniak.swisstransfer.ui.components

import androidx.compose.foundation.layout.*
import androidx.compose.material3.Scaffold
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier

@Composable
fun BottomStickyButtonScaffold(
modifier: Modifier = Modifier,
topBar: @Composable () -> Unit,
topButton: @Composable ((Modifier) -> Unit)? = null,
bottomButton: @Composable ((Modifier) -> Unit)? = null,
content: @Composable BoxScope.() -> Unit,
) {
Scaffold(topBar = topBar) { contentPaddings ->
Column(
modifier = modifier
.fillMaxWidth()
.padding(contentPaddings)
) {
Box(modifier = Modifier.weight(1f), content = content)
DoubleButtonCombo(topButton, bottomButton)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/*
* Infomaniak SwissTransfer - Android
* Copyright (C) 2024 Infomaniak Network SA
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package com.infomaniak.swisstransfer.ui.components

import androidx.compose.foundation.layout.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import com.infomaniak.swisstransfer.ui.theme.Margin

private val WIDTH_LIMIT = 800.dp
private val WIDTH_THRESHOLD = 500.dp

@Composable
fun ColumnScope.DoubleButtonCombo(
topButton: @Composable ((Modifier) -> Unit)? = null,
bottomButton: @Composable ((Modifier) -> Unit)? = null
) {
BoxWithConstraints(
modifier = Modifier
.widthIn(max = WIDTH_LIMIT)
.align(Alignment.CenterHorizontally),
) {
when {
topButton == null && bottomButton == null -> Unit
topButton != null && bottomButton != null -> {
if (maxWidth < WIDTH_THRESHOLD) {
VerticallyStackedButtons(topButton, bottomButton)
} else {
HorizontallyStackedButtons(topButton, bottomButton)
}
}
else -> SingleButton(button = topButton ?: bottomButton!!)
}
}
}

@Composable
private fun VerticallyStackedButtons(
topButton: @Composable (Modifier) -> Unit,
bottomButton: @Composable (Modifier) -> Unit
) {
Column(Modifier.fillMaxWidth()) {
topButton(
Modifier
.fillMaxWidth()
.padding(horizontal = Margin.Medium)
)

Spacer(modifier = Modifier.height(Margin.Medium))

bottomButton(
Modifier
.fillMaxWidth()
.padding(start = Margin.Medium, end = Margin.Medium, bottom = Margin.Large)
)
}
}

@Composable
private fun HorizontallyStackedButtons(
topButton: @Composable (Modifier) -> Unit,
bottomButton: @Composable (Modifier) -> Unit
) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(bottom = Margin.Large, start = Margin.Medium, end = Margin.Medium),
horizontalArrangement = Arrangement.spacedBy(Margin.Medium),
verticalAlignment = Alignment.CenterVertically,
) {
topButton(Modifier.weight(1f))
bottomButton(Modifier.weight(1f))
}
}

@Composable
private fun SingleButton(button: @Composable (Modifier) -> Unit) {
button(
Modifier
.fillMaxWidth()
.widthIn(WIDTH_LIMIT / 2)
.padding(bottom = Margin.Large, start = Margin.Medium, end = Margin.Medium),
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/*
* Infomaniak SwissTransfer - Android
* Copyright (C) 2024 Infomaniak Network SA
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package com.infomaniak.swisstransfer.ui.components

import android.content.res.Configuration
import androidx.annotation.StringRes
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.material3.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.infomaniak.swisstransfer.R
import com.infomaniak.swisstransfer.ui.icons.AppIcons
import com.infomaniak.swisstransfer.ui.icons.app.Add
import com.infomaniak.swisstransfer.ui.theme.Margin
import com.infomaniak.swisstransfer.ui.theme.Shapes
import com.infomaniak.swisstransfer.ui.theme.SwissTransferTheme

@Composable
fun LargeButton(
modifier: Modifier = Modifier,
@StringRes titleRes: Int,
style: ButtonType = ButtonType.PRIMARY,
enabled: Boolean = true,
onClick: () -> Unit,
imageVector: ImageVector? = null,
) {
Button(
modifier = modifier.height(56.dp),
colors = style.buttonColors(),
shape = Shapes.medium,
enabled = enabled,
onClick = onClick,
) {
imageVector?.let {
Icon(modifier = Modifier.size(Margin.Medium), imageVector = it, contentDescription = null)
Spacer(modifier = Modifier.width(Margin.Small))
}
Text(text = stringResource(id = titleRes))
}
}

enum class ButtonType(val buttonColors: @Composable () -> ButtonColors) {
PRIMARY({
ButtonDefaults.buttonColors(
containerColor = SwissTransferTheme.materialColors.primary,
contentColor = SwissTransferTheme.materialColors.onPrimary,
)
}),
SECONDARY({
ButtonDefaults.buttonColors(
containerColor = SwissTransferTheme.colors.tertiaryButtonBackground,
contentColor = SwissTransferTheme.materialColors.primary,
)
}),
TERTIARY({
ButtonDefaults.buttonColors(
containerColor = Color.Transparent,
contentColor = SwissTransferTheme.materialColors.primary,
)
}),
}

@Preview(name = "Light")
@Preview(name = "Dark", uiMode = Configuration.UI_MODE_NIGHT_YES or Configuration.UI_MODE_TYPE_NORMAL)
@Composable
private fun LargeButtonPreview() {
SwissTransferTheme {
Column(modifier = Modifier.background(SwissTransferTheme.materialColors.background)) {
ButtonType.entries.forEach {
LargeButton(
titleRes = R.string.appName,
style = it,
imageVector = AppIcons.Add,
onClick = {},
)
Spacer(modifier = Modifier.height(Margin.Small))
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Infomaniak SwissTransfer - Android
* Copyright (C) 2024 Infomaniak Network SA
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package com.infomaniak.swisstransfer.ui.components

import androidx.compose.material3.CenterAlignedTopAppBar
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.Color
import com.infomaniak.swisstransfer.ui.theme.SwissTransferTheme

@Composable
@OptIn(ExperimentalMaterial3Api::class)
fun SwissTransferTobAppBar() {
CenterAlignedTopAppBar(
colors = TopAppBarDefaults.topAppBarColors(
containerColor = SwissTransferTheme.materialColors.tertiary,
titleContentColor = Color.White, // TODO
),
title = {
Text("Title")
}
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,52 @@

package com.infomaniak.swisstransfer.ui.screen.newtransfer.importfiles

import androidx.compose.foundation.layout.Column
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import com.infomaniak.swisstransfer.R
import com.infomaniak.swisstransfer.ui.components.BottomStickyButtonScaffold
import com.infomaniak.swisstransfer.ui.components.ButtonType
import com.infomaniak.swisstransfer.ui.components.LargeButton
import com.infomaniak.swisstransfer.ui.components.SwissTransferTobAppBar
import com.infomaniak.swisstransfer.ui.icons.AppIcons
import com.infomaniak.swisstransfer.ui.icons.app.Add
import com.infomaniak.swisstransfer.ui.theme.SwissTransferTheme
import com.infomaniak.swisstransfer.ui.utils.PreviewMobile
import com.infomaniak.swisstransfer.ui.utils.PreviewTablet

@Composable
fun ImportFilesScreen() {
Text("ImportFilesScreen")
BottomStickyButtonScaffold(
topBar = { SwissTransferTobAppBar() },
topButton = { modifier ->
LargeButton(
modifier = modifier,
titleRes = R.string.buttonAddFiles,
imageVector = AppIcons.Add,
style = ButtonType.TERTIARY,
onClick = { /*TODO*/ },
)
},
bottomButton = { modifier ->
LargeButton(
modifier = modifier,
titleRes = R.string.buttonNext,
onClick = { /*TODO*/ },
)
},
) {
Column {
Text("ImportFilesScreen")
}
}
}

@PreviewMobile
@PreviewTablet
@Composable
private fun ImportFilesScreenPreview() {
SwissTransferTheme {
ImportFilesScreen()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,5 @@ val CustomDarkColorScheme = CustomColorScheme(
secondaryTextColor = Color(shark),
navigationItemBackground = Color(dark2),
divider = Color(dark3),
tertiaryButtonBackground = Color(dark2),
)
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ private const val elephant = 0xFF666666
private const val shark = 0xFF9F9F9F
private const val mouse = 0xFFE0E0E0
private const val polar_bear = 0xFFF5F5F5
private const val rabbit = 0xFFF1F1F1

private const val specific1 = 0xFFD8F0E3
private const val specific2 = 0xFFCCDBDE
Expand Down Expand Up @@ -62,4 +63,5 @@ val CustomLightColorScheme = CustomColorScheme(
secondaryTextColor = Color(elephant),
navigationItemBackground = LightColorScheme.background,
divider = Color(mouse),
tertiaryButtonBackground = Color(rabbit),
)
Original file line number Diff line number Diff line change
Expand Up @@ -65,4 +65,5 @@ data class CustomColorScheme(
val secondaryTextColor: Color = Color.Unspecified,
val navigationItemBackground: Color = Color.Unspecified,
val divider: Color = Color.Unspecified,
val tertiaryButtonBackground: Color = Color.Unspecified,
)
Loading
Loading