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-1318: Shared, iOS code blanks variable block type #1150

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
3 changes: 3 additions & 0 deletions config/detekt/baseline.xml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
<ID>CyclomaticComplexMethod:LoadingView.kt$LoadingView$override fun onDraw(canvas: Canvas)</ID>
<ID>CyclomaticComplexMethod:ProfileReducer.kt$ProfileReducer$override fun reduce(state: State, message: Message): ReducerResult</ID>
<ID>CyclomaticComplexMethod:StepQuizActionDispatcher.kt$StepQuizActionDispatcher$override suspend fun doSuspendableAction(action: Action)</ID>
<ID>CyclomaticComplexMethod:StepQuizCodeBlanksReducer.kt$StepQuizCodeBlanksReducer$private fun handleDeleteButtonClicked( state: State ): StepQuizCodeBlanksReducerResult?</ID>
<ID>CyclomaticComplexMethod:StepQuizHintsReducer.kt$StepQuizHintsReducer$override fun reduce(state: State, message: Message): StepQuizHintsReducerResult</ID>
<ID>CyclomaticComplexMethod:StepQuizReducer.kt$StepQuizReducer$override fun reduce(state: State, message: Message): StepQuizReducerResult</ID>
<ID>CyclomaticComplexMethod:StepQuizReplyValidator.kt$StepQuizReplyValidator$fun validate(dataset: Dataset?, reply: Reply, stepBlockName: String): ReplyValidationResult</ID>
Expand Down Expand Up @@ -64,6 +65,8 @@
<ID>LongMethod:ProblemOfDayCardFormDelegate.kt$ProblemOfDayCardFormDelegate$fun render( dateFormatter: SharedDateFormatter, binding: LayoutProblemOfTheDayCardBinding, state: HomeFeature.ProblemOfDayState, areProblemsLimited: Boolean )</ID>
<ID>LongMethod:ProfileBadges.kt$@Composable fun ProfileBadges( viewState: BadgesViewState, windowWidthSizeClass: WindowWidthSizeClass, onBadgeClick: (BadgeKind) -&gt; Unit, onExpandButtonClick: (ProfileFeature.Message.BadgesVisibilityButton) -&gt; Unit, modifier: Modifier = Modifier )</ID>
<ID>LongMethod:ProfileSettingsDialogFragment.kt$ProfileSettingsDialogFragment$override fun onViewCreated(view: View, savedInstanceState: Bundle?)</ID>
<ID>LongMethod:StepQuizCodeBlanksReducer.kt$StepQuizCodeBlanksReducer$private fun handleDeleteButtonClicked( state: State ): StepQuizCodeBlanksReducerResult?</ID>
<ID>LongMethod:StepQuizCodeBlanksReducer.kt$StepQuizCodeBlanksReducer$private fun handleSuggestionClicked( state: State, message: Message.SuggestionClicked ): StepQuizCodeBlanksReducerResult?</ID>
<ID>LongMethod:StreakFreezeDialogFragment.kt$StreakFreezeDialogFragment$override fun onViewCreated(view: View, savedInstanceState: Bundle?)</ID>
<ID>LongMethod:TrackProgressContent.kt$@Composable fun TrackProgressContent( viewState: ProgressScreenViewState.TrackProgressViewState.Content, onNewMessage: (ProgressScreenFeature.Message) -&gt; Unit, modifier: Modifier = Modifier )</ID>
<ID>LongParameterList:AppInteractor.kt$AppInteractor$( private val appRepository: AppRepository, private val authInteractor: AuthInteractor, private val currentProfileStateRepository: CurrentProfileStateRepository, private val userStorageInteractor: UserStorageInteractor, private val analyticInteractor: AnalyticInteractor, private val progressesRepository: ProgressesRepository, private val trackRepository: TrackRepository, private val providersRepository: ProvidersRepository, private val projectsRepository: ProjectsRepository, private val shareStreakRepository: ShareStreakRepository, private val pushNotificationsInteractor: PushNotificationsInteractor )</ID>
Expand Down
4 changes: 4 additions & 0 deletions iosHyperskillApp/iosHyperskillApp.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@
2C370439288BE57A008043BF /* StepQuizCodeFullScreenCodeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C370438288BE57A008043BF /* StepQuizCodeFullScreenCodeView.swift */; };
2C37960F2876F36F00C197E2 /* ProfileViewData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C37960E2876F36F00C197E2 /* ProfileViewData.swift */; };
2C3796122877001700C197E2 /* ProfileHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C3796112877001700C197E2 /* ProfileHeaderView.swift */; };
2C3B84E82C637AE100FE9D5C /* StepQuizCodeBlanksVariableInstructionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C3B84E72C637AE100FE9D5C /* StepQuizCodeBlanksVariableInstructionView.swift */; };
2C3CE3962C1073990011BECA /* StepToolbarContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C3CE3952C1073990011BECA /* StepToolbarContent.swift */; };
2C3E656D2A12722800BC8DC0 /* TrackSelectionListHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C3E656C2A12722800BC8DC0 /* TrackSelectionListHeaderView.swift */; };
2C3E65702A127F2300BC8DC0 /* BrandLinearGradient.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C3E656F2A127F2300BC8DC0 /* BrandLinearGradient.swift */; };
Expand Down Expand Up @@ -957,6 +958,7 @@
2C370438288BE57A008043BF /* StepQuizCodeFullScreenCodeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StepQuizCodeFullScreenCodeView.swift; sourceTree = "<group>"; };
2C37960E2876F36F00C197E2 /* ProfileViewData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileViewData.swift; sourceTree = "<group>"; };
2C3796112877001700C197E2 /* ProfileHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileHeaderView.swift; sourceTree = "<group>"; };
2C3B84E72C637AE100FE9D5C /* StepQuizCodeBlanksVariableInstructionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StepQuizCodeBlanksVariableInstructionView.swift; sourceTree = "<group>"; };
2C3CE3952C1073990011BECA /* StepToolbarContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StepToolbarContent.swift; sourceTree = "<group>"; };
2C3E656C2A12722800BC8DC0 /* TrackSelectionListHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrackSelectionListHeaderView.swift; sourceTree = "<group>"; };
2C3E656F2A127F2300BC8DC0 /* BrandLinearGradient.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrandLinearGradient.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -3714,6 +3716,7 @@
2CD67CA22C452DED00240C17 /* StepQuizCodeBlanksOptionView.swift */,
2CB3BC552C46171000F5354F /* StepQuizCodeBlanksPrintInstructionView.swift */,
2C677D012C4A3F860019AF03 /* StepQuizCodeBlanksSuggestionsView.swift */,
2C3B84E72C637AE100FE9D5C /* StepQuizCodeBlanksVariableInstructionView.swift */,
2C84E70B2C47BAB6002EE787 /* StepQuizCodeBlanksView.swift */,
);
path = Views;
Expand Down Expand Up @@ -5127,6 +5130,7 @@
2CD48D872858639500CFCC4A /* StepQuizViewModel.swift in Sources */,
2C7CB6862ADFF389006F78DA /* FillBlanksQuizView.swift in Sources */,
E94D238D28057F440003273F /* AuthCredentialsView.swift in Sources */,
2C3B84E82C637AE100FE9D5C /* StepQuizCodeBlanksVariableInstructionView.swift in Sources */,
2CEEE03728917F1100282849 /* TimeIntervalExtensions.swift in Sources */,
2CE31F4827F1BB79008EEE66 /* AuthSocialAssembly.swift in Sources */,
2C0DB9012864332B001EA35E /* CodeTextViewLayoutManager.swift in Sources */,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,31 +11,21 @@ extension Block.Options {
codeTemplates: [String: String]? = nil,
samples: [[String]]? = nil,
files: [Block.OptionsFile]? = nil,
codeBlanksStrings: [String]? = nil
codeBlanksStrings: [String]? = nil,
codeBlanksVariables: [String]? = nil,
codeBlanksEnabled: Bool? = nil
) {
let isMultipleChoice: KotlinBoolean? = {
if let isMultipleChoice {
return KotlinBoolean(value: isMultipleChoice)
}
return nil
}()

let isCheckbox: KotlinBoolean? = {
if let isCheckbox {
return KotlinBoolean(value: isCheckbox)
}
return nil
}()

self.init(
isMultipleChoice: isMultipleChoice,
isMultipleChoice: isMultipleChoice.flatMap(KotlinBoolean.init(value:)),
language: language,
isCheckbox: isCheckbox,
isCheckbox: isCheckbox.flatMap(KotlinBoolean.init(value:)),
limits: limits,
codeTemplates: codeTemplates,
samples: samples,
files: files,
codeBlanksStrings: codeBlanksStrings
codeBlanksStrings: codeBlanksStrings,
codeBlanksVariables: codeBlanksVariables,
codeBlanksEnabled: codeBlanksEnabled.flatMap(KotlinBoolean.init(value:))
)
}
// swiftlint:enable discouraged_optional_boolean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,20 @@ extension StepQuizViewModel: StepQuizCodeBlanksOutputProtocol {
)
}

func handleStepQuizCodeBlanksDidTapOnCodeBlockChild(
codeBlock: StepQuizCodeBlanksViewStateCodeBlockItem,
codeBlockChild: StepQuizCodeBlanksViewStateCodeBlockChildItem
) {
onNewMessage(
StepQuizFeatureMessageStepQuizCodeBlanksMessage(
message: StepQuizCodeBlanksFeatureMessageCodeBlockChildClicked(
codeBlockItem: codeBlock,
codeBlockChildItem: codeBlockChild
)
)
)
}

func handleStepQuizCodeBlanksDidTapDelete() {
onNewMessage(
StepQuizFeatureMessageStepQuizCodeBlanksMessage(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ import shared
protocol StepQuizCodeBlanksOutputProtocol: AnyObject {
func handleStepQuizCodeBlanksDidTapOnSuggestion(_ suggestion: Suggestion)
func handleStepQuizCodeBlanksDidTapOnCodeBlock(_ codeBlock: StepQuizCodeBlanksViewStateCodeBlockItem)
func handleStepQuizCodeBlanksDidTapOnCodeBlockChild(
codeBlock: StepQuizCodeBlanksViewStateCodeBlockItem,
codeBlockChild: StepQuizCodeBlanksViewStateCodeBlockChildItem
)
func handleStepQuizCodeBlanksDidTapDelete()
func handleStepQuizCodeBlanksDidTapEnter()
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,18 @@ final class StepQuizCodeBlanksViewModel {
moduleOutput?.handleStepQuizCodeBlanksDidTapOnCodeBlock(codeBlock)
}

@MainActor
func doCodeBlockChildMainAction(
codeBlock: StepQuizCodeBlanksViewStateCodeBlockItem,
codeBlockChild: StepQuizCodeBlanksViewStateCodeBlockChildItem
) {
selectionFeedbackGenerator.triggerFeedback()
moduleOutput?.handleStepQuizCodeBlanksDidTapOnCodeBlockChild(
codeBlock: codeBlock,
codeBlockChild: codeBlockChild
)
}

@MainActor
func doDeleteAction() {
impactFeedbackGenerator.triggerFeedback()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ extension StepQuizCodeBlanksBlankView {
fileprivate var size: CGSize {
switch self {
case .small:
CGSize(width: 100, height: 32)
CGSize(width: 100, height: 40)
case .large:
CGSize(width: 208, height: 48)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import shared
import SwiftUI

struct StepQuizCodeBlanksVariableInstructionView: View {
let variableItem: StepQuizCodeBlanksViewStateCodeBlockItemVariable

let onChildTap: (StepQuizCodeBlanksViewStateCodeBlockChildItem) -> Void

var body: some View {
ScrollView(.horizontal, showsIndicators: false) {
HStack(alignment: .center, spacing: LayoutInsets.smallInset) {
if let nameChild = variableItem.name {
childView(child: nameChild)
.onTapGesture {
onChildTap(nameChild)
}
}

Text("=")
.font(StepQuizCodeBlanksAppearance.blankFont)
.foregroundColor(StepQuizCodeBlanksAppearance.blankTextColor)

if let valueChild = variableItem.value {
childView(child: valueChild)
.onTapGesture {
onChildTap(valueChild)
}
}
}
.padding(.horizontal, LayoutInsets.defaultInset)
.padding(.vertical, LayoutInsets.smallInset)
.background(Color(ColorPalette.violet400Alpha7))
.cornerRadius(8)
.animation(.default, value: variableItem)
.padding(.horizontal)
}
.scrollBounceBehaviorBasedOnSize(axes: .horizontal)
}

@ViewBuilder
private func childView(
child: StepQuizCodeBlanksViewStateCodeBlockChildItem
) -> some View {
if let value = child.value {
StepQuizCodeBlanksOptionView(text: value, isActive: child.isActive)
} else {
StepQuizCodeBlanksBlankView(style: .small, isActive: child.isActive)
}
}
}

#if DEBUG
#Preview {
VStack {
StepQuizCodeBlanksVariableInstructionView(
variableItem: StepQuizCodeBlanksViewStateCodeBlockItemVariable(
id: 0,
children: [
StepQuizCodeBlanksViewStateCodeBlockChildItem(id: 0, isActive: true, value: nil),
StepQuizCodeBlanksViewStateCodeBlockChildItem(id: 1, isActive: false, value: nil)
]
),
onChildTap: { _ in }
)

StepQuizCodeBlanksVariableInstructionView(
variableItem: StepQuizCodeBlanksViewStateCodeBlockItemVariable(
id: 0,
children: [
StepQuizCodeBlanksViewStateCodeBlockChildItem(id: 0, isActive: false, value: "fruit_a"),
StepQuizCodeBlanksViewStateCodeBlockChildItem(id: 1, isActive: true, value: nil)
]
),
onChildTap: { _ in }
)

StepQuizCodeBlanksVariableInstructionView(
variableItem: StepQuizCodeBlanksViewStateCodeBlockItemVariable(
id: 0,
children: [
StepQuizCodeBlanksViewStateCodeBlockChildItem(id: 0, isActive: false, value: "fruit_a"),
StepQuizCodeBlanksViewStateCodeBlockChildItem(
id: 1,
isActive: true,
value: "Typing messages out of the blue"
)
]
),
onChildTap: { _ in }
)
}
.frame(maxWidth: .infinity)
.padding()
}
#endif
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,19 @@ struct StepQuizCodeBlanksView: View {
.onTapGesture {
viewModel.doCodeBlockMainAction(codeBlock)
}
case .variable(let variableItem):
StepQuizCodeBlanksVariableInstructionView(
variableItem: variableItem,
onChildTap: { codeBlockChild in
viewModel.doCodeBlockChildMainAction(
codeBlock: codeBlock,
codeBlockChild: codeBlockChild
)
}
)
.onTapGesture {
viewModel.doCodeBlockMainAction(codeBlock)
}
}
}

Expand Down Expand Up @@ -125,7 +138,14 @@ extension StepQuizCodeBlanksView: Equatable {
StepQuizCodeBlanksView(
viewStateKs: .content(
StepQuizCodeBlanksViewStateContent(
codeBlocks: [StepQuizCodeBlanksViewStateCodeBlockItemPrint(id: 0, isActive: true, output: nil)],
codeBlocks: [
StepQuizCodeBlanksViewStateCodeBlockItemPrint(
id: 0,
children: [
StepQuizCodeBlanksViewStateCodeBlockChildItem(id: 0, isActive: true, value: nil)
]
)
],
suggestions: [
Suggestion.ConstantString(text: "There is a cat on the keyboard, it is true"),
Suggestion.ConstantString(text: "Typing messages out of the blue")
Expand All @@ -149,13 +169,19 @@ extension StepQuizCodeBlanksView: Equatable {
codeBlocks: [
StepQuizCodeBlanksViewStateCodeBlockItemPrint(
id: 0,
isActive: false,
output: "There is a cat on the keyboard, it is true"
children: [
StepQuizCodeBlanksViewStateCodeBlockChildItem(
id: 0,
isActive: false,
value: "There is a cat on the keyboard, it is true"
)
]
),
StepQuizCodeBlanksViewStateCodeBlockItemPrint(
id: 1,
isActive: true,
output: nil
children: [
StepQuizCodeBlanksViewStateCodeBlockChildItem(id: 0, isActive: true, value: nil)
]
)
],
suggestions: [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,6 @@ enum class HyperskillAnalyticPart(val partName: String) {
USERS_INTERVIEW_WIDGET("users_interview_widget"),
UNSUPPORTED_QUIZ_PLACEHOLDER("unsupported_quiz_placeholder"),
CODE_BLANKS("code_blanks"),
CODE_BLOCK("code_block"),
STEP_QUIZ_FEEDBACK("step_quiz_feedback")
}
Original file line number Diff line number Diff line change
Expand Up @@ -136,5 +136,6 @@ enum class HyperskillAnalyticTarget(val targetName: String) {
SHOW_REPLIES("show_replies"),
CODE_BLOCK("code_block"),
CODE_BLOCK_SUGGESTION("code_block_suggestion"),
CODE_BLOCK_CHILD("code_block_child"),
LOAD_MORE("load_more")
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,11 @@ data class Block(
@SerialName("files")
val files: List<File>? = null,
@SerialName("code_blanks_strings")
val codeBlanksStrings: List<String>? = null
val codeBlanksStrings: List<String>? = null,
@SerialName("code_blanks_variables")
val codeBlanksVariables: List<String>? = null,
@SerialName("code_blanks_enabled")
val codeBlanksEnabled: Boolean? = null
) {
@Serializable
data class File(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ package org.hyperskill.app.step_quiz_code_blanks.domain.analytic
internal object StepQuizCodeBlanksAnalyticParams {
const val PARAM_CODE_BLOCK = "code_block"
const val PARAM_SUGGESTION = "suggestion"
const val PARAM_CODE_BLOCK_CHILD = "code_block_child"
}
Loading
Loading