Skip to content

Commit

Permalink
Merge pull request #294 from StepicOrg/release/1.58
Browse files Browse the repository at this point in the history
Release/1.58
  • Loading branch information
Ostrenkiy authored May 5, 2018
2 parents d1f1a90 + cd60512 commit d247632
Show file tree
Hide file tree
Showing 34 changed files with 271 additions and 122 deletions.
4 changes: 2 additions & 2 deletions Stepic/AdaptiveRatingsAPI.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class AdaptiveRatingsAPI: APIEndpoint {
override var name: String { return "rating" }
var restoreName: String { return "rating-restore" }

typealias RatingRecord = (userId: Int, exp: Int, rank: Int)
typealias RatingRecord = (userId: Int, exp: Int, rank: Int, isFake: Bool)
typealias Scoreboard = (allCount: Int, leaders: [RatingRecord])

func update(courseId: Int, exp: Int) -> Promise<Void> {
Expand Down Expand Up @@ -66,7 +66,7 @@ class AdaptiveRatingsAPI: APIEndpoint {
reject(error)
case .success(let json):
if response.response?.statusCode == 200 {
let leaders = json["users"].arrayValue.map { RatingRecord(userId: $0["user"].intValue, exp: $0["exp"].intValue, rank: $0["rank"].intValue) }
let leaders = json["users"].arrayValue.map { RatingRecord(userId: $0["user"].intValue, exp: $0["exp"].intValue, rank: $0["rank"].intValue, isFake: !$0["is_not_fake"].boolValue) }
fulfill(Scoreboard(allCount: json["count"].intValue, leaders: leaders))
} else {
reject(RatingsAPIError.serverError)
Expand Down
35 changes: 30 additions & 5 deletions Stepic/AdaptiveRatingsPresenter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class AdaptiveRatingsPresenter {
weak var view: AdaptiveRatingsView?

fileprivate var ratingsAPI: AdaptiveRatingsAPI
fileprivate var usersAPI: UsersAPI
fileprivate var ratingManager: AdaptiveRatingManager

private var scoreboard: [Int: ScoreboardViewData] = [:]
Expand All @@ -40,10 +41,11 @@ class AdaptiveRatingsPresenter {
private var nouns: [(String, String)] = []
private var adjs: [(String, String)] = []

init(ratingsAPI: AdaptiveRatingsAPI, ratingManager: AdaptiveRatingManager, view: AdaptiveRatingsView) {
init(ratingsAPI: AdaptiveRatingsAPI, usersAPI: UsersAPI, ratingManager: AdaptiveRatingManager, view: AdaptiveRatingsView) {
self.view = view
self.ratingManager = ratingManager
self.ratingsAPI = ratingsAPI
self.usersAPI = usersAPI

loadNamesFromFiles()
}
Expand Down Expand Up @@ -78,15 +80,38 @@ class AdaptiveRatingsPresenter {
fileprivate func reloadRating(days: Int? = nil, force: Bool = false) -> Promise<ScoreboardViewData> {
return Promise { fulfill, reject in
let currentUser = AuthInfo.shared.userId
var usersForDeanonIds = [Int]()
var loadedScoreboard: AdaptiveRatingsAPI.Scoreboard? = nil

ratingsAPI.cancelAllTasks()
ratingsAPI.retrieve(courseId: ratingManager.courseId, count: 10, days: days).then { scoreboard -> Void in
ratingsAPI.retrieve(courseId: ratingManager.courseId, count: 10, days: days).then { scoreboard -> Promise<[User]> in
loadedScoreboard = scoreboard
usersForDeanonIds = scoreboard.leaders.filter({ !$0.isFake }).map { $0.userId }

return User.fetchAsync(ids: usersForDeanonIds)
}.then { cachedUsers -> Promise<[User]> in
self.usersAPI.retrieve(ids: usersForDeanonIds, existing: cachedUsers)
}.recover { _ -> Promise<[User]> in
// Unable to fetch users -> recover with empty array
return Promise(value: [])
}.then { users -> Void in
var userNames: [Int: String] = [:]
let locale = String(Locale.preferredLanguages.first?.split(separator: "-").first ?? "en")
users.forEach { user in
if ["ru", "ua"].contains(locale) {
userNames[user.id] = "\(user.firstName) \(user.lastName)"
} else {
userNames[user.id] = StringHelper.cyrillicToLatin("\(user.firstName) \(user.lastName)")
}
}

var curLeaders: [RatingViewData] = []
scoreboard.leaders.forEach { record in
curLeaders.append(RatingViewData(position: record.rank, exp: record.exp, name: self.generateNameBy(userId: record.userId), me: currentUser == record.userId))
loadedScoreboard?.leaders.forEach { record in
let name = userNames[record.userId] ?? self.generateNameBy(userId: record.userId)
curLeaders.append(RatingViewData(position: record.rank, exp: record.exp, name: name, me: currentUser == record.userId))
}

let curScoreboard = ScoreboardViewData(allCount: scoreboard.allCount, leaders: curLeaders)
let curScoreboard = ScoreboardViewData(allCount: loadedScoreboard?.allCount ?? 0, leaders: curLeaders)
fulfill(curScoreboard)
}.catch { error in
reject(error)
Expand Down
2 changes: 1 addition & 1 deletion Stepic/AdaptiveStatsPagerViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ class AdaptiveStatsPagerViewController: PagerController {
return vc
case .rating:
let vc = ControllerHelper.instantiateViewController(identifier: "Ratings", storyboardName: "Adaptive") as! AdaptiveRatingsViewController
vc.presenter = AdaptiveRatingsPresenter(ratingsAPI: AdaptiveRatingsAPI(), ratingManager: ratingsManager, view: vc)
vc.presenter = AdaptiveRatingsPresenter(ratingsAPI: AdaptiveRatingsAPI(), usersAPI: UsersAPI(), ratingManager: ratingsManager, view: vc)
return vc
default:
return UIViewController()
Expand Down
8 changes: 6 additions & 2 deletions Stepic/ChoiceQuizViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,12 @@ class ChoiceQuizViewController: QuizViewController {
self.view.layoutIfNeeded()
}

override func getReply() -> Reply {
return ChoiceReply(choices: self.choices)
override func getReply() -> Reply? {
if self.choices.contains(true) || dataset?.isMultipleChoice == true {
return ChoiceReply(choices: self.choices)
} else {
return nil
}
}

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
Expand Down
17 changes: 10 additions & 7 deletions Stepic/CourseListPresenter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -163,11 +163,14 @@ class CourseListPresenter {

func getData(from courses: [Course]) -> [CourseViewData] {
return courses.map { course in
CourseViewData(course: course, action: { [weak self] in
self?.actionButtonPressed(course: course)
}, secondaryAction: { [weak self] in
self?.secondaryActionButtonPressed(course: course)
})
CourseViewData(course: course,
isAdaptive: adaptiveStorageManager.canOpenInAdaptiveMode(courseId: course.id),
action: { [weak self] in
self?.actionButtonPressed(course: course)
},
secondaryAction: { [weak self] in
self?.secondaryActionButtonPressed(course: course)
})
}
}

Expand All @@ -182,8 +185,8 @@ class CourseListPresenter {
}.then { [weak self] course -> Void in
self?.view?.finishProgressHUD(success: true, message: "")

if let controller = self?.getSectionsController(for: course, didSubscribe: true) {
self?.view?.show(controller: controller)
if let navigation = self?.view?.getNavigationController() {
LastStepRouter.continueLearning(for: course, using: navigation)
}
}.catch { [weak self] error in
guard let error = error as? CourseSubscriber.CourseSubscriptionError else {
Expand Down
6 changes: 2 additions & 4 deletions Stepic/CourseListViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ class CourseListViewController: UIViewController, CourseListView {
super.viewDidLoad()

delegate?.setupContentView()
setup3dTouch()
if refreshEnabled {
delegate?.setupRefresh()
}
Expand All @@ -70,10 +69,9 @@ class CourseListViewController: UIViewController, CourseListView {
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
presenter?.willAppear()
}

private func setup3dTouch() {
if(traitCollection.forceTouchCapability == .available) {
// Setup 3D touch
if traitCollection.forceTouchCapability == .available {
registerForPreviewing(with: self, sourceView: view)
}
}
Expand Down
4 changes: 3 additions & 1 deletion Stepic/CourseListViewData.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ struct CourseViewData {
var progress: Float?
var action: (() -> Void)?
var secondaryAction: (() -> Void)?
var isAdaptive: Bool

init(course: Course, action: @escaping () -> Void, secondaryAction: @escaping () -> Void) {
init(course: Course, isAdaptive: Bool, action: @escaping () -> Void, secondaryAction: @escaping () -> Void) {
self.id = course.id
self.title = course.title
self.isEnrolled = course.enrolled
Expand All @@ -29,5 +30,6 @@ struct CourseViewData {
self.progress = course.enrolled ? course.progress?.percentPassed : nil
self.action = action
self.secondaryAction = secondaryAction
self.isAdaptive = isAdaptive
}
}
68 changes: 21 additions & 47 deletions Stepic/CoursePreviewViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class CoursePreviewViewController: UIViewController, ShareableController {
var video: Video!
var moviePlayer: MPMoviePlayerController?
var parentShareBlock: ((UIActivityViewController) -> Void)?
let subscriber = CourseSubscriber()

var course: Course? = nil {
didSet {
Expand Down Expand Up @@ -160,20 +161,16 @@ class CoursePreviewViewController: UIViewController, ShareableController {
[weak self] in
SVProgressHUD.show()
button.isEnabled = false
_ = ApiDataDownloader.enrollments.joinCourse(c, delete: true, success : {
SVProgressHUD.showSuccess(withStatus: "")
self?.subscriber.leave(course: c).then { [weak self] course -> Void in
button.isEnabled = true
c.enrolled = false
CoreDataHelper.instance.save()
CourseSubscriptionManager.sharedManager.unsubscribedFrom(course: c)
WatchDataHelper.parseAndAddPlainCourses(WatchCoursesDisplayingHelper.getCurrentlyDisplayingCourses())
self?.initBarButtonItems(dropAvailable: c.enrolled)
SVProgressHUD.showSuccess(withStatus: "")
self?.course = course
self?.initBarButtonItems(dropAvailable: course.enrolled)
_ = self?.navigationController?.popToRootViewController(animated: true)
}, error: {
status in
SVProgressHUD.showError(withStatus: status)
button.isEnabled = true
})
}.catch { _ in
SVProgressHUD.showError(withStatus: "")
button.isEnabled = true
}
})
}))

Expand Down Expand Up @@ -385,44 +382,21 @@ class CoursePreviewViewController: UIViewController, ShareableController {
if !c.enrolled {
SVProgressHUD.show()
sender.isEnabled = false
_ = ApiDataDownloader.enrollments.joinCourse(c, success : {
[weak self] in

let successBlock = {
[weak self] in
SVProgressHUD.showSuccess(withStatus: "")
sender.isEnabled = true
sender.setTitle(NSLocalizedString("Continue", comment: ""), for: .normal)
self?.course?.enrolled = true
CoreDataHelper.instance.save()
CourseSubscriptionManager.sharedManager.subscribedTo(course: c)
WatchDataHelper.parseAndAddPlainCourses(WatchCoursesDisplayingHelper.getCurrentlyDisplayingCourses())
self?.performSegue(withIdentifier: "showSections", sender: nil)
self?.initBarButtonItems(dropAvailable: c.enrolled)
}
subscriber.join(course: c).then { [weak self] course -> Void in
SVProgressHUD.showSuccess(withStatus: "")
sender.isEnabled = true
sender.setTitle(NSLocalizedString("Continue", comment: ""), for: .normal)
self?.course = course
self?.initBarButtonItems(dropAvailable: course.enrolled)

guard let progressId = c.progressId else {
successBlock()
return
if let navigation = self?.navigationController {
LastStepRouter.continueLearning(for: course, using: navigation)
}

ApiDataDownloader.progresses.retrieve(ids: [progressId], existing: c.progress != nil ? [c.progress!] : [], refreshMode: .update, success: {
progresses in
guard let progress = progresses.first else {
return
}
c.progress = progress
successBlock()
}, error: {
_ in
successBlock()
})

}, error: {
status in
SVProgressHUD.showError(withStatus: status)
sender.isEnabled = true
})
}.catch { _ in
SVProgressHUD.showError(withStatus: "")
sender.isEnabled = true
}
} else {
if AdaptiveStorageManager.shared.canOpenInAdaptiveMode(courseId: c.id) {
guard let cardsViewController = ControllerHelper.instantiateViewController(identifier: "CardsSteps", storyboardName: "Adaptive") as? BaseCardsStepsViewController else {
Expand Down
1 change: 1 addition & 0 deletions Stepic/CourseSubscriber.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ class CourseSubscriber {

let success: (Course) -> Void = {
course in
course.enrolled = !unsubscribe
CoreDataHelper.instance.save()

if unsubscribe {
Expand Down
16 changes: 0 additions & 16 deletions Stepic/CourseWidgetTableViewCell.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,23 +33,7 @@ class CourseWidgetTableViewCell: UITableViewCell {
// Configure the view for the selected state
}

func initWithCourse(_ course: Course, action: (() -> Void)?) {
widgetView.title = course.title
widgetView.action = action
widgetView.actionButtonState = course.enrolled ? .continueLearning : .join
widgetView.secondaryActionButtonState = course.enrolled ? .syllabus : .info
widgetView.imageURL = URL(string: course.coverURLString)
widgetView.rating = course.reviewSummary?.average
widgetView.learners = course.learnersCount
widgetView.progress = course.enrolled ? course.progress?.percentPassed : nil
isLoading = false
}

func setup(courseViewData course: CourseViewData, colorMode: CourseListColorMode) {
widgetView.setup(courseViewData: course, colorMode: colorMode)

if AdaptiveStorageManager.shared.canOpenInAdaptiveMode(courseId: course.id) {
widgetView.secondaryActionButtonState = .info
}
}
}
12 changes: 11 additions & 1 deletion Stepic/CourseWidgetView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class CourseWidgetView: NibInitializableView {
@IBOutlet weak var courseStatsCollectionView: UICollectionView!
@IBOutlet weak var actionButton: StepikButton!
@IBOutlet weak var secondaryActionButton: StepikButton!
@IBOutlet weak var isAdaptiveLabel: StepikLabel!

@IBOutlet weak var courseStatsCollectionViewFlowLayout: UICollectionViewFlowLayout!

Expand Down Expand Up @@ -91,6 +92,7 @@ class CourseWidgetView: NibInitializableView {
courseStatsCollectionView.isHidden = hidden
actionButton.isHidden = hidden
secondaryActionButton.isHidden = hidden
isAdaptiveLabel.superview?.isHidden = hidden
}

var isLoading: Bool = false {
Expand Down Expand Up @@ -184,6 +186,8 @@ class CourseWidgetView: NibInitializableView {
courseStatsCollectionViewFlowLayout.minimumInteritemSpacing = 8
courseStatsCollectionViewFlowLayout.minimumLineSpacing = 8
view.backgroundColor = UIColor.clear

isAdaptiveLabel.text = NSLocalizedString("WidgetAdaptiveLabel", comment: "")
}

override func layoutSubviews() {
Expand All @@ -203,6 +207,13 @@ class CourseWidgetView: NibInitializableView {
progress = course.progress
self.colorMode = colorMode
isLoading = false

if course.isAdaptive {
secondaryActionButtonState = .info
isAdaptiveLabel.superview?.isHidden = false
} else {
isAdaptiveLabel.superview?.isHidden = true
}
}

@IBAction func actionButtonPressed(_ sender: Any) {
Expand All @@ -212,7 +223,6 @@ class CourseWidgetView: NibInitializableView {
@IBAction func secondaryActionButtonPressed(_ sender: Any) {
secondaryAction?()
}

}

extension CourseWidgetView: UICollectionViewDelegate {
Expand Down
Loading

0 comments on commit d247632

Please sign in to comment.