From b76d824de31cb2c1f0540ddf25fc448dcb7e7c9e Mon Sep 17 00:00:00 2001 From: IvanStepanok <128456094+IvanStepanok@users.noreply.github.com> Date: Wed, 4 Oct 2023 18:24:57 +0300 Subject: [PATCH 001/158] october bugfixes (#100) * october bugfixes Change some icons to help adjust color themes (DeleteAccountView, Send button on the keyboard, etc.) Fix CSSInjector style by adding 100% width. Need for normal work at Handouts view. Add new logic for icons viewing in CourseVerticalView. Fix a bug where the discussion page does not appear in case there is only one on the page. Fix a bug with text trimming on ParentCommentView. Change button design on PostsView by Design code. Fix the issue with the English localization on DeleteAccountView. Fix error handling at DeleteAccountViewModel. * update xcode version for unit tests * Downgrade xcode version for unit tests * Update unit_tests.yml * Update Fastfile * Update unit_tests.yml * code style improvements --- .github/workflows/unit_tests.yml | 3 -- .../Discussions/send.imageset/Contents.json | 4 +- .../Discussions/send.imageset/Group 62-2.svg | 12 ------ .../Discussions/send.imageset/Group 62.svg | 12 ------ .../Discussions/send.imageset/send 1.svg | 11 +++++ .../Discussions/send.imageset/send.svg | 11 +++++ .../Contents.json | 4 +- .../bg_delete.imageset/bg_delete 1.svg | 7 ++++ .../bg_delete.imageset/delete_bg_light.svg | 7 ++++ .../deleteAccount.imageset/Group-2.svg | 13 ------ .../Profile/deleteAccount.imageset/Group.svg | 13 ------ .../delete_char.imageset/Contents.json | 15 +++++++ .../delete_char.imageset/delete_char.svg | 8 ++++ .../delete_eyes.imageset/Contents.json | 12 ++++++ .../delete_eyes.imageset/delete_eyes.svg | 7 ++++ Core/Core/Configuration/CSSInjector.swift | 6 ++- Core/Core/SwiftGen/Assets.swift | 4 +- .../View/Base/FlexibleKeyboardInputView.swift | 14 +++++-- .../Handouts/HandoutsUpdatesDetailView.swift | 11 ++++- .../Outline/CourseVerticalView.swift | 16 +++++++- .../Presentation/Unit/CourseUnitView.swift | 5 +++ .../Comments/Base/ParentCommentView.swift | 1 + .../Presentation/Posts/PostsView.swift | 40 +++++++++++++------ .../DeleteAccount/DeleteAccountView.swift | 10 ++++- .../DeleteAccountViewModel.swift | 2 +- Profile/Profile/SwiftGen/Strings.swift | 4 +- Profile/Profile/en.lproj/Localizable.strings | 2 +- fastlane/Fastfile | 2 +- 28 files changed, 172 insertions(+), 84 deletions(-) delete mode 100644 Core/Core/Assets.xcassets/Discussions/send.imageset/Group 62-2.svg delete mode 100644 Core/Core/Assets.xcassets/Discussions/send.imageset/Group 62.svg create mode 100644 Core/Core/Assets.xcassets/Discussions/send.imageset/send 1.svg create mode 100644 Core/Core/Assets.xcassets/Discussions/send.imageset/send.svg rename Core/Core/Assets.xcassets/Profile/{deleteAccount.imageset => bg_delete.imageset}/Contents.json (77%) create mode 100644 Core/Core/Assets.xcassets/Profile/bg_delete.imageset/bg_delete 1.svg create mode 100644 Core/Core/Assets.xcassets/Profile/bg_delete.imageset/delete_bg_light.svg delete mode 100644 Core/Core/Assets.xcassets/Profile/deleteAccount.imageset/Group-2.svg delete mode 100644 Core/Core/Assets.xcassets/Profile/deleteAccount.imageset/Group.svg create mode 100644 Core/Core/Assets.xcassets/Profile/delete_char.imageset/Contents.json create mode 100644 Core/Core/Assets.xcassets/Profile/delete_char.imageset/delete_char.svg create mode 100644 Core/Core/Assets.xcassets/Profile/delete_eyes.imageset/Contents.json create mode 100644 Core/Core/Assets.xcassets/Profile/delete_eyes.imageset/delete_eyes.svg diff --git a/.github/workflows/unit_tests.yml b/.github/workflows/unit_tests.yml index e9d655c49..16dee327e 100644 --- a/.github/workflows/unit_tests.yml +++ b/.github/workflows/unit_tests.yml @@ -35,9 +35,6 @@ jobs: run: source ci_scripts/ci_prepare_env.sh && setup_github_actions_environment - - run: | - xcversion installed - - name: SwiftLint run: bundle exec fastlane linting diff --git a/Core/Core/Assets.xcassets/Discussions/send.imageset/Contents.json b/Core/Core/Assets.xcassets/Discussions/send.imageset/Contents.json index 66cc886a8..501261e9c 100644 --- a/Core/Core/Assets.xcassets/Discussions/send.imageset/Contents.json +++ b/Core/Core/Assets.xcassets/Discussions/send.imageset/Contents.json @@ -1,7 +1,7 @@ { "images" : [ { - "filename" : "Group 62.svg", + "filename" : "send.svg", "idiom" : "universal" }, { @@ -11,7 +11,7 @@ "value" : "dark" } ], - "filename" : "Group 62-2.svg", + "filename" : "send 1.svg", "idiom" : "universal" } ], diff --git a/Core/Core/Assets.xcassets/Discussions/send.imageset/Group 62-2.svg b/Core/Core/Assets.xcassets/Discussions/send.imageset/Group 62-2.svg deleted file mode 100644 index bafc12f2e..000000000 --- a/Core/Core/Assets.xcassets/Discussions/send.imageset/Group 62-2.svg +++ /dev/null @@ -1,12 +0,0 @@ - diff --git a/Core/Core/Assets.xcassets/Discussions/send.imageset/Group 62.svg b/Core/Core/Assets.xcassets/Discussions/send.imageset/Group 62.svg deleted file mode 100644 index 312dc8d1a..000000000 --- a/Core/Core/Assets.xcassets/Discussions/send.imageset/Group 62.svg +++ /dev/null @@ -1,12 +0,0 @@ - diff --git a/Core/Core/Assets.xcassets/Discussions/send.imageset/send 1.svg b/Core/Core/Assets.xcassets/Discussions/send.imageset/send 1.svg new file mode 100644 index 000000000..db8ab01ea --- /dev/null +++ b/Core/Core/Assets.xcassets/Discussions/send.imageset/send 1.svg @@ -0,0 +1,11 @@ + diff --git a/Core/Core/Assets.xcassets/Discussions/send.imageset/send.svg b/Core/Core/Assets.xcassets/Discussions/send.imageset/send.svg new file mode 100644 index 000000000..db8ab01ea --- /dev/null +++ b/Core/Core/Assets.xcassets/Discussions/send.imageset/send.svg @@ -0,0 +1,11 @@ + diff --git a/Core/Core/Assets.xcassets/Profile/deleteAccount.imageset/Contents.json b/Core/Core/Assets.xcassets/Profile/bg_delete.imageset/Contents.json similarity index 77% rename from Core/Core/Assets.xcassets/Profile/deleteAccount.imageset/Contents.json rename to Core/Core/Assets.xcassets/Profile/bg_delete.imageset/Contents.json index 2a3f6edf2..118426dbb 100644 --- a/Core/Core/Assets.xcassets/Profile/deleteAccount.imageset/Contents.json +++ b/Core/Core/Assets.xcassets/Profile/bg_delete.imageset/Contents.json @@ -1,7 +1,7 @@ { "images" : [ { - "filename" : "Group-2.svg", + "filename" : "delete_bg_light.svg", "idiom" : "universal" }, { @@ -11,7 +11,7 @@ "value" : "dark" } ], - "filename" : "Group.svg", + "filename" : "bg_delete 1.svg", "idiom" : "universal" } ], diff --git a/Core/Core/Assets.xcassets/Profile/bg_delete.imageset/bg_delete 1.svg b/Core/Core/Assets.xcassets/Profile/bg_delete.imageset/bg_delete 1.svg new file mode 100644 index 000000000..92b146822 --- /dev/null +++ b/Core/Core/Assets.xcassets/Profile/bg_delete.imageset/bg_delete 1.svg @@ -0,0 +1,7 @@ + diff --git a/Core/Core/Assets.xcassets/Profile/bg_delete.imageset/delete_bg_light.svg b/Core/Core/Assets.xcassets/Profile/bg_delete.imageset/delete_bg_light.svg new file mode 100644 index 000000000..96007a9b5 --- /dev/null +++ b/Core/Core/Assets.xcassets/Profile/bg_delete.imageset/delete_bg_light.svg @@ -0,0 +1,7 @@ + diff --git a/Core/Core/Assets.xcassets/Profile/deleteAccount.imageset/Group-2.svg b/Core/Core/Assets.xcassets/Profile/deleteAccount.imageset/Group-2.svg deleted file mode 100644 index 60f0fafb9..000000000 --- a/Core/Core/Assets.xcassets/Profile/deleteAccount.imageset/Group-2.svg +++ /dev/null @@ -1,13 +0,0 @@ - diff --git a/Core/Core/Assets.xcassets/Profile/deleteAccount.imageset/Group.svg b/Core/Core/Assets.xcassets/Profile/deleteAccount.imageset/Group.svg deleted file mode 100644 index 09d83d54a..000000000 --- a/Core/Core/Assets.xcassets/Profile/deleteAccount.imageset/Group.svg +++ /dev/null @@ -1,13 +0,0 @@ - diff --git a/Core/Core/Assets.xcassets/Profile/delete_char.imageset/Contents.json b/Core/Core/Assets.xcassets/Profile/delete_char.imageset/Contents.json new file mode 100644 index 000000000..44ef99c1d --- /dev/null +++ b/Core/Core/Assets.xcassets/Profile/delete_char.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "delete_char.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "template" + } +} diff --git a/Core/Core/Assets.xcassets/Profile/delete_char.imageset/delete_char.svg b/Core/Core/Assets.xcassets/Profile/delete_char.imageset/delete_char.svg new file mode 100644 index 000000000..d1422ad6a --- /dev/null +++ b/Core/Core/Assets.xcassets/Profile/delete_char.imageset/delete_char.svg @@ -0,0 +1,8 @@ + diff --git a/Core/Core/Assets.xcassets/Profile/delete_eyes.imageset/Contents.json b/Core/Core/Assets.xcassets/Profile/delete_eyes.imageset/Contents.json new file mode 100644 index 000000000..19c371f58 --- /dev/null +++ b/Core/Core/Assets.xcassets/Profile/delete_eyes.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "delete_eyes.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Core/Core/Assets.xcassets/Profile/delete_eyes.imageset/delete_eyes.svg b/Core/Core/Assets.xcassets/Profile/delete_eyes.imageset/delete_eyes.svg new file mode 100644 index 000000000..af854563b --- /dev/null +++ b/Core/Core/Assets.xcassets/Profile/delete_eyes.imageset/delete_eyes.svg @@ -0,0 +1,7 @@ + diff --git a/Core/Core/Configuration/CSSInjector.swift b/Core/Core/Configuration/CSSInjector.swift index 9e7faf0ec..b90afc26f 100644 --- a/Core/Core/Configuration/CSSInjector.swift +++ b/Core/Core/Configuration/CSSInjector.swift @@ -115,6 +115,10 @@ public class CSSInjector { let style = """ -
"""
diff --git a/Core/Core/SwiftGen/Assets.swift b/Core/Core/SwiftGen/Assets.swift
index 887501306..ee82da098 100644
--- a/Core/Core/SwiftGen/Assets.swift
+++ b/Core/Core/SwiftGen/Assets.swift
@@ -84,8 +84,10 @@ public enum CoreAssets {
public static let profile = ImageAsset(name: "profile")
public static let programs = ImageAsset(name: "programs")
public static let addPhoto = ImageAsset(name: "addPhoto")
+ public static let bgDelete = ImageAsset(name: "bg_delete")
public static let checkmark = ImageAsset(name: "checkmark")
- public static let deleteAccount = ImageAsset(name: "deleteAccount")
+ public static let deleteChar = ImageAsset(name: "delete_char")
+ public static let deleteEyes = ImageAsset(name: "delete_eyes")
public static let done = ImageAsset(name: "done")
public static let gallery = ImageAsset(name: "gallery")
public static let leaveProfile = ImageAsset(name: "leaveProfile")
diff --git a/Core/Core/View/Base/FlexibleKeyboardInputView.swift b/Core/Core/View/Base/FlexibleKeyboardInputView.swift
index 97bc11401..e8d6d0d8a 100644
--- a/Core/Core/View/Base/FlexibleKeyboardInputView.swift
+++ b/Core/Core/View/Base/FlexibleKeyboardInputView.swift
@@ -74,9 +74,17 @@ public struct FlexibleKeyboardInputView: View {
}
}, label: {
VStack {
- commentText.trimmingCharacters(in: .whitespacesAndNewlines).count > 0
- ? CoreAssets.send.swiftUIImage
- : CoreAssets.sendDisabled.swiftUIImage
+ if commentText.trimmingCharacters(in: .whitespacesAndNewlines).count > 0 {
+ ZStack {
+ Circle()
+ .frame(width: 36, height: 36)
+ .foregroundColor(.accentColor)
+ CoreAssets.send.swiftUIImage
+ .offset(y: 1)
+ }
+ } else {
+ CoreAssets.sendDisabled.swiftUIImage
+ }
}
.frame(width: 36, height: 36)
.foregroundColor(.white)
diff --git a/Course/Course/Presentation/Handouts/HandoutsUpdatesDetailView.swift b/Course/Course/Presentation/Handouts/HandoutsUpdatesDetailView.swift
index 57b12b542..46d79825d 100644
--- a/Course/Course/Presentation/Handouts/HandoutsUpdatesDetailView.swift
+++ b/Course/Course/Presentation/Handouts/HandoutsUpdatesDetailView.swift
@@ -10,8 +10,9 @@ import Core
public struct HandoutsUpdatesDetailView: View {
- @Environment(\.colorScheme) var colorScheme
+ @Environment(\.colorScheme) var colorSchemeNative
private var idiom: UIUserInterfaceIdiom { UIDevice.current.userInterfaceIdiom }
+ @State var colorScheme: ColorScheme = UITraitCollection.current.userInterfaceStyle == .light ? .light : .dark
private var router: CourseRouter
private let cssInjector: CSSInjector
@@ -36,6 +37,10 @@ public struct HandoutsUpdatesDetailView: View {
self.cssInjector = cssInjector
}
+ private func updateColorScheme() {
+ colorScheme = UITraitCollection.current.userInterfaceStyle == .light ? .light : .dark
+ }
+
private func fixBrokenLinks(in htmlString: String) -> String {
do {
let regex = try NSRegularExpression(
@@ -126,6 +131,10 @@ public struct HandoutsUpdatesDetailView: View {
.navigationBarHidden(false)
.navigationBarBackButtonHidden(false)
.navigationTitle(title)
+ .onChange(of: colorSchemeNative) { newValue in
+ guard UIApplication.shared.applicationState == .active else { return }
+ updateColorScheme()
+ }
}
}
diff --git a/Course/Course/Presentation/Outline/CourseVerticalView.swift b/Course/Course/Presentation/Outline/CourseVerticalView.swift
index c5cb290af..20b1bc56f 100644
--- a/Course/Course/Presentation/Outline/CourseVerticalView.swift
+++ b/Course/Course/Presentation/Outline/CourseVerticalView.swift
@@ -31,6 +31,20 @@ public struct CourseVerticalView: View {
self.viewModel = viewModel
}
+ private func verticalImage(childs: [CourseBlock]) -> Image {
+ if childs.contains(where: { $0.type == .problem }) {
+ return CoreAssets.pen.swiftUIImage.renderingMode(.template)
+ } else if childs.contains(where: { $0.type == .video }) {
+ return CoreAssets.video.swiftUIImage.renderingMode(.template)
+ } else if childs.contains(where: { $0.type == .discussion }) {
+ return CoreAssets.discussion.swiftUIImage.renderingMode(.template)
+ } else if childs.contains(where: { $0.type == .html }) {
+ return CoreAssets.extra.swiftUIImage.renderingMode(.template)
+ } else {
+ return CoreAssets.extra.swiftUIImage.renderingMode(.template)
+ }
+ }
+
public var body: some View {
ZStack(alignment: .top) {
// MARK: - Page Body
@@ -67,7 +81,7 @@ public struct CourseVerticalView: View {
.renderingMode(.template)
.foregroundColor(.accentColor)
} else {
- vertical.type.image
+ verticalImage(childs: vertical.childs)
}
Text(vertical.displayName)
.font(Theme.Fonts.titleMedium)
diff --git a/Course/Course/Presentation/Unit/CourseUnitView.swift b/Course/Course/Presentation/Unit/CourseUnitView.swift
index e9afacbc1..411d8ac15 100644
--- a/Course/Course/Presentation/Unit/CourseUnitView.swift
+++ b/Course/Course/Presentation/Unit/CourseUnitView.swift
@@ -197,6 +197,11 @@ public struct CourseUnitView: View {
}
}
}
+ .onAppear {
+ DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
+ showDiscussion = viewModel.selectedLesson().type == .discussion
+ }
+ }
.navigationBarHidden(false)
.navigationBarBackButtonHidden(false)
.navigationTitle("")
diff --git a/Discussion/Discussion/Presentation/Comments/Base/ParentCommentView.swift b/Discussion/Discussion/Presentation/Comments/Base/ParentCommentView.swift
index ab6aa3455..0e8a35828 100644
--- a/Discussion/Discussion/Presentation/Comments/Base/ParentCommentView.swift
+++ b/Discussion/Discussion/Presentation/Comments/Base/ParentCommentView.swift
@@ -68,6 +68,7 @@ public struct ParentCommentView: View {
.font(Theme.Fonts.titleLarge)
Text(comments.postBodyHtml.hideHtmlTagsAndUrls())
.font(Theme.Fonts.bodyMedium)
+ .fixedSize(horizontal: false, vertical: true)
.padding(.bottom, 8)
ForEach(Array(comments.postBody.extractURLs().enumerated()), id: \.offset) { _, url in
if url.isImage() {
diff --git a/Discussion/Discussion/Presentation/Posts/PostsView.swift b/Discussion/Discussion/Presentation/Posts/PostsView.swift
index dc7145a3a..906a47ce2 100644
--- a/Discussion/Discussion/Presentation/Posts/PostsView.swift
+++ b/Discussion/Discussion/Presentation/Posts/PostsView.swift
@@ -20,8 +20,16 @@ public struct PostsView: View {
private let courseID: String
private var showTopMenu: Bool
- public init(courseID: String, currentBlockID: String, topics: Topics, title: String, type: ThreadType,
- viewModel: PostsViewModel, router: DiscussionRouter, showTopMenu: Bool = true) {
+ public init(
+ courseID: String,
+ currentBlockID: String,
+ topics: Topics,
+ title: String,
+ type: ThreadType,
+ viewModel: PostsViewModel,
+ router: DiscussionRouter,
+ showTopMenu: Bool = true
+ ) {
self.courseID = courseID
self.title = title
self.currentBlockID = currentBlockID
@@ -155,18 +163,24 @@ public struct PostsView: View {
.multilineTextAlignment(.center)
.frame(maxWidth: .infinity)
.padding(.top, 12)
- StyledButton(DiscussionLocalization.Posts.NoDiscussion.createbutton,
- action: {
- router.createNewThread(courseID: courseID,
- selectedTopic: currentBlockID,
- onPostCreated: {
- reloadPage(onSuccess: {
- withAnimation {
- scroll.scrollTo(1)
- }
+ StyledButton(
+ DiscussionLocalization.Posts.NoDiscussion.createbutton,
+ action: {
+ router.createNewThread(courseID: courseID,
+ selectedTopic: currentBlockID,
+ onPostCreated: {
+ reloadPage(onSuccess: {
+ withAnimation {
+ scroll.scrollTo(1)
+ }
+ })
})
- })
- }).frame(width: 215).padding(.top, 40)
+ },
+ isTransparent: true)
+ .frame(width: 215)
+ .padding(.top, 40)
+ .colorMultiply(.accentColor)
+
}.padding(24)
.padding(.top, 100)
}
diff --git a/Profile/Profile/Presentation/DeleteAccount/DeleteAccountView.swift b/Profile/Profile/Presentation/DeleteAccount/DeleteAccountView.swift
index 88c5546a2..7f8afff4c 100644
--- a/Profile/Profile/Presentation/DeleteAccount/DeleteAccountView.swift
+++ b/Profile/Profile/Presentation/DeleteAccount/DeleteAccountView.swift
@@ -23,8 +23,14 @@ public struct DeleteAccountView: View {
ScrollView {
VStack {
Group {
- CoreAssets.deleteAccount.swiftUIImage
- .padding(.top, 50)
+ ZStack {
+ CoreAssets.bgDelete.swiftUIImage
+ CoreAssets.deleteChar.swiftUIImage
+ .foregroundColor(.accentColor)
+ .offset(y: -31)
+ CoreAssets.deleteEyes.swiftUIImage
+ .offset(x: -7, y: -27)
+ }.padding(.top, 50)
Text(ProfileLocalization.DeleteAccount.areYouSure)
.foregroundColor(Theme.Colors.textPrimary)
+ Text(ProfileLocalization.DeleteAccount.wantToDelete)
diff --git a/Profile/Profile/Presentation/DeleteAccount/DeleteAccountViewModel.swift b/Profile/Profile/Presentation/DeleteAccount/DeleteAccountViewModel.swift
index 58dbe5c52..c5f464d6d 100644
--- a/Profile/Profile/Presentation/DeleteAccount/DeleteAccountViewModel.swift
+++ b/Profile/Profile/Presentation/DeleteAccount/DeleteAccountViewModel.swift
@@ -47,7 +47,7 @@ public class DeleteAccountViewModel: ObservableObject {
}
} catch {
isShowProgress = false
- if error.asAFError?.responseCode == 403 {
+ if error.validationError?.statusCode == 403 {
incorrectPassword = true
} else if let validationError = error.validationError,
let value = validationError.data?["error_code"] as? String,
diff --git a/Profile/Profile/SwiftGen/Strings.swift b/Profile/Profile/SwiftGen/Strings.swift
index f31fe2bf0..7f57c3ee7 100644
--- a/Profile/Profile/SwiftGen/Strings.swift
+++ b/Profile/Profile/SwiftGen/Strings.swift
@@ -50,8 +50,8 @@ public enum ProfileLocalization {
public static let backToProfile = ProfileLocalization.tr("Localizable", "DELETE_ACCOUNT.BACK_TO_PROFILE", fallback: "Back to profile")
/// Yes, delete account
public static let comfirm = ProfileLocalization.tr("Localizable", "DELETE_ACCOUNT.COMFIRM", fallback: "Yes, delete account")
- /// To confirm this action you need to enter you account password.
- public static let description = ProfileLocalization.tr("Localizable", "DELETE_ACCOUNT.DESCRIPTION", fallback: "To confirm this action you need to enter you account password.")
+ /// To confirm this action you need to enter your account password.
+ public static let description = ProfileLocalization.tr("Localizable", "DELETE_ACCOUNT.DESCRIPTION", fallback: "To confirm this action you need to enter your account password.")
/// The password is incorrect. Please try again.
public static let incorrectPassword = ProfileLocalization.tr("Localizable", "DELETE_ACCOUNT.INCORRECT_PASSWORD", fallback: "The password is incorrect. Please try again.")
/// Password
diff --git a/Profile/Profile/en.lproj/Localizable.strings b/Profile/Profile/en.lproj/Localizable.strings
index 5c0cd4270..9eef8b47f 100644
--- a/Profile/Profile/en.lproj/Localizable.strings
+++ b/Profile/Profile/en.lproj/Localizable.strings
@@ -48,7 +48,7 @@
"DELETE_ACCOUNT.TITLE" = "Delete account";
"DELETE_ACCOUNT.ARE_YOU_SURE" = "Are you sure you want to ";
"DELETE_ACCOUNT.WANT_TO_DELETE" = "delete your account?";
-"DELETE_ACCOUNT.DESCRIPTION" = "To confirm this action you need to enter you account password.";
+"DELETE_ACCOUNT.DESCRIPTION" = "To confirm this action you need to enter your account password.";
"DELETE_ACCOUNT.PASSWORD" = "Password";
"DELETE_ACCOUNT.PASSWORD_DESCRIPTION" = "Enter password";
"DELETE_ACCOUNT.COMFIRM" = "Yes, delete account";
diff --git a/fastlane/Fastfile b/fastlane/Fastfile
index 0f4ba890a..35445da9e 100644
--- a/fastlane/Fastfile
+++ b/fastlane/Fastfile
@@ -14,7 +14,7 @@
# update_fastlane
before_all do
- xcversion(version: "~> 14.3")
+ xcversion(version: "~> 15.0.0")
ENV["FASTLANE_XCODEBUILD_SETTINGS_TIMEOUT"] = "180"
ENV["FASTLANE_XCODE_LIST_TIMEOUT"] = "180"
From ec3ad4e0413175ddb03f6e990d0afdedf36eb86d Mon Sep 17 00:00:00 2001
From: IvanStepanok <128456094+IvanStepanok@users.noreply.github.com>
Date: Fri, 13 Oct 2023 12:24:44 +0300
Subject: [PATCH 002/158] Transcript navigation (#101)
* Transcript navigation
Display of video transcripts with active sentence highlighting.
Tapping on transcript sentences to navigate to the corresponding part of the video. Mechanism to quickly return to the current active sentence after scrolling.
https://github.com/openedx/openedx-app-ios/assets/128456094/b2cf1f49-e23b-42dd-a9b0-0ddac26bda59
---
Core/Core/Extensions/DateExtension.swift | 17 ++++++++-
.../Video/EncodedVideoPlayer.swift | 20 ++++++++--
.../Presentation/Video/SubtittlesView.swift | 37 ++++++++++++++-----
.../Video/YouTubeVideoPlayer.swift | 7 +++-
.../Video/YouTubeVideoPlayerViewModel.swift | 12 +++++-
5 files changed, 77 insertions(+), 16 deletions(-)
diff --git a/Core/Core/Extensions/DateExtension.swift b/Core/Core/Extensions/DateExtension.swift
index fae6cd14c..059b54cc2 100644
--- a/Core/Core/Extensions/DateExtension.swift
+++ b/Core/Core/Extensions/DateExtension.swift
@@ -13,7 +13,7 @@ public extension Date {
var dateFormatter: DateFormatter?
dateFormatter = DateFormatter()
dateFormatter?.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ"
-
+ dateFormatter?.locale = Locale(identifier: "en_US_POSIX")
date = dateFormatter?.date(from: iso8601) ?? Date()
defer {
dateFormatter = nil
@@ -25,6 +25,7 @@ public extension Date {
let formatter = RelativeDateTimeFormatter()
formatter.locale = .current
formatter.unitsStyle = .full
+ formatter.locale = Locale(identifier: "en_US_POSIX")
if self.description == Date().description {
return CoreLocalization.Date.justNow
} else {
@@ -38,6 +39,7 @@ public extension Date {
let components = calendar.dateComponents([.year, .month, .day], from: now)
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss,SSS"
+ dateFormatter.locale = Locale(identifier: "en_US_POSIX")
let dateString = "\(components.year!)-\(components.month!)-\(components.day!) \(subtitleTime)"
guard let date = dateFormatter.date(from: dateString) else {
self = now
@@ -70,6 +72,19 @@ public enum DateStringStyle {
}
public extension Date {
+
+ func secondsSinceMidnight() -> Double {
+ let calendar = Calendar.current
+ let components = calendar.dateComponents([.hour, .minute, .second], from: self)
+
+ guard let hours = components.hour, let minutes = components.minute, let seconds = components.second else {
+ return 0.0
+ }
+
+ let totalSeconds = Double(hours) * 3600.0 + Double(minutes) * 60.0 + Double(seconds)
+ return totalSeconds
+ }
+
func dateToString(style: DateStringStyle) -> String {
let dateFormatter = DateFormatter()
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
diff --git a/Course/Course/Presentation/Video/EncodedVideoPlayer.swift b/Course/Course/Presentation/Video/EncodedVideoPlayer.swift
index 251b59417..0afcfba01 100644
--- a/Course/Course/Presentation/Video/EncodedVideoPlayer.swift
+++ b/Course/Course/Presentation/Video/EncodedVideoPlayer.swift
@@ -30,6 +30,7 @@ public struct EncodedVideoPlayer: View {
@State private var isViewedOnce: Bool = false
@State private var currentTime: Double = 0
@State private var isOrientationChanged: Bool = false
+ @State private var pause: Bool = false
@State var showAlert = false
@State var alertMessage: String? {
@@ -64,7 +65,9 @@ public struct EncodedVideoPlayer: View {
}
}
}, seconds: { seconds in
- currentTime = seconds
+ if !pause {
+ currentTime = seconds
+ }
})
.aspectRatio(16 / 9, contentMode: .fit)
.cornerRadius(12)
@@ -89,8 +92,13 @@ public struct EncodedVideoPlayer: View {
}
}
SubtittlesView(languages: viewModel.languages,
- currentTime: $currentTime,
- viewModel: viewModel)
+ currentTime: $currentTime,
+ viewModel: viewModel, scrollTo: { date in
+ viewModel.controller.player?.seek(to: CMTime(seconds: date.secondsSinceMidnight(),
+ preferredTimescale: 10000))
+ pauseScrolling()
+ currentTime = (date.secondsSinceMidnight() + 1)
+ })
Spacer()
if !orientation.isLandscape || idiom != .pad {
VStack {}.onAppear {
@@ -120,6 +128,12 @@ public struct EncodedVideoPlayer: View {
}
}
}
+ private func pauseScrolling() {
+ pause = true
+ DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
+ self.pause = false
+ }
+ }
}
#if DEBUG
diff --git a/Course/Course/Presentation/Video/SubtittlesView.swift b/Course/Course/Presentation/Video/SubtittlesView.swift
index 6501cb409..eb3496bdc 100644
--- a/Course/Course/Presentation/Video/SubtittlesView.swift
+++ b/Course/Course/Presentation/Video/SubtittlesView.swift
@@ -18,17 +18,21 @@ public struct SubtittlesView: View {
@ObservedObject
private var viewModel: VideoPlayerViewModel
+ private var scrollTo: ((Date) -> Void) = { _ in }
@Binding var currentTime: Double
@State var id = 0
+ @State var pause: Bool = false
@State var languages: [SubtitleUrl]
public init(languages: [SubtitleUrl],
currentTime: Binding |