diff --git a/Core/Core/Assets.xcassets/Colors/Snackbar/SnackbarInfoAlert.colorset/Contents.json b/Core/Core/Assets.xcassets/Colors/Snackbar/SnackbarInfoAlert.colorset/Contents.json new file mode 100644 index 000000000..3e35599d4 --- /dev/null +++ b/Core/Core/Assets.xcassets/Colors/Snackbar/SnackbarInfoAlert.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "1.000", + "green" : "0.667", + "red" : "0.259" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "1.000", + "green" : "0.584", + "red" : "0.000" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Core/Core/SwiftGen/Assets.swift b/Core/Core/SwiftGen/Assets.swift index cbb63d5b6..e9d8dfc49 100644 --- a/Core/Core/SwiftGen/Assets.swift +++ b/Core/Core/SwiftGen/Assets.swift @@ -38,6 +38,7 @@ public enum CoreAssets { public static let shadowColor = ColorAsset(name: "ShadowColor") public static let snackbarErrorColor = ColorAsset(name: "SnackbarErrorColor") public static let snackbarErrorTextColor = ColorAsset(name: "SnackbarErrorTextColor") + public static let snackbarInfoAlert = ColorAsset(name: "SnackbarInfoAlert") public static let styledButtonBackground = ColorAsset(name: "StyledButtonBackground") public static let styledButtonText = ColorAsset(name: "StyledButtonText") public static let textPrimary = ColorAsset(name: "TextPrimary") diff --git a/Core/Core/View/Base/CourseButton.swift b/Core/Core/View/Base/CourseButton.swift index d91b570d4..c3a607e35 100644 --- a/Core/Core/View/Base/CourseButton.swift +++ b/Core/Core/View/Base/CourseButton.swift @@ -26,7 +26,8 @@ public struct CourseButton: View { public var body: some View { HStack { if isCompleted { - Image(systemName: "checkmark.circle.fill") + CoreAssets.finished.swiftUIImage + .renderingMode(.template) .foregroundColor(.accentColor) } else { image diff --git a/Course/Course/Presentation/Outline/CourseBlocksView.swift b/Course/Course/Presentation/Outline/CourseBlocksView.swift index 5113d5983..bf44cd0bb 100644 --- a/Course/Course/Presentation/Outline/CourseBlocksView.swift +++ b/Course/Course/Presentation/Outline/CourseBlocksView.swift @@ -15,7 +15,8 @@ public struct CourseBlocksView: View { private var title: String @ObservedObject private var viewModel: CourseBlocksViewModel - + private var idiom: UIUserInterfaceIdiom { UIDevice.current.userInterfaceIdiom } + public init(title: String, viewModel: CourseBlocksViewModel) { self.title = title @@ -26,78 +27,86 @@ public struct CourseBlocksView: View { ZStack(alignment: .top) { // MARK: - Page name - VStack(alignment: .center) { - NavigationBar(title: title, - leftButtonAction: { viewModel.router.back() }) - - // MARK: - Page Body - ScrollView { - VStack(alignment: .leading) { - // MARK: - Lessons list - ForEach(viewModel.blocks, id: \.id) { block in - let index = viewModel.blocks.firstIndex(where: { $0.id == block.id }) - Button(action: { - viewModel.router.showCourseUnit(blockId: block.id, - courseID: block.blockId, - sectionName: title, - blocks: viewModel.blocks) - }, label: { - HStack { - Group { - if block.completion == 1 { - CoreAssets.finished.swiftUIImage - } else { - block.type.image - } - Text(block.displayName) - .multilineTextAlignment(.leading) - .font(Theme.Fonts.titleMedium) - .multilineTextAlignment(.leading) - }.foregroundColor(CoreAssets.textPrimary.swiftUIColor) - Spacer() - if let state = viewModel.downloadState[block.id] { - switch state { - case .available: - DownloadAvailableView() - .onTapGesture { - viewModel.onDownloadViewTap(blockId: block.id, state: state) - } - .onForeground { - viewModel.onForeground() - } - case .downloading: - DownloadProgressView() - .onTapGesture { - viewModel.onDownloadViewTap(blockId: block.id, state: state) - } - .onBackground { - viewModel.onBackground() - } - case .finished: - DownloadFinishedView() - .onTapGesture { - viewModel.onDownloadViewTap(blockId: block.id, state: state) - } + GeometryReader { proxy in + VStack(alignment: .center) { + NavigationBar(title: title, + leftButtonAction: { viewModel.router.back() }) + + // MARK: - Page Body + ScrollView { + VStack(alignment: .leading) { + // MARK: - Lessons list + ForEach(viewModel.blocks, id: \.id) { block in + let index = viewModel.blocks.firstIndex(where: { $0.id == block.id }) + Button(action: { + viewModel.router.showCourseUnit(blockId: block.id, + courseID: block.blockId, + sectionName: title, + blocks: viewModel.blocks) + }, label: { + HStack { + Group { + if block.completion == 1 { + CoreAssets.finished.swiftUIImage + .renderingMode(.template) + .foregroundColor(.accentColor) + } else { + block.type.image + } + Text(block.displayName) + .multilineTextAlignment(.leading) + .font(Theme.Fonts.titleMedium) + .lineLimit(1) + .frame(maxWidth: idiom == .pad + ? proxy.size.width * 0.5 + : proxy.size.width * 0.6, + alignment: .leading) + }.foregroundColor(CoreAssets.textPrimary.swiftUIColor) + Spacer() + if let state = viewModel.downloadState[block.id] { + switch state { + case .available: + DownloadAvailableView() + .onTapGesture { + viewModel.onDownloadViewTap(blockId: block.id, state: state) + } + .onForeground { + viewModel.onForeground() + } + case .downloading: + DownloadProgressView() + .onTapGesture { + viewModel.onDownloadViewTap(blockId: block.id, state: state) + } + .onBackground { + viewModel.onBackground() + } + case .finished: + DownloadFinishedView() + .onTapGesture { + viewModel.onDownloadViewTap(blockId: block.id, state: state) + } + } } + Image(systemName: "chevron.right") + .padding(.vertical, 8) } - Image(systemName: "chevron.right") - .padding(.vertical, 8) + }).padding(.horizontal, 36) + .padding(.vertical, 14) + if index != viewModel.blocks.count - 1 { + Divider() + .frame(height: 1) + .overlay(CoreAssets.cardViewStroke.swiftUIColor) + .padding(.horizontal, 24) } - }).padding(.horizontal, 36) - .padding(.vertical, 14) - if index != viewModel.blocks.count - 1 { - Divider() - .frame(height: 1) - .overlay(CoreAssets.cardViewStroke.swiftUIColor) - .padding(.horizontal, 24) } } - } - Spacer(minLength: 84) - }.frameLimit() - .onRightSwipeGesture { - viewModel.router.back() - } + Spacer(minLength: 84) + }.frameLimit() + .onRightSwipeGesture { + viewModel.router.back() + } + } } // MARK: - Offline mode SnackBar diff --git a/Course/Course/Presentation/Outline/CourseOutlineView.swift b/Course/Course/Presentation/Outline/CourseOutlineView.swift index 3a26579b6..59ba3e669 100644 --- a/Course/Course/Presentation/Outline/CourseOutlineView.swift +++ b/Course/Course/Presentation/Outline/CourseOutlineView.swift @@ -17,6 +17,7 @@ public struct CourseOutlineView: View { private let isVideo: Bool @State private var openCertificateView: Bool = false + private var idiom: UIUserInterfaceIdiom { UIDevice.current.userInterfaceIdiom } public init( viewModel: CourseContainerViewModel, @@ -117,6 +118,11 @@ public struct CourseOutlineView: View { Text(child.displayName) .font(Theme.Fonts.titleMedium) .multilineTextAlignment(.leading) + .lineLimit(1) + .frame(maxWidth: idiom == .pad + ? proxy.size.width * 0.5 + : proxy.size.width * 0.6, + alignment: .leading) }.foregroundColor(CoreAssets.textPrimary.swiftUIColor) Spacer() if let state = viewModel.downloadState[child.id] { diff --git a/Course/Course/Presentation/Outline/CourseVerticalView.swift b/Course/Course/Presentation/Outline/CourseVerticalView.swift index be44690b6..f68e7b314 100644 --- a/Course/Course/Presentation/Outline/CourseVerticalView.swift +++ b/Course/Course/Presentation/Outline/CourseVerticalView.swift @@ -15,6 +15,7 @@ public struct CourseVerticalView: View { private var title: String @ObservedObject private var viewModel: CourseVerticalViewModel + private var idiom: UIUserInterfaceIdiom { UIDevice.current.userInterfaceIdiom } public init( title: String, @@ -31,74 +32,82 @@ public struct CourseVerticalView: View { leftButtonAction: { viewModel.router.back() }) // MARK: - Page Body - ScrollView { - VStack(alignment: .leading) { - // MARK: - Lessons list - ForEach(viewModel.verticals, id: \.id) { vertical in - let index = viewModel.verticals.firstIndex(where: {$0.id == vertical.id}) - Button(action: { - viewModel.router.showCourseBlocksView( - title: vertical.displayName, - blocks: vertical.childs - ) - }, label: { - HStack { - Group { - if vertical.completion == 1 { - Image(systemName: "checkmark.circle.fill") - .foregroundColor(.accentColor) - } else { - vertical.type.image - } - Text(vertical.displayName) - .font(Theme.Fonts.titleMedium) - .multilineTextAlignment(.leading) - .frame(maxWidth: .infinity, alignment: .leading) - }.foregroundColor(CoreAssets.textPrimary.swiftUIColor) - Spacer() - if let state = viewModel.downloadState[vertical.id] { - switch state { - case .available: - DownloadAvailableView() - .onTapGesture { - viewModel.onDownloadViewTap(blockId: vertical.id, state: state) - } - .onForeground { - viewModel.onForeground() - } - case .downloading: - DownloadProgressView() - .onTapGesture { - viewModel.onDownloadViewTap(blockId: vertical.id, state: state) - } - .onBackground { - viewModel.onBackground() - } - case .finished: - DownloadFinishedView() - .onTapGesture { - viewModel.onDownloadViewTap(blockId: vertical.id, state: state) - } + GeometryReader { proxy in + ScrollView { + VStack(alignment: .leading) { + // MARK: - Lessons list + ForEach(viewModel.verticals, id: \.id) { vertical in + let index = viewModel.verticals.firstIndex(where: {$0.id == vertical.id}) + Button(action: { + viewModel.router.showCourseBlocksView( + title: vertical.displayName, + blocks: vertical.childs + ) + }, label: { + HStack { + Group { + if vertical.completion == 1 { + CoreAssets.finished.swiftUIImage + .renderingMode(.template) + .foregroundColor(.accentColor) + } else { + vertical.type.image + } + Text(vertical.displayName) + .font(Theme.Fonts.titleMedium) + .lineLimit(1) + .frame(maxWidth: idiom == .pad + ? proxy.size.width * 0.5 + : proxy.size.width * 0.6, + alignment: .leading) + .multilineTextAlignment(.leading) + .frame(maxWidth: .infinity, alignment: .leading) + }.foregroundColor(CoreAssets.textPrimary.swiftUIColor) + Spacer() + if let state = viewModel.downloadState[vertical.id] { + switch state { + case .available: + DownloadAvailableView() + .onTapGesture { + viewModel.onDownloadViewTap(blockId: vertical.id, state: state) + } + .onForeground { + viewModel.onForeground() + } + case .downloading: + DownloadProgressView() + .onTapGesture { + viewModel.onDownloadViewTap(blockId: vertical.id, state: state) + } + .onBackground { + viewModel.onBackground() + } + case .finished: + DownloadFinishedView() + .onTapGesture { + viewModel.onDownloadViewTap(blockId: vertical.id, state: state) + } + } } + Image(systemName: "chevron.right") + .padding(.vertical, 8) } - Image(systemName: "chevron.right") - .padding(.vertical, 8) + }).padding(.horizontal, 36) + .padding(.vertical, 14) + if index != viewModel.verticals.count - 1 { + Divider() + .frame(height: 1) + .overlay(CoreAssets.cardViewStroke.swiftUIColor) + .padding(.horizontal, 24) } - }).padding(.horizontal, 36) - .padding(.vertical, 14) - if index != viewModel.verticals.count - 1 { - Divider() - .frame(height: 1) - .overlay(CoreAssets.cardViewStroke.swiftUIColor) - .padding(.horizontal, 24) } } - } - Spacer(minLength: 84) - }.frameLimit() - .onRightSwipeGesture { - viewModel.router.back() - } + Spacer(minLength: 84) + }.frameLimit() + .onRightSwipeGesture { + viewModel.router.back() + } + } } // MARK: - Offline mode SnackBar diff --git a/Course/Course/Presentation/Unit/CourseNavigationView.swift b/Course/Course/Presentation/Unit/CourseNavigationView.swift index 106a05173..9692e14fe 100644 --- a/Course/Course/Presentation/Unit/CourseNavigationView.swift +++ b/Course/Course/Presentation/Unit/CourseNavigationView.swift @@ -12,11 +12,12 @@ struct CourseNavigationView: View { @ObservedObject private var viewModel: CourseUnitViewModel private let sectionName: String + @Binding var killPlayer: Bool - init(sectionName: String, viewModel: CourseUnitViewModel) { + init(sectionName: String, viewModel: CourseUnitViewModel, killPlayer: Binding) { self.viewModel = viewModel self.sectionName = sectionName - + self._killPlayer = killPlayer } var body: some View { @@ -24,24 +25,24 @@ struct CourseNavigationView: View { if viewModel.selectedLesson() == viewModel.blocks.first && viewModel.blocks.count != 1 { UnitButtonView(type: .first, action: { + killPlayer.toggle() viewModel.select(move: .next) - self.viewModel.createLessonType() - self.viewModel.killPlayer.toggle() + viewModel.createLessonType() }) } else { if viewModel.previousLesson != "" { UnitButtonView(type: .previous, action: { + killPlayer.toggle() viewModel.select(move: .previous) - self.viewModel.createLessonType() - self.viewModel.killPlayer.toggle() + viewModel.createLessonType() }) } if viewModel.nextLesson != "" { UnitButtonView(type: .next, action: { + killPlayer.toggle() viewModel.select(move: .next) - self.viewModel.createLessonType() - self.viewModel.killPlayer.toggle() + viewModel.createLessonType() }) } if viewModel.selectedLesson() == viewModel.blocks.last { @@ -54,6 +55,7 @@ struct CourseNavigationView: View { image: CoreAssets.goodWork.swiftUIImage, onCloseTapped: {}, okTapped: { + killPlayer.toggle() viewModel.router.dismiss(animated: false) viewModel.router.removeLastView(controllers: 2) } @@ -78,7 +80,7 @@ struct CourseNavigationView_Previews: PreviewProvider { connectivity: Connectivity(), manager: DownloadManagerMock()) - CourseNavigationView(sectionName: "Name", viewModel: viewModel) + CourseNavigationView(sectionName: "Name", viewModel: viewModel, killPlayer: .constant(false)) } } #endif diff --git a/Course/Course/Presentation/Unit/CourseUnitView.swift b/Course/Course/Presentation/Unit/CourseUnitView.swift index 4b57e5945..92af45d6c 100644 --- a/Course/Course/Presentation/Unit/CourseUnitView.swift +++ b/Course/Course/Presentation/Unit/CourseUnitView.swift @@ -22,6 +22,7 @@ public struct CourseUnitView: View { } } } + @State var killPlayer: Bool = false private let sectionName: String public init(viewModel: CourseUnitViewModel, @@ -41,7 +42,7 @@ public struct CourseUnitView: View { NavigationBar(title: "", leftButtonAction: { viewModel.router.back() - self.viewModel.killPlayer.toggle() + killPlayer.toggle() }) // MARK: - Page Body @@ -72,7 +73,7 @@ public struct CourseUnitView: View { blockID: blockID, courseID: viewModel.courseID, languages: viewModel.languages(), - killPlayer: $viewModel.killPlayer + killPlayer: $killPlayer ) Spacer() case .web(let url): @@ -133,7 +134,7 @@ public struct CourseUnitView: View { .padding(.horizontal, 20) UnitButtonView(type: .reload, action: { self.viewModel.createLessonType() - self.viewModel.killPlayer.toggle() + killPlayer.toggle() }).frame(width: 100) }.frame(maxWidth: .infinity, maxHeight: .infinity) } @@ -163,7 +164,8 @@ public struct CourseUnitView: View { // MARK: - Course Navigation CourseNavigationView( sectionName: sectionName, - viewModel: viewModel + viewModel: viewModel, + killPlayer: $killPlayer ).padding(.vertical, 12) .frameLimit(sizePortrait: 420) .background( @@ -176,7 +178,7 @@ public struct CourseUnitView: View { }.frame(maxWidth: .infinity) .onRightSwipeGesture { viewModel.router.back() - self.viewModel.killPlayer.toggle() + killPlayer.toggle() } } diff --git a/Course/Course/Presentation/Unit/CourseUnitViewModel.swift b/Course/Course/Presentation/Unit/CourseUnitViewModel.swift index 9c4cf1b01..2d859ae5c 100644 --- a/Course/Course/Presentation/Unit/CourseUnitViewModel.swift +++ b/Course/Course/Presentation/Unit/CourseUnitViewModel.swift @@ -47,7 +47,6 @@ public class CourseUnitViewModel: ObservableObject { @Published var previousLesson: String = "" @Published var nextLesson: String = "" @Published var lessonType: LessonType? - @Published var killPlayer = false @Published var showError: Bool = false var errorMessage: String? { didSet { diff --git a/Course/Course/Presentation/Video/EncodedVideoPlayer.swift b/Course/Course/Presentation/Video/EncodedVideoPlayer.swift index 30766bcc1..0eaaad718 100644 --- a/Course/Course/Presentation/Video/EncodedVideoPlayer.swift +++ b/Course/Course/Presentation/Video/EncodedVideoPlayer.swift @@ -100,6 +100,7 @@ public struct EncodedVideoPlayer: View { } } }.onChange(of: killPlayer, perform: { _ in + controller.player?.pause() controller.player?.replaceCurrentItem(with: nil) }) // MARK: - Alert @@ -109,7 +110,7 @@ public struct EncodedVideoPlayer: View { HStack(spacing: 6) { CoreAssets.rotateDevice.swiftUIImage.renderingMode(.template) Text(alertMessage ?? "") - }.shadowCardStyle(bgColor: CoreAssets.accentColor.swiftUIColor, + }.shadowCardStyle(bgColor: CoreAssets.snackbarInfoAlert.swiftUIColor, textColor: .white) .transition(.move(edge: .bottom)) .onAppear { diff --git a/Course/Course/Presentation/Video/YouTubeVideoPlayer.swift b/Course/Course/Presentation/Video/YouTubeVideoPlayer.swift index d5ffad4f9..3662ba357 100644 --- a/Course/Course/Presentation/Video/YouTubeVideoPlayer.swift +++ b/Course/Course/Presentation/Video/YouTubeVideoPlayer.swift @@ -162,7 +162,7 @@ public struct YouTubeVideoPlayer: View { HStack(spacing: 6) { CoreAssets.rotateDevice.swiftUIImage.renderingMode(.template) Text(alertMessage ?? "") - }.shadowCardStyle(bgColor: CoreAssets.accentColor.swiftUIColor, + }.shadowCardStyle(bgColor: CoreAssets.snackbarInfoAlert.swiftUIColor, textColor: .white) .transition(.move(edge: .bottom)) .onAppear {