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 exam lessons screen #351

Merged
merged 29 commits into from
Aug 30, 2018
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
c0f7095
Remove unnecessary LessonsTableViewController.xib file
ivan-magda Aug 25, 2018
c28b97b
Return Guarantee when getting lessons from cache
ivan-magda Aug 25, 2018
0b910a1
layout LessonTableViewCell
ivan-magda Aug 25, 2018
d4256d6
Fill cells with the data
ivan-magda Aug 25, 2018
9a17ecc
Localize lesson pages count
ivan-magda Aug 25, 2018
8126973
Refactor move view data building to the view model
ivan-magda Aug 25, 2018
013bce0
Show practice lessons
ivan-magda Aug 25, 2018
11ca257
Navigate to the adaptive screen
ivan-magda Aug 25, 2018
90c4bfe
Add lesson table header view with dynamic height
ivan-magda Aug 25, 2018
78ae07d
Use guard let syntax
ivan-magda Aug 25, 2018
4d36397
Localize lessons view controller title
ivan-magda Aug 26, 2018
989c8a8
Localize topic lessons count
ivan-magda Aug 26, 2018
452448c
Extend LessonsView with updateHeader(title:,subtitle:)
ivan-magda Aug 26, 2018
a37b46f
Refactor rename LessonsPresenter->LessonsPresenterProtocol
ivan-magda Aug 26, 2018
44dddb5
Refactor rename LessonsPresenterImpl->LessonsPresenter
ivan-magda Aug 26, 2018
302a1a0
Add table header view gradient
ivan-magda Aug 26, 2018
b9c425d
Refactor extract table view estimated row height
ivan-magda Aug 26, 2018
264b6f5
Refactor rename LessonsAssembly->LessonsAssemblyProtocol
ivan-magda Aug 26, 2018
d8f33f2
Refactor rename LessonsAssemblyImpl->LessonsAssembly
ivan-magda Aug 26, 2018
d85a709
Refactor rename LessonsRouter->LessonsRouterProtocol
ivan-magda Aug 26, 2018
ed38cb1
Refactor rename LessonsRouterImpl->LessonsRouter
ivan-magda Aug 26, 2018
578ac2c
Fix tests
ivan-magda Aug 26, 2018
26dc7a1
Use StringHelper for pluralization
ivan-magda Aug 28, 2018
b03c32d
Refactor rename LessonHeaderTableView -> LessonTableHeaderView
ivan-magda Aug 28, 2018
ab8b242
Up code quality
ivan-magda Aug 28, 2018
71dd5ec
Use coordinator on size class change
ivan-magda Aug 28, 2018
61f1514
merge dev into feature/exam-new-lessons-screen
ivan-magda Aug 28, 2018
515009d
merge dev into feature/exam-new-lessons-screen
ivan-magda Aug 28, 2018
b05952c
Merge branch 'dev' into feature/exam-new-lessons-screen
ivan-magda Aug 30, 2018
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
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,6 @@ protocol AssemblyFactory: class {
var applicationAssembly: ApplicationAssembly { get }
var authAssembly: AuthAssembly { get }
var topicsAssembly: TopicsAssembly { get }
var lessonsAssembly: LessonsAssembly { get }
var lessonsAssembly: LessonsAssemblyProtocol { get }
var stepsAssembly: StepsAssemblyProtocol { get }
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ final class AssemblyFactoryImpl: AssemblyFactory {
return TopicsAssemblyImpl(assemblyFactory: self, serviceFactory: serviceFactory)
}

var lessonsAssembly: LessonsAssembly {
return LessonsAssemblyImpl(assemblyFactory: self, serviceFactory: serviceFactory)
var lessonsAssembly: LessonsAssemblyProtocol {
return LessonsAssembly(assemblyFactory: self, serviceFactory: serviceFactory)
}

var stepsAssembly: StepsAssemblyProtocol {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,35 @@
import Foundation

public struct KnowledgeGraphLesson {
let id: Int
let type: LessonType
let courseId: String

public enum LessonType: String {
case theory
case practice
}

let id: Int
let type: LessonType
let courseId: String
public init(rawValue: String) {
switch rawValue {
case "theory":
self = .theory
case "practice":
self = .practice
default:
self = LessonType.default
}
}

static var `default`: LessonType {
return .theory
}
}
}

extension KnowledgeGraphLesson {
init(id: Int, type: String, courseId: String) {
self.id = id
self.type = LessonType(rawValue: type)!
self.type = LessonType(rawValue: type)
self.courseId = courseId
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

import Foundation

struct LessonPlainObject: Codable, Equatable {
struct LessonPlainObject: Equatable {
let id: Int
let steps: [Int]
let title: String
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,26 @@

import Foundation

protocol LessonsAssembly: class {
func module(navigationController: UINavigationController, topicId: String) -> UIViewController
final class LessonsAssembly: BaseAssembly, LessonsAssemblyProtocol {
func module(navigationController: UINavigationController, topicId: String) -> UIViewController {
let controller = LessonsTableViewController()
let router = LessonsRouter(
assemblyFactory: assemblyFactory,
navigationController: navigationController
)

let knowledgeGraph = serviceFactory.knowledgeGraphProvider.knowledgeGraph
let presenter = LessonsPresenter(
view: controller,
router: router,
topicId: topicId,
knowledgeGraph: knowledgeGraph,
lessonsService: serviceFactory.lessonsService,
courseService: serviceFactory.courseService
)
controller.presenter = presenter
controller.title = NSLocalizedString("LessonsViewControllerTitle", comment: "")

return controller
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
//
// LessonsAssemblyProtocol.swift
// ExamEGERussian
//
// Created by Ivan Magda on 30/07/2018.
// Copyright © 2018 Alex Karpov. All rights reserved.
//

import Foundation

protocol LessonsAssemblyProtocol: class {
func module(
navigationController: UINavigationController,
topicId: String
) -> UIViewController
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,168 @@
//

import Foundation
import PromiseKit

protocol LessonsPresenter: class {
func refresh()
func selectLesson(with viewData: LessonsViewData)
final class LessonsPresenter: LessonsPresenterProtocol {
private weak var view: LessonsView?
private let router: LessonsRouterProtocol

private let topicId: String
private let knowledgeGraph: KnowledgeGraph

private var lessons = [LessonPlainObject]() {
didSet {
updateView()
}
}
private var topic: KnowledgeGraphVertex<String> {
return knowledgeGraph[topicId]!.key
}
private var lessonsIds: [Int] {
return topic.lessons.map { $0.id }
}
private var coursesIds: [Int] {
return topic.lessons.compactMap { Int($0.courseId) }
}

private let lessonsService: LessonsService
private let courseService: CourseService

init(view: LessonsView,
router: LessonsRouterProtocol,
topicId: String,
knowledgeGraph: KnowledgeGraph,
lessonsService: LessonsService,
courseService: CourseService
) {
self.view = view
self.router = router
self.topicId = topicId
self.knowledgeGraph = knowledgeGraph
self.lessonsService = lessonsService
self.courseService = courseService
}

// MARK: LessonsPresenterProtocol

func refresh() {
getLessons()
joinCoursesIfNeeded()
}

func selectLesson(with viewData: LessonsViewData) {
guard let lesson = topic.lessons.first(where: { $0.id == viewData.id }) else {
return
}

switch lesson.type {
case .theory:
if let lesson = lessons.first(where: { $0.id == viewData.id }) {
router.showTheory(lesson: lesson)
} else {
displayError()
}
case .practice:
router.showPractice(courseId: lesson.courseId)
}
}
}

// MARK: - LessonsPresenterImpl (Business Logic) -

extension LessonsPresenter {
private func joinCoursesIfNeeded() {
guard !coursesIds.isEmpty else {
return
}

courseService.joinCourses(with: coursesIds).done { courses in
print("Successfully joined courses with ids: \(courses.map { $0.id })")
}.catch { [weak self] _ in
self?.displayError()
}
}

private func getLessons() {
obtainLessonsFromCache().done {
self.fetchLessons()
}
}

private func obtainLessonsFromCache() -> Guarantee<Void> {
return Guarantee { seal in
self.lessonsService.obtainLessons(with: self.lessonsIds).done { [weak self] lessons in
self?.lessons = lessons
seal(())
}.catch { error in
print("\(#function): \(error)")
seal(())
}
}
}

private func fetchLessons() {
guard lessonsIds.count > 0 else {
return
}

lessonsService.fetchLessons(with: lessonsIds).done { [weak self] lessons in
self?.lessons = lessons
}.catch { [weak self] _ in
self?.displayError()
}
}
}

// MARK: - LessonsPresenterImpl (Update View) -

extension LessonsPresenter {
private func displayError(
title: String = NSLocalizedString("Error", comment: ""),
message: String = NSLocalizedString("ErrorMessage", comment: "")
) {
view?.displayError(title: title, message: message)
}

private func updateView() {
let theory = lessons.map {
LessonsViewData(
id: $0.id,
title: $0.title,
subtitle: countLocalizedString(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Это pluralize? Уже есть хелпер в /StepicAdaptiveCourse/StringHelper.swift, он не подходит?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Про такую штуку не знал, попробую.

Stringsdict вроде бы стандарт для таких ситуаций 🤔

key: "lesson pages count",
comment: "Lessons pages count string format to be found in Localized.stringsdict",
count: UInt($0.steps.count)
)
)
}
let practice = topic.lessons.filter { $0.type == .practice }.map {
LessonsViewData(
id: $0.id,
title: NSLocalizedString("PracticeLessonTitle", comment: ""),
subtitle: NSLocalizedString("PracticeLessonDescription", comment: "")
)
}

view?.setLessons(theory + practice)
view?.updateHeader(
title: topic.title,
subtitle: countLocalizedString(
key: "topic lessons count",
comment: "Lessons count in the topic string format to be found in Localized.stringsdict",
count: UInt(topic.lessons.count)
)
)
}

private func countLocalizedString(
key: String,
comment: String = "",
count: UInt
) -> String {
let formatString = NSLocalizedString(key, comment: comment)
let resultString = String.localizedStringWithFormat(formatString, count)

return resultString
}
}
Loading