Skip to content

Commit

Permalink
Shared sync access to the features map & content trial refactoring (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
XanderZhu authored Aug 1, 2024
1 parent 5921753 commit 5d448f6
Show file tree
Hide file tree
Showing 48 changed files with 362 additions and 462 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -207,8 +207,8 @@ class HomeFragment :

val homeState = state.homeState
if (homeState is HomeFeature.HomeState.Content) {
renderProblemOfDay(viewBinding, homeState.problemOfDayState, homeState.areProblemsLimited)
renderTopicsRepetition(homeState.repetitionsState, homeState.areProblemsLimited)
renderProblemOfDay(viewBinding, homeState.problemOfDayState, homeState.isProblemsLimitEnabled)
renderTopicsRepetition(homeState.repetitionsState, homeState.isProblemsLimitEnabled)
}

renderChallengeCard(state.challengeWidgetViewState)
Expand Down Expand Up @@ -242,19 +242,19 @@ class HomeFragment :
private fun renderProblemOfDay(
viewBinding: FragmentHomeBinding,
state: HomeFeature.ProblemOfDayState,
areProblemsLimited: Boolean
isProblemsLimitEnabled: Boolean
) {
problemOfDayCardFormDelegate.render(
dateFormatter = dateFormatter,
binding = viewBinding.homeScreenProblemOfDayCard,
state = state,
areProblemsLimited = areProblemsLimited
areProblemsLimited = isProblemsLimitEnabled
)
}

private fun renderTopicsRepetition(
repetitionsState: HomeFeature.RepetitionsState,
areProblemsLimited: Boolean
isProblemsLimitEnabled: Boolean
) {
viewBinding.homeScreenTopicsRepetitionCard.root.isVisible =
repetitionsState is HomeFeature.RepetitionsState.Available
Expand All @@ -263,7 +263,7 @@ class HomeFragment :
context = requireContext(),
binding = viewBinding.homeScreenTopicsRepetitionCard,
recommendedRepetitionsCount = repetitionsState.recommendedRepetitionsCount,
areProblemsLimited = areProblemsLimited
isProblemsLimitEnabled = isProblemsLimitEnabled
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class TopicsRepetitionCardFormDelegate {
context: Context,
binding: LayoutTopicsRepetitionCardBinding,
recommendedRepetitionsCount: Int,
areProblemsLimited: Boolean
isProblemsLimitEnabled: Boolean
) {
with(binding) {
topicsRepetitionBackgroundImageView.setImageResource(
Expand Down Expand Up @@ -49,7 +49,7 @@ class TopicsRepetitionCardFormDelegate {
}
)
topicsRepetitionUnlimitedBadge.isVisible =
areProblemsLimited && recommendedRepetitionsCount > 0
isProblemsLimitEnabled && recommendedRepetitionsCount > 0
}
}
}
2 changes: 1 addition & 1 deletion config/detekt/baseline.xml
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,6 @@
<ID>ReturnCount:SearchReducer.kt$SearchReducer$private fun handleSearchResultsItemClickedMessage( state: State, message: Message.SearchResultsItemClicked ): SearchReducerResult?</ID>
<ID>ReturnCount:SharedDateFormatter.kt$SharedDateFormatter$fun formatTimeDistance(millis: Long): String</ID>
<ID>ReturnCount:StateExtentions.kt$internal fun ChallengeWidgetFeature.State.Content.setCurrentChallengeIntervalProgressAsCompleted(): Challenge?</ID>
<ID>ReturnCount:StepQuizActionDispatcher.kt$StepQuizActionDispatcher$private suspend fun handleUpdateProblemsLimitAction( action: InternalAction.UpdateProblemsLimit, onNewMessage: (Message) -&gt; Unit )</ID>
<ID>ReturnCount:StepQuizCodeBlanksReducer.kt$StepQuizCodeBlanksReducer$private fun handleDeleteButtonClicked( state: State ): StepQuizCodeBlanksReducerResult?</ID>
<ID>ReturnCount:StepQuizCodeBlanksReducer.kt$StepQuizCodeBlanksReducer$private fun handleSuggestionClicked( state: State, message: Message.SuggestionClicked ): StepQuizCodeBlanksReducerResult?</ID>
<ID>ReturnCount:StepQuizHintsInteractor.kt$StepQuizHintsInteractor$suspend fun getLastSeenHint(stepId: Long): Comment?</ID>
Expand Down Expand Up @@ -282,6 +281,7 @@
<ID>TooManyFunctions:SharedDateFormatter.kt$SharedDateFormatter</ID>
<ID>TooManyFunctions:StepActionDispatcher.kt$StepActionDispatcher : CoroutineActionDispatcher</ID>
<ID>TooManyFunctions:StudyPlanWidgetDelegate.kt$StudyPlanWidgetDelegate</ID>
<ID>TooManyFunctions:SubscriptionsInteractor.kt$SubscriptionsInteractor</ID>
<ID>TopLevelPropertyNaming:HyperskillNotificationChannel.kt$private const val dailyReminderId = "dailyReminderChannel"</ID>
<ID>TopLevelPropertyNaming:HyperskillNotificationChannel.kt$private const val otherId = "otherChannel"</ID>
<ID>TopLevelPropertyNaming:HyperskillNotificationChannel.kt$private const val regularLearningRemindersId = "regularLearningRemindersChannel"</ID>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ struct HomeView: View {

ProblemOfDayAssembly(
problemOfDayState: data.problemOfDayState,
isFreemiumEnabled: data.areProblemsLimited,
isFreemiumEnabled: data.isProblemsLimitEnabled,
output: viewModel
)
.makeModule()
Expand All @@ -96,7 +96,7 @@ struct HomeView: View {
TopicsRepetitionsCardView(
topicsToRepeatCount: Int(availableRepetitionsState.recommendedRepetitionsCount),
onTap: viewModel.doTopicsRepetitionsPresentation,
isFreemiumEnabled: data.areProblemsLimited
isFreemiumEnabled: data.isProblemsLimitEnabled
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,20 @@ import org.hyperskill.app.subscriptions.domain.repository.CurrentSubscriptionSta
import ru.nobird.app.core.model.mapOfNotNull

class AnalyticInteractor(
// Provide CurrentSubscriptionStateRepository lazily
// because it depends on AnalyticInteractor
currentSubscriptionStateRepositoryProvider: () -> CurrentSubscriptionStateRepository,
private val currentProfileStateRepository: CurrentProfileStateRepository,
private val currentSubscriptionStateRepository: CurrentSubscriptionStateRepository,
private val notificationInteractor: NotificationInteractor,
private val platform: Platform,
private val analyticEngines: List<AnalyticEngine>,
override val eventMonitor: AnalyticEventMonitor?
) : Analytic {

private val currentSubscriptionStateRepository: CurrentSubscriptionStateRepository by lazy {
currentSubscriptionStateRepositoryProvider.invoke()
}

private var userProperties: MutableMap<String, Any> = mutableMapOf()

override fun reportEvent(event: AnalyticEvent, forceReportEvent: Boolean) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ class AnalyticComponentImpl(
AnalyticInteractor(
analyticEngines = analyticEngines,
currentProfileStateRepository = appGraph.profileDataComponent.currentProfileStateRepository,
currentSubscriptionStateRepository = appGraph.stateRepositoriesComponent.currentSubscriptionStateRepository,
currentSubscriptionStateRepositoryProvider = {
appGraph.stateRepositoriesComponent.currentSubscriptionStateRepository
},
notificationInteractor = appGraph.buildNotificationComponent().notificationInteractor,
eventMonitor = BatchAnalyticEventMonitor(listOfNotNull(sentryInteractor, loggableAnalyticEventMonitor)),
platform = appGraph.commonComponent.platform
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Deferred
import kotlinx.coroutines.async
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import org.hyperskill.app.core.domain.DataSourceType
Expand Down Expand Up @@ -43,7 +43,7 @@ abstract class BaseStateRepository<State : Any?> : StateRepository<State> {
*
* @return shared flow
*/
override val changes: SharedFlow<State>
override val changes: Flow<State>
get() = mutableSharedFlow

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package org.hyperskill.app.core.domain.repository

import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.first

interface StateRepository<State : Any?> {
Expand All @@ -26,7 +26,7 @@ interface StateRepository<State : Any?> {
*
* @return shared flow
*/
val changes: SharedFlow<State>
val changes: Flow<State>

/**
* Update state locally in app.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import org.hyperskill.app.gamification_toolbar.remote.GamificationToolbarRemoteD
import org.hyperskill.app.learning_activities.data.repository.NextLearningActivityStateRepositoryImpl
import org.hyperskill.app.learning_activities.domain.repository.NextLearningActivityStateRepository
import org.hyperskill.app.learning_activities.remote.LearningActivitiesRemoteDataSourceImpl
import org.hyperskill.app.purchases.domain.interactor.PurchaseInteractor
import org.hyperskill.app.study_plan.data.repository.CurrentStudyPlanStateRepositoryImpl
import org.hyperskill.app.study_plan.domain.repository.CurrentStudyPlanStateRepository
import org.hyperskill.app.study_plan.remote.StudyPlanRemoteDataSourceImpl
Expand All @@ -20,6 +21,10 @@ class StateRepositoriesComponentImpl(appGraph: AppGraph) : StateRepositoriesComp

private val authorizedHttpClient = appGraph.networkComponent.authorizedHttpClient

private val featuresDataSource = appGraph.profileDataComponent.featuresDataSource

private val purchaseInteractor: PurchaseInteractor = appGraph.buildPurchaseComponent().purchaseInteractor

/**
* Current subscription
*/
Expand All @@ -34,7 +39,12 @@ class StateRepositoriesComponentImpl(appGraph: AppGraph) : StateRepositoriesComp
}

override val currentSubscriptionStateRepository: CurrentSubscriptionStateRepository =
CurrentSubscriptionStateRepositoryImpl(subscriptionsRemoteDataSource, currentSubscriptionStateHolder)
CurrentSubscriptionStateRepositoryImpl(
subscriptionsRemoteDataSource = subscriptionsRemoteDataSource,
stateHolder = currentSubscriptionStateHolder,
featuresDataSource = featuresDataSource,
purchaseInteractor = purchaseInteractor
)

/**
* Study plan
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package org.hyperskill.app.features.data.source

import org.hyperskill.app.profile.domain.model.FeatureValues
import org.hyperskill.app.profile.domain.model.FeaturesMap

interface FeaturesDataSource {
fun getFeaturesMap(): FeaturesMap
fun getFeatureValues(): FeatureValues
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,8 @@ internal class GamificationToolbarComponentImpl(
topicCompletedFlow = appGraph.stepCompletionFlowDataComponent.topicCompletedFlow,
currentGamificationToolbarDataStateRepository = appGraph.stateRepositoriesComponent
.currentGamificationToolbarDataStateRepository,
currentSubscriptionStateRepository = appGraph.stateRepositoriesComponent.currentSubscriptionStateRepository,
subscriptionInteractor = appGraph.subscriptionDataComponent.subscriptionsInteractor,
currentProfileStateRepository = appGraph.profileDataComponent.currentProfileStateRepository,
purchaseInteractor = appGraph.buildPurchaseComponent().purchaseInteractor,
sentryInteractor = appGraph.sentryComponent.sentryInteractor
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import org.hyperskill.app.streaks.domain.model.Streak
import org.hyperskill.app.study_plan.domain.model.StudyPlan
import org.hyperskill.app.subscriptions.domain.model.FreemiumChargeLimitsStrategy
import org.hyperskill.app.subscriptions.domain.model.Subscription
import org.hyperskill.app.subscriptions.domain.model.SubscriptionLimitType
import org.hyperskill.app.subscriptions.domain.model.SubscriptionWithLimitType

object GamificationToolbarFeature {
sealed interface State {
Expand All @@ -22,8 +24,7 @@ object GamificationToolbarFeature {
val historicalStreak: HistoricalStreak,
val subscription: Subscription,
val chargeLimitsStrategy: FreemiumChargeLimitsStrategy,
internal val isMobileContentTrialEnabled: Boolean,
internal val canMakePayments: Boolean = false,
internal val subscriptionLimitType: SubscriptionLimitType,
internal val isRefreshing: Boolean = false
) : State
}
Expand Down Expand Up @@ -72,9 +73,8 @@ object GamificationToolbarFeature {
data class FetchGamificationToolbarDataSuccess(
val gamificationToolbarData: GamificationToolbarData,
val subscription: Subscription,
val chargeLimitsStrategy: FreemiumChargeLimitsStrategy,
val isMobileContentTrialEnabled: Boolean,
val canMakePayments: Boolean
val subscriptionLimitType: SubscriptionLimitType,
val chargeLimitsStrategy: FreemiumChargeLimitsStrategy
) : InternalMessage

object PullToRefresh : InternalMessage
Expand All @@ -89,7 +89,9 @@ object GamificationToolbarFeature {
data class GamificationToolbarDataChanged(
val gamificationToolbarData: GamificationToolbarData
) : InternalMessage
data class SubscriptionChanged(val subscription: Subscription) : InternalMessage
data class SubscriptionChanged(
val subscriptionWithLimitType: SubscriptionWithLimitType
) : InternalMessage
}

sealed interface Action {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import org.hyperskill.app.streaks.domain.model.HistoricalStreak
import org.hyperskill.app.streaks.domain.model.StreakState
import org.hyperskill.app.subscriptions.domain.model.FreemiumChargeLimitsStrategy
import org.hyperskill.app.subscriptions.domain.model.Subscription
import org.hyperskill.app.subscriptions.domain.model.SubscriptionLimitType
import ru.nobird.app.presentation.redux.reducer.StateReducer

private typealias GamificationToolbarReducerResult = Pair<State, Set<Action>>
Expand All @@ -33,9 +34,8 @@ class GamificationToolbarReducer(
createContentState(
gamificationToolbarData = message.gamificationToolbarData,
subscription = message.subscription,
chargeLimitsStrategy = message.chargeLimitsStrategy,
isMobileContentTrialEnabled = message.isMobileContentTrialEnabled,
canMakePayments = message.canMakePayments
subscriptionLimitType = message.subscriptionLimitType,
chargeLimitsStrategy = message.chargeLimitsStrategy
) to emptySet()
is InternalMessage.PullToRefresh ->
handlePullToRefreshMessage(state)
Expand Down Expand Up @@ -99,7 +99,10 @@ class GamificationToolbarReducer(
if (state.isRefreshing) {
state to emptySet()
} else {
state.copy(subscription = message.subscription) to emptySet()
state.copy(
subscription = message.subscriptionWithLimitType.subscription,
subscriptionLimitType = message.subscriptionWithLimitType.subscriptionLimitType
) to emptySet()
}
else -> state to emptySet()
}
Expand Down Expand Up @@ -226,17 +229,15 @@ class GamificationToolbarReducer(
private fun createContentState(
gamificationToolbarData: GamificationToolbarData,
subscription: Subscription,
chargeLimitsStrategy: FreemiumChargeLimitsStrategy,
isMobileContentTrialEnabled: Boolean,
canMakePayments: Boolean
subscriptionLimitType: SubscriptionLimitType,
chargeLimitsStrategy: FreemiumChargeLimitsStrategy
): State.Content =
State.Content(
trackProgress = gamificationToolbarData.trackProgress,
currentStreak = gamificationToolbarData.currentStreak,
historicalStreak = HistoricalStreak(gamificationToolbarData.streakState),
subscription = subscription,
chargeLimitsStrategy = chargeLimitsStrategy,
isMobileContentTrialEnabled = isMobileContentTrialEnabled,
canMakePayments = canMakePayments
subscriptionLimitType = subscriptionLimitType
)
}
Loading

0 comments on commit 5d448f6

Please sign in to comment.