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

Unit progress navigation style #258

Merged
merged 41 commits into from
Feb 2, 2024
Merged
Show file tree
Hide file tree
Changes from 40 commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
ab96cc7
chore: add lesson line progress view
eyatsenkoperpetio Dec 11, 2023
33b59a1
chore: add colors and config to course unit view model
eyatsenkoperpetio Dec 11, 2023
4507540
chore: add ajax provider and refactor code, fix crash on Config resolve
eyatsenkoperpetio Dec 13, 2023
4de4be1
Merge branch 'develop' into feat/unit_progress
eyatsenkoperpetio Dec 13, 2023
bafaff0
chore: update when back if some changed
eyatsenkoperpetio Dec 13, 2023
3352528
chore: hide progress dots when line show
eyatsenkoperpetio Dec 13, 2023
ededc14
chore: padding and separate views
eyatsenkoperpetio Dec 15, 2023
e77e1bc
Merge branch 'develop' into feat/unit_progress
eyatsenkoperpetio Jan 17, 2024
fd16f64
chore: added one more state and change inset what fixes dark mode
rnr Jan 17, 2024
96e5d72
Merge pull request #7 from touchapp/feat/unit_progress_line_improvements
forgotvas Jan 19, 2024
9154c48
fix: arrow buttons in unit content
forgotvas Jan 23, 2024
ee9723e
fix: animation
forgotvas Jan 23, 2024
5cf0197
fix: different navigation stacks
forgotvas Jan 23, 2024
1a31646
fix: offset in landscape mode
forgotvas Jan 23, 2024
7f3c4a2
fix: offset on orientation change
forgotvas Jan 23, 2024
bfd5507
fix: unit tests
forgotvas Jan 23, 2024
9079d30
Merge pull request #8 from touchapp/feat/unit-animation
rnr Jan 23, 2024
1fc1863
Merge branch 'develop' into feat/unit_progress
rnr Jan 24, 2024
5c5ba04
chore: fixed warnings
rnr Jan 24, 2024
462fa00
chore: fixed warnings
rnr Jan 24, 2024
c0a6184
Merge branch 'develop' into feat/unit_progress
rnr Jan 25, 2024
5d18fdf
chore: fixed rounded corners and padding for progress line
rnr Jan 26, 2024
9ff5efa
fix: paddings
forgotvas Jan 28, 2024
2f85376
Merge pull request #9 from touchapp/fix/unit_progress
rnr Jan 28, 2024
1b01de7
chore: moved rounded corners to view extension
rnr Jan 29, 2024
59ea2f7
chore: delete unused code
rnr Jan 29, 2024
d88becc
fix: use full width if we are using horizontal navigation
forgotvas Jan 29, 2024
b939721
Merge branch 'fixed_rounded_corners_and_progress_line_padding' of htt…
forgotvas Jan 29, 2024
cce4537
Merge pull request #10 from touchapp/fixed_rounded_corners_and_progre…
rnr Jan 29, 2024
23cb12f
chore: refactor of ajax completion handler
forgotvas Jan 29, 2024
d2abb01
chore: warning fix
forgotvas Jan 29, 2024
18d6f44
chore: added forMainFrameOnly parameter
forgotvas Jan 29, 2024
ca3b9cf
fix: previous button for horizontal navigation
forgotvas Jan 30, 2024
d2adf89
Merge pull request #12 from touchapp/fix/prev-button
rnr Jan 30, 2024
b7c45a7
Merge pull request #11 from touchapp/chore/ajax-refactor
forgotvas Jan 31, 2024
554c4e5
chore: resolve PR comments
eyatsenkoperpetio Feb 1, 2024
e5af1a7
chore: update course struct after complete unit
eyatsenkoperpetio Feb 1, 2024
3524328
Merge branch 'develop' into feat/unit_progress
eyatsenkoperpetio Feb 1, 2024
ddb566e
Merge branch 'develop' into feat/unit_progress
eyatsenkoperpetio Feb 1, 2024
b91cf6d
chore: down up dropdown button
eyatsenkoperpetio Feb 1, 2024
79378bc
chore: remove refresh course
eyatsenkoperpetio Feb 2, 2024
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
16 changes: 16 additions & 0 deletions Core/Core.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,8 @@
BA8FA66C2AD59BBC00EA029A /* GoogleSignIn in Frameworks */ = {isa = PBXBuildFile; productRef = BA8FA66B2AD59BBC00EA029A /* GoogleSignIn */; };
BA8FA66E2AD59E7D00EA029A /* FacebookAuthProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA8FA66D2AD59E7D00EA029A /* FacebookAuthProvider.swift */; };
BA8FA6702AD59EA300EA029A /* MicrosoftAuthProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA8FA66F2AD59EA300EA029A /* MicrosoftAuthProvider.swift */; };
BAD9CA2F2B289B3500DE790A /* ajaxHandler.js in Resources */ = {isa = PBXBuildFile; fileRef = BAD9CA2E2B289B3500DE790A /* ajaxHandler.js */; };
BAD9CA332B28A8F300DE790A /* AjaxProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = BAD9CA322B28A8F300DE790A /* AjaxProvider.swift */; };
BAAD62C62AFCF00B000E6103 /* CustomDisclosureGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = BAAD62C52AFCF00B000E6103 /* CustomDisclosureGroup.swift */; };
BAD9CA422B2B140100DE790A /* AgreementConfigTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BAD9CA412B2B140100DE790A /* AgreementConfigTests.swift */; };
BADB3F5B2AD6EC56004D5CFA /* ResultExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = BADB3F5A2AD6EC56004D5CFA /* ResultExtension.swift */; };
Expand Down Expand Up @@ -306,6 +308,8 @@
BA8FA6692AD59B5500EA029A /* GoogleAuthProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GoogleAuthProvider.swift; sourceTree = "<group>"; };
BA8FA66D2AD59E7D00EA029A /* FacebookAuthProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FacebookAuthProvider.swift; sourceTree = "<group>"; };
BA8FA66F2AD59EA300EA029A /* MicrosoftAuthProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MicrosoftAuthProvider.swift; sourceTree = "<group>"; };
BAD9CA2E2B289B3500DE790A /* ajaxHandler.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = ajaxHandler.js; sourceTree = "<group>"; };
BAD9CA322B28A8F300DE790A /* AjaxProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AjaxProvider.swift; sourceTree = "<group>"; };
BAAD62C52AFCF00B000E6103 /* CustomDisclosureGroup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomDisclosureGroup.swift; sourceTree = "<group>"; };
BAD9CA412B2B140100DE790A /* AgreementConfigTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AgreementConfigTests.swift; sourceTree = "<group>"; };
BADB3F5A2AD6EC56004D5CFA /* ResultExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResultExtension.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -718,10 +722,20 @@
isa = PBXGroup;
children = (
BA30427C2B20B235009B64B7 /* SocialAuth */,
BAD9CA3D2B29BB1A00DE790A /* Ajax */,
);
path = Providers;
sourceTree = "<group>";
};
BAD9CA3D2B29BB1A00DE790A /* Ajax */ = {
isa = PBXGroup;
children = (
BAD9CA322B28A8F300DE790A /* AjaxProvider.swift */,
BAD9CA2E2B289B3500DE790A /* ajaxHandler.js */,
);
path = Ajax;
sourceTree = "<group>";
};
C9DFE47E699CFFA85A77AF2C /* Pods */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -906,6 +920,7 @@
0770DE5228D0ADFF006D8A5D /* Assets.xcassets in Resources */,
0770DE5B28D0B209006D8A5D /* Localizable.strings in Resources */,
0770DE5428D0B00C006D8A5D /* swiftgen.yml in Resources */,
BAD9CA2F2B289B3500DE790A /* ajaxHandler.js in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -992,6 +1007,7 @@
0727877D28D25212002E9142 /* ProgressBar.swift in Sources */,
0236961F28F9A2F600EEF206 /* AuthEndpoint.swift in Sources */,
02B3E3B32930198600A50475 /* AVPlayerViewControllerExtension.swift in Sources */,
BAD9CA332B28A8F300DE790A /* AjaxProvider.swift in Sources */,
0295C885299B99DD00ABE571 /* RefreshableScrollView.swift in Sources */,
0282DA7328F98CC9003C3F07 /* WebUnitView.swift in Sources */,
E0D586362B314CD3009B4BA7 /* LogistrationBottomView.swift in Sources */,
Expand Down
13 changes: 8 additions & 5 deletions Core/Core/Configuration/Config/UIComponentsConfig.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,24 @@

import Foundation

private enum Keys: String {
private enum Keys: String, RawStringExtractable {
case courseNestedListEnabled = "COURSE_NESTED_LIST_ENABLED"
case courseTopTabBarEnabled = "COURSE_TOP_TAB_BAR_ENABLED"
case courseBannerEnabled = "COURSE_BANNER_ENABLED"
case courseUnitProgressEnabled = "COURSE_UNIT_PROGRESS_ENABLED"
}

public class UIComponentsConfig: NSObject {
public var courseNestedListEnabled: Bool = false
public var courseNestedListEnabled: Bool
public var courseBannerEnabled: Bool
public var courseUnitProgressEnabled: Bool
public var courseTopTabBarEnabled: Bool

init(dictionary: [String: Any]) {
courseNestedListEnabled = dictionary[Keys.courseNestedListEnabled.rawValue] as? Bool ?? false
courseBannerEnabled = dictionary[Keys.courseBannerEnabled.rawValue] as? Bool ?? false
courseTopTabBarEnabled = dictionary[Keys.courseTopTabBarEnabled.rawValue] as? Bool ?? false
courseNestedListEnabled = dictionary[Keys.courseNestedListEnabled] as? Bool ?? false
courseBannerEnabled = dictionary[Keys.courseBannerEnabled] as? Bool ?? false
courseUnitProgressEnabled = dictionary[Keys.courseUnitProgressEnabled] as? Bool ?? false
courseTopTabBarEnabled = dictionary[Keys.courseTopTabBarEnabled] as? Bool ?? false
super.init()
}
}
Expand Down
16 changes: 8 additions & 8 deletions Core/Core/Domain/Model/CourseBlockModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public struct CourseStructure: Equatable {
public let encodedVideo: String
public let displayName: String
public let topicID: String?
public let childs: [CourseChapter]
public var childs: [CourseChapter]
public let media: DataLayer.CourseMedia //FIXME Domain model
public let certificate: Certificate?

Expand Down Expand Up @@ -72,7 +72,7 @@ public struct CourseChapter: Identifiable {
public let id: String
public let displayName: String
public let type: BlockType
public let childs: [CourseSequential]
public var childs: [CourseSequential]

public init(
blockId: String,
Expand All @@ -96,8 +96,8 @@ public struct CourseSequential: Identifiable {
public let displayName: String
public let type: BlockType
public let completion: Double
public let childs: [CourseVertical]
public var childs: [CourseVertical]

public var isDownloadable: Bool {
return childs.first(where: { $0.isDownloadable }) != nil
}
Expand Down Expand Up @@ -130,7 +130,7 @@ public struct CourseVertical: Identifiable, Hashable {
public let displayName: String
public let type: BlockType
public let completion: Double
public let childs: [CourseBlock]
public var childs: [CourseBlock]

public var isDownloadable: Bool {
return childs.first(where: { $0.isDownloadable }) != nil
Expand Down Expand Up @@ -165,7 +165,7 @@ public struct SubtitleUrl: Equatable {
}
}

public struct CourseBlock: Hashable {
public struct CourseBlock: Hashable, Identifiable {
public static func == (lhs: CourseBlock, rhs: CourseBlock) -> Bool {
lhs.id == rhs.id &&
lhs.blockId == rhs.blockId &&
Expand All @@ -175,13 +175,13 @@ public struct CourseBlock: Hashable {
public func hash(into hasher: inout Hasher) {
hasher.combine(id)
}

public let blockId: String
public let id: String
public let courseId: String
public let topicId: String?
public let graded: Bool
public let completion: Double
public var completion: Double
public let type: BlockType
public let displayName: String
public let studentUrl: String
Expand Down
2 changes: 2 additions & 0 deletions Core/Core/Extensions/Notification.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,6 @@ public extension Notification.Name {
static let onAppUpgradeAccountSettingsTapped = Notification.Name("onAppUpgradeAccountSettingsTapped")
static let onNewVersionAvaliable = Notification.Name("onNewVersionAvaliable")
static let webviewReloadNotification = Notification.Name("webviewReloadNotification")
static let onBlockCompletion = Notification.Name.init("onBlockCompletion")
static let onRefreshCourse = Notification.Name.init("refreshCourse")
}
1 change: 1 addition & 0 deletions Core/Core/Extensions/ViewExtension.swift
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ public extension View {
ZStack {
self
.frame(maxWidth: maxIpadWidth, maxHeight: idiom == .pad ? ipadMaxHeight : .infinity)
.clipShape(RoundedCorners(tl: 24, tr: 24))
RoundedCorners(tl: 24, tr: 24)
.stroke(style: StrokeStyle(lineWidth: 1))
.foregroundColor(strokeColor)
Expand Down
87 changes: 87 additions & 0 deletions Core/Core/Providers/Ajax/AjaxProvider.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
//
// AjaxProvider.swift
// Core
//
// Created by Eugene Yatsenko on 12.12.2023.
//

import Foundation
import WebKit
import Swinject

struct AjaxInjection: WebViewScriptInjectionProtocol {
private struct AJAXCallbackData {
private enum Keys: String {
case url = "url"
case statusCode = "status"
case responseText = "response_text"
}

let url: String
let statusCode: Int
let responseText: String

init(data: [AnyHashable: Any]) {
url = data[Keys.url.rawValue] as? String ?? ""
statusCode = data[Keys.statusCode.rawValue] as? Int ?? 0
responseText = data[Keys.responseText.rawValue] as? String ?? ""
}
}

private enum XBlockCompletionCallbackType: String {
case html = "publish_completion"
case problem = "problem_check"
case dragAndDrop = "do_attempt"
case ora = "render_grade"
}

private let AJAXCallBackHandler = "ajaxCallbackHandler"
private let ajaxScriptFile = "ajaxHandler"

var id: String = "AjaxInjection"
var script: String {
guard let url = Bundle(for: CoreBundle.self).url(forResource: ajaxScriptFile, withExtension: "js"),
let script = try? String(contentsOf: url, encoding: .utf8) else { return "" }
return script
}

var messages: [WebviewMessage]? {
[
WebviewMessage(name: AJAXCallBackHandler) { result, _ in
guard let data = result as? [AnyHashable: Any] else { return }
let callback = AJAXCallbackData(data: data)
let requestURL = callback.url

if callback.statusCode != 200 {
return
}

var complete = false
if isBlockOf(type: .ora, with: requestURL) {
complete = callback.responseText.contains("is--complete")
} else {
complete = isBlockOf(type: .html, with: requestURL)
|| isBlockOf(type: .problem, with: requestURL)
|| isBlockOf(type: .dragAndDrop, with: requestURL)
}
if complete {
NotificationCenter.default.post(
name: NSNotification.blockCompletion,
object: nil
)
}
}
]
}
var forMainFrameOnly: Bool = false

var injectionTime: WKUserScriptInjectionTime = .atDocumentEnd

private func isBlockOf(type: XBlockCompletionCallbackType, with requestURL: String) -> Bool {
return requestURL.contains(type.rawValue)
}
}

public extension NSNotification {
static let blockCompletion = Notification.Name.init("block_completion")
}
18 changes: 18 additions & 0 deletions Core/Core/Providers/Ajax/ajaxHandler.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//Every time an Ajax call is being invoked the listener will recognize it and will call the native app with the request details

$(document).ajaxSuccess(function(event, request, settings) {
callNativeApp({
"status": request.status,
"url":settings.url,
"response_text": request.responseText
});
});

function callNativeApp(data) {
try {
webkit.messageHandlers.ajaxCallbackHandler.postMessage(data);
}
catch(err) {
console.log('The native context does not exist yet');
}
}
4 changes: 2 additions & 2 deletions Core/Core/View/Base/AppReview/AppReviewViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,10 @@ public class AppReviewViewModel: ObservableObject {
@Published var clients: [ThirdPartyMailClient] = []
let allClients = ThirdPartyMailClient.clients

private let config: Config
private let config: ConfigProtocol
var storage: CoreStorage

public init(config: Config, storage: CoreStorage) {
public init(config: ConfigProtocol, storage: CoreStorage) {
self.config = config
self.storage = storage
}
Expand Down
44 changes: 32 additions & 12 deletions Core/Core/View/Base/UnitButtonView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,22 @@ public struct UnitButtonView: View {
private let action: () -> Void
private let type: UnitButtonType
private let bgColor: Color?
private let isVerticalNavigation: Bool

public init(type: UnitButtonType, bgColor: Color? = nil, action: @escaping () -> Void) {
private var nextButtonDegrees: Double {
isVerticalNavigation ? -90 : 180
}

public init(
type: UnitButtonType,
isVerticalNavigation: Bool = true,
bgColor: Color? = nil,
action: @escaping () -> Void
) {
self.type = type
self.bgColor = bgColor
self.action = action
self.isVerticalNavigation = isVerticalNavigation
}

public var body: some View {
Expand All @@ -68,7 +79,7 @@ public struct UnitButtonView: View {
.font(Theme.Fonts.labelLarge)
CoreAssets.arrowLeft.swiftUIImage.renderingMode(.template)
.foregroundColor(Theme.Colors.styledButtonText)
.rotationEffect(Angle.degrees(-90))
.rotationEffect(Angle.degrees(nextButtonDegrees))
}.padding(.horizontal, 16)
case .next, .nextBig:
HStack {
Expand All @@ -81,20 +92,29 @@ public struct UnitButtonView: View {
}
CoreAssets.arrowLeft.swiftUIImage.renderingMode(.template)
.foregroundColor(Theme.Colors.styledButtonText)
.rotationEffect(Angle.degrees(-90))
.rotationEffect(Angle.degrees(nextButtonDegrees))
.padding(.trailing, 20)
}
case .previous:
HStack {
Text(type.stringValue())
.foregroundColor(Theme.Colors.accentColor)
.font(Theme.Fonts.labelLarge)
.padding(.leading, 20)
CoreAssets.arrowLeft.swiftUIImage.renderingMode(.template)
.rotationEffect(Angle.degrees(90))
.padding(.trailing, 20)
.foregroundColor(Theme.Colors.accentColor)

if isVerticalNavigation {
Text(type.stringValue())
.foregroundColor(Theme.Colors.accentColor)
.font(Theme.Fonts.labelLarge)
.padding(.leading, 20)
CoreAssets.arrowLeft.swiftUIImage.renderingMode(.template)
.rotationEffect(Angle.degrees(90))
.padding(.trailing, 20)
.foregroundColor(Theme.Colors.accentColor)
} else {
CoreAssets.arrowLeft.swiftUIImage.renderingMode(.template)
.padding(.leading, 20)
.foregroundColor(Theme.Colors.accentColor)
Text(type.stringValue())
.foregroundColor(Theme.Colors.accentColor)
.font(Theme.Fonts.labelLarge)
.padding(.trailing, 20)
}
}
case .last:
HStack {
Expand Down
Loading
Loading