@@ -10,16 +10,20 @@ import androidx.compose.runtime.rememberCoroutineScope
1010import androidx.compose.runtime.rememberUpdatedState
1111import androidx.compose.runtime.setValue
1212import androidx.compose.runtime.snapshotFlow
13+ import java.util.Locale
1314import javax.inject.Inject
1415import javax.inject.Singleton
1516import kotlinx.coroutines.ExperimentalCoroutinesApi
1617import kotlinx.coroutines.NonCancellable
18+ import kotlinx.coroutines.flow.MutableStateFlow
19+ import kotlinx.coroutines.flow.SharingStarted
1720import kotlinx.coroutines.flow.combine
1821import kotlinx.coroutines.flow.distinctUntilChanged
1922import kotlinx.coroutines.flow.flatMapLatest
2023import kotlinx.coroutines.flow.map
2124import kotlinx.coroutines.flow.onEach
2225import kotlinx.coroutines.flow.onStart
26+ import kotlinx.coroutines.flow.shareIn
2327import kotlinx.coroutines.launch
2428import org.cru.godtools.base.Settings
2529import org.cru.godtools.base.ToolFileSystem
@@ -32,7 +36,6 @@ import org.cru.godtools.db.repository.rememberAttachmentFile
3236import org.cru.godtools.db.repository.rememberLanguage
3337import org.cru.godtools.model.Language
3438import org.cru.godtools.model.Tool
35- import org.cru.godtools.model.Translation
3639
3740@Singleton
3841class ToolCardPresenter @Inject constructor(
@@ -47,37 +50,59 @@ class ToolCardPresenter @Inject constructor(
4750 @OptIn(ExperimentalCoroutinesApi ::class )
4851 fun present (
4952 tool : Tool ,
53+ customLocale : Locale ? = null,
5054 loadAppLanguage : Boolean = false,
5155 secondLanguage : Language ? = null,
5256 loadAvailableLanguages : Boolean = false,
5357 eventSink : (ToolCard .Event ) -> Unit = {},
5458 ): ToolCard .State {
5559 val coroutineScope = rememberCoroutineScope()
5660 val toolCode by rememberUpdatedState(tool.code)
57- val appLocale by settings.produceAppLocaleState()
58- val defaultLocale by rememberUpdatedState(tool.defaultLocale)
5961
6062 // App Translation
61- var appTranslation: Translation ? by remember { mutableStateOf(null ) }
63+ val appLocale by settings.produceAppLocaleState()
64+ val appTranslationFlow = remember {
65+ combine(
66+ snapshotFlow { toolCode },
67+ snapshotFlow { appLocale },
68+ ) { t, l -> translationsRepository.findLatestTranslationFlow(t, l) }
69+ .flatMapLatest { it }
70+ .shareIn(coroutineScope, SharingStarted .WhileSubscribed (5_000 ), 1 )
71+ }
72+ val appTranslation by appTranslationFlow.collectAsState(null )
6273 val appLanguage = if (loadAppLanguage) languagesRepository.rememberLanguage(appLocale) else null
63- val appLanguageAvailable by remember { derivedStateOf { appTranslation != null } }
6474
65- // Translation
75+ // Custom Translation
76+ val customLocaleFlow = remember { MutableStateFlow (customLocale) }.apply { value = customLocale }
77+ val customLanguage = languagesRepository.rememberLanguage(customLocale)
78+ val customTranslationFlow = remember {
79+ combine(
80+ snapshotFlow { toolCode },
81+ customLocaleFlow
82+ ) { t, l -> translationsRepository.findLatestTranslationFlow(t, l) }
83+ .flatMapLatest { it }
84+ .shareIn(coroutineScope, SharingStarted .WhileSubscribed (5_000 ), 1 )
85+ }
86+ val customTranslation by customTranslationFlow.collectAsState(null )
87+
88+ // Default Translation
89+ val defaultLocale by rememberUpdatedState(tool.defaultLocale)
90+ val defaultTranslationFlow = remember {
91+ combine(
92+ snapshotFlow { toolCode },
93+ snapshotFlow { defaultLocale }
94+ ) { t, l -> translationsRepository.findLatestTranslationFlow(t, l) }
95+ .flatMapLatest { it }
96+ .onStart { emit(null ) }
97+ }
98+
99+ // Primary Translation
66100 var isLoaded by remember { mutableStateOf(false ) }
67101 val translation by remember {
68- val toolCodeFlow = snapshotFlow { toolCode }
69- toolCodeFlow
70- .combine(snapshotFlow { appLocale }) { t, l -> translationsRepository.findLatestTranslationFlow(t, l) }
71- .flatMapLatest { it }
72- .onEach { appTranslation = it }
73- .combine(
74- toolCodeFlow
75- .combine(snapshotFlow { defaultLocale }) { t, l ->
76- translationsRepository.findLatestTranslationFlow(t, l)
77- }
78- .flatMapLatest { it }
79- .onStart { emit(null ) }
80- ) { t1, t2 -> t1 ? : t2 }
102+ combine(
103+ customLocaleFlow.flatMapLatest { if (it != null ) customTranslationFlow else appTranslationFlow },
104+ defaultTranslationFlow
105+ ) { t1, t2 -> t1 ? : t2 }
81106 .onEach { isLoaded = true }
82107 }.collectAsState(null )
83108
@@ -103,13 +128,17 @@ class ToolCardPresenter @Inject constructor(
103128 tool = tool,
104129 isLoaded = isLoaded,
105130 banner = attachmentsRepository.rememberAttachmentFile(fileSystem, tool.bannerId),
106- // TODO: add support for specifying a locale for the ToolCardPresenter instead of just defaulting to the
107- // appLocale
108- language = appLanguage,
109- languageAvailable = appLanguageAvailable,
131+ language = when (customLocale) {
132+ null -> appLanguage
133+ else -> customLanguage
134+ },
135+ languageAvailable = when (customLocale) {
136+ null -> appTranslation != null
137+ else -> customTranslation != null
138+ },
110139 translation = translation,
111140 appLanguage = appLanguage,
112- appLanguageAvailable = appLanguageAvailable ,
141+ appLanguageAvailable = appTranslation != null ,
113142 secondLanguage = secondLanguage,
114143 secondLanguageAvailable = secondLanguageAvailable,
115144 availableLanguages = when {
0 commit comments