-
Notifications
You must be signed in to change notification settings - Fork 4
Add dashboard tools personalization mode #4392
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
84e700d
c2d78a9
f893cdd
aaf621a
be690aa
0a41e79
76d0fa3
4966a34
22a36b6
b6f0c40
a8dd2f7
448e707
6632a9d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| package org.cru.godtools.ui.dashboard | ||
|
|
||
| import androidx.compose.runtime.Composable | ||
| import androidx.compose.runtime.remember | ||
| import com.slack.circuit.runtime.CircuitContext | ||
| import kotlin.uuid.ExperimentalUuidApi | ||
| import kotlin.uuid.Uuid | ||
| import org.ccci.gto.android.common.sync.SyncTracker | ||
| import org.ccci.gto.android.common.sync.rememberSyncTracker | ||
|
|
||
| internal class SyncTaskRegistry(val syncTracker: SyncTracker) { | ||
| private val tasks = mutableMapOf<String, SyncTracker.(force: Boolean) -> Unit>() | ||
|
|
||
| @OptIn(ExperimentalUuidApi::class) | ||
| fun registerSyncTask(task: SyncTracker.(force: Boolean) -> Unit): String { | ||
| val id = Uuid.generateV7().toString() | ||
| synchronized(tasks) { tasks[id] = task } | ||
| syncTracker.task(false) | ||
| return id | ||
| } | ||
|
|
||
| fun unregisterSyncTask(id: String) { | ||
| synchronized(tasks) { tasks.remove(id) } | ||
| } | ||
|
|
||
| fun triggerSyncTasks(force: Boolean = false) { | ||
| synchronized(tasks) { tasks.values.toList() }.forEach { syncTracker.it(force) } | ||
| } | ||
|
|
||
| companion object { | ||
| internal var CircuitContext.syncTaskRegistry: SyncTaskRegistry? | ||
| get() = tag() ?: parent?.syncTaskRegistry | ||
| set(value) = putTag(value) | ||
|
|
||
| @Composable | ||
| internal fun rememberSyncRegistry(): SyncTaskRegistry { | ||
| val syncTracker = rememberSyncTracker() | ||
| return remember(syncTracker) { SyncTaskRegistry(syncTracker) } | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,27 +2,49 @@ package org.cru.godtools.ui.dashboard.tools | |
|
|
||
| import java.util.Locale | ||
| import javax.inject.Inject | ||
| import kotlinx.coroutines.ExperimentalCoroutinesApi | ||
| import kotlinx.coroutines.flow.Flow | ||
| import kotlinx.coroutines.flow.combine | ||
| import kotlinx.coroutines.flow.distinctUntilChanged | ||
| import kotlinx.coroutines.flow.emitAll | ||
| import kotlinx.coroutines.flow.flatMapLatest | ||
| import kotlinx.coroutines.flow.flowOf | ||
| import kotlinx.coroutines.flow.map | ||
| import org.ccci.gto.android.common.kotlin.coroutines.flow.combineTransformLatest | ||
| import org.cru.godtools.base.Settings | ||
| import org.cru.godtools.db.repository.ToolsRepository | ||
| import org.cru.godtools.model.Tool | ||
| import org.cru.godtools.ui.dashboard.tools.ToolsPresenter.UiState.Mode | ||
|
|
||
| internal class FilteredToolsFlowProducer @Inject constructor(private val toolsRepository: ToolsRepository) { | ||
| fun getFlow(category: String? = null, language: Locale? = null): Flow<List<Tool>> { | ||
| val baseFlow = when (language) { | ||
| null -> toolsRepository.getNormalToolsFlow() | ||
| else -> toolsRepository.getNormalToolsFlowByLanguage(language) | ||
| } | ||
|
|
||
| val defaultVariantsFlow = toolsRepository.getMetaToolsFlow() | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure what a metatool is, and I think that might be hindering me from getting whats going on here.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wait... maybe I do know what that is. Is this how the 4 Spiritual Laws booklet relates to the KGP or Would You Like To Know God Personally?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. metatools are a way of grouping tools together that are the same content just presented towards different audiences. You can see them if you open tool details of 4 laws or kgp, it's on the "Versions" tab. We previously had been hiding those other versions from the all tools list, but part of the requested changes was to make them available on the all tools UI |
||
| .map { it.associateBy({ it.code }, { it.defaultVariantCode }) } | ||
| internal class FilteredToolsFlowProducer @Inject constructor( | ||
| private val settings: Settings, | ||
| private val toolsRepository: ToolsRepository | ||
| ) { | ||
| @OptIn(ExperimentalCoroutinesApi::class) | ||
| fun getFlow(mode: Mode, category: String? = null, language: Locale? = null): Flow<List<Tool>> { | ||
| val baseFlow = when { | ||
| mode == Mode.PERSONALIZATION -> { | ||
| val languageFlow = if (language != null) flowOf(language) else settings.appLanguageFlow | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this to take into account if someone sets a personalization country and the language is different then their app language and we need to pull the tools for that specific language? Want to make sure I understand what is happening here
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. on the Dashboard they want the list of tools/lessons to take the language filter into account and default to the appLanguage |
||
| val fallbackFlow = languageFlow.flatMapLatest { toolsRepository.getPersonalizedToolsFlow(it, null) } | ||
|
|
||
| return baseFlow | ||
| .map { it.filterNot { it.isHidden }.sortedBy { it.defaultOrder } } | ||
| .combine(defaultVariantsFlow) { tools, defaultVariants -> | ||
| tools.filter { it.metatoolCode == null || it.code == defaultVariants[it.metatoolCode] } | ||
| languageFlow | ||
| .combineTransformLatest(settings.getPersonalizationCountryFlow()) { language, country -> | ||
| emitAll(toolsRepository.getPersonalizedToolsFlow(language, country)) | ||
| } | ||
| .combine(fallbackFlow) { personalized, fallback -> personalized.ifEmpty { fallback } } | ||
| .distinctUntilChanged() | ||
| } | ||
| .map { tools -> if (category == null) tools else tools.filter { it.category == category } } | ||
|
|
||
| language != null -> toolsRepository.getNormalToolsFlowByLanguage(language) | ||
| .map { it.sortedBy { it.defaultOrder } } | ||
|
|
||
| else -> toolsRepository.getNormalToolsFlow().map { it.sortedBy { it.defaultOrder } } | ||
| } | ||
|
|
||
| return baseFlow.map { | ||
| it | ||
| .filterNot { it.isHidden } | ||
| .filter { category == null || it.category == category } | ||
| } | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was to remove the blue bar at the top of the screen right? If not, then I'm confused with what's happening here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, we kept the dashboard app bar, but removed the blue theme from it