Skip to content
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

ALTAPPS-1357: Shared, iOS code blanks mechanics onboarding final #1185

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading