Skip to content

Commit ca4fe88

Browse files
authored
Merge pull request #67 from NeoUtils/develop
Release v2.6.0 - Web Parity Update
2 parents 3bc8318 + 0d934db commit ca4fe88

File tree

25 files changed

+733
-352
lines changed

25 files changed

+733
-352
lines changed

.idea/misc.xml

Lines changed: 0 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

application/src/commonMain/kotlin/com/neoutils/neoregex/App.kt

Lines changed: 38 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -16,19 +16,27 @@
1616
* along with this program. If not, see <https://www.gnu.org/licenses/>.
1717
*/
1818

19+
@file:OptIn(InternalVoyagerApi::class)
20+
1921
package com.neoutils.neoregex
2022

2123
import androidx.compose.runtime.Composable
2224
import androidx.compose.runtime.LaunchedEffect
25+
import androidx.compose.runtime.getValue
26+
import androidx.compose.runtime.rememberCoroutineScope
2327
import androidx.compose.ui.Modifier
28+
import androidx.lifecycle.compose.collectAsStateWithLifecycle
29+
import cafe.adriel.voyager.core.annotation.InternalVoyagerApi
2430
import cafe.adriel.voyager.navigator.Navigator
31+
import cafe.adriel.voyager.navigator.internal.BackHandler
2532
import cafe.adriel.voyager.transitions.FadeTransition
2633
import com.neoutils.neoregex.core.designsystem.theme.NeoBackground
2734
import com.neoutils.neoregex.core.dispatcher.NavigationManager
2835
import com.neoutils.neoregex.core.dispatcher.model.Navigation
2936
import com.neoutils.neoregex.feature.about.screen.AboutScreen
3037
import com.neoutils.neoregex.feature.about.screen.LibrariesScreen
3138
import com.neoutils.neoregex.feature.matcher.MatcherScreen
39+
import kotlinx.coroutines.launch
3240
import org.koin.compose.koinInject
3341

3442
@Composable
@@ -41,38 +49,51 @@ fun App(
4149
screen = MatcherScreen(),
4250
) { navigator ->
4351

44-
LaunchedEffect(navigator.lastItem) {
45-
when (navigator.lastItem) {
46-
is MatcherScreen -> {
47-
navigation.setScreen(Navigation.Screen.Matcher)
48-
}
52+
val canPop by navigation.canPopBack.collectAsStateWithLifecycle()
4953

50-
is AboutScreen -> {
51-
navigation.setScreen(Navigation.Screen.About)
52-
}
54+
val coroutines = rememberCoroutineScope()
5355

54-
is LibrariesScreen -> {
55-
navigation.setScreen(Navigation.Screen.Libraries)
56-
}
56+
BackHandler(enabled = canPop) {
57+
coroutines.launch {
58+
navigation.emit(
59+
Navigation.Event.OnBack
60+
)
5761
}
5862
}
5963

6064
LaunchedEffect(Unit) {
6165
navigation.event.collect { event ->
6266
when (event) {
63-
Navigation.Event.Matcher -> {
64-
navigator.popUntilRoot()
65-
}
67+
is Navigation.Event.Navigate -> {
68+
when (event.screen) {
69+
Navigation.Screen.About -> {
70+
navigator.push(AboutScreen())
71+
}
6672

67-
Navigation.Event.About -> {
68-
navigator.popUntilRoot()
69-
navigator.push(AboutScreen())
73+
Navigation.Screen.Libraries -> {
74+
navigator.push(LibrariesScreen())
75+
}
76+
77+
Navigation.Screen.Matcher -> {
78+
navigator.popUntilRoot()
79+
}
80+
}
7081
}
7182

7283
Navigation.Event.OnBack -> {
7384
navigator.pop()
7485
}
7586
}
87+
88+
navigation.update(
89+
screen = when (navigator.lastItem) {
90+
is MatcherScreen -> Navigation.Screen.Matcher
91+
is AboutScreen -> Navigation.Screen.About
92+
is LibrariesScreen -> Navigation.Screen.Libraries
93+
94+
else -> error("Invalid screen")
95+
}
96+
)
7697
}
7798
}
7899

application/src/webMain/kotlin/com/neoutils/neoregex/App.web.kt

Lines changed: 8 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,17 @@ import androidx.compose.material.icons.rounded.Close
3131
import androidx.compose.material3.*
3232
import androidx.compose.material3.MaterialTheme.colorScheme
3333
import androidx.compose.material3.MaterialTheme.typography
34-
import androidx.compose.runtime.*
34+
import androidx.compose.runtime.Composable
35+
import androidx.compose.runtime.CompositionLocalProvider
36+
import androidx.compose.runtime.LaunchedEffect
37+
import androidx.compose.runtime.getValue
3538
import androidx.compose.ui.Alignment
3639
import androidx.compose.ui.Modifier
3740
import androidx.compose.ui.draw.clip
3841
import androidx.compose.ui.graphics.Color
3942
import androidx.compose.ui.graphics.RectangleShape
4043
import androidx.compose.ui.platform.LocalDensity
4144
import androidx.compose.ui.text.font.FontWeight
42-
import androidx.compose.ui.text.style.TextDecoration
4345
import androidx.compose.ui.unit.Dp
4446
import androidx.compose.ui.unit.dp
4547
import androidx.compose.ui.unit.sp
@@ -49,20 +51,16 @@ import com.neoutils.neoregex.core.common.util.ColorTheme
4951
import com.neoutils.neoregex.core.common.util.rememberColorTheme
5052
import com.neoutils.neoregex.core.datasource.PreferencesDataSource
5153
import com.neoutils.neoregex.core.datasource.model.Preferences
52-
import com.neoutils.neoregex.core.designsystem.component.Link
53-
import com.neoutils.neoregex.core.designsystem.component.LinkColor
5454
import com.neoutils.neoregex.core.designsystem.theme.NeoTheme
5555
import com.neoutils.neoregex.core.designsystem.theme.NeoTheme.dimensions
56-
import com.neoutils.neoregex.core.dispatcher.NavigationManager
57-
import com.neoutils.neoregex.core.dispatcher.model.Navigation
5856
import com.neoutils.neoregex.core.resources.Res
5957
import com.neoutils.neoregex.core.resources.app_name
6058
import com.neoutils.neoregex.core.resources.web_warning_text
59+
import com.neoutils.neoregex.core.sharedui.component.Navigation
6160
import com.neoutils.neoregex.core.sharedui.component.Options
6261
import com.neoutils.neoregex.core.sharedui.di.WithKoin
6362
import com.neoutils.neoregex.core.sharedui.extension.surface
6463
import kotlinx.browser.document
65-
import kotlinx.coroutines.launch
6664
import org.jetbrains.compose.resources.stringResource
6765
import org.koin.compose.koinInject
6866

@@ -113,7 +111,6 @@ fun WebApp() = WithKoin {
113111
@Composable
114112
private fun Header(
115113
modifier: Modifier = Modifier,
116-
navigation: NavigationManager = koinInject(),
117114
shadowElevation: Dp = dimensions.tiny
118115
) = TopAppBar(
119116
modifier = modifier.surface(
@@ -124,10 +121,9 @@ private fun Header(
124121
}
125122
),
126123
title = {
127-
val screen by navigation.screen.collectAsStateWithLifecycle()
128-
129124
Row(
130-
verticalAlignment = Alignment.CenterVertically
125+
verticalAlignment = Alignment.CenterVertically,
126+
horizontalArrangement = Arrangement.spacedBy(18.dp)
131127
) {
132128
Text(
133129
text = stringResource(Res.string.app_name),
@@ -136,76 +132,7 @@ private fun Header(
136132
),
137133
)
138134

139-
Spacer(Modifier.width(18.dp))
140-
141-
val coroutine = rememberCoroutineScope()
142-
143-
Row(
144-
horizontalArrangement = Arrangement.spacedBy(8.dp)
145-
) {
146-
val colors = LinkColor(
147-
idle = colorScheme.onSurface,
148-
hover = colorScheme.onSurface.copy(alpha = 0.8f),
149-
press = colorScheme.onSurface.copy(alpha = 0.6f),
150-
pressed = colorScheme.onSurface
151-
)
152-
153-
Link(
154-
text = "Matcher",
155-
onClick = {
156-
coroutine.launch {
157-
navigation.navigate(
158-
Navigation.Event.Matcher
159-
)
160-
}
161-
},
162-
style = typography.labelMedium.copy(
163-
textDecoration = TextDecoration.None,
164-
fontWeight = if (screen == Navigation.Screen.Matcher) {
165-
FontWeight.Bold
166-
} else {
167-
FontWeight.Normal
168-
}
169-
),
170-
enabled = screen != Navigation.Screen.Matcher,
171-
colors = colors,
172-
)
173-
174-
Link(
175-
text = "About",
176-
onClick = {
177-
coroutine.launch {
178-
navigation.navigate(
179-
Navigation.Event.About
180-
)
181-
}
182-
},
183-
style = typography.labelMedium.copy(
184-
textDecoration = TextDecoration.None,
185-
fontWeight = if (screen == Navigation.Screen.About) {
186-
FontWeight.Bold
187-
} else {
188-
FontWeight.Normal
189-
}
190-
),
191-
enabled = screen != Navigation.Screen.About,
192-
colors = colors
193-
)
194-
195-
AnimatedVisibility(
196-
visible = screen == Navigation.Screen.Libraries
197-
) {
198-
Link(
199-
text = "Libraries",
200-
style = typography.labelMedium.copy(
201-
textDecoration = TextDecoration.None,
202-
fontWeight = FontWeight.Bold
203-
),
204-
enabled = false,
205-
colors = colors
206-
)
207-
}
208-
}
135+
Navigation()
209136
}
210137
},
211138
actions = {
@@ -275,4 +202,3 @@ fun TopLabel(
275202

276203
content()
277204
}
278-

application/src/webMain/resources/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<head>
44
<meta name="viewport" content="width=device-width, initial-scale=1.0">
55
<link rel="icon" href="favicon.ico" type="image/x-icon">
6-
<title>NeoRegex - Regular expression validator</title>
6+
<title>NeoRegex</title>
77
<script src="skiko.js"></script>
88
<link type="text/css" rel="stylesheet" href="styles.css">
99
</head>

build-logic/src/main/kotlin/extension/Project.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ import org.gradle.kotlin.dsl.the
2626
val config = Config(
2727
version = Config.Version(
2828
major = 2,
29-
minor = 5,
30-
patch = 2,
29+
minor = 6,
30+
patch = 0,
3131
phase = Config.Phase.RELEASE
3232
),
3333
android = Config.Android(

core/dispatcher/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ kotlin {
2929
sourceSets {
3030
commonMain.dependencies {
3131
api(projects.core.common)
32+
api(projects.core.resources)
3233
}
3334
}
3435
}

core/dispatcher/src/commonMain/kotlin/com/neoutils/neoregex/core/dispatcher/NavigationManager.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,9 @@ interface NavigationManager {
2626

2727
val event: Flow<Navigation.Event>
2828
val screen: StateFlow<Navigation.Screen>
29+
val canPopBack: StateFlow<Boolean>
2930

30-
fun setScreen(screen: Navigation.Screen)
31+
fun update(screen: Navigation.Screen)
3132

32-
suspend fun navigate(event: Navigation.Event)
33+
suspend fun emit(event: Navigation.Event)
3334
}

core/dispatcher/src/commonMain/kotlin/com/neoutils/neoregex/core/dispatcher/impl/NavigationManagerImpl.kt

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,23 @@ internal class NavigationManagerImpl : NavigationManager {
2929

3030
private val _event = Channel<Navigation.Event>(Channel.UNLIMITED)
3131
private val _current = MutableStateFlow<Navigation.Screen>(Navigation.Screen.Matcher)
32+
private val _canPop = MutableStateFlow(value = false)
3233

3334
override val screen = _current.asStateFlow()
3435
override val event = _event.receiveAsFlow()
36+
override val canPopBack = _canPop.asStateFlow()
37+
38+
override fun update(screen: Navigation.Screen) {
39+
_canPop.value = when (screen) {
40+
Navigation.Screen.About -> true
41+
Navigation.Screen.Libraries -> true
42+
Navigation.Screen.Matcher -> false
43+
}
3544

36-
override fun setScreen(screen: Navigation.Screen) {
3745
_current.value = screen
3846
}
3947

40-
override suspend fun navigate(event: Navigation.Event) {
48+
override suspend fun emit(event: Navigation.Event) {
4149
_event.send(event)
4250
}
4351
}

core/dispatcher/src/commonMain/kotlin/com/neoutils/neoregex/core/dispatcher/model/Navigation.kt

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,36 @@
1818

1919
package com.neoutils.neoregex.core.dispatcher.model
2020

21+
import com.neoutils.neoregex.core.resources.Res
22+
import com.neoutils.neoregex.core.resources.screen_about
23+
import com.neoutils.neoregex.core.resources.screen_libraries
24+
import com.neoutils.neoregex.core.resources.screen_matcher
25+
import org.jetbrains.compose.resources.StringResource
26+
2127
sealed class Navigation {
2228

2329
sealed class Event : Navigation() {
24-
data object Matcher : Event()
25-
data object About : Event()
30+
data class Navigate(
31+
val screen: Screen
32+
) : Event()
33+
2634
data object OnBack : Event()
2735
}
2836

29-
sealed class Screen(val canBack: Boolean) : Navigation() {
30-
data object Matcher : Screen(canBack = false)
31-
data object About : Screen(canBack = true)
32-
data object Libraries : Screen(canBack = true)
37+
sealed class Screen : Navigation() {
38+
39+
abstract val title: StringResource
40+
41+
data object Matcher : Screen() {
42+
override val title = Res.string.screen_matcher
43+
}
44+
45+
data object About : Screen() {
46+
override val title = Res.string.screen_about
47+
}
48+
49+
data object Libraries : Screen() {
50+
override val title = Res.string.screen_libraries
51+
}
3352
}
3453
}

core/dispatcher/src/webMain/kotlin/com/neoutils/neoregex/core/dispatcher/di/NavigationModule.web.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,10 @@ package com.neoutils.neoregex.core.dispatcher.di
2020

2121
import com.neoutils.neoregex.core.dispatcher.NavigationManager
2222
import com.neoutils.neoregex.core.dispatcher.impl.NavigationManagerImpl
23+
import com.neoutils.neoregex.core.dispatcher.impl.NavigationManagerWeb
2324
import org.koin.dsl.bind
2425
import org.koin.dsl.module
2526

2627
actual val navigationModule = module {
27-
single { NavigationManagerImpl() } bind NavigationManager::class
28+
single { NavigationManagerWeb() } bind NavigationManager::class
2829
}

0 commit comments

Comments
 (0)