Skip to content

Commit

Permalink
Shared, Android: Make primary comments action available for theory st…
Browse files Browse the repository at this point in the history
…ep (#1135)

^ALTAPPS-1313
  • Loading branch information
XanderZhu authored Jul 31, 2024
1 parent b071584 commit e4533ee
Show file tree
Hide file tree
Showing 6 changed files with 132 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ class StepMenuDelegate(
val state = menuActionsStateFlow.value
renderMainAction(menu, state.primaryActions)
renderSecondaryActions(menu, state.secondaryActions)
renderCommentsAction(menu, state)
}

private fun renderMainAction(
Expand All @@ -86,11 +87,11 @@ class StepMenuDelegate(
) {
StepMenuPrimaryAction.entries.forEach { action ->
val params: StepMenuPrimaryActionParams? = primaryActions[action]
val menuItem: MenuItem? = menu.findItem(
val menuItem: MenuItem? =
when (action) {
StepMenuPrimaryAction.THEORY -> R.id.theory
StepMenuPrimaryAction.THEORY -> menu.findItem(R.id.theory)
StepMenuPrimaryAction.COMMENTS -> null
}
)
val isVisible = params?.isVisible == true
menuItem?.isVisible = isVisible
if (isVisible) {
Expand All @@ -107,12 +108,22 @@ class StepMenuDelegate(
StepMenuSecondaryAction.REPORT -> R.id.practiceFeedback
StepMenuSecondaryAction.SKIP -> R.id.skip
StepMenuSecondaryAction.OPEN_IN_WEB -> R.id.open_in_web
StepMenuSecondaryAction.COMMENTS -> R.id.comments
StepMenuSecondaryAction.COMMENTS -> null
}
menu.findItem(menuItemId)?.isVisible = actions.contains(action)
menuItemId?.let(menu::findItem)?.isVisible = actions.contains(action)
}
}

private fun renderCommentsAction(menu: Menu, state: MenuActionsState) {
val commentsAction = menu.findItem(R.id.comments)
val isPrimary = state.primaryActions[StepMenuPrimaryAction.COMMENTS]?.isVisible == true
commentsAction?.isVisible =
isPrimary || state.secondaryActions.contains(StepMenuSecondaryAction.COMMENTS)
commentsAction?.setShowAsAction(
if (isPrimary) MenuItem.SHOW_AS_ACTION_IF_ROOM else MenuItem.SHOW_AS_ACTION_NEVER
)
}

override fun onMenuItemSelected(menuItem: MenuItem): Boolean =
when (menuItem.itemId) {
R.id.theory -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import org.hyperskill.app.android.step.view.model.LimitsWidgetCallback
import org.hyperskill.app.android.step.view.model.StepCompletionHost
import org.hyperskill.app.android.step.view.model.StepCompletionView
import org.hyperskill.app.android.step.view.model.StepMenuPrimaryAction
import org.hyperskill.app.android.step.view.model.StepMenuPrimaryActionParams
import org.hyperskill.app.android.step.view.model.StepPracticeCallback
import org.hyperskill.app.android.step.view.model.StepToolbarCallback
import org.hyperskill.app.android.step.view.model.StepToolbarHost
Expand Down Expand Up @@ -136,6 +137,13 @@ class StepWrapperFragment :
parentOfType(StepToolbarHost::class.java)?.apply {
renderTopicProgress(state.stepToolbarViewState)
renderSecondaryMenuActions(state.stepMenuSecondaryActions)
renderPrimaryAction(
StepMenuPrimaryAction.COMMENTS,
StepMenuPrimaryActionParams(
isVisible = state.isCommentsToolbarItemAvailable,
isEnabled = true
)
)
}
(childFragmentManager.findFragmentByTag(STEP_CONTENT_TAG) as? StepCompletionView)
?.renderPracticeLoading(stepState.stepCompletionState.isPracticingLoading)
Expand Down Expand Up @@ -215,6 +223,9 @@ class StepWrapperFragment :
(childFragmentManager.findFragmentByTag(STEP_CONTENT_TAG) as? StepPracticeCallback)
?.onTheoryClick()
}
StepMenuPrimaryAction.COMMENTS -> {
stepViewModel.onActionClick(StepMenuSecondaryAction.COMMENTS)
}
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.hyperskill.app.android.step.view.model

enum class StepMenuPrimaryAction {
THEORY
THEORY,
COMMENTS
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ object StepFeature {
val stepState: StepState,
val stepToolbarViewState: StepToolbarFeature.ViewState,
val stepMenuSecondaryActions: Set<StepMenuSecondaryAction>,
val isCommentsToolbarItemAvailable: Boolean,
val isLoadingShowed: Boolean
)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.hyperskill.app.step.view.mapper

import org.hyperskill.app.step.domain.model.Step
import org.hyperskill.app.step.domain.model.StepMenuSecondaryAction
import org.hyperskill.app.step.domain.model.StepRoute
import org.hyperskill.app.step.domain.model.areCommentsAvailable
Expand All @@ -13,17 +14,18 @@ internal class StepViewStateMapper(
StepFeature.ViewState(
stepState = state.stepState,
stepToolbarViewState = StepToolbarViewStateMapper.map(state.stepToolbarState),
stepMenuSecondaryActions = getStepToolbarActions(state.stepState, stepRoute),
isLoadingShowed = state.isLoadingShowed
stepMenuSecondaryActions = getStepMenuSecondaryActions(state.stepState, stepRoute),
isLoadingShowed = state.isLoadingShowed,
isCommentsToolbarItemAvailable = isPrimaryCommentsToolbarItemAvailable(state.stepState)
)

private fun getStepToolbarActions(
private fun getStepMenuSecondaryActions(
stepState: StepFeature.StepState,
stepRoute: StepRoute
): Set<StepMenuSecondaryAction> =
StepMenuSecondaryAction.entries.filter { action ->
when (action) {
StepMenuSecondaryAction.COMMENTS -> isCommentsToolbarItemAvailable(stepState)
StepMenuSecondaryAction.COMMENTS -> isSecondaryCommentsMenuActionAvailable(stepState)
StepMenuSecondaryAction.SKIP -> isSkipButtonAvailable(stepState, stepRoute)
StepMenuSecondaryAction.SHARE,
StepMenuSecondaryAction.REPORT,
Expand All @@ -39,8 +41,13 @@ internal class StepViewStateMapper(
stepRoute is StepRoute.Learn.Step &&
stepState.step.canSkip

private fun isCommentsToolbarItemAvailable(stepState: StepFeature.StepState): Boolean {
private fun isPrimaryCommentsToolbarItemAvailable(stepState: StepFeature.StepState): Boolean {
val step = (stepState as? StepFeature.StepState.Data)?.step ?: return false
return step.areCommentsAvailable
return step.type == Step.Type.THEORY && step.areCommentsAvailable
}

private fun isSecondaryCommentsMenuActionAvailable(stepState: StepFeature.StepState): Boolean {
val step = (stepState as? StepFeature.StepState.Data)?.step ?: return false
return step.type == Step.Type.PRACTICE && step.areCommentsAvailable
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package org.hyperskill.step
import kotlin.test.Test
import kotlin.test.assertContains
import kotlin.test.assertFalse
import kotlin.test.assertTrue
import org.hyperskill.app.comments.domain.model.CommentStatisticsEntry
import org.hyperskill.app.comments.domain.model.CommentThread
import org.hyperskill.app.step.domain.model.Step
Expand All @@ -16,9 +17,10 @@ import org.hyperskill.step.domain.model.stub

class StepViewStateMapperTest {
@Test
fun `Comments secondary action should be presented when comments are present`() {
fun `Comments secondary action should be presented for practical step when comments are present`() {
val step = Step.stub(
id = 1,
type = Step.Type.PRACTICE,
commentsStatistics = listOf(
CommentStatisticsEntry(
thread = CommentThread.COMMENT,
Expand All @@ -36,9 +38,10 @@ class StepViewStateMapperTest {
}

@Test
fun `Comments secondary action should not be presented when no comments are present`() {
fun `Comments secondary action should not be presented for practical step when no comments are present`() {
val step = Step.stub(
id = 1,
type = Step.Type.PRACTICE,
commentsStatistics = listOf(
CommentStatisticsEntry(
thread = CommentThread.COMMENT,
Expand All @@ -55,6 +58,90 @@ class StepViewStateMapperTest {
assertFalse(viewState.stepMenuSecondaryActions.contains(StepMenuSecondaryAction.COMMENTS))
}

@Test
fun `Comments primary action should not be available for practical step when comments are presented`() {
val step = Step.stub(
id = 1,
type = Step.Type.PRACTICE,
commentsStatistics = listOf(
CommentStatisticsEntry(
thread = CommentThread.COMMENT,
totalCount = 1
)
)
)
val stepRoute = StepRoute.Learn.Step(step.id, null)
val state = stubState(stepState = stubStepDataState(step, stepRoute))

val mapper = StepViewStateMapper(stepRoute)
val viewState = mapper.map(state)

assertFalse(viewState.isCommentsToolbarItemAvailable)
}

@Test
fun `Comments primary action should be available for theory step when comments are presented`() {
val step = Step.stub(
id = 1,
type = Step.Type.THEORY,
commentsStatistics = listOf(
CommentStatisticsEntry(
thread = CommentThread.COMMENT,
totalCount = 1
)
)
)
val stepRoute = StepRoute.Learn.Step(step.id, null)
val state = stubState(stepState = stubStepDataState(step, stepRoute))

val mapper = StepViewStateMapper(stepRoute)
val viewState = mapper.map(state)

assertTrue(viewState.isCommentsToolbarItemAvailable)
}

@Test
fun `Comments primary action should not be available for theory step when no comments presented`() {
val step = Step.stub(
id = 1,
type = Step.Type.THEORY,
commentsStatistics = listOf(
CommentStatisticsEntry(
thread = CommentThread.COMMENT,
totalCount = 0
)
)
)
val stepRoute = StepRoute.Learn.Step(step.id, null)
val state = stubState(stepState = stubStepDataState(step, stepRoute))

val mapper = StepViewStateMapper(stepRoute)
val viewState = mapper.map(state)

assertFalse(viewState.isCommentsToolbarItemAvailable)
}

@Test
fun `Comments secondary action should not be presented for theory step when comments are presented`() {
val step = Step.stub(
id = 1,
type = Step.Type.THEORY,
commentsStatistics = listOf(
CommentStatisticsEntry(
thread = CommentThread.COMMENT,
totalCount = 1
)
)
)
val stepRoute = StepRoute.Learn.Step(step.id, null)
val state = stubState(stepState = stubStepDataState(step, stepRoute))

val mapper = StepViewStateMapper(stepRoute)
val viewState = mapper.map(state)

assertFalse(viewState.stepMenuSecondaryActions.contains(StepMenuSecondaryAction.COMMENTS))
}

@Test
fun `stepMenuActions contains SKIP when skip is available`() {
val step = Step.stub(
Expand Down

0 comments on commit e4533ee

Please sign in to comment.