Skip to content
Open
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
@@ -0,0 +1,44 @@
/*
* Infomaniak Core - Android
* Copyright (C) 2026 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 (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.core.ui.compose.contactcard

import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Immutable
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.takeOrElse

@Immutable
data class ContactCardColors(
val waveBackground: Color,
val background: Color,
)

object ContactCardDefaults {
@Composable
fun colors(
waveBackground: Color = Color.Unspecified,
background: Color = Color.Unspecified,
): ContactCardColors {
val defaultWave = MaterialTheme.colorScheme.surfaceContainerLowest
val defaultBackground = MaterialTheme.colorScheme.primaryContainer
return ContactCardColors(
waveBackground = waveBackground.takeOrElse { defaultWave },
background = background.takeOrElse { defaultBackground },
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Infomaniak Core - Android
* Copyright (C) 2026 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 (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.core.ui.compose.contactcard

sealed interface ContactCardTopBarState {
data class Editor(val onCancel: () -> Unit, val onSave: () -> Unit) : ContactCardTopBarState
data class Preview(val onClose: () -> Unit, val onMore: () -> Unit) : ContactCardTopBarState
data class Default(val onBack: () -> Unit) : ContactCardTopBarState
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/*
* Infomaniak Core - Android
* Copyright (C) 2026 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 (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.core.ui.compose.contactcard.component

import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Edit
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.infomaniak.core.ui.compose.margin.Margin

@Composable
internal fun BottomSheetAction(
icon: ImageVector,
label: String,
onClick: () -> Unit,
) {
TextButton(
onClick = onClick,
shape = RectangleShape,
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = Margin.Mini),
contentPadding = PaddingValues(Margin.Small),
colors = ButtonDefaults.textButtonColors(
contentColor = MaterialTheme.colorScheme.onSurface,
)
) {
Row(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
) {
Icon(
imageVector = icon,
contentDescription = null,
tint = MaterialTheme.colorScheme.primary,
modifier = Modifier.size(24.dp),
)
Spacer(Modifier.width(Margin.Medium))
Text(
text = label,
style = MaterialTheme.typography.bodyLarge,
)
}
}
}

@Preview(name = "BottomSheetAction")
@Composable
private fun BottomSheetActionPreview() {
MaterialTheme {
Surface {
BottomSheetAction(
icon = Icons.Default.Edit,
label = "Edit",
onClick = {},
)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* Infomaniak Core - Android
* Copyright (C) 2026 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 (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.core.ui.compose.contactcard.component

import androidx.compose.ui.unit.dp

internal val CardCornerRadius = 12.dp
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* Infomaniak Core - Android
* Copyright (C) 2026 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 (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.core.ui.compose.contactcard.component

import androidx.compose.foundation.layout.RowScope
import androidx.compose.material3.CenterAlignedTopAppBar
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.stringResource
import com.infomaniak.core.ui.compose.contactcard.R

@Composable
@OptIn(ExperimentalMaterial3Api::class)
internal fun ContactCardTopBar(
navigationIcon: @Composable () -> Unit = {},
actions: @Composable RowScope.() -> Unit = {},
containerColor: Color = Color.Transparent,
) {
CenterAlignedTopAppBar(
title = {
Text(
text = stringResource(R.string.contactCardTitle),
style = MaterialTheme.typography.titleMedium,
color = MaterialTheme.colorScheme.onSurface,
)
},
navigationIcon = navigationIcon,
actions = actions,
colors = TopAppBarDefaults.centerAlignedTopAppBarColors(
containerColor = containerColor,
titleContentColor = MaterialTheme.colorScheme.onSurface,
navigationIconContentColor = MaterialTheme.colorScheme.primary,
actionIconContentColor = MaterialTheme.colorScheme.primary,
),
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/*
* Infomaniak Core - Android
* Copyright (C) 2026 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 (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.core.ui.compose.contactcard.component

import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.dp
import com.infomaniak.core.auth.models.user.Card
import com.infomaniak.core.auth.models.user.CardLinkType
import com.infomaniak.core.ui.compose.contactcard.R
import com.infomaniak.core.ui.compose.margin.Margin

@Composable
internal fun ContactInfoRows(card: Card, modifier: Modifier = Modifier) {
val rows = buildList {
card.company?.takeIf { it.isNotBlank() }?.let { add(stringResource(R.string.company) to it) }
card.phone.takeIf { it.isNotBlank() }?.let { add(stringResource(R.string.phone) to it) }
card.links.orEmpty().firstOrNull { it.type == CardLinkType.Website && it.url.isNotBlank() }?.let {
add(stringResource(R.string.webSite) to it.url)
}
}
Column(modifier = modifier) {
rows.forEachIndexed { index, (label, value) ->

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if you don't have anything in rows, no need to have an empty column ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There will always be at least one Row since phone is required

if (index > 0) {
HorizontalDivider(
thickness = 0.5.dp,
color = MaterialTheme.colorScheme.outlineVariant,
)
}
Row(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = Margin.Small),
horizontalArrangement = androidx.compose.foundation.layout.Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically,
) {
Text(
text = label,
color = MaterialTheme.colorScheme.onSurfaceVariant,
style = MaterialTheme.typography.bodyMedium,
)
Text(
text = value,
color = MaterialTheme.colorScheme.primary,
style = MaterialTheme.typography.bodyMedium,
fontWeight = FontWeight.SemiBold,
)
}
}
}
}

@Preview(name = "ContactInfoRows")
@Composable
private fun ContactInfoRowsPreview(
@PreviewParameter(ContactPreviewProvider::class) contactData: PreviewContactData,
) {
MaterialTheme {
Surface {
ContactInfoRows(card = contactData.card)
}
}
}
Loading
Loading