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

New profile block created courses #745

Merged
merged 6 commits into from
Jul 21, 2020
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
48 changes: 47 additions & 1 deletion Stepic.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions Stepic/Legacy/Analytics/Events/AmplitudeAnalyticsEvents.swift
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,7 @@ extension AnalyticsEvent {
case story(id: Int)
case deepLink(url: String)
case notification
case profile(id: Int)
case unknown

var name: String {
Expand All @@ -499,6 +500,8 @@ extension AnalyticsEvent {
return "deeplink"
case .notification:
return "notification"
case .profile:
return "profile"
case .unknown:
return "unknown"
}
Expand All @@ -512,6 +515,8 @@ extension AnalyticsEvent {
return ["query": query]
case .collection(let id):
return ["collection": id]
case .profile(let id):
return ["profile": id]
case .query(let courseListType):
var params: [String: Any] = [
"type": courseListType.analyticName
Expand Down
10 changes: 10 additions & 0 deletions Stepic/Legacy/Model/Entities/User/User+CoreDataProperties.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ extension User {
@NSManaged var managedReputation: NSNumber?
@NSManaged var managedReputationRank: NSNumber?
@NSManaged var managedJoinDate: Date?
@NSManaged var managedCreatedCoursesArray: NSObject?
@NSManaged var managedCreatedCoursesCount: NSNumber?
@NSManaged var managedSolvedStepsCount: NSNumber?
@NSManaged var managedCreatedLessonsCount: NSNumber?
Expand Down Expand Up @@ -207,6 +208,15 @@ extension User {
}
}

var createdCoursesArray: [Course.IdType] {
get {
(self.managedCreatedCoursesArray as? [Int]) ?? []
}
set {
self.managedCreatedCoursesArray = newValue as NSObject?
}
}

var createdCoursesCount: Int {
get {
self.managedCreatedCoursesCount?.intValue ?? 0
Expand Down
2 changes: 1 addition & 1 deletion Stepic/Legacy/Model/Model.xcdatamodeld/.xccurrentversion
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@
<plist version="1.0">
<dict>
<key>_XCCurrentVersionName</key>
<string>Model_new_profile_certificates_v55.xcdatamodel</string>
<string>Model_new_profile_created_courses_v56.xcdatamodel</string>
</dict>
</plist>

Large diffs are not rendered by default.

8 changes: 7 additions & 1 deletion Stepic/Legacy/Model/Network/Endpoints/CoursesAPI.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ final class CoursesAPI: APIEndpoint {

func retrieve(
tag: Int? = nil,
teacher: Int? = nil,
featured: Bool? = nil,
enrolled: Bool? = nil,
excludeEnded: Bool? = nil,
Expand Down Expand Up @@ -93,6 +94,10 @@ final class CoursesAPI: APIEndpoint {
params["tag"] = tag
}

if let teacher = teacher {
params["teacher"] = teacher
}

params["page"] = page

return self.retrieve.requestWithFetching(
Expand Down Expand Up @@ -134,7 +139,8 @@ final class CoursesAPI: APIEndpoint {
}

enum Order: String {
case activityDescending = "-activity"
case activityDesc = "-activity"
case popularityDesc = "-popularity"
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ final class PopularCourseListNetworkService: BaseCourseListNetworkService, Cours
Promise { seal in
self.coursesAPI.retrieve(
isCataloged: true,
order: .activityDescending,
order: .activityDesc,
language: self.type.language.popularCoursesParameter,
page: page
).done { result in
Expand All @@ -114,7 +114,7 @@ final class TagCourseListNetworkService: BaseCourseListNetworkService, CourseLis
Promise { seal in
self.coursesAPI.retrieve(
tag: self.type.id,
order: .activityDescending,
order: .activityDesc,
language: self.type.language.languageString,
page: page
).done { result in
Expand Down Expand Up @@ -183,3 +183,26 @@ final class SearchResultCourseListNetworkService: BaseCourseListNetworkService,
}
}
}

final class TeacherCourseListNetworkService: BaseCourseListNetworkService, CourseListNetworkServiceProtocol {
let type: TeacherCourseListType

init(type: TeacherCourseListType, coursesAPI: CoursesAPI) {
self.type = type
super.init(coursesAPI: coursesAPI)
}

func fetch(page: Int) -> Promise<([Course], Meta)> {
Promise { seal in
self.coursesAPI.retrieve(
teacher: self.type.teacherID,
order: .popularityDesc,
page: page
).done { result in
seal.fulfill(result)
}.catch { _ in
seal.reject(Error.fetchFailed)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,23 @@ final class PassiveCourseListPersistenceStorage: CourseListPersistenceStorage {

func getCoursesList() -> [Course.IdType] { self.list }
}

final class CreatedCoursesCourseListPersistenceStorage: CourseListPersistenceStorage {
private let teacherID: User.IdType

private var teacherEntity: User? {
User.fetchById(self.teacherID)?.first
}

init(teacherID: User.IdType) {
self.teacherID = teacherID
}

func update(newCachedList: [Course.IdType]) {
self.teacherEntity?.createdCoursesArray = newCachedList
}

func getCoursesList() -> [Course.IdType] {
self.teacherEntity?.createdCoursesArray ?? []
}
}
12 changes: 12 additions & 0 deletions Stepic/Sources/Modules/CourseList/Provider/CourseListTypes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ struct SearchResultCourseListType: CourseListType {
var analyticName: String { "search_result_course_list" }
}

struct TeacherCourseListType: CourseListType {
let teacherID: User.IdType

var analyticName: String { "teacher_course_list" }
}

// MARK: - Services factory

final class CourseListServicesFactory {
Expand Down Expand Up @@ -100,6 +106,10 @@ final class CourseListServicesFactory {
)
} else if self.type is SearchResultCourseListType {
return nil
} else if let type = self.type as? TeacherCourseListType {
return CourseListPersistenceService(
storage: CreatedCoursesCourseListPersistenceStorage(teacherID: type.teacherID)
)
} else {
fatalError("Unsupported course list type")
}
Expand All @@ -126,6 +136,8 @@ final class CourseListServicesFactory {
coursesAPI: self.coursesAPI,
searchResultsAPI: self.searchResultsAPI
)
} else if let type = self.type as? TeacherCourseListType {
return TeacherCourseListNetworkService(type: type, coursesAPI: self.coursesAPI)
} else {
fatalError("Unsupported course list type")
}
Expand Down
28 changes: 11 additions & 17 deletions Stepic/Sources/Modules/CourseList/Views/CourseListColorMode.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@ import Foundation
enum CourseListColorMode {
case light
case dark
case clear

static var `default`: CourseListColorMode { .light }
}

extension CourseListColorMode {
var exploreBlockHeaderViewAppearance: ExploreBlockHeaderView.Appearance {
switch self {
case .light:
case .light, .clear:
return .init(
titleLabelColor: .stepikPrimaryText,
showAllButtonColor: .stepikTertiaryText
Expand All @@ -24,23 +25,16 @@ extension CourseListColorMode {
}

var exploreBlockContainerViewAppearance: ExploreBlockContainerView.Appearance {
switch self {
case .light:
var appearance = ExploreBlockContainerView.Appearance()
appearance.backgroundColor = self.exploreBlockContainerViewBackgroundColor
return appearance
case .dark:
var appearance = ExploreBlockContainerView.Appearance()
appearance.backgroundColor = self.exploreBlockContainerViewBackgroundColor
return appearance
}
var appearance = ExploreBlockContainerView.Appearance()
appearance.backgroundColor = self.exploreBlockContainerViewBackgroundColor
return appearance
}

private var exploreBlockContainerViewBackgroundColor: UIColor {
if #available(iOS 13.0, *) {
return UIColor { (traitCollection: UITraitCollection) -> UIColor in
switch self {
case .light:
case .light, .clear:
return .stepikBackground
case .dark:
if traitCollection.userInterfaceStyle == .dark {
Expand All @@ -51,7 +45,7 @@ extension CourseListColorMode {
}
} else {
switch self {
case .light:
case .light, .clear:
return .white
case .dark:
return .stepikAccentFixed
Expand All @@ -65,7 +59,7 @@ extension CourseListColorMode {

var courseWidgetStatsViewAppearance: CourseWidgetStatsView.Appearance {
switch self {
case .light:
case .light, .clear:
return .init(
imagesRenderingBackgroundColor: .stepikAccent,
imagesRenderingTintColor: .stepikGreenFixed,
Expand All @@ -89,7 +83,7 @@ extension CourseListColorMode {
)

switch self {
case .light:
case .light, .clear:
appearance.textColor = .stepikPrimaryText
case .dark:
appearance.textColor = .white
Expand All @@ -105,7 +99,7 @@ extension CourseListColorMode {
)

switch self {
case .light:
case .light, .clear:
appearance.textColor = .stepikSecondaryText
case .dark:
appearance.textColor = UIColor.dynamic(
Expand All @@ -119,7 +113,7 @@ extension CourseListColorMode {

var courseWidgetBorderColor: UIColor {
switch self {
case .light:
case .light, .clear:
return .dynamic(light: .stepikGrey8Fixed, dark: .stepikSeparator)
case .dark:
if #available(iOS 13.0, *) {
Expand Down
34 changes: 34 additions & 0 deletions Stepic/Sources/Modules/CourseList/Views/CourseListView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,8 @@ class CourseListView: UIView {
return self.appearance.lightModeBackgroundColor
case .dark:
return self.appearance.darkModeBackgroundColor
case .clear:
return .clear
}
}

Expand Down Expand Up @@ -186,6 +188,11 @@ extension CourseListView: ProgrammaticallyInitializableViewProtocol {
DarkCourseListCollectionViewCell.self,
forCellWithReuseIdentifier: DarkCourseListCollectionViewCell.defaultReuseIdentifier
)
case .clear:
self.collectionView.register(
ClearCourseListCollectionViewCell.self,
forCellWithReuseIdentifier: ClearCourseListCollectionViewCell.defaultReuseIdentifier
)
}

self.collectionView.register(
Expand Down Expand Up @@ -445,6 +452,18 @@ final class HorizontalCourseListView: CourseListView {
fatalError("init(coder:) has not been implemented")
}

override func updateCollectionViewData(delegate: UICollectionViewDelegate, dataSource: UICollectionViewDataSource) {
if dataSource.collectionView(self.collectionView, numberOfItemsInSection: 0) == 1 {
self.horizontalCourseFlowLayout.rowsCount = 1
} else {
self.horizontalCourseFlowLayout.rowsCount = self.rowsCount
}

super.updateCollectionViewData(delegate: delegate, dataSource: dataSource)

self.invalidateIntrinsicContentSize()
}

override func calculateItemSize() -> CGSize {
if self.isAdaptiveColumnsCount {
let (columnsCount, columnWidth) = self.calculateAdaptiveLayoutColumnAttributes(
Expand Down Expand Up @@ -519,3 +538,18 @@ private class DarkCourseListCollectionViewCell: CourseListCollectionViewCell {
String(describing: CourseListCollectionViewCell.self)
}
}

private class ClearCourseListCollectionViewCell: CourseListCollectionViewCell {
override init(frame: CGRect) {
super.init(frame: frame, colorMode: .clear)
}

@available(*, unavailable)
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

static var defaultReuseIdentifier: String {
String(describing: CourseListCollectionViewCell.self)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ extension HorizontalCourseListFlowLayout {

final class HorizontalCourseListFlowLayout: BaseListFlowLayout {
let appearance: Appearance
let rowsCount: Int
var rowsCount: Int
var columnsCount: Int

private var _contentWidth: CGFloat = 0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ final class CourseWidgetView: UIView {
self.colorMode = colorMode
super.init(frame: frame)

self.setupView()
self.addSubviews()
self.makeConstraints()
}
Expand Down Expand Up @@ -123,6 +124,12 @@ final class CourseWidgetView: UIView {
}

extension CourseWidgetView: ProgrammaticallyInitializableViewProtocol {
func setupView() {
if self.colorMode == .clear {
self.backgroundColor = .stepikBackground
}
}

func addSubviews() {
self.addSubview(self.coverView)
self.addSubview(self.titleLabel)
Expand Down
1 change: 1 addition & 0 deletions Stepic/Sources/Modules/NewProfile/NewProfileDataFlow.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ enum NewProfile {

enum Submodule: String, UniqueIdentifiable {
case streakNotifications
case createdCourses
case userActivity
case achievements
case certificates
Expand Down
8 changes: 8 additions & 0 deletions Stepic/Sources/Modules/NewProfile/NewProfileInteractor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,14 @@ extension NewProfileInteractor: NewProfileCertificatesOutputProtocol {
}
}

// MARK: - NewProfileInteractor: NewProfileCreatedCoursesOutputProtocol -

extension NewProfileInteractor: NewProfileCreatedCoursesOutputProtocol {
func handleCreatedCoursesEmptyState() {
self.presenter.presentSubmoduleEmptyState(response: .init(module: .createdCourses))
}
}

// MARK: - NewProfileInteractor: SettingsOutputProtocol -

extension NewProfileInteractor: SettingsOutputProtocol {
Expand Down
Loading