Skip to content

Commit

Permalink
feat: [FC-0047] move the certificate view from the banner to the mess…
Browse files Browse the repository at this point in the history
…age section (openedx#387)

* feat: move the certificate view from the banner to the message section

* refactor: Rename badge to certificateBadge and improve code structure

- Rename `badge` to `certificateBadge` on Assets to enhance semantic clarity.
- Refactor conditional unwrapping of `certificate.url` in viewModel for improved code readability.
Add SFPro-Light font to whitelabel configuration

* fix: update Theming_implementation

add light font
  • Loading branch information
IvanStepanok authored Apr 10, 2024
1 parent 76f0430 commit 16b17b6
Show file tree
Hide file tree
Showing 14 changed files with 143 additions and 52 deletions.
15 changes: 15 additions & 0 deletions Core/Core/Assets.xcassets/certificateBadge.imageset/Contents.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"images" : [
{
"filename" : "certificateIcon.svg",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"template-rendering-intent" : "template"
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions Core/Core/SwiftGen/Assets.swift
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ public enum CoreAssets {
public static let arrowLeft = ImageAsset(name: "arrowLeft")
public static let arrowRight16 = ImageAsset(name: "arrowRight16")
public static let certificate = ImageAsset(name: "certificate")
public static let certificateBadge = ImageAsset(name: "certificateBadge")
public static let check = ImageAsset(name: "check")
public static let checkEmail = ImageAsset(name: "checkEmail")
public static let clearInput = ImageAsset(name: "clearInput")
Expand Down
12 changes: 12 additions & 0 deletions Course/Course.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
02B6B3BC28E1D14F00232911 /* CourseRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02B6B3BB28E1D14F00232911 /* CourseRepository.swift */; };
02B6B3BE28E1D15C00232911 /* CourseEndpoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02B6B3BD28E1D15C00232911 /* CourseEndpoint.swift */; };
02B6B3C928E1E68100232911 /* Core.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 02B6B3C828E1E68100232911 /* Core.framework */; };
02D4FC2E2BBD7C9C00C47748 /* MessageSectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02D4FC2D2BBD7C9C00C47748 /* MessageSectionView.swift */; };
02F0144F28F46474002E513D /* CourseContainerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02F0144E28F46474002E513D /* CourseContainerView.swift */; };
02F0145728F4A2FF002E513D /* CourseContainerViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02F0145628F4A2FF002E513D /* CourseContainerViewModel.swift */; };
02F066E829DC71750073E13B /* SubtittlesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02F066E729DC71750073E13B /* SubtittlesView.swift */; };
Expand Down Expand Up @@ -141,6 +142,7 @@
02B6B3BD28E1D15C00232911 /* CourseEndpoint.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CourseEndpoint.swift; sourceTree = "<group>"; };
02B6B3C228E1DCD100232911 /* CourseDetails.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CourseDetails.swift; sourceTree = "<group>"; };
02B6B3C828E1E68100232911 /* Core.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Core.framework; sourceTree = BUILT_PRODUCTS_DIR; };
02D4FC2D2BBD7C9C00C47748 /* MessageSectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageSectionView.swift; sourceTree = "<group>"; };
02ED50CF29A64BB6008341CD /* uk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = uk; path = uk.lproj/Localizable.strings; sourceTree = "<group>"; };
02F0144E28F46474002E513D /* CourseContainerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CourseContainerView.swift; sourceTree = "<group>"; };
02F0145628F4A2FF002E513D /* CourseContainerViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CourseContainerViewModel.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -362,6 +364,14 @@
name = Frameworks;
sourceTree = "<group>";
};
02D4FC2C2BBD7C7500C47748 /* MessageSectionView */ = {
isa = PBXGroup;
children = (
02D4FC2D2BBD7C9C00C47748 /* MessageSectionView.swift */,
);
path = MessageSectionView;
sourceTree = "<group>";
};
02DFC65029ACC20A00EA4BB9 /* Handouts */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -562,6 +572,7 @@
BAD9CA482B2C88D500DE790A /* Subviews */ = {
isa = PBXGroup;
children = (
02D4FC2C2BBD7C7500C47748 /* MessageSectionView */,
BAC0E0D92B32F0A2006B68A9 /* CourseVideoDownloadBarView */,
BA58CF622B471047005B102E /* VideoDownloadQualityBarView */,
);
Expand Down Expand Up @@ -831,6 +842,7 @@
0270210328E736E700F54332 /* CourseOutlineView.swift in Sources */,
068DDA602B1E198700FF8CCB /* CourseUnitVerticalsDropdownView.swift in Sources */,
022C64E029ADEA9B000F532B /* Data_UpdatesResponse.swift in Sources */,
02D4FC2E2BBD7C9C00C47748 /* MessageSectionView.swift in Sources */,
02454CA02A2618E70043052A /* YouTubeView.swift in Sources */,
02454CA22A26190A0043052A /* EncodedVideoView.swift in Sources */,
065275352BB1B39C0093BCCA /* PlayerViewControllerHolder.swift in Sources */,
Expand Down
69 changes: 30 additions & 39 deletions Course/Course/Presentation/Outline/CourseOutlineView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@ public struct CourseOutlineView: View {
}

downloadQualityBars

certificateView

if let continueWith = viewModel.continueWith,
let courseStructure = viewModel.courseStructure,
!isVideo {
Expand All @@ -100,7 +101,7 @@ public struct CourseOutlineView: View {
viewModel.trackResumeCourseClicked(
blockId: continueBlock?.id ?? ""
)

if let course = viewModel.courseStructure {
viewModel.router.showCourseUnit(
courseName: course.displayName,
Expand Down Expand Up @@ -270,6 +271,33 @@ public struct CourseOutlineView: View {
}
}
}

@ViewBuilder
private var certificateView: some View {
// MARK: - Course Certificate
if let certificate = viewModel.courseStructure?.certificate,
let url = certificate.url,
url.count > 0 {
MessageSectionView(
title: CourseLocalization.Outline.passedTheCourse(title),
actionTitle: CourseLocalization.Outline.viewCertificate,
action: {
openCertificateView = true
viewModel.trackViewCertificateClicked(courseID: courseID)
}
)
.padding(.horizontal, 24)
.fullScreenCover(
isPresented: $openCertificateView,
content: {
WebBrowser(
url: url,
pageTitle: CourseLocalization.Outline.certificate
)
}
)
}
}

private func courseBanner(proxy: GeometryProxy) -> some View {
ZStack {
Expand All @@ -282,43 +310,6 @@ public struct CourseOutlineView: View {
.aspectRatio(contentMode: .fill)
.frame(maxWidth: proxy.size.width - 12, maxHeight: .infinity)
}

// MARK: - Course Certificate
if let certificate = viewModel.courseStructure?.certificate {
if let url = certificate.url, url.count > 0 {
Theme.Colors.certificateForeground
VStack(alignment: .center, spacing: 8) {
CoreAssets.certificate.swiftUIImage
Text(CourseLocalization.Outline.congratulations)
.multilineTextAlignment(.center)
.font(Theme.Fonts.headlineMedium)
Text(CourseLocalization.Outline.passedTheCourse)
.font(Theme.Fonts.bodyMedium)
.multilineTextAlignment(.center)
StyledButton(
CourseLocalization.Outline.viewCertificate,
action: {
openCertificateView = true
viewModel.trackViewCertificateClicked(courseID: courseID)
},
isTransparent: true
)
.frame(width: 141)
.padding(.top, 8)

.fullScreenCover(
isPresented: $openCertificateView,
content: {
WebBrowser(
url: url,
pageTitle: CourseLocalization.Outline.certificate
)
})
}.padding(.horizontal, 24)
.padding(.top, 8)
.foregroundColor(.white)
}
}
}
.frame(maxHeight: 250)
.cornerRadius(12)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
//
// MessageSectionView.swift
// Course
//
// Created by  Stepanok Ivan on 03.04.2024.
//

import SwiftUI
import Core
import Theme

public struct MessageSectionView: View {

private let title: String
private let actionTitle: String
private var action: (() -> Void) = {}

public init(
title: String,
actionTitle: String,
action: @escaping () -> Void
) {
self.title = title
self.actionTitle = actionTitle
self.action = action
}

public var body: some View {
HStack(alignment: .top, spacing: 8) {
CoreAssets.certificateBadge.swiftUIImage
.resizable()
.frame(width: 24, height: 24)
.foregroundColor(Theme.Colors.textPrimary)
VStack(alignment: .leading, spacing: 8) {
Text(title)
.font(Theme.Fonts.bodyMicro)
.foregroundColor(Theme.Colors.textPrimary)

Button(action: {
action()
}, label: {
Text(actionTitle)
.font(Theme.Fonts.bodyMicro)
.underline()
.foregroundColor(Theme.Colors.textPrimary)
})
}
}
.frame(minWidth: 0, maxWidth: .infinity, alignment: .leading)
.padding(.all, 12)
.background(RoundedRectangle(cornerRadius: 8)
.stroke(lineWidth: 1)
.fill(Theme.Colors.textInputStroke)
)
}
}

#Preview {
MessageSectionView(
title: "Congratulations, you have earned this course certificate in “Course Title.”",
actionTitle: "View Certificate",
action: {
}
)
.loadFonts()
}
14 changes: 7 additions & 7 deletions Course/Course/SwiftGen/Strings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -237,17 +237,17 @@ public enum CourseLocalization {
public enum Outline {
/// Certificate
public static let certificate = CourseLocalization.tr("Localizable", "OUTLINE.CERTIFICATE", fallback: "Certificate")
/// Localizable.strings
/// Course
///
/// Created by  Stepanok Ivan on 26.09.2022.
public static let congratulations = CourseLocalization.tr("Localizable", "OUTLINE.CONGRATULATIONS", fallback: "Congratulations!")
/// This course hasn't started yet.
public static let courseHasntStarted = CourseLocalization.tr("Localizable", "OUTLINE.COURSE_HASNT_STARTED", fallback: "This course hasn't started yet.")
/// Course videos
public static let courseVideos = CourseLocalization.tr("Localizable", "OUTLINE.COURSE_VIDEOS", fallback: "Course videos")
/// You’ve completed the course
public static let passedTheCourse = CourseLocalization.tr("Localizable", "OUTLINE.PASSED_THE_COURSE", fallback: "You’ve completed the course")
/// Localizable.strings
/// Course
///
/// Created by  Stepanok Ivan on 26.09.2022.
public static func passedTheCourse(_ p1: Any) -> String {
return CourseLocalization.tr("Localizable", "OUTLINE.PASSED_THE_COURSE", String(describing: p1), fallback: "Congratulations, you have earned this course certificate in “%@.”")
}
/// View certificate
public static let viewCertificate = CourseLocalization.tr("Localizable", "OUTLINE.VIEW_CERTIFICATE", fallback: "View certificate")
}
Expand Down
3 changes: 1 addition & 2 deletions Course/Course/en.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@

*/

"OUTLINE.CONGRATULATIONS" = "Congratulations!";
"OUTLINE.PASSED_THE_COURSE" = "You’ve completed the course";
"OUTLINE.PASSED_THE_COURSE" = "Congratulations, you have earned this course certificate in “%@\.”";
"OUTLINE.VIEW_CERTIFICATE" = "View certificate";
"OUTLINE.CERTIFICATE" = "Certificate";
"OUTLINE.COURSE_VIDEOS" = "Course videos";
Expand Down
3 changes: 1 addition & 2 deletions Course/Course/uk.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@

*/

"OUTLINE.CONGRATULATIONS" = "Вітаємо!";
"OUTLINE.PASSED_THE_COURSE" = "Ви пройшли курс";
"OUTLINE.PASSED_THE_COURSE" = "Вітаємо, ви отримали сертифікат курсу “%@\.“";
"OUTLINE.VIEW_CERTIFICATE" = "Переглянути сертифікат";
"OUTLINE.CERTIFICATE" = "Сертифікат";
"OUTLINE.COURSE_VIDEOS" = "Відео з курсу";
Expand Down
2 changes: 2 additions & 0 deletions Documentation/Theming_implementation.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ assets:
### Font
The `whitelabel.yaml` configuration may contain the path to a font file, and an existing font in the project will be replaced with this font.
This ttf file must contain multiple ttf fonts "merged" into a single ttf file. Font types used in the application:
- light
- regular
- medium
- semiBold
Expand All @@ -91,6 +92,7 @@ font:
project_font_file_path: 'path/to/font/file/in/project/font.ttf' # path to existing ttf font file in project
project_font_names_json_path: 'path/to/names/file/in project/fonts.json' # path to existing font names json-file in project
font_names:
light: 'FontName-Light'
regular: 'FontName-Regular'
medium: 'FontName-Medium'
semiBold: 'FontName-Semibold'
Expand Down
2 changes: 1 addition & 1 deletion Theme/Theme/Fonts/FontParser.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import Foundation

public enum FontIdentifier: String {
case regular, medium, semiBold, bold
case light, regular, medium, semiBold, bold
}

public class FontParser {
Expand Down
1 change: 1 addition & 0 deletions Theme/Theme/Fonts/fonts.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
"light": "SFPro-Light",
"regular": "SFPro-Regular",
"medium": "SFPro-Medium",
"semiBold": "SFPro-Semibold",
Expand Down
1 change: 1 addition & 0 deletions Theme/Theme/Theme.swift
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ public struct Theme {
public static let bodyLarge: Font = .custom(fontsParser.fontName(for: .regular), size: 16)
public static let bodyMedium: Font = .custom(fontsParser.fontName(for: .regular), size: 14)
public static let bodySmall: Font = .custom(fontsParser.fontName(for: .regular), size: 12)
public static let bodyMicro: Font = .custom(fontsParser.fontName(for: .light), size: 11)

public static let labelLarge: Font = .custom(fontsParser.fontName(for: .medium), size: 14)
public static let labelMedium: Font = .custom(fontsParser.fontName(for: .regular), size: 12)
Expand Down
3 changes: 2 additions & 1 deletion config_script/whitelabel.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ class WhitelabelApp:
project_font_file_path: 'path/to/font/file/in/project/font.ttf' # path to existing ttf font file in project
project_font_names_json_path: 'path/to/names/file/in project/fonts.json' # path to existing font names json-file in project
font_names:
light: 'SFPro-Light'
regular: 'FontName-Regular'
medium: 'FontName-Medium'
semiBold: 'FontName-Semibold'
Expand Down Expand Up @@ -545,4 +546,4 @@ def main():

if __name__ == "__main__":
main()


0 comments on commit 16b17b6

Please sign in to comment.