Skip to content

Commit 063baa7

Browse files
authored
Internal navigation fix (#227)
* Internal navigation fix * Update drawer resources * Fix drawer selected item state memory leak on context recreation (language change)
1 parent 88d5ec6 commit 063baa7

File tree

18 files changed

+153
-48
lines changed

18 files changed

+153
-48
lines changed

data/src/main/java/com/shifthackz/aisdv1/data/preference/PreferenceManagerImpl.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@ class PreferenceManagerImpl(
247247
const val KEY_HUGGING_FACE_MODEL_KEY = "key_hugging_face_model_key"
248248
const val KEY_STABILITY_AI_API_KEY = "key_stability_ai_api_key"
249249
const val KEY_STABILITY_AI_ENGINE_ID_KEY = "key_stability_ai_engine_id_key"
250-
const val KEY_FORCE_SETUP_AFTER_UPDATE = "force_upd_setup_v0.x.x-v0.5.8"
250+
const val KEY_FORCE_SETUP_AFTER_UPDATE = "force_upd_setup_v0.x.x-v0.6.2"
251251
const val KEY_LOCAL_MODEL_ID = "key_local_model_id"
252252
const val KEY_LOCAL_NN_API = "key_local_nn_api"
253253
const val KEY_DESIGN_DYNAMIC_COLORS = "key_design_dynamic_colors"

presentation/src/main/java/com/shifthackz/aisdv1/presentation/core/GenerationFormUpdateEvent.kt

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,41 @@ package com.shifthackz.aisdv1.presentation.core
22

33
import com.shifthackz.aisdv1.domain.entity.AiGenerationResult
44
import io.reactivex.rxjava3.core.BackpressureStrategy
5+
import io.reactivex.rxjava3.subjects.BehaviorSubject
56
import io.reactivex.rxjava3.subjects.PublishSubject
67

78
class GenerationFormUpdateEvent {
89

910
private val sRoute: PublishSubject<AiGenerationResult.Type> = PublishSubject.create()
10-
private val sTxt2Img: PublishSubject<AiGenerationResult> = PublishSubject.create()
11-
private val sImg2Img: PublishSubject<AiGenerationResult> = PublishSubject.create()
11+
private val sTxt2Img: BehaviorSubject<Payload> = BehaviorSubject.createDefault(Payload.None)
12+
private val sImg2Img: BehaviorSubject<Payload> = BehaviorSubject.createDefault(Payload.None)
1213

13-
fun update(generation: AiGenerationResult, route: AiGenerationResult.Type) {
14+
fun update(
15+
generation: AiGenerationResult,
16+
route: AiGenerationResult.Type,
17+
inputImage: Boolean,
18+
) {
1419
sRoute.onNext(route)
1520
when (route) {
16-
AiGenerationResult.Type.TEXT_TO_IMAGE -> sTxt2Img.onNext(generation)
17-
AiGenerationResult.Type.IMAGE_TO_IMAGE -> sImg2Img.onNext(generation)
21+
AiGenerationResult.Type.TEXT_TO_IMAGE -> sTxt2Img.onNext(Payload.T2IForm(generation))
22+
AiGenerationResult.Type.IMAGE_TO_IMAGE -> sImg2Img.onNext(Payload.I2IForm(generation, inputImage))
1823
}
1924
}
2025

26+
fun clear() {
27+
sTxt2Img.onNext(Payload.None)
28+
sImg2Img.onNext(Payload.None)
29+
}
30+
2131
fun observeRoute() = sRoute.toFlowable(BackpressureStrategy.LATEST)
2232

2333
fun observeTxt2ImgForm() = sTxt2Img.toFlowable(BackpressureStrategy.LATEST)
2434

2535
fun observeImg2ImgForm() = sImg2Img.toFlowable(BackpressureStrategy.LATEST)
36+
37+
sealed interface Payload {
38+
data object None : Payload
39+
data class T2IForm(val ai: AiGenerationResult): Payload
40+
data class I2IForm(val ai: AiGenerationResult, val inputImage: Boolean): Payload
41+
}
2642
}

presentation/src/main/java/com/shifthackz/aisdv1/presentation/core/GenerationMviViewModel.kt

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -250,9 +250,17 @@ abstract class GenerationMviViewModel<S : GenerationMviState, I : GenerationMviI
250250
ServerSetupLaunchSource.SETTINGS
251251
)
252252

253-
is GenerationMviIntent.UpdateFromGeneration -> updateFormPreviousAiGeneration(
254-
intent.ai
255-
)
253+
is GenerationMviIntent.UpdateFromGeneration -> {
254+
val payload = when (intent.ai.type) {
255+
AiGenerationResult.Type.TEXT_TO_IMAGE -> {
256+
GenerationFormUpdateEvent.Payload.T2IForm(intent.ai)
257+
}
258+
AiGenerationResult.Type.IMAGE_TO_IMAGE -> {
259+
GenerationFormUpdateEvent.Payload.I2IForm(intent.ai, false)
260+
}
261+
}
262+
updateFormPreviousAiGeneration(payload)
263+
}
256264

257265
is GenerationMviIntent.Drawer -> when (intent.intent) {
258266
DrawerIntent.Close -> drawerRouter.closeDrawer()
@@ -261,9 +269,14 @@ abstract class GenerationMviViewModel<S : GenerationMviState, I : GenerationMviI
261269
}
262270
}
263271

264-
protected open fun updateFormPreviousAiGeneration(ai: AiGenerationResult) =
265-
updateGenerationState {
266-
it
272+
protected open fun updateFormPreviousAiGeneration(payload: GenerationFormUpdateEvent.Payload) {
273+
val ai = when (payload) {
274+
is GenerationFormUpdateEvent.Payload.I2IForm -> payload.ai
275+
is GenerationFormUpdateEvent.Payload.T2IForm -> payload.ai
276+
else -> return
277+
}
278+
updateGenerationState { oldState ->
279+
oldState
267280
.copyState(
268281
advancedOptionsVisible = true,
269282
prompt = ai.prompt,
@@ -282,6 +295,7 @@ abstract class GenerationMviViewModel<S : GenerationMviState, I : GenerationMviI
282295
else state.copyState(selectedSampler = ai.sampler)
283296
}
284297
}
298+
}
285299

286300
protected fun setActiveModal(modal: Modal) = updateGenerationState {
287301
it.copyState(screenModal = modal)

presentation/src/main/java/com/shifthackz/aisdv1/presentation/navigation/NavigationEffect.kt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,11 @@ sealed interface NavigationEffect : MviEffect {
2828
data object Close : Drawer
2929
}
3030

31-
data class Home(val route: String) : NavigationEffect
31+
sealed interface Home : NavigationEffect {
32+
val route: String
33+
34+
data class Route(override val route: String) : Home
35+
36+
data class Update(override val route: String) : Home
37+
}
3238
}

presentation/src/main/java/com/shifthackz/aisdv1/presentation/navigation/graph/DrawerNavGraph.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ import com.shifthackz.aisdv1.presentation.utils.Constants
1515
import com.shifthackz.aisdv1.presentation.widget.source.getNameUiText
1616

1717
fun mainDrawerNavItems(settings: Settings? = null): List<NavItem> = buildList {
18-
add(txt2ImgTab())
19-
add(img2imgTab())
18+
add(txt2ImgTab().copy(name = R.string.title_text_to_image.asUiText()))
19+
add(img2imgTab().copy(name = R.string.title_image_to_image.asUiText()))
2020
add(galleryTab())
2121
settings?.source?.takeIf { it.featureTags.contains(FeatureTag.OwnServer) }?.let {
2222
add(webUi(it))
@@ -30,7 +30,7 @@ private fun webUi(source: ServerSource) = NavItem(
3030
R.string.drawer_web_ui.asUiText(),
3131
" (".asUiText(),
3232
source.getNameUiText(),
33-
")".asUiText()
33+
")".asUiText(),
3434
),
3535
route = Constants.ROUTE_WEB_UI,
3636
icon = NavItem.Icon.Vector(

presentation/src/main/java/com/shifthackz/aisdv1/presentation/navigation/graph/HomeNavGraph.kt

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ package com.shifthackz.aisdv1.presentation.navigation.graph
33
import androidx.compose.foundation.layout.size
44
import androidx.compose.material.icons.Icons
55
import androidx.compose.material.icons.filled.Settings
6+
import androidx.compose.runtime.Composable
7+
import androidx.compose.runtime.LaunchedEffect
68
import androidx.compose.ui.Modifier
79
import androidx.compose.ui.unit.dp
810
import androidx.navigation.NavGraphBuilder
@@ -11,12 +13,14 @@ import androidx.navigation.get
1113
import com.shifthackz.aisdv1.core.model.asUiText
1214
import com.shifthackz.aisdv1.presentation.R
1315
import com.shifthackz.aisdv1.presentation.model.NavItem
16+
import com.shifthackz.aisdv1.presentation.navigation.router.home.HomeRouter
1417
import com.shifthackz.aisdv1.presentation.screen.gallery.list.GalleryScreen
1518
import com.shifthackz.aisdv1.presentation.screen.home.HomeNavigationScreen
1619
import com.shifthackz.aisdv1.presentation.screen.img2img.ImageToImageScreen
1720
import com.shifthackz.aisdv1.presentation.screen.settings.SettingsScreen
1821
import com.shifthackz.aisdv1.presentation.screen.txt2img.TextToImageScreen
1922
import com.shifthackz.aisdv1.presentation.utils.Constants
23+
import org.koin.compose.koinInject
2024

2125
fun NavGraphBuilder.homeScreenNavGraph(route: String = Constants.ROUTE_HOME) {
2226
addDestination(
@@ -40,7 +44,11 @@ fun txt2ImgTab() = NavItem(
4044
resId = R.drawable.ic_text,
4145
modifier = Modifier.size(24.dp),
4246
),
43-
content = { TextToImageScreen() },
47+
content = {
48+
HomeTabBase(Constants.ROUTE_TXT_TO_IMG) {
49+
TextToImageScreen()
50+
}
51+
},
4452
)
4553

4654
fun img2imgTab() = NavItem(
@@ -51,7 +59,9 @@ fun img2imgTab() = NavItem(
5159
modifier = Modifier.size(24.dp),
5260
),
5361
content = {
54-
ImageToImageScreen()
62+
HomeTabBase(Constants.ROUTE_IMG_TO_IMG) {
63+
ImageToImageScreen()
64+
}
5565
},
5666
)
5767

@@ -63,7 +73,9 @@ fun galleryTab() = NavItem(
6373
modifier = Modifier.size(24.dp),
6474
),
6575
content = {
66-
GalleryScreen()
76+
HomeTabBase(Constants.ROUTE_GALLERY) {
77+
GalleryScreen()
78+
}
6779
},
6880
)
6981

@@ -74,6 +86,20 @@ fun settingsTab() = NavItem(
7486
vector = Icons.Default.Settings,
7587
),
7688
content = {
77-
SettingsScreen()
89+
HomeTabBase(Constants.ROUTE_SETTINGS) {
90+
SettingsScreen()
91+
}
7892
}
7993
)
94+
95+
@Composable
96+
private fun HomeTabBase(
97+
route: String,
98+
content: @Composable () -> Unit,
99+
) {
100+
val homeRouter: HomeRouter = koinInject()
101+
LaunchedEffect(Unit) {
102+
homeRouter.updateExternallyWithoutNavigation(route)
103+
}
104+
content()
105+
}

presentation/src/main/java/com/shifthackz/aisdv1/presentation/navigation/router/home/HomeRouter.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import com.shifthackz.aisdv1.presentation.navigation.router.Router
55

66
interface HomeRouter : Router<NavigationEffect.Home> {
77

8+
fun updateExternallyWithoutNavigation(route: String)
9+
810
fun navigateToRoute(route: String)
911

1012
fun navigateToTxt2Img()

presentation/src/main/java/com/shifthackz/aisdv1/presentation/navigation/router/home/HomeRouterImpl.kt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,12 @@ class HomeRouterImpl : HomeRouter {
99

1010
private val effectSubject: PublishSubject<NavigationEffect.Home> = PublishSubject.create()
1111

12+
override fun updateExternallyWithoutNavigation(route: String) {
13+
effectSubject.onNext(NavigationEffect.Home.Update(route))
14+
}
15+
1216
override fun navigateToRoute(route: String) {
13-
effectSubject.onNext(NavigationEffect.Home(route))
17+
effectSubject.onNext(NavigationEffect.Home.Route(route))
1418
}
1519

1620
override fun navigateToTxt2Img() {

presentation/src/main/java/com/shifthackz/aisdv1/presentation/screen/drawer/DrawerScreen.kt

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ import androidx.compose.material3.NavigationDrawerItemDefaults
2121
import androidx.compose.material3.Text
2222
import androidx.compose.material3.rememberDrawerState
2323
import androidx.compose.runtime.Composable
24-
import androidx.compose.runtime.remember
2524
import androidx.compose.ui.Alignment
2625
import androidx.compose.ui.Modifier
2726
import androidx.compose.ui.res.painterResource
@@ -57,13 +56,16 @@ fun DrawerScreen(
5756
currentRootRoute
5857
}
5958

60-
val routes = remember { navItems.map(NavItem::route).take(4) }
6159
MviComponent(
6260
viewModel = koinViewModel<DrawerViewModel>(),
6361
applySystemUiColors = false,
6462
) { _, intentHandler ->
6563
ModalNavigationDrawer(
66-
gesturesEnabled = routes.contains(currentRoute),
64+
gesturesEnabled = if (drawerState.isOpen) {
65+
true
66+
} else {
67+
currentRootRoute == Constants.ROUTE_HOME
68+
},
6769
drawerState = drawerState,
6870
drawerContent = {
6971
ModalDrawerSheet {

presentation/src/main/java/com/shifthackz/aisdv1/presentation/screen/gallery/detail/GalleryDetailViewModel.kt

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,14 +121,21 @@ class GalleryDetailViewModel(
121121
}
122122
}
123123

124-
private fun sendPromptToGenerationScreen(screenType: AiGenerationResult.Type) =
124+
private fun sendPromptToGenerationScreen(screenType: AiGenerationResult.Type) {
125+
val state = (currentState as? GalleryDetailState.Content) ?: return
125126
!getGenerationResult(itemId)
126127
.subscribeOnMainThread(schedulersProvider)
127128
.doFinally { mainRouter.navigateBack() }
128129
.subscribeBy(::errorLog) { ai ->
129-
generationFormUpdateEvent.update(ai, screenType)
130+
generationFormUpdateEvent.update(
131+
ai,
132+
screenType,
133+
state.selectedTab == GalleryDetailState.Tab.ORIGINAL,
134+
)
130135
}
131136

137+
}
138+
132139
private fun getGenerationResult(id: Long): Single<AiGenerationResult> {
133140
if (id <= 0) return getLastResultFromCacheUseCase()
134141
return getGenerationResultUseCase(id)

0 commit comments

Comments
 (0)