Skip to content

Commit

Permalink
Shared, iOS: Code blanks mechanics onboarding final (#1185)
Browse files Browse the repository at this point in the history
^ALTAPPS-1357
  • Loading branch information
ivan-magda authored Sep 19, 2024
1 parent a72c824 commit c6af5a6
Show file tree
Hide file tree
Showing 12 changed files with 155 additions and 61 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,15 @@ extension StepQuizCodeBlanksActionButton {
)
}

static func enter(action: @escaping () -> Void) -> StepQuizCodeBlanksActionButton {
StepQuizCodeBlanksActionButton(imageSystemName: "return", action: action)
static func enter(
isAnimationEffectActive: Bool,
action: @escaping () -> Void
) -> StepQuizCodeBlanksActionButton {
StepQuizCodeBlanksActionButton(
imageSystemName: "return",
isAnimationEffectActive: isAnimationEffectActive,
action: action
)
}

static func space(
Expand Down Expand Up @@ -98,14 +105,14 @@ extension StepQuizCodeBlanksActionButton {
VStack {
HStack {
StepQuizCodeBlanksActionButton.delete(isAnimationEffectActive: false, action: {})
StepQuizCodeBlanksActionButton.enter(action: {})
StepQuizCodeBlanksActionButton.enter(isAnimationEffectActive: false, action: {})
StepQuizCodeBlanksActionButton.space(isAnimationEffectActive: false, action: {})
StepQuizCodeBlanksActionButton.decreaseIndentLevel(action: {})
}

HStack {
StepQuizCodeBlanksActionButton.delete(isAnimationEffectActive: false, action: {})
StepQuizCodeBlanksActionButton.enter(action: {})
StepQuizCodeBlanksActionButton.enter(isAnimationEffectActive: false, action: {})
StepQuizCodeBlanksActionButton.space(isAnimationEffectActive: false, action: {})
StepQuizCodeBlanksActionButton.decreaseIndentLevel(action: {})
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ struct StepQuizCodeBlanksActionButtonsView: View {
let isDecreaseIndentLevelButtonHidden: Bool

let isDeleteButtonHighlightEffectActive: Bool
let isEnterButtonHighlightEffectActive: Bool
let isSpaceButtonHighlightEffectActive: Bool

let onSpaceTap: () -> Void
Expand Down Expand Up @@ -38,7 +39,10 @@ struct StepQuizCodeBlanksActionButtonsView: View {
.disabled(!isDeleteButtonEnabled)

StepQuizCodeBlanksActionButton
.enter(action: onEnterTap)
.enter(
isAnimationEffectActive: isEnterButtonHighlightEffectActive,
action: onEnterTap
)
}
.padding(.horizontal)
}
Expand All @@ -52,6 +56,7 @@ struct StepQuizCodeBlanksActionButtonsView: View {
isSpaceButtonHidden: false,
isDecreaseIndentLevelButtonHidden: false,
isDeleteButtonHighlightEffectActive: false,
isEnterButtonHighlightEffectActive: false,
isSpaceButtonHighlightEffectActive: true,
onSpaceTap: {},
onDeleteTap: {},
Expand All @@ -64,6 +69,7 @@ struct StepQuizCodeBlanksActionButtonsView: View {
isSpaceButtonHidden: true,
isDecreaseIndentLevelButtonHidden: true,
isDeleteButtonHighlightEffectActive: true,
isEnterButtonHighlightEffectActive: true,
isSpaceButtonHighlightEffectActive: false,
onSpaceTap: {},
onDeleteTap: {},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ struct StepQuizCodeBlanksCodeBlocksView: View {
isSpaceButtonHidden: state.isSpaceButtonHidden,
isDecreaseIndentLevelButtonHidden: state.isDecreaseIndentLevelButtonHidden,
isDeleteButtonHighlightEffectActive: state.isDeleteButtonHighlightEffectActive,
isEnterButtonHighlightEffectActive: state.isEnterButtonHighlightEffectActive,
isSpaceButtonHighlightEffectActive: state.isSpaceButtonHighlightEffectActive,
onSpaceTap: onSpaceTap,
onDeleteTap: onDeleteTap,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,16 @@ object StepQuizCodeBlanksFeature {
) : State {
companion object;

internal val codeBlanksStringsSuggestions: List<Suggestion.ConstantString> =
internal val stringsSuggestions: List<Suggestion.ConstantString> =
step.codeBlanksStringsSuggestions()

internal val codeBlanksVariablesSuggestions: List<Suggestion.ConstantString> =
internal val variablesSuggestions: List<Suggestion.ConstantString> =
step.codeBlanksVariablesSuggestions()

internal val codeBlanksVariablesAndStringsSuggestions: List<Suggestion.ConstantString> =
codeBlanksVariablesSuggestions + codeBlanksStringsSuggestions
internal val variablesAndStringsSuggestions: List<Suggestion.ConstantString> =
variablesSuggestions + stringsSuggestions

internal val codeBlanksOperationsSuggestions: List<Suggestion.ConstantString> =
internal val operationsSuggestions: List<Suggestion.ConstantString> =
step.codeBlanksOperationsSuggestions()
}
}
Expand All @@ -41,11 +41,12 @@ object StepQuizCodeBlanksFeature {
data object Unavailable : OnboardingState

data object HighlightDeleteButton : OnboardingState
data object HighlightEnterButton : OnboardingState
data object HighlightSpaceButton : OnboardingState

sealed interface PrintSuggestionAndCallToAction : OnboardingState {
data object HighlightSuggestions : PrintSuggestionAndCallToAction
data object HighlightCallToActionButton : PrintSuggestionAndCallToAction
sealed interface FirstProgram : OnboardingState {
data object HighlightSuggestions : FirstProgram
data object HighlightCallToActionButton : FirstProgram
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,23 @@ import org.hyperskill.app.step_quiz_code_blanks.presentation.StepQuizCodeBlanksF
import org.hyperskill.app.step_quiz_code_blanks.presentation.StepQuizCodeBlanksFeature.OnboardingState
import org.hyperskill.app.step_quiz_code_blanks.presentation.StepQuizCodeBlanksFeature.State

private typealias StepQuizCodeBlanksOnboardingReducerResult = Pair<OnboardingState, Set<Action>>

class StepQuizCodeBlanksOnboardingReducer {
companion object {
private const val DELETE_BUTTON_STEP_ID = 50969L
private const val SPACE_BUTTON_STEP_ID = 50970L
private val PRINT_SUGGESTION_AND_CALL_TO_ACTION_STEP_IDS = setOf(47329L, 50968L)
internal val FIRST_PROGRAM_STEP_IDS = setOf(47329L, 50984L)
internal const val DELETE_BUTTON_STEP_ID = 50986L
internal const val ENTER_BUTTON_STEP_ID = 50985L
internal const val SPACE_BUTTON_STEP_ID = 50997L
}

internal fun reduceInitializeMessage(
message: InternalMessage.Initialize
): OnboardingState =
when (message.step.id) {
in PRINT_SUGGESTION_AND_CALL_TO_ACTION_STEP_IDS ->
OnboardingState.PrintSuggestionAndCallToAction.HighlightSuggestions
in FIRST_PROGRAM_STEP_IDS -> OnboardingState.FirstProgram.HighlightSuggestions
DELETE_BUTTON_STEP_ID -> OnboardingState.HighlightDeleteButton
ENTER_BUTTON_STEP_ID -> OnboardingState.HighlightEnterButton
SPACE_BUTTON_STEP_ID -> OnboardingState.HighlightSpaceButton
else -> OnboardingState.Unavailable
}
Expand All @@ -29,13 +32,13 @@ class StepQuizCodeBlanksOnboardingReducer {
state: State.Content,
activeCodeBlock: CodeBlock?,
newCodeBlock: CodeBlock
): Pair<OnboardingState, Set<Action>> {
val isFulfilledOnboardingPrintCodeBlock =
state.onboardingState is OnboardingState.PrintSuggestionAndCallToAction.HighlightSuggestions &&
): StepQuizCodeBlanksOnboardingReducerResult {
val isFulfilledFirstProgramOnboarding =
state.onboardingState is OnboardingState.FirstProgram.HighlightSuggestions &&
activeCodeBlock is CodeBlock.Print && activeCodeBlock.hasAnyUnselectedChild() &&
newCodeBlock is CodeBlock.Print && newCodeBlock.areAllChildrenSelected()
return if (isFulfilledOnboardingPrintCodeBlock) {
OnboardingState.PrintSuggestionAndCallToAction.HighlightCallToActionButton to
return if (isFulfilledFirstProgramOnboarding) {
OnboardingState.FirstProgram.HighlightCallToActionButton to
setOf(
InternalAction.ParentFeatureActionRequested(
StepQuizCodeBlanksFeature.ParentFeatureAction.HighlightCallToActionButton
Expand All @@ -45,4 +48,31 @@ class StepQuizCodeBlanksOnboardingReducer {
state.onboardingState to emptySet()
}
}

internal fun reduceDeleteButtonClickedMessage(
state: State.Content
): StepQuizCodeBlanksOnboardingReducerResult =
if (state.onboardingState is OnboardingState.HighlightDeleteButton) {
OnboardingState.Unavailable to emptySet()
} else {
state.onboardingState to emptySet()
}

internal fun reduceEnterButtonClickedMessage(
state: State.Content
): StepQuizCodeBlanksOnboardingReducerResult =
if (state.onboardingState is OnboardingState.HighlightEnterButton) {
OnboardingState.Unavailable to emptySet()
} else {
state.onboardingState to emptySet()
}

internal fun reduceSpaceButtonClickedMessage(
state: State.Content
): StepQuizCodeBlanksOnboardingReducerResult =
if (state.onboardingState is OnboardingState.HighlightSpaceButton) {
OnboardingState.Unavailable to emptySet()
} else {
state.onboardingState to emptySet()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ class StepQuizCodeBlanksReducer(
children = listOf(
CodeBlockChild.SelectSuggestion(
isActive = true,
suggestions = state.codeBlanksVariablesAndStringsSuggestions,
suggestions = state.variablesAndStringsSuggestions,
selectedSuggestion = null
)
)
Expand All @@ -98,12 +98,12 @@ class StepQuizCodeBlanksReducer(
children = listOf(
CodeBlockChild.SelectSuggestion(
isActive = true,
suggestions = state.codeBlanksVariablesSuggestions,
suggestions = state.variablesSuggestions,
selectedSuggestion = null
),
CodeBlockChild.SelectSuggestion(
isActive = false,
suggestions = state.codeBlanksStringsSuggestions,
suggestions = state.stringsSuggestions,
selectedSuggestion = null
)
)
Expand All @@ -114,7 +114,7 @@ class StepQuizCodeBlanksReducer(
children = listOf(
CodeBlockChild.SelectSuggestion(
isActive = true,
suggestions = state.codeBlanksVariablesAndStringsSuggestions,
suggestions = state.variablesAndStringsSuggestions,
selectedSuggestion = null
)
)
Expand All @@ -125,7 +125,7 @@ class StepQuizCodeBlanksReducer(
children = listOf(
CodeBlockChild.SelectSuggestion(
isActive = true,
suggestions = state.codeBlanksVariablesAndStringsSuggestions,
suggestions = state.variablesAndStringsSuggestions,
selectedSuggestion = null
)
)
Expand Down Expand Up @@ -511,7 +511,13 @@ class StepQuizCodeBlanksReducer(
}
}

return state.copy(codeBlocks = newCodeBlocks) to actions
val (onboardingState, onboardingActions) =
stepQuizCodeBlanksOnboardingReducer.reduceDeleteButtonClickedMessage(state)

return state.copy(
codeBlocks = newCodeBlocks,
onboardingState = onboardingState
) to actions + onboardingActions
}

private fun handleEnterButtonClicked(
Expand Down Expand Up @@ -564,7 +570,13 @@ class StepQuizCodeBlanksReducer(
)
}

state.copy(codeBlocks = newCodeBlocks) to actions
val (onboardingState, onboardingActions) =
stepQuizCodeBlanksOnboardingReducer.reduceEnterButtonClickedMessage(state)

state.copy(
codeBlocks = newCodeBlocks,
onboardingState = onboardingState
) to actions + onboardingActions
} else {
state to actions
}
Expand Down Expand Up @@ -603,20 +615,19 @@ class StepQuizCodeBlanksReducer(

val newChildSuggestions = when {
activeChild.selectedSuggestion?.isOpeningParentheses == true ->
state.codeBlanksVariablesSuggestions + state.codeBlanksStringsSuggestions
state.variablesSuggestions + state.stringsSuggestions

activeChild.selectedSuggestion?.isClosingParentheses == true ->
state.codeBlanksOperationsSuggestions
state.operationsSuggestions

activeChild.selectedSuggestion in state.codeBlanksStringsSuggestions ||
activeChild.selectedSuggestion in state.codeBlanksVariablesSuggestions ->
state.codeBlanksOperationsSuggestions
activeChild.selectedSuggestion in state.stringsSuggestions ||
activeChild.selectedSuggestion in state.variablesSuggestions ->
state.operationsSuggestions

activeChild.selectedSuggestion in state.codeBlanksOperationsSuggestions ->
state.codeBlanksVariablesSuggestions + state.codeBlanksStringsSuggestions
activeChild.selectedSuggestion in state.operationsSuggestions ->
state.variablesSuggestions + state.stringsSuggestions

else ->
state.codeBlanksOperationsSuggestions + state.codeBlanksVariablesAndStringsSuggestions
else -> state.operationsSuggestions + state.variablesAndStringsSuggestions
}

val newChild = CodeBlockChild.SelectSuggestion(
Expand Down Expand Up @@ -644,7 +655,13 @@ class StepQuizCodeBlanksReducer(
}
}

return state.copy(codeBlocks = newCodeBlocks) to actions
val (onboardingState, onboardingActions) =
stepQuizCodeBlanksOnboardingReducer.reduceSpaceButtonClickedMessage(state)

return state.copy(
codeBlocks = newCodeBlocks,
onboardingState = onboardingState
) to actions + onboardingActions
}

private fun handleDecreaseIndentLevelButtonClicked(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ object StepQuizCodeBlanksViewStateMapper {
null -> false
}

val isSpaceButtonHidden = if (state.codeBlanksOperationsSuggestions.isNotEmpty()) {
val isSpaceButtonHidden = if (state.operationsSuggestions.isNotEmpty()) {
when (activeCodeBlock) {
is CodeBlock.Print,
is CodeBlock.IfStatement,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,24 @@ sealed interface StepQuizCodeBlanksViewState {
) : StepQuizCodeBlanksViewState {
val isActionButtonsHidden: Boolean
get() = when (onboardingState) {
is OnboardingState.PrintSuggestionAndCallToAction -> true
is OnboardingState.FirstProgram -> true
OnboardingState.HighlightDeleteButton,
OnboardingState.HighlightEnterButton,
OnboardingState.HighlightSpaceButton,
OnboardingState.Unavailable -> false
}

val isDeleteButtonHighlightEffectActive: Boolean
get() = isDeleteButtonEnabled && onboardingState == OnboardingState.HighlightDeleteButton

val isEnterButtonHighlightEffectActive: Boolean
get() = onboardingState == OnboardingState.HighlightEnterButton

val isSpaceButtonHighlightEffectActive: Boolean
get() = !isSpaceButtonHidden && onboardingState == OnboardingState.HighlightSpaceButton

val isSuggestionsHighlightEffectActive: Boolean
get() = onboardingState == OnboardingState.PrintSuggestionAndCallToAction.HighlightSuggestions
get() = onboardingState == OnboardingState.FirstProgram.HighlightSuggestions
}

sealed interface CodeBlockItem {
Expand Down
Loading

0 comments on commit c6af5a6

Please sign in to comment.