Skip to content

Commit ef7d1b0

Browse files
committed
feat(common, saved): deletion confirmation
1 parent 52c4e56 commit ef7d1b0

File tree

5 files changed

+236
-133
lines changed

5 files changed

+236
-133
lines changed

core/shared-ui/src/commonMain/kotlin/com/neoutils/neoregex/core/sharedui/component/Menu.kt

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ import androidx.compose.material.icons.filled.*
3333
import androidx.compose.material3.DropdownMenu
3434
import androidx.compose.material3.DropdownMenuItem
3535
import androidx.compose.material3.Icon
36+
import androidx.compose.material3.MaterialTheme.colorScheme
37+
import androidx.compose.material3.MaterialTheme.typography
3638
import androidx.compose.material3.Text
3739
import androidx.compose.runtime.*
3840
import androidx.compose.ui.Modifier
@@ -42,11 +44,11 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
4244
import com.neoutils.neoregex.core.designsystem.theme.configButton
4345
import com.neoutils.neoregex.core.dispatcher.control.Controller
4446
import com.neoutils.neoregex.core.dispatcher.event.Command
47+
import com.neoutils.neoregex.core.dispatcher.model.Navigation
4548
import com.neoutils.neoregex.core.dispatcher.navigator.NavigationManager
4649
import com.neoutils.neoregex.core.manager.salvage.SalvageManager
4750
import kotlinx.coroutines.launch
4851
import org.koin.compose.koinInject
49-
import com.neoutils.neoregex.core.dispatcher.model.Navigation
5052

5153
@Composable
5254
fun Menu(
@@ -192,6 +194,18 @@ fun Menu(
192194
coroutine.launch {
193195
control.dispatcher(Command.Save(it))
194196
}
197+
},
198+
confirmLabel = {
199+
Text(text = "Save")
200+
},
201+
title = {
202+
Text(
203+
text = "Save pattern",
204+
color = colorScheme.onSurfaceVariant,
205+
style = typography.titleSmall.copy(
206+
fontFamily = null,
207+
)
208+
)
195209
}
196210
)
197211
}
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
/*
2+
* NeoRegex.
3+
*
4+
* Copyright (C) 2025 Irineu A. Silva.
5+
*
6+
* This program is free software: you can redistribute it and/or modify
7+
* it under the terms of the GNU General Public License as published by
8+
* the Free Software Foundation, either version 3 of the License.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
17+
*/
18+
19+
package com.neoutils.neoregex.core.sharedui.component
20+
21+
import androidx.compose.foundation.BorderStroke
22+
import androidx.compose.foundation.background
23+
import androidx.compose.foundation.layout.*
24+
import androidx.compose.foundation.shape.RoundedCornerShape
25+
import androidx.compose.material3.*
26+
import androidx.compose.material3.MaterialTheme.colorScheme
27+
import androidx.compose.runtime.Composable
28+
import androidx.compose.ui.Alignment
29+
import androidx.compose.ui.Modifier
30+
import androidx.compose.ui.unit.dp
31+
32+
@OptIn(ExperimentalMaterial3Api::class)
33+
@Composable
34+
fun NeoRegexDialog(
35+
onDismissRequest: () -> Unit,
36+
onConfirm: () -> Unit,
37+
modifier: Modifier = Modifier,
38+
title: @Composable () -> Unit,
39+
enableConfirm: Boolean = true,
40+
cancelLabel: @Composable () -> Unit = {
41+
Text(text = "Cancel")
42+
},
43+
confirmLabel: @Composable () -> Unit = {
44+
Text(text = "Delete")
45+
},
46+
content: @Composable () -> Unit
47+
) = BasicAlertDialog(
48+
onDismissRequest = onDismissRequest,
49+
modifier = modifier
50+
) {
51+
Surface(
52+
color = colorScheme.background,
53+
contentColor = colorScheme.onBackground,
54+
border = BorderStroke(width = 1.dp, colorScheme.outline)
55+
) {
56+
Column {
57+
Box(
58+
modifier = Modifier
59+
.background(colorScheme.surfaceVariant)
60+
.padding(horizontal = 16.dp)
61+
.fillMaxWidth()
62+
.height(40.dp),
63+
contentAlignment = Alignment.Center
64+
) {
65+
title()
66+
}
67+
68+
HorizontalDivider(color = colorScheme.outlineVariant)
69+
70+
Column(
71+
modifier = Modifier.padding(16.dp),
72+
horizontalAlignment = Alignment.CenterHorizontally
73+
) {
74+
75+
content()
76+
77+
Spacer(Modifier.height(16.dp))
78+
79+
Row(
80+
modifier = Modifier.fillMaxWidth(),
81+
horizontalArrangement = Arrangement.SpaceAround
82+
) {
83+
OutlinedButton(
84+
onClick = {
85+
onDismissRequest()
86+
},
87+
shape = RoundedCornerShape(8.dp),
88+
colors = ButtonDefaults.outlinedButtonColors(
89+
contentColor = colorScheme.onBackground
90+
)
91+
) {
92+
cancelLabel()
93+
}
94+
95+
OutlinedButton(
96+
onClick = {
97+
onConfirm()
98+
onDismissRequest()
99+
},
100+
enabled = enableConfirm,
101+
shape = RoundedCornerShape(8.dp),
102+
colors = ButtonDefaults.outlinedButtonColors(
103+
contentColor = colorScheme.onBackground
104+
)
105+
) {
106+
confirmLabel()
107+
}
108+
}
109+
}
110+
}
111+
}
112+
}

core/shared-ui/src/commonMain/kotlin/com/neoutils/neoregex/core/sharedui/component/PatternNameDialog.kt

Lines changed: 55 additions & 125 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,16 @@
1818

1919
package com.neoutils.neoregex.core.sharedui.component
2020

21-
import androidx.compose.foundation.BorderStroke
22-
import androidx.compose.foundation.background
2321
import androidx.compose.foundation.border
24-
import androidx.compose.foundation.layout.*
22+
import androidx.compose.foundation.layout.PaddingValues
23+
import androidx.compose.foundation.layout.fillMaxWidth
2524
import androidx.compose.foundation.shape.RoundedCornerShape
2625
import androidx.compose.foundation.text.KeyboardActions
27-
import androidx.compose.material3.*
26+
import androidx.compose.material3.LocalTextStyle
2827
import androidx.compose.material3.MaterialTheme.colorScheme
2928
import androidx.compose.material3.MaterialTheme.typography
29+
import androidx.compose.material3.Text
3030
import androidx.compose.runtime.*
31-
import androidx.compose.ui.Alignment
3231
import androidx.compose.ui.Modifier
3332
import androidx.compose.ui.focus.FocusRequester
3433
import androidx.compose.ui.focus.focusRequester
@@ -38,137 +37,68 @@ import androidx.compose.ui.unit.dp
3837
import com.neoutils.neoregex.core.designsystem.textfield.NeoTextField
3938
import com.neoutils.neoregex.core.designsystem.theme.NeoTheme.dimensions
4039

41-
@OptIn(ExperimentalMaterial3Api::class)
4240
@Composable
4341
fun PatternNameDialog(
4442
onDismissRequest: () -> Unit,
4543
onConfirm: (String) -> Unit,
4644
modifier: Modifier = Modifier,
47-
name: MutableState<String> = remember { mutableStateOf("") },
48-
hint: @Composable () -> Unit = {
49-
Text(
50-
text = "Pattern name",
51-
style = LocalTextStyle.current.let {
52-
it.copy(
53-
color = it.color.copy(
54-
alpha = 0.5f
55-
)
56-
)
57-
},
58-
overflow = TextOverflow.Ellipsis,
59-
maxLines = 1
60-
)
61-
},
62-
title: @Composable () -> Unit = {
63-
Text(
64-
text = "Save pattern",
65-
color = colorScheme.onSurfaceVariant,
66-
style = typography.titleSmall.copy(
67-
fontFamily = null,
68-
)
69-
)
70-
},
71-
cancelLabel: @Composable () -> Unit = {
72-
Text(text = "Cancel")
73-
},
74-
confirmLabel: @Composable () -> Unit = {
75-
Text(text = "Save")
76-
}
77-
) = BasicAlertDialog(
45+
name: MutableState<String> = remember { mutableStateOf("") },
46+
title: @Composable () -> Unit,
47+
confirmLabel: @Composable () -> Unit
48+
) = NeoRegexDialog(
7849
onDismissRequest = onDismissRequest,
50+
title = title,
51+
confirmLabel = confirmLabel,
52+
onConfirm = {
53+
onConfirm(name.value)
54+
},
55+
enableConfirm = name.value.isNotBlank(),
7956
modifier = modifier
8057
) {
81-
Surface(
82-
color = colorScheme.background,
83-
contentColor = colorScheme.onBackground,
84-
border = BorderStroke(width = 1.dp, colorScheme.outline)
85-
) {
86-
Column {
87-
Box(
88-
modifier = Modifier
89-
.background(colorScheme.surfaceVariant)
90-
.padding(horizontal = 16.dp)
91-
.fillMaxWidth()
92-
.height(40.dp),
93-
contentAlignment = Alignment.Center
94-
) {
95-
title()
96-
}
97-
98-
HorizontalDivider(color = colorScheme.outlineVariant)
99-
100-
Column(
101-
modifier = Modifier.padding(16.dp),
102-
horizontalAlignment = Alignment.CenterHorizontally
103-
) {
104-
105-
var focused by remember { mutableStateOf(false) }
58+
var focused by remember { mutableStateOf(false) }
10659

107-
val focusRequester = remember { FocusRequester() }
60+
val focusRequester = remember { FocusRequester() }
10861

109-
LaunchedEffect(Unit) { focusRequester.requestFocus() }
62+
LaunchedEffect(Unit) { focusRequester.requestFocus() }
11063

111-
NeoTextField(
112-
hint = hint,
113-
value = name.value,
114-
onValueChange = { name.value = it },
115-
keyboardActions = KeyboardActions(
116-
onDone = {
117-
onConfirm(name.value)
118-
onDismissRequest()
119-
}
120-
),
121-
singleLine = true,
122-
textStyle = typography.bodyMedium.copy(
123-
color = colorScheme.onBackground
124-
),
125-
contentPadding = PaddingValues(dimensions.wide),
126-
modifier = Modifier
127-
.fillMaxWidth()
128-
.focusRequester(focusRequester)
129-
.onFocusChanged { focused = it.isFocused }
130-
.border(
131-
width = 1.dp,
132-
color = colorScheme.outline.copy(
133-
alpha = if (focused) 1f else 0.5f
134-
),
135-
shape = RoundedCornerShape(4.dp)
136-
)
137-
)
138-
139-
Spacer(Modifier.height(16.dp))
140-
141-
Row(
142-
modifier = Modifier.fillMaxWidth(),
143-
horizontalArrangement = Arrangement.SpaceAround
144-
) {
145-
OutlinedButton(
146-
onClick = {
147-
onDismissRequest()
148-
},
149-
shape = RoundedCornerShape(8.dp),
150-
colors = ButtonDefaults.outlinedButtonColors(
151-
contentColor = colorScheme.onBackground
152-
)
153-
) {
154-
cancelLabel()
155-
}
156-
157-
OutlinedButton(
158-
onClick = {
159-
onConfirm(name.value)
160-
onDismissRequest()
161-
},
162-
enabled = name.value.isNotBlank(),
163-
shape = RoundedCornerShape(8.dp),
164-
colors = ButtonDefaults.outlinedButtonColors(
165-
contentColor = colorScheme.onBackground
166-
)
167-
) {
168-
confirmLabel()
169-
}
170-
}
64+
NeoTextField(
65+
value = name.value,
66+
onValueChange = { name.value = it },
67+
keyboardActions = KeyboardActions(
68+
onDone = {
69+
onConfirm(name.value)
70+
onDismissRequest()
17171
}
72+
),
73+
singleLine = true,
74+
textStyle = typography.bodyMedium.copy(
75+
color = colorScheme.onBackground
76+
),
77+
contentPadding = PaddingValues(dimensions.wide),
78+
modifier = Modifier
79+
.fillMaxWidth()
80+
.focusRequester(focusRequester)
81+
.onFocusChanged { focused = it.isFocused }
82+
.border(
83+
width = 1.dp,
84+
color = colorScheme.outline.copy(
85+
alpha = if (focused) 1f else 0.5f
86+
),
87+
shape = RoundedCornerShape(4.dp)
88+
),
89+
hint = {
90+
Text(
91+
text = "Pattern name",
92+
style = LocalTextStyle.current.let {
93+
it.copy(
94+
color = it.color.copy(
95+
alpha = 0.5f
96+
)
97+
)
98+
},
99+
overflow = TextOverflow.Ellipsis,
100+
maxLines = 1
101+
)
172102
}
173-
}
103+
)
174104
}

core/shared-ui/src/commonMain/kotlin/com/neoutils/neoregex/core/sharedui/component/SalvageUi.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ fun SalvageUi(
164164
},
165165
confirmLabel = {
166166
Text(text = "Confirm")
167-
}
167+
},
168168
)
169169
}
170170
}

0 commit comments

Comments
 (0)