From 3a7de47760704962b38905167f474451d72e1c67 Mon Sep 17 00:00:00 2001 From: yamilmedina Date: Tue, 16 Apr 2024 18:56:40 +0200 Subject: [PATCH 01/10] feat: confirm on exit --- .../sketch/DrawingCanvasBottomSheet.kt | 60 +++++++++++++++++-- .../feature/sketch/DrawingCanvasViewModel.kt | 9 +++ .../feature/sketch/model/DrawingState.kt | 3 +- .../sketch/src/main/res/values/strings.xml | 4 ++ 4 files changed, 69 insertions(+), 7 deletions(-) diff --git a/features/sketch/src/main/java/com/wire/android/feature/sketch/DrawingCanvasBottomSheet.kt b/features/sketch/src/main/java/com/wire/android/feature/sketch/DrawingCanvasBottomSheet.kt index 85fb1f48c28..cd46f3b68af 100644 --- a/features/sketch/src/main/java/com/wire/android/feature/sketch/DrawingCanvasBottomSheet.kt +++ b/features/sketch/src/main/java/com/wire/android/feature/sketch/DrawingCanvasBottomSheet.kt @@ -28,13 +28,16 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.shape.CutCornerShape import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.AlertDialog import androidx.compose.material.Icon import androidx.compose.material.Text +import androidx.compose.material.TextButton import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Circle import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.MaterialTheme import androidx.compose.material3.ModalBottomSheet +import androidx.compose.material3.ModalBottomSheetProperties import androidx.compose.material3.SheetState import androidx.compose.material3.rememberModalBottomSheetState import androidx.compose.runtime.Composable @@ -44,7 +47,10 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.window.DialogProperties +import androidx.compose.ui.window.SecureFlagPolicy import androidx.lifecycle.viewmodel.compose.viewModel import com.wire.android.feature.sketch.model.DrawingState import com.wire.android.model.ClickBlockParams @@ -79,10 +85,15 @@ fun DrawingCanvasBottomSheet( shape = CutCornerShape(dimensions().spacing0x), containerColor = colorsScheme().background, dragHandle = { - DrawingTopBar(scope, sheetState, conversationTitle, onDismissSketch, viewModel::onUndoLastStroke, viewModel.state) + DrawingTopBar(conversationTitle, viewModel::onShowConfirmationDialog, viewModel::onUndoLastStroke, viewModel.state) }, sheetState = sheetState, - onDismissRequest = onDismissSketch + onDismissRequest = viewModel::onShowConfirmationDialog, + properties = ModalBottomSheetProperties( + isFocusable = true, + securePolicy = SecureFlagPolicy.SecureOn, + shouldDismissOnBackPress = false + ) ) { Row( Modifier @@ -109,13 +120,14 @@ fun DrawingCanvasBottomSheet( } ) } + + if (viewModel.state.showConfirmationDialog) { + DiscardDialogConfirmation(scope, sheetState, onDismissSketch, viewModel::onHideConfirmationDialog) + } } -@OptIn(ExperimentalMaterial3Api::class) @Composable private fun DrawingTopBar( - scope: CoroutineScope = rememberCoroutineScope(), - sheetState: SheetState, conversationTitle: String, onDismissSketch: () -> Unit, onUndoStroke: () -> Unit, @@ -128,7 +140,7 @@ private fun DrawingTopBar( horizontalArrangement = Arrangement.SpaceBetween, ) { WireTertiaryIconButton( - onButtonClicked = { scope.launch { sheetState.hide() }.invokeOnCompletion { onDismissSketch() } }, + onButtonClicked = onDismissSketch, iconResource = R.drawable.ic_close, contentDescription = R.string.content_description_close_button, minSize = MaterialTheme.wireDimensions.buttonCircleMinSize, @@ -205,4 +217,40 @@ private fun DrawingToolbar( ) } +@OptIn(ExperimentalMaterial3Api::class) +@Composable +private fun DiscardDialogConfirmation( + scope: CoroutineScope, + sheetState: SheetState, + onDismissSketch: () -> Unit, + onHideConfirmationDialog: () -> Unit, +) { + AlertDialog( + onDismissRequest = onHideConfirmationDialog, + title = { Text(stringResource(R.string.confirm_changes_title)) }, + text = { Text(stringResource(R.string.confirm_changes_text)) }, + confirmButton = { + TextButton(onClick = { + scope.launch { sheetState.hide() }.invokeOnCompletion { + onHideConfirmationDialog() + onDismissSketch() + } + }) { + Text(stringResource(R.string.confirm_changes_dismiss)) + } + }, + dismissButton = { + TextButton(onClick = { + onHideConfirmationDialog() + }) { + Text(stringResource(R.string.confirm_changes_confirm)) + } + }, + properties = DialogProperties( + dismissOnBackPress = false, + dismissOnClickOutside = false + ) + ) +} + private const val MAX_LINES_TOPBAR = 1 diff --git a/features/sketch/src/main/java/com/wire/android/feature/sketch/DrawingCanvasViewModel.kt b/features/sketch/src/main/java/com/wire/android/feature/sketch/DrawingCanvasViewModel.kt index 84d8b244dc6..b5f6668aae0 100644 --- a/features/sketch/src/main/java/com/wire/android/feature/sketch/DrawingCanvasViewModel.kt +++ b/features/sketch/src/main/java/com/wire/android/feature/sketch/DrawingCanvasViewModel.kt @@ -51,10 +51,19 @@ class DrawingCanvasViewModel : ViewModel() { initializeCanvas() } + private fun initializeCanvas() { state = DrawingState(currentPath = DrawingPathProperties()) } + fun onShowConfirmationDialog() { + state = state.copy(showConfirmationDialog = true) + } + + fun onHideConfirmationDialog() { + state = state.copy(showConfirmationDialog = false) + } + /** * Marks the start of the drawing. */ diff --git a/features/sketch/src/main/java/com/wire/android/feature/sketch/model/DrawingState.kt b/features/sketch/src/main/java/com/wire/android/feature/sketch/model/DrawingState.kt index 79b54266ccf..12de2bae850 100644 --- a/features/sketch/src/main/java/com/wire/android/feature/sketch/model/DrawingState.kt +++ b/features/sketch/src/main/java/com/wire/android/feature/sketch/model/DrawingState.kt @@ -26,5 +26,6 @@ internal data class DrawingState( val drawingMotionEvent: DrawingMotionEvent = DrawingMotionEvent.Idle, val currentPath: DrawingPathProperties = DrawingPathProperties(), val currentPosition: Offset = Offset.Unspecified, - var canvasSize: Size? = null + var canvasSize: Size? = null, + val showConfirmationDialog: Boolean = false ) diff --git a/features/sketch/src/main/res/values/strings.xml b/features/sketch/src/main/res/values/strings.xml index 1cfe8046a73..af2e78af51c 100644 --- a/features/sketch/src/main/res/values/strings.xml +++ b/features/sketch/src/main/res/values/strings.xml @@ -22,4 +22,8 @@ Pick your favorite color and start sketching 🎨 close Color + Discard drawing? + If you leave without sending, your drawing will be lost. + Cancel + Discard From 60c46a0376dbfda3e4ebb9b50bfdfd62cf48fb69 Mon Sep 17 00:00:00 2001 From: yamilmedina Date: Tue, 16 Apr 2024 19:32:34 +0200 Subject: [PATCH 02/10] feat: confirm on exit, reinit --- .../sketch/DrawingCanvasBottomSheet.kt | 41 ++++++++++++------- .../feature/sketch/DrawingCanvasViewModel.kt | 2 +- 2 files changed, 27 insertions(+), 16 deletions(-) diff --git a/features/sketch/src/main/java/com/wire/android/feature/sketch/DrawingCanvasBottomSheet.kt b/features/sketch/src/main/java/com/wire/android/feature/sketch/DrawingCanvasBottomSheet.kt index cd46f3b68af..4504dd13055 100644 --- a/features/sketch/src/main/java/com/wire/android/feature/sketch/DrawingCanvasBottomSheet.kt +++ b/features/sketch/src/main/java/com/wire/android/feature/sketch/DrawingCanvasBottomSheet.kt @@ -64,6 +64,7 @@ import com.wire.android.ui.common.button.WireTertiaryIconButton import com.wire.android.ui.common.button.wireSendPrimaryButtonColors import com.wire.android.ui.common.colorsScheme import com.wire.android.ui.common.dimensions +import com.wire.android.ui.theme.wireColorScheme import com.wire.android.ui.theme.wireDimensions import com.wire.android.ui.theme.wireTypography import kotlinx.coroutines.CoroutineScope @@ -81,14 +82,24 @@ fun DrawingCanvasBottomSheet( val context = LocalContext.current val scope = rememberCoroutineScope() val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true, confirmValueChange = { false }) + val onDismissEvent: () -> Unit = remember { + { + if (viewModel.state.paths.isNotEmpty()) { + viewModel.onShowConfirmationDialog() + } else { + scope.launch { sheetState.hide() }.invokeOnCompletion { onDismissSketch() } + } + } + } + ModalBottomSheet( shape = CutCornerShape(dimensions().spacing0x), containerColor = colorsScheme().background, dragHandle = { - DrawingTopBar(conversationTitle, viewModel::onShowConfirmationDialog, viewModel::onUndoLastStroke, viewModel.state) + DrawingTopBar(conversationTitle, onDismissEvent, viewModel::onUndoLastStroke, viewModel.state) }, sheetState = sheetState, - onDismissRequest = viewModel::onShowConfirmationDialog, + onDismissRequest = onDismissEvent, properties = ModalBottomSheetProperties( isFocusable = true, securePolicy = SecureFlagPolicy.SecureOn, @@ -122,14 +133,20 @@ fun DrawingCanvasBottomSheet( } if (viewModel.state.showConfirmationDialog) { - DiscardDialogConfirmation(scope, sheetState, onDismissSketch, viewModel::onHideConfirmationDialog) + val dismissEvent: () -> Unit = remember { + { + viewModel.initializeCanvas() + onDismissSketch() + } + } + DiscardDialogConfirmation(scope, sheetState, dismissEvent, viewModel::onHideConfirmationDialog) } } @Composable private fun DrawingTopBar( conversationTitle: String, - onDismissSketch: () -> Unit, + dismissAction: () -> Unit, onUndoStroke: () -> Unit, state: DrawingState ) { @@ -140,7 +157,7 @@ private fun DrawingTopBar( horizontalArrangement = Arrangement.SpaceBetween, ) { WireTertiaryIconButton( - onButtonClicked = onDismissSketch, + onButtonClicked = dismissAction, iconResource = R.drawable.ic_close, contentDescription = R.string.content_description_close_button, minSize = MaterialTheme.wireDimensions.buttonCircleMinSize, @@ -226,6 +243,8 @@ private fun DiscardDialogConfirmation( onHideConfirmationDialog: () -> Unit, ) { AlertDialog( + backgroundColor = MaterialTheme.wireColorScheme.background, + contentColor = MaterialTheme.wireColorScheme.onBackground, onDismissRequest = onHideConfirmationDialog, title = { Text(stringResource(R.string.confirm_changes_title)) }, text = { Text(stringResource(R.string.confirm_changes_text)) }, @@ -235,17 +254,9 @@ private fun DiscardDialogConfirmation( onHideConfirmationDialog() onDismissSketch() } - }) { - Text(stringResource(R.string.confirm_changes_dismiss)) - } - }, - dismissButton = { - TextButton(onClick = { - onHideConfirmationDialog() - }) { - Text(stringResource(R.string.confirm_changes_confirm)) - } + }) { Text(stringResource(R.string.confirm_changes_dismiss)) } }, + dismissButton = { TextButton(onClick = { onHideConfirmationDialog() }) { Text(stringResource(R.string.confirm_changes_confirm)) } }, properties = DialogProperties( dismissOnBackPress = false, dismissOnClickOutside = false diff --git a/features/sketch/src/main/java/com/wire/android/feature/sketch/DrawingCanvasViewModel.kt b/features/sketch/src/main/java/com/wire/android/feature/sketch/DrawingCanvasViewModel.kt index b5f6668aae0..aed98820ad7 100644 --- a/features/sketch/src/main/java/com/wire/android/feature/sketch/DrawingCanvasViewModel.kt +++ b/features/sketch/src/main/java/com/wire/android/feature/sketch/DrawingCanvasViewModel.kt @@ -52,7 +52,7 @@ class DrawingCanvasViewModel : ViewModel() { } - private fun initializeCanvas() { + fun initializeCanvas() { state = DrawingState(currentPath = DrawingPathProperties()) } From 1ad6a6597213620c17ceefe65858a3efd2c07ca1 Mon Sep 17 00:00:00 2001 From: yamilmedina Date: Tue, 16 Apr 2024 19:34:46 +0200 Subject: [PATCH 03/10] feat: confirm on exit, detkt --- .../wire/android/feature/sketch/DrawingCanvasBottomSheet.kt | 6 +++++- .../wire/android/feature/sketch/DrawingCanvasViewModel.kt | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/features/sketch/src/main/java/com/wire/android/feature/sketch/DrawingCanvasBottomSheet.kt b/features/sketch/src/main/java/com/wire/android/feature/sketch/DrawingCanvasBottomSheet.kt index 4504dd13055..a044e3d7292 100644 --- a/features/sketch/src/main/java/com/wire/android/feature/sketch/DrawingCanvasBottomSheet.kt +++ b/features/sketch/src/main/java/com/wire/android/feature/sketch/DrawingCanvasBottomSheet.kt @@ -256,7 +256,11 @@ private fun DiscardDialogConfirmation( } }) { Text(stringResource(R.string.confirm_changes_dismiss)) } }, - dismissButton = { TextButton(onClick = { onHideConfirmationDialog() }) { Text(stringResource(R.string.confirm_changes_confirm)) } }, + dismissButton = { + TextButton(onClick = { + onHideConfirmationDialog() + }) { Text(stringResource(R.string.confirm_changes_confirm)) } + }, properties = DialogProperties( dismissOnBackPress = false, dismissOnClickOutside = false diff --git a/features/sketch/src/main/java/com/wire/android/feature/sketch/DrawingCanvasViewModel.kt b/features/sketch/src/main/java/com/wire/android/feature/sketch/DrawingCanvasViewModel.kt index aed98820ad7..f3183943b26 100644 --- a/features/sketch/src/main/java/com/wire/android/feature/sketch/DrawingCanvasViewModel.kt +++ b/features/sketch/src/main/java/com/wire/android/feature/sketch/DrawingCanvasViewModel.kt @@ -42,6 +42,7 @@ import kotlinx.coroutines.withContext import java.io.File import java.io.FileOutputStream +@Suppress("TooManyFunctions") class DrawingCanvasViewModel : ViewModel() { internal var state: DrawingState by mutableStateOf(DrawingState()) @@ -51,7 +52,6 @@ class DrawingCanvasViewModel : ViewModel() { initializeCanvas() } - fun initializeCanvas() { state = DrawingState(currentPath = DrawingPathProperties()) } From 3156dc207cec85713b39cedba8ac75b3a4746477 Mon Sep 17 00:00:00 2001 From: yamilmedina Date: Tue, 16 Apr 2024 19:35:32 +0200 Subject: [PATCH 04/10] feat: confirm on exit, detkt --- .../feature/sketch/DrawingCanvasBottomSheet.kt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/features/sketch/src/main/java/com/wire/android/feature/sketch/DrawingCanvasBottomSheet.kt b/features/sketch/src/main/java/com/wire/android/feature/sketch/DrawingCanvasBottomSheet.kt index a044e3d7292..2432b30919f 100644 --- a/features/sketch/src/main/java/com/wire/android/feature/sketch/DrawingCanvasBottomSheet.kt +++ b/features/sketch/src/main/java/com/wire/android/feature/sketch/DrawingCanvasBottomSheet.kt @@ -91,6 +91,12 @@ fun DrawingCanvasBottomSheet( } } } + val dismissEvent: () -> Unit = remember { + { + viewModel.initializeCanvas() + onDismissSketch() + } + } ModalBottomSheet( shape = CutCornerShape(dimensions().spacing0x), @@ -133,12 +139,6 @@ fun DrawingCanvasBottomSheet( } if (viewModel.state.showConfirmationDialog) { - val dismissEvent: () -> Unit = remember { - { - viewModel.initializeCanvas() - onDismissSketch() - } - } DiscardDialogConfirmation(scope, sheetState, dismissEvent, viewModel::onHideConfirmationDialog) } } From 18903e4b6e9e469c14c62523f6ddc2e06c1741cf Mon Sep 17 00:00:00 2001 From: yamilmedina Date: Wed, 17 Apr 2024 09:57:11 +0200 Subject: [PATCH 05/10] feat: extract dialog to file --- .../sketch/DrawingCanvasBottomSheet.kt | 41 ------------ .../DrawingDiscardConfirmationDialog.kt | 65 +++++++++++++++++++ 2 files changed, 65 insertions(+), 41 deletions(-) create mode 100644 features/sketch/src/main/java/com/wire/android/feature/sketch/DrawingDiscardConfirmationDialog.kt diff --git a/features/sketch/src/main/java/com/wire/android/feature/sketch/DrawingCanvasBottomSheet.kt b/features/sketch/src/main/java/com/wire/android/feature/sketch/DrawingCanvasBottomSheet.kt index 2432b30919f..d9348f3a4a2 100644 --- a/features/sketch/src/main/java/com/wire/android/feature/sketch/DrawingCanvasBottomSheet.kt +++ b/features/sketch/src/main/java/com/wire/android/feature/sketch/DrawingCanvasBottomSheet.kt @@ -28,17 +28,14 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.shape.CutCornerShape import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.AlertDialog import androidx.compose.material.Icon import androidx.compose.material.Text -import androidx.compose.material.TextButton import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Circle import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.MaterialTheme import androidx.compose.material3.ModalBottomSheet import androidx.compose.material3.ModalBottomSheetProperties -import androidx.compose.material3.SheetState import androidx.compose.material3.rememberModalBottomSheetState import androidx.compose.runtime.Composable import androidx.compose.runtime.remember @@ -47,9 +44,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextOverflow -import androidx.compose.ui.window.DialogProperties import androidx.compose.ui.window.SecureFlagPolicy import androidx.lifecycle.viewmodel.compose.viewModel import com.wire.android.feature.sketch.model.DrawingState @@ -64,10 +59,8 @@ import com.wire.android.ui.common.button.WireTertiaryIconButton import com.wire.android.ui.common.button.wireSendPrimaryButtonColors import com.wire.android.ui.common.colorsScheme import com.wire.android.ui.common.dimensions -import com.wire.android.ui.theme.wireColorScheme import com.wire.android.ui.theme.wireDimensions import com.wire.android.ui.theme.wireTypography -import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch @OptIn(ExperimentalMaterial3Api::class) @@ -234,38 +227,4 @@ private fun DrawingToolbar( ) } -@OptIn(ExperimentalMaterial3Api::class) -@Composable -private fun DiscardDialogConfirmation( - scope: CoroutineScope, - sheetState: SheetState, - onDismissSketch: () -> Unit, - onHideConfirmationDialog: () -> Unit, -) { - AlertDialog( - backgroundColor = MaterialTheme.wireColorScheme.background, - contentColor = MaterialTheme.wireColorScheme.onBackground, - onDismissRequest = onHideConfirmationDialog, - title = { Text(stringResource(R.string.confirm_changes_title)) }, - text = { Text(stringResource(R.string.confirm_changes_text)) }, - confirmButton = { - TextButton(onClick = { - scope.launch { sheetState.hide() }.invokeOnCompletion { - onHideConfirmationDialog() - onDismissSketch() - } - }) { Text(stringResource(R.string.confirm_changes_dismiss)) } - }, - dismissButton = { - TextButton(onClick = { - onHideConfirmationDialog() - }) { Text(stringResource(R.string.confirm_changes_confirm)) } - }, - properties = DialogProperties( - dismissOnBackPress = false, - dismissOnClickOutside = false - ) - ) -} - private const val MAX_LINES_TOPBAR = 1 diff --git a/features/sketch/src/main/java/com/wire/android/feature/sketch/DrawingDiscardConfirmationDialog.kt b/features/sketch/src/main/java/com/wire/android/feature/sketch/DrawingDiscardConfirmationDialog.kt new file mode 100644 index 00000000000..edf2093dde6 --- /dev/null +++ b/features/sketch/src/main/java/com/wire/android/feature/sketch/DrawingDiscardConfirmationDialog.kt @@ -0,0 +1,65 @@ +/* + * Wire + * Copyright (C) 2024 Wire Swiss GmbH + * + * 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.wire.android.feature.sketch + +import androidx.compose.material.AlertDialog +import androidx.compose.material.Text +import androidx.compose.material.TextButton +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.SheetState +import androidx.compose.runtime.Composable +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.window.DialogProperties +import com.wire.android.ui.theme.wireColorScheme +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +internal fun DiscardDialogConfirmation( + scope: CoroutineScope, + sheetState: SheetState, + onDismissSketch: () -> Unit, + onHideConfirmationDialog: () -> Unit, +) { + AlertDialog( + backgroundColor = MaterialTheme.wireColorScheme.background, + contentColor = MaterialTheme.wireColorScheme.onBackground, + onDismissRequest = onHideConfirmationDialog, + title = { Text(stringResource(R.string.confirm_changes_title)) }, + text = { Text(stringResource(R.string.confirm_changes_text)) }, + confirmButton = { + TextButton(onClick = { + scope.launch { sheetState.hide() }.invokeOnCompletion { + onHideConfirmationDialog() + onDismissSketch() + } + }) { Text(stringResource(R.string.confirm_changes_dismiss)) } + }, + dismissButton = { + TextButton(onClick = { + onHideConfirmationDialog() + }) { Text(stringResource(R.string.confirm_changes_confirm)) } + }, + properties = DialogProperties( + dismissOnBackPress = false, + dismissOnClickOutside = false + ) + ) +} From 52df95310c4ccae1ed1e39dd27f236c77ef87139 Mon Sep 17 00:00:00 2001 From: yamilmedina Date: Wed, 17 Apr 2024 09:58:01 +0200 Subject: [PATCH 06/10] feat: extract dialog to file --- ...rawingDiscardConfirmationDialog.kt => DrawingDiscardDialog.kt} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename features/sketch/src/main/java/com/wire/android/feature/sketch/{DrawingDiscardConfirmationDialog.kt => DrawingDiscardDialog.kt} (100%) diff --git a/features/sketch/src/main/java/com/wire/android/feature/sketch/DrawingDiscardConfirmationDialog.kt b/features/sketch/src/main/java/com/wire/android/feature/sketch/DrawingDiscardDialog.kt similarity index 100% rename from features/sketch/src/main/java/com/wire/android/feature/sketch/DrawingDiscardConfirmationDialog.kt rename to features/sketch/src/main/java/com/wire/android/feature/sketch/DrawingDiscardDialog.kt From 5efe21b60347036b87bf6756b776d9efc56dca81 Mon Sep 17 00:00:00 2001 From: yamilmedina Date: Wed, 17 Apr 2024 10:14:48 +0200 Subject: [PATCH 07/10] feat: commons dialog --- .../android/ui/common/PrevieWireDialog.kt | 174 ++++++++++++++++++ .../android/ui/server/ApiVersioningDialogs.kt | 11 -- .../com/wire/android/ui/common/WireDialog.kt | 155 +--------------- .../feature/sketch/DrawingDiscardDialog.kt | 44 ++--- 4 files changed, 200 insertions(+), 184 deletions(-) create mode 100644 app/src/main/kotlin/com/wire/android/ui/common/PrevieWireDialog.kt rename {app => core/ui-common}/src/main/kotlin/com/wire/android/ui/common/WireDialog.kt (65%) diff --git a/app/src/main/kotlin/com/wire/android/ui/common/PrevieWireDialog.kt b/app/src/main/kotlin/com/wire/android/ui/common/PrevieWireDialog.kt new file mode 100644 index 00000000000..c33f8f2e8ef --- /dev/null +++ b/app/src/main/kotlin/com/wire/android/ui/common/PrevieWireDialog.kt @@ -0,0 +1,174 @@ +/* + * Wire + * Copyright (C) 2024 Wire Swiss GmbH + * + * 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.wire.android.ui.common + +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.material3.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.ExperimentalComposeUiApi +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.SpanStyle +import androidx.compose.ui.text.buildAnnotatedString +import androidx.compose.ui.text.input.TextFieldValue +import androidx.compose.ui.text.withStyle +import androidx.compose.ui.tooling.preview.Preview +import com.wire.android.ui.common.button.WireButtonState +import com.wire.android.ui.common.textfield.WirePasswordTextField +import com.wire.android.ui.theme.WireTheme +import com.wire.android.ui.theme.wireTypography + +@Preview(showBackground = true) +@Composable +fun PreviewWireDialog() { + var password by remember { mutableStateOf(TextFieldValue("")) } + WireTheme { + Box( + contentAlignment = Alignment.Center, + modifier = Modifier.fillMaxWidth() + ) { + WireDialogContent( + optionButton1Properties = WireDialogButtonProperties( + text = "OK", + onClick = { }, + type = WireDialogButtonType.Primary, + state = if (password.text.isEmpty()) WireButtonState.Disabled else WireButtonState.Error, + ), + dismissButtonProperties = WireDialogButtonProperties( + text = "Cancel", + onClick = { } + ), + title = "title", + text = buildAnnotatedString { + val style = SpanStyle( + color = colorsScheme().onBackground, + fontWeight = MaterialTheme.wireTypography.body01.fontWeight, + fontSize = MaterialTheme.wireTypography.body01.fontSize, + fontFamily = MaterialTheme.wireTypography.body01.fontFamily, + fontStyle = MaterialTheme.wireTypography.body01.fontStyle + ) + withStyle(style) { append("text\nsecond line\nthirdLine\nfourth line\nfifth line\nsixth line\nseventh line") } + }, + ) { + WirePasswordTextField( + value = password, + onValueChange = { password = it }, + autofill = false + ) + } + } + } +} + +@OptIn(ExperimentalComposeUiApi::class) +@Preview(showBackground = true) +@Composable +fun PreviewWireDialogWith2OptionButtons() { + var password by remember { mutableStateOf(TextFieldValue("")) } + WireTheme { + Box( + contentAlignment = Alignment.Center, + modifier = Modifier.fillMaxWidth() + ) { + WireDialogContent( + optionButton1Properties = WireDialogButtonProperties( + text = "OK", + onClick = { }, + type = WireDialogButtonType.Primary, + state = if (password.text.isEmpty()) WireButtonState.Disabled else WireButtonState.Error, + ), + optionButton2Properties = WireDialogButtonProperties( + text = "Later", + onClick = { }, + type = WireDialogButtonType.Primary, + state = if (password.text.isEmpty()) WireButtonState.Disabled else WireButtonState.Error, + ), + dismissButtonProperties = WireDialogButtonProperties( + text = "Cancel", + onClick = { } + ), + title = "title", + text = buildAnnotatedString { + val style = SpanStyle( + color = colorsScheme().onBackground, + fontWeight = MaterialTheme.wireTypography.body01.fontWeight, + fontSize = MaterialTheme.wireTypography.body01.fontSize, + fontFamily = MaterialTheme.wireTypography.body01.fontFamily, + fontStyle = MaterialTheme.wireTypography.body01.fontStyle + ) + withStyle(style) { append("text") } + }, + buttonsHorizontalAlignment = false + ) { + WirePasswordTextField( + value = password, + onValueChange = { password = it }, + autofill = true + ) + } + } + } +} + +@Preview(showBackground = true) +@Composable +fun PreviewWireDialogCentered() { + var password by remember { mutableStateOf(TextFieldValue("")) } + WireTheme { + Box( + contentAlignment = Alignment.Center, + modifier = Modifier.fillMaxWidth() + ) { + WireDialogContent( + optionButton1Properties = WireDialogButtonProperties( + text = "OK", + onClick = { }, + type = WireDialogButtonType.Primary, + state = if (password.text.isEmpty()) WireButtonState.Disabled else WireButtonState.Error, + ), + dismissButtonProperties = WireDialogButtonProperties( + text = "Cancel", + onClick = { } + ), + centerContent = true, + title = "title", + text = buildAnnotatedString { + val style = SpanStyle( + color = colorsScheme().onBackground, + fontWeight = MaterialTheme.wireTypography.body01.fontWeight, + fontSize = MaterialTheme.wireTypography.body01.fontSize, + fontFamily = MaterialTheme.wireTypography.body01.fontFamily, + fontStyle = MaterialTheme.wireTypography.body01.fontStyle + ) + withStyle(style) { append("text\nsecond line\nthirdLine\nfourth line\nfifth line\nsixth line\nseventh line") } + }, + ) { + WirePasswordTextField( + value = password, + onValueChange = { password = it }, + autofill = false + ) + } + } + } +} diff --git a/app/src/main/kotlin/com/wire/android/ui/server/ApiVersioningDialogs.kt b/app/src/main/kotlin/com/wire/android/ui/server/ApiVersioningDialogs.kt index 3bc7c85e5e8..f93d04a3b9f 100644 --- a/app/src/main/kotlin/com/wire/android/ui/server/ApiVersioningDialogs.kt +++ b/app/src/main/kotlin/com/wire/android/ui/server/ApiVersioningDialogs.kt @@ -18,26 +18,15 @@ package com.wire.android.ui.server -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.offset -import androidx.compose.foundation.layout.width import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.ExperimentalComposeUiApi -import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource -import androidx.compose.ui.tooling.preview.Devices import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp import androidx.compose.ui.window.DialogProperties import com.wire.android.R import com.wire.android.ui.common.WireDialog import com.wire.android.ui.common.WireDialogButtonProperties import com.wire.android.ui.common.WireDialogButtonType -import com.wire.android.ui.theme.WireTheme -@OptIn(ExperimentalComposeUiApi::class) @Composable private fun ApiVersioningDialog( title: String, diff --git a/app/src/main/kotlin/com/wire/android/ui/common/WireDialog.kt b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/WireDialog.kt similarity index 65% rename from app/src/main/kotlin/com/wire/android/ui/common/WireDialog.kt rename to core/ui-common/src/main/kotlin/com/wire/android/ui/common/WireDialog.kt index 14f24856b50..79abc2029a5 100644 --- a/app/src/main/kotlin/com/wire/android/ui/common/WireDialog.kt +++ b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/WireDialog.kt @@ -31,17 +31,13 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.text.ClickableText import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.Stable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment -import androidx.compose.ui.ExperimentalComposeUiApi import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Shape import androidx.compose.ui.platform.LocalUriHandler @@ -49,9 +45,7 @@ import androidx.compose.ui.semantics.semantics import androidx.compose.ui.text.AnnotatedString import androidx.compose.ui.text.SpanStyle import androidx.compose.ui.text.buildAnnotatedString -import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.text.withStyle -import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.window.Dialog import androidx.compose.ui.window.DialogProperties import com.wire.android.ui.common.button.WireButtonState @@ -59,9 +53,6 @@ import com.wire.android.ui.common.button.WirePrimaryButton import com.wire.android.ui.common.button.WireSecondaryButton import com.wire.android.ui.common.button.WireTertiaryButton import com.wire.android.ui.common.progress.WireCircularProgressIndicator -import com.wire.android.ui.common.textfield.WirePasswordTextField -import com.wire.android.ui.markdown.MarkdownConstants -import com.wire.android.ui.theme.WireTheme import com.wire.android.ui.theme.wireColorScheme import com.wire.android.ui.theme.wireDimensions import com.wire.android.ui.theme.wireTypography @@ -160,7 +151,7 @@ fun WireDialog( } @Composable -private fun WireDialogContent( +fun WireDialogContent( title: String, titleLoading: Boolean = false, text: AnnotatedString? = null, @@ -209,7 +200,7 @@ private fun WireDialogContent( modifier = Modifier.padding(bottom = MaterialTheme.wireDimensions.dialogTextsSpacing), onClick = { offset -> text.getStringAnnotations( - tag = MarkdownConstants.TAG_URL, + tag = TAG_URL, start = offset, end = offset, ).firstOrNull()?.let { result -> uriHandler.openUri(result.item) } @@ -299,143 +290,6 @@ private fun WireDialogButtonProperties?.getButton(modifier: Modifier = Modifier) } } -@OptIn(ExperimentalComposeUiApi::class) -@Preview(showBackground = true) -@Composable -fun PreviewWireDialog() { - var password by remember { mutableStateOf(TextFieldValue("")) } - WireTheme { - Box( - contentAlignment = Alignment.Center, - modifier = Modifier.fillMaxWidth() - ) { - WireDialogContent( - optionButton1Properties = WireDialogButtonProperties( - text = "OK", - onClick = { }, - type = WireDialogButtonType.Primary, - state = if (password.text.isEmpty()) WireButtonState.Disabled else WireButtonState.Error, - ), - dismissButtonProperties = WireDialogButtonProperties( - text = "Cancel", - onClick = { } - ), - title = "title", - text = buildAnnotatedString { - val style = SpanStyle( - color = colorsScheme().onBackground, - fontWeight = MaterialTheme.wireTypography.body01.fontWeight, - fontSize = MaterialTheme.wireTypography.body01.fontSize, - fontFamily = MaterialTheme.wireTypography.body01.fontFamily, - fontStyle = MaterialTheme.wireTypography.body01.fontStyle - ) - withStyle(style) { append("text\nsecond line\nthirdLine\nfourth line\nfifth line\nsixth line\nseventh line") } - }, - ) { - WirePasswordTextField( - value = password, - onValueChange = { password = it }, - autofill = false - ) - } - } - } -} - -@OptIn(ExperimentalComposeUiApi::class) -@Preview(showBackground = true) -@Composable -fun PreviewWireDialogWith2OptionButtons() { - var password by remember { mutableStateOf(TextFieldValue("")) } - WireTheme { - Box( - contentAlignment = Alignment.Center, - modifier = Modifier.fillMaxWidth() - ) { - WireDialogContent( - optionButton1Properties = WireDialogButtonProperties( - text = "OK", - onClick = { }, - type = WireDialogButtonType.Primary, - state = if (password.text.isEmpty()) WireButtonState.Disabled else WireButtonState.Error, - ), - optionButton2Properties = WireDialogButtonProperties( - text = "Later", - onClick = { }, - type = WireDialogButtonType.Primary, - state = if (password.text.isEmpty()) WireButtonState.Disabled else WireButtonState.Error, - ), - dismissButtonProperties = WireDialogButtonProperties( - text = "Cancel", - onClick = { } - ), - title = "title", - text = buildAnnotatedString { - val style = SpanStyle( - color = colorsScheme().onBackground, - fontWeight = MaterialTheme.wireTypography.body01.fontWeight, - fontSize = MaterialTheme.wireTypography.body01.fontSize, - fontFamily = MaterialTheme.wireTypography.body01.fontFamily, - fontStyle = MaterialTheme.wireTypography.body01.fontStyle - ) - withStyle(style) { append("text") } - }, - buttonsHorizontalAlignment = false - ) { - WirePasswordTextField( - value = password, - onValueChange = { password = it }, - autofill = true - ) - } - } - } -} - -@OptIn(ExperimentalComposeUiApi::class) -@Preview(showBackground = true) -@Composable -fun PreviewWireDialogCentered() { - var password by remember { mutableStateOf(TextFieldValue("")) } - WireTheme { - Box( - contentAlignment = Alignment.Center, - modifier = Modifier.fillMaxWidth() - ) { - WireDialogContent( - optionButton1Properties = WireDialogButtonProperties( - text = "OK", - onClick = { }, - type = WireDialogButtonType.Primary, - state = if (password.text.isEmpty()) WireButtonState.Disabled else WireButtonState.Error, - ), - dismissButtonProperties = WireDialogButtonProperties( - text = "Cancel", - onClick = { } - ), - centerContent = true, - title = "title", - text = buildAnnotatedString { - val style = SpanStyle( - color = colorsScheme().onBackground, - fontWeight = MaterialTheme.wireTypography.body01.fontWeight, - fontSize = MaterialTheme.wireTypography.body01.fontSize, - fontFamily = MaterialTheme.wireTypography.body01.fontFamily, - fontStyle = MaterialTheme.wireTypography.body01.fontStyle - ) - withStyle(style) { append("text\nsecond line\nthirdLine\nfourth line\nfifth line\nsixth line\nseventh line") } - }, - ) { - WirePasswordTextField( - value = password, - onValueChange = { password = it }, - autofill = false - ) - } - } - } -} - enum class WireDialogButtonType { Primary, Secondary, Tertiary } data class WireDialogButtonProperties( @@ -445,3 +299,6 @@ data class WireDialogButtonProperties( val type: WireDialogButtonType = WireDialogButtonType.Secondary, val loading: Boolean = false ) + +// todo, replace when markdown is moved to commons +private const val TAG_URL = "linkTag" diff --git a/features/sketch/src/main/java/com/wire/android/feature/sketch/DrawingDiscardDialog.kt b/features/sketch/src/main/java/com/wire/android/feature/sketch/DrawingDiscardDialog.kt index edf2093dde6..bd4747bf777 100644 --- a/features/sketch/src/main/java/com/wire/android/feature/sketch/DrawingDiscardDialog.kt +++ b/features/sketch/src/main/java/com/wire/android/feature/sketch/DrawingDiscardDialog.kt @@ -17,16 +17,15 @@ */ package com.wire.android.feature.sketch -import androidx.compose.material.AlertDialog -import androidx.compose.material.Text -import androidx.compose.material.TextButton import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.MaterialTheme import androidx.compose.material3.SheetState import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource import androidx.compose.ui.window.DialogProperties -import com.wire.android.ui.theme.wireColorScheme +import com.wire.android.ui.common.WireDialog +import com.wire.android.ui.common.WireDialogButtonProperties +import com.wire.android.ui.common.WireDialogButtonType +import com.wire.android.ui.common.button.WireButtonState import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch @@ -38,28 +37,25 @@ internal fun DiscardDialogConfirmation( onDismissSketch: () -> Unit, onHideConfirmationDialog: () -> Unit, ) { - AlertDialog( - backgroundColor = MaterialTheme.wireColorScheme.background, - contentColor = MaterialTheme.wireColorScheme.onBackground, - onDismissRequest = onHideConfirmationDialog, - title = { Text(stringResource(R.string.confirm_changes_title)) }, - text = { Text(stringResource(R.string.confirm_changes_text)) }, - confirmButton = { - TextButton(onClick = { + WireDialog( + title = stringResource(id = R.string.confirm_changes_title), + text = stringResource(id = R.string.confirm_changes_text), + onDismiss = onHideConfirmationDialog, + optionButton1Properties = WireDialogButtonProperties( + onClick = { scope.launch { sheetState.hide() }.invokeOnCompletion { onHideConfirmationDialog() onDismissSketch() } - }) { Text(stringResource(R.string.confirm_changes_dismiss)) } - }, - dismissButton = { - TextButton(onClick = { - onHideConfirmationDialog() - }) { Text(stringResource(R.string.confirm_changes_confirm)) } - }, - properties = DialogProperties( - dismissOnBackPress = false, - dismissOnClickOutside = false - ) + }, + text = stringResource(id = R.string.confirm_changes_dismiss), + type = WireDialogButtonType.Primary, + state = WireButtonState.Error + ), + dismissButtonProperties = WireDialogButtonProperties( + text = stringResource(id = R.string.confirm_changes_confirm), + onClick = onHideConfirmationDialog + ), + properties = DialogProperties(usePlatformDefaultWidth = false, dismissOnBackPress = false, dismissOnClickOutside = false) ) } From 0339332ae90f91e7aed41b5ddc2c1bb88f55b345 Mon Sep 17 00:00:00 2001 From: yamilmedina Date: Wed, 17 Apr 2024 11:07:07 +0200 Subject: [PATCH 08/10] feat: test coverage --- .../sketch/DrawingCanvasViewModelTest.kt | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/features/sketch/src/test/java/com/wire/android/feature/sketch/DrawingCanvasViewModelTest.kt b/features/sketch/src/test/java/com/wire/android/feature/sketch/DrawingCanvasViewModelTest.kt index 18a08020773..c283683861a 100644 --- a/features/sketch/src/test/java/com/wire/android/feature/sketch/DrawingCanvasViewModelTest.kt +++ b/features/sketch/src/test/java/com/wire/android/feature/sketch/DrawingCanvasViewModelTest.kt @@ -1,6 +1,7 @@ package com.wire.android.feature.sketch import androidx.compose.ui.geometry.Offset +import androidx.compose.ui.graphics.Color import com.wire.android.feature.sketch.model.DrawingMotionEvent import kotlinx.coroutines.test.runTest import org.junit.Assert.assertEquals @@ -94,6 +95,50 @@ class DrawingCanvasViewModelTest { } } + @Test + fun givenOnColorChanged_WhenCallingTheAction_ThenUpdateCurrentPathWithTheSelectedColor() = runTest { + // given + val (_, viewModel) = Arrangement().arrange() + assertEquals(viewModel.state.currentPath.color, Color.Black) + + // when + val newColor = Color.Magenta + viewModel.onColorChanged(newColor) + + // then + with(viewModel.state) { + assertEquals(currentPath.color, newColor) + } + } + + @Test + fun givenWeWantToDiscard_WhenCallingTheAction_ThenUpdateStateToShowConfirmation() = runTest { + // given + val (_, viewModel) = Arrangement().arrange() + + // when + viewModel.onShowConfirmationDialog() + + // then + with(viewModel.state) { + assertEquals(true, showConfirmationDialog) + } + } + + @Test + fun givenWeCancelToDiscard_WhenCallingTheAction_ThenUpdateStateToHideConfirmation() = runTest { + // given + val (_, viewModel) = Arrangement().arrange() + + // when + viewModel.onHideConfirmationDialog() + + // then + with(viewModel.state) { + assertEquals(false, showConfirmationDialog) + } + } + private fun stopDrawing(viewModel: DrawingCanvasViewModel) = with(viewModel) { draw(viewModel) onStopDrawing() From 592a9a9506037b7fee6ffd64979e5d124ba68500 Mon Sep 17 00:00:00 2001 From: yamilmedina Date: Wed, 17 Apr 2024 11:21:55 +0200 Subject: [PATCH 09/10] feat: wrong name in file --- .../ui/common/{PrevieWireDialog.kt => PreviewWireDialog.kt} | 0 .../android/feature/sketch/model/DrawingPathProperties.kt | 4 ++++ 2 files changed, 4 insertions(+) rename app/src/main/kotlin/com/wire/android/ui/common/{PrevieWireDialog.kt => PreviewWireDialog.kt} (100%) diff --git a/app/src/main/kotlin/com/wire/android/ui/common/PrevieWireDialog.kt b/app/src/main/kotlin/com/wire/android/ui/common/PreviewWireDialog.kt similarity index 100% rename from app/src/main/kotlin/com/wire/android/ui/common/PrevieWireDialog.kt rename to app/src/main/kotlin/com/wire/android/ui/common/PreviewWireDialog.kt diff --git a/features/sketch/src/main/java/com/wire/android/feature/sketch/model/DrawingPathProperties.kt b/features/sketch/src/main/java/com/wire/android/feature/sketch/model/DrawingPathProperties.kt index 2a533337928..44e66765510 100644 --- a/features/sketch/src/main/java/com/wire/android/feature/sketch/model/DrawingPathProperties.kt +++ b/features/sketch/src/main/java/com/wire/android/feature/sketch/model/DrawingPathProperties.kt @@ -34,6 +34,10 @@ import androidx.compose.ui.graphics.drawscope.DrawScope import androidx.compose.ui.graphics.drawscope.Stroke import androidx.compose.ui.graphics.toArgb +/** + * Represents the current path properties [DrawingState.currentPath] + * This can be extended in the future to [strokeWidth], [drawMode] ,etc. + */ internal class DrawingPathProperties( var path: Path = Path(), var strokeWidth: Float = 10f, From ebdf6c0efd899ec18048d67507e3937bc3f01803 Mon Sep 17 00:00:00 2001 From: yamilmedina Date: Wed, 17 Apr 2024 12:22:05 +0200 Subject: [PATCH 10/10] feat: preview to components --- .../sketch/DrawingCanvasBottomSheet.kt | 26 ++++++++++--- .../sketch/PreviewDrawingComponents.kt | 39 +++++++++++++++++++ 2 files changed, 59 insertions(+), 6 deletions(-) create mode 100644 features/sketch/src/main/java/com/wire/android/feature/sketch/PreviewDrawingComponents.kt diff --git a/features/sketch/src/main/java/com/wire/android/feature/sketch/DrawingCanvasBottomSheet.kt b/features/sketch/src/main/java/com/wire/android/feature/sketch/DrawingCanvasBottomSheet.kt index d9348f3a4a2..15d60f7361a 100644 --- a/features/sketch/src/main/java/com/wire/android/feature/sketch/DrawingCanvasBottomSheet.kt +++ b/features/sketch/src/main/java/com/wire/android/feature/sketch/DrawingCanvasBottomSheet.kt @@ -18,6 +18,8 @@ package com.wire.android.feature.sketch import android.net.Uri +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.border import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row @@ -26,13 +28,14 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size +import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.CutCornerShape import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.Icon import androidx.compose.material.Text import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Circle import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.ModalBottomSheet import androidx.compose.material3.ModalBottomSheetProperties @@ -137,7 +140,7 @@ fun DrawingCanvasBottomSheet( } @Composable -private fun DrawingTopBar( +internal fun DrawingTopBar( conversationTitle: String, dismissAction: () -> Unit, onUndoStroke: () -> Unit, @@ -176,7 +179,7 @@ private fun DrawingTopBar( @OptIn(ExperimentalMaterial3Api::class) @Composable -private fun DrawingToolbar( +internal fun DrawingToolbar( state: DrawingState, onColorChanged: (Color) -> Unit, onSendSketch: () -> Unit = {}, @@ -194,14 +197,25 @@ private fun DrawingToolbar( horizontalArrangement = Arrangement.SpaceBetween ) { WireSecondaryButton( - onClick = { openColorPickerSheet() }, - leadingIcon = { Icon(Icons.Default.Circle, null, tint = state.currentPath.color) }, + onClick = openColorPickerSheet, + leadingIcon = { + Icon( + Icons.Default.Circle, + null, + tint = state.currentPath.color, + modifier = Modifier + .border( + shape = CircleShape, + border = BorderStroke(dimensions().spacing1x, colorsScheme().secondaryText) + ) + ) + }, leadingIconAlignment = IconAlignment.Center, fillMaxWidth = false, minSize = dimensions().buttonSmallMinSize, minClickableSize = dimensions().buttonMinClickableSize, shape = RoundedCornerShape(dimensions().spacing12x), - contentPadding = PaddingValues(horizontal = dimensions().spacing8x, vertical = dimensions().spacing4x) + contentPadding = PaddingValues(horizontal = dimensions().spacing8x, vertical = dimensions().spacing4x), ) Spacer(Modifier.size(dimensions().spacing2x)) WirePrimaryIconButton( diff --git a/features/sketch/src/main/java/com/wire/android/feature/sketch/PreviewDrawingComponents.kt b/features/sketch/src/main/java/com/wire/android/feature/sketch/PreviewDrawingComponents.kt new file mode 100644 index 00000000000..b7146cf9173 --- /dev/null +++ b/features/sketch/src/main/java/com/wire/android/feature/sketch/PreviewDrawingComponents.kt @@ -0,0 +1,39 @@ +/* + * Wire + * Copyright (C) 2024 Wire Swiss GmbH + * + * 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.wire.android.feature.sketch + +import androidx.compose.runtime.Composable +import androidx.compose.ui.tooling.preview.Preview +import com.wire.android.feature.sketch.model.DrawingState +import com.wire.android.ui.theme.WireTheme + +@Preview(showBackground = true) +@Composable +fun PreviewToolBar() { + WireTheme { + DrawingToolbar(DrawingState(), {}, {}) + } +} + +@Preview(showBackground = true) +@Composable +fun PreviewTopBar() { + WireTheme { + DrawingTopBar("Conversation Name", {}, {}, DrawingState()) + } +}