Skip to content

Commit

Permalink
ALTAPPS-590: Fix topic progress doesn't change on home screen without…
Browse files Browse the repository at this point in the history
… screen refreshing
  • Loading branch information
ivan-magda committed Feb 9, 2023
1 parent 27dcaa7 commit 4bbb741
Show file tree
Hide file tree
Showing 16 changed files with 149 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ import org.hyperskill.app.profile_settings.injection.ProfileSettingsComponent
import org.hyperskill.app.profile_settings.injection.ProfileSettingsComponentImpl
import org.hyperskill.app.progresses.injection.ProgressesDataComponent
import org.hyperskill.app.progresses.injection.ProgressesDataComponentImpl
import org.hyperskill.app.progresses.injection.ProgressesFlowDataComponent
import org.hyperskill.app.progresses.injection.ProgressesFlowDataComponentImpl
import org.hyperskill.app.reactions.injection.ReactionsDataComponent
import org.hyperskill.app.reactions.injection.ReactionsDataComponentImpl
import org.hyperskill.app.sentry.injection.SentryComponent
Expand Down Expand Up @@ -177,6 +179,9 @@ class AndroidAppComponentImpl(
override val stepCompletionFlowDataComponent: StepCompletionFlowDataComponent =
StepCompletionFlowDataComponentImpl()

override val progressesFlowDataComponent: ProgressesFlowDataComponent =
ProgressesFlowDataComponentImpl()

override val sentryComponent: SentryComponent =
SentryComponentImpl(SentryManagerImpl(commonComponent.buildKonfig))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import shared
extension TopicProgress {
convenience init(
id: String = UUID().uuidString,
vid: String = UUID().uuidString,
stagePosition: Int32? = nil,
repeatedCount: Int32? = nil,
isCompleted: Bool = false,
Expand All @@ -13,6 +14,7 @@ extension TopicProgress {
) {
self.init(
id: id,
vid: vid,
stagePosition: stagePosition != nil ? KotlinInt(value: stagePosition.require()) : nil,
repeatedCount: repeatedCount != nil ? KotlinInt(value: repeatedCount.require()) : nil,
isCompleted: isCompleted,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import org.hyperskill.app.profile.injection.ProfileDataComponent
import org.hyperskill.app.profile.injection.ProfileHypercoinsDataComponent
import org.hyperskill.app.profile_settings.injection.ProfileSettingsComponent
import org.hyperskill.app.progresses.injection.ProgressesDataComponent
import org.hyperskill.app.progresses.injection.ProgressesFlowDataComponent
import org.hyperskill.app.reactions.injection.ReactionsDataComponent
import org.hyperskill.app.sentry.injection.SentryComponent
import org.hyperskill.app.step.domain.model.StepRoute
Expand Down Expand Up @@ -59,6 +60,7 @@ interface AppGraph {
val streakFlowDataComponent: StreakFlowDataComponent
val topicsRepetitionsFlowDataComponent: TopicsRepetitionsFlowDataComponent
val stepCompletionFlowDataComponent: StepCompletionFlowDataComponent
val progressesFlowDataComponent: ProgressesFlowDataComponent

fun buildAuthSocialComponent(): AuthSocialComponent
fun buildAuthCredentialsComponent(): AuthCredentialsComponent
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package org.hyperskill.app.progresses.data.flow

import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.SharedFlow
import org.hyperskill.app.progresses.domain.flow.TopicProgressFlow
import org.hyperskill.app.topics.domain.model.TopicProgress

class TopicProgressFlowImpl : TopicProgressFlow {
private val topicProgressMutableSharedFlow = MutableSharedFlow<TopicProgress>()

override fun observe(): SharedFlow<TopicProgress> =
topicProgressMutableSharedFlow

override suspend fun notifyDataChanged(data: TopicProgress) {
topicProgressMutableSharedFlow.emit(data)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package org.hyperskill.app.progresses.domain.flow

import org.hyperskill.app.core.domain.flow.SharedDataFlow
import org.hyperskill.app.topics.domain.model.TopicProgress

interface TopicProgressFlow : SharedDataFlow<TopicProgress>
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package org.hyperskill.app.progresses.injection

import org.hyperskill.app.progresses.domain.flow.TopicProgressFlow

interface ProgressesFlowDataComponent {
val topicProgressFlow: TopicProgressFlow
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package org.hyperskill.app.progresses.injection

import org.hyperskill.app.progresses.data.flow.TopicProgressFlowImpl
import org.hyperskill.app.progresses.domain.flow.TopicProgressFlow

class ProgressesFlowDataComponentImpl : ProgressesFlowDataComponent {
override val topicProgressFlow: TopicProgressFlow = TopicProgressFlowImpl()
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class StepCompletionComponentImpl(
appGraph.commonComponent.resourceProvider,
appGraph.sentryComponent.sentryInteractor,
appGraph.stepCompletionFlowDataComponent.topicCompletedFlow,
appGraph.progressesFlowDataComponent.topicProgressFlow,
appGraph.buildNotificationComponent().notificationInteractor
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import org.hyperskill.app.analytic.domain.interactor.AnalyticInteractor
import org.hyperskill.app.core.presentation.ActionDispatcherOptions
import org.hyperskill.app.core.view.mapper.ResourceProvider
import org.hyperskill.app.notification.domain.interactor.NotificationInteractor
import org.hyperskill.app.progresses.domain.flow.TopicProgressFlow
import org.hyperskill.app.progresses.domain.interactor.ProgressesInteractor
import org.hyperskill.app.sentry.domain.interactor.SentryInteractor
import org.hyperskill.app.sentry.domain.model.transaction.HyperskillSentryTransactionBuilder
Expand All @@ -28,6 +29,7 @@ class StepCompletionActionDispatcher(
private val resourceProvider: ResourceProvider,
private val sentryInteractor: SentryInteractor,
private val topicCompletedFlow: TopicCompletedFlow,
private val topicProgressFlow: TopicProgressFlow,
notificationInteractor: NotificationInteractor,
) : CoroutineActionDispatcher<Action, Message>(config.createConfig()) {
init {
Expand Down Expand Up @@ -67,12 +69,11 @@ class StepCompletionActionDispatcher(
onNewMessage(message)
}
is Action.CheckTopicCompletionStatus -> {
val topicIsCompleted = progressesInteractor
val topicProgress = progressesInteractor
.getTopicProgress(action.topicId)
.map { it.isCompleted }
.getOrElse { return onNewMessage(Message.CheckTopicCompletionStatus.Error) }

if (topicIsCompleted) {
if (topicProgress.isCompleted) {
topicCompletedFlow.notifyDataChanged(action.topicId)

val topicTitle = topicsInteractor
Expand All @@ -89,6 +90,7 @@ class StepCompletionActionDispatcher(
)
)
} else {
topicProgressFlow.notifyDataChanged(topicProgress)
onNewMessage(Message.CheckTopicCompletionStatus.Uncompleted)
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
package org.hyperskill.app.topics.domain.model

import kotlin.math.round
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlin.math.round

@Serializable
data class TopicProgress(
@SerialName("id")
val id: String,
@SerialName("vid")
val vid: String,
@SerialName("stage_position")
val stagePosition: Int? = null,
@SerialName("repeated_count")
Expand All @@ -22,6 +24,9 @@ data class TopicProgress(
val isInCurrentTrack: Boolean
)

val TopicProgress.topicId: Long?
get() = vid.substringAfter("topic-").toLongOrNull()

val TopicProgress.completenessPercentage: Float
get() = if (isCompleted || isSkipped) {
100f
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ class TopicsToDiscoverNextComponentImpl(
appGraph.buildTopicsToDiscoverNextDataComponent().topicsToDiscoverNextInteractor,
appGraph.sentryComponent.sentryInteractor,
appGraph.analyticComponent.analyticInteractor,
appGraph.stepCompletionFlowDataComponent.topicCompletedFlow
appGraph.stepCompletionFlowDataComponent.topicCompletedFlow,
appGraph.progressesFlowDataComponent.topicProgressFlow
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import org.hyperskill.app.analytic.domain.interactor.AnalyticInteractor
import org.hyperskill.app.core.presentation.ActionDispatcherOptions
import org.hyperskill.app.progresses.domain.flow.TopicProgressFlow
import org.hyperskill.app.sentry.domain.interactor.SentryInteractor
import org.hyperskill.app.step_completion.domain.flow.TopicCompletedFlow
import org.hyperskill.app.topics_to_discover_next.domain.interactor.TopicsToDiscoverNextInteractor
Expand All @@ -16,13 +17,18 @@ class TopicsToDiscoverNextActionDispatcher(
private val topicsToDiscoverNextInteractor: TopicsToDiscoverNextInteractor,
private val sentryInteractor: SentryInteractor,
private val analyticInteractor: AnalyticInteractor,
topicCompletedFlow: TopicCompletedFlow
topicCompletedFlow: TopicCompletedFlow,
topicProgressFlow: TopicProgressFlow
) : CoroutineActionDispatcher<Action, Message>(config.createConfig()) {

init {
topicCompletedFlow.observe()
.onEach { onNewMessage(Message.TopicCompleted(it)) }
.launchIn(actionScope)

topicProgressFlow.observe()
.onEach { onNewMessage(Message.TopicProgressChanged(it)) }
.launchIn(actionScope)
}

override suspend fun doSuspendableAction(action: Action) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package org.hyperskill.app.topics_to_discover_next.presentation
import org.hyperskill.app.analytic.domain.model.AnalyticEvent
import org.hyperskill.app.sentry.domain.model.transaction.HyperskillSentryTransaction
import org.hyperskill.app.topics.domain.model.Topic
import org.hyperskill.app.topics.domain.model.TopicProgress

interface TopicsToDiscoverNextFeature {
sealed interface State {
Expand Down Expand Up @@ -50,7 +51,11 @@ interface TopicsToDiscoverNextFeature {

object PullToRefresh : Message

/**
* Flow Messages
*/
data class TopicCompleted(val topicId: Long) : Message
data class TopicProgressChanged(val topicProgress: TopicProgress) : Message

/**
* A message that indicates about click on topic.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.hyperskill.app.topics_to_discover_next.presentation

import org.hyperskill.app.topics.domain.model.topicId
import org.hyperskill.app.topics_to_discover_next.domain.analytic.TopicsToDiscoverNextClickedHyperskillAnalyticEvent
import org.hyperskill.app.topics_to_discover_next.domain.model.TopicsToDiscoverNextScreen
import org.hyperskill.app.topics_to_discover_next.presentation.TopicsToDiscoverNextFeature.Action
Expand Down Expand Up @@ -51,6 +52,19 @@ class TopicsToDiscoverNextReducer(
} else {
null
}
is Message.TopicProgressChanged ->
if (state is State.Content) {
val newTopicsToDiscoverNext = state.topicsToDiscoverNext.map { topic ->
if (topic.id == message.topicProgress.topicId) {
topic.copy(progress = message.topicProgress)
} else {
topic
}
}
state.copy(topicsToDiscoverNext = newTopicsToDiscoverNext) to emptySet()
} else {
null
}
is Message.TopicToDiscoverNextClicked -> {
val targetTopic = (state as? State.Content)
?.topicsToDiscoverNext?.firstOrNull { it.id == message.topicId }
Expand Down
57 changes: 57 additions & 0 deletions shared/src/commonTest/kotlin/org/hyperskill/TopicProgressTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package org.hyperskill

import kotlin.test.Test
import kotlin.test.assertEquals
import org.hyperskill.app.topics.domain.model.TopicProgress
import org.hyperskill.app.topics.domain.model.topicId

class TopicProgressTest {
@Test
fun testTopicProgressGetTopicId() {
val topicProgress = TopicProgress(
id = "2-123",
vid = "topic-123",
isCompleted = false,
isSkipped = false,
isInCurrentTrack = true
)
assertEquals(123L, topicProgress.topicId)
}

@Test
fun testTopicProgressGetTopicIdNull() {
val topicProgresses = listOf(
TopicProgress(
id = "2-abc",
vid = "topic-abc",
isCompleted = false,
isSkipped = false,
isInCurrentTrack = true
),
TopicProgress(
id = "2-abc",
vid = "abc-defog",
isCompleted = false,
isSkipped = false,
isInCurrentTrack = true
),
TopicProgress(
id = "1-abc",
vid = "",
isCompleted = false,
isSkipped = false,
isInCurrentTrack = true
),
TopicProgress(
id = "1-abc",
vid = "qwerty",
isCompleted = false,
isSkipped = false,
isInCurrentTrack = true
)
)
topicProgresses.forEach {
assertEquals(null, it.topicId)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ import org.hyperskill.app.profile_settings.injection.ProfileSettingsComponent
import org.hyperskill.app.profile_settings.injection.ProfileSettingsComponentImpl
import org.hyperskill.app.progresses.injection.ProgressesDataComponent
import org.hyperskill.app.progresses.injection.ProgressesDataComponentImpl
import org.hyperskill.app.progresses.injection.ProgressesFlowDataComponent
import org.hyperskill.app.progresses.injection.ProgressesFlowDataComponentImpl
import org.hyperskill.app.reactions.injection.ReactionsDataComponent
import org.hyperskill.app.reactions.injection.ReactionsDataComponentImpl
import org.hyperskill.app.sentry.domain.model.manager.SentryManager
Expand Down Expand Up @@ -123,6 +125,9 @@ class AppGraphImpl(
override val stepCompletionFlowDataComponent: StepCompletionFlowDataComponent =
StepCompletionFlowDataComponentImpl()

override val progressesFlowDataComponent: ProgressesFlowDataComponent =
ProgressesFlowDataComponentImpl()

override val sentryComponent: SentryComponent =
SentryComponentImpl(sentryManager)

Expand Down

0 comments on commit 4bbb741

Please sign in to comment.