Skip to content
Permalink
Browse files

Add and refactor completion state around it

  • Loading branch information...
GianniCarlo committed Feb 25, 2019
1 parent 6bd5bb5 commit 6463875300bff5db7c2fd147a0d84c2cfd927117
@@ -74,6 +74,7 @@ class ItemListViewController: UIViewController, ItemList, ItemListAlerts, ItemLi
func setupObservers() {
NotificationCenter.default.addObserver(self, selector: #selector(self.bookReady), name: .bookReady, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(self.updateProgress(_:)), name: .updatePercentage, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(self.updateProgress(_:)), name: .bookEnd, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(self.adjustBottomOffsetForMiniPlayer), name: .playerPresented, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(self.adjustBottomOffsetForMiniPlayer), name: .playerDismissed, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(self.onBookPlay), name: .bookPlayed, object: nil)
@@ -301,8 +302,7 @@ class ItemListViewController: UIViewController, ItemList, ItemListAlerts, ItemLi

@objc func updateProgress(_ notification: Notification) {
guard let userInfo = notification.userInfo,
let fileURL = userInfo["fileURL"] as? URL,
let progress = userInfo["progress"] as? Double else {
let fileURL = userInfo["fileURL"] as? URL else {
return
}

@@ -311,12 +311,19 @@ class ItemListViewController: UIViewController, ItemList, ItemListAlerts, ItemLi
return book.fileURL == fileURL
}

if let playlist = item as? Playlist {
return playlist.getBook(with: fileURL) != nil
}

return false
}), let cell = self.tableView.cellForRow(at: IndexPath(row: index, section: .library)) as? BookCellView else {
return
}

cell.progress = progress
let item = self.items[index]
let progress = userInfo["progress"] as? Double ?? item.progress

cell.progress = item.isFinished ? 1.0 : progress
}

@objc func adjustBottomOffsetForMiniPlayer() {
@@ -409,12 +416,12 @@ extension ItemListViewController: UITableViewDataSource {

if let book = item as? Book {
cell.subtitle = book.author
cell.progress = book.progress
} else if let playlist = item as? Playlist {
cell.subtitle = playlist.info()
cell.progress = playlist.totalProgress()
}

cell.progress = item.isFinished ? 1.0 : item.progress

return cell
}

@@ -26,7 +26,7 @@ public class Book: LibraryItem {
return self.title
}

var progress: Double {
override var progress: Double {
return self.currentTime / self.duration
}

@@ -38,10 +38,9 @@ public class Book: LibraryItem {
return !(self.chapters?.array.isEmpty ?? true)
}

// TODO: This is a makeshift version of a proper completion property.
// See https://github.com/TortugaPower/BookPlayer/issues/201
override var isCompleted: Bool {
return Int(round(self.currentTime)) == Int(round(self.duration))
func markAsFinished(_ flag: Bool) {
self.isFinished = flag
self.playlist?.updateCompletionState()
}

func setChapters(from asset: AVAsset, context: NSManagedObjectContext) {
@@ -81,6 +80,7 @@ public class Book: LibraryItem {
self.author = authorFromMeta ?? "Unknown Author"
self.duration = CMTimeGetSeconds(asset.duration)
self.originalFileName = bookUrl.originalUrl.lastPathComponent
self.isFinished = false

var colors: ArtworkColors!
if let data = AVMetadataItem.metadataItems(from: asset.metadata, withKey: AVMetadataKey.commonKeyArtwork, keySpace: AVMetadataKeySpace.common).first?.value?.copy(with: nil) as? NSData {
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="14460.32" systemVersion="18B75" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="14460.32" systemVersion="18D109" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
<entity name="ArtworkColors" representedClassName=".ArtworkColors" syncable="YES">
<attribute name="backgroundHex" attributeType="String" syncable="YES"/>
<attribute name="displayOnDark" attributeType="Boolean" usesScalarValueType="YES" syncable="YES"/>
@@ -31,6 +31,7 @@
<attribute name="currentTime" attributeType="Double" defaultValueString="0.0" usesScalarValueType="YES" syncable="YES"/>
<attribute name="duration" optional="YES" attributeType="Double" defaultValueString="0.0" usesScalarValueType="YES" syncable="YES"/>
<attribute name="identifier" attributeType="String" syncable="YES"/>
<attribute name="isFinished" optional="YES" attributeType="Boolean" usesScalarValueType="YES" syncable="YES"/>
<attribute name="originalFileName" optional="YES" attributeType="String" syncable="YES"/>
<attribute name="percentCompleted" attributeType="Double" defaultValueString="0.0" usesScalarValueType="YES" syncable="YES"/>
<attribute name="speed" attributeType="Float" defaultValueString="1" usesScalarValueType="YES" syncable="YES"/>
@@ -43,10 +44,10 @@
</entity>
<elements>
<element name="ArtworkColors" positionX="-261" positionY="330" width="128" height="135"/>
<element name="Book" positionX="-65" positionY="329" width="128" height="135"/>
<element name="Book" positionX="-65" positionY="329" width="128" height="133"/>
<element name="Chapter" positionX="162" positionY="99" width="128" height="120"/>
<element name="Library" positionX="160" positionY="9" width="128" height="58"/>
<element name="LibraryItem" positionX="-63" positionY="-18" width="128" height="180"/>
<element name="LibraryItem" positionX="-63" positionY="-18" width="128" height="193"/>
<element name="Playlist" positionX="16" positionY="207" width="128" height="73"/>
</elements>
</model>
@@ -27,11 +27,11 @@ public class LibraryItem: NSManagedObject {

var cachedArtwork: UIImage?

var isCompleted: Bool {
return false
}

func getBookToPlay() -> Book? {
return nil
}

var progress: Double {
return 1.0
}
}
@@ -24,4 +24,5 @@ extension LibraryItem {
@NSManaged public var speed: Float
@NSManaged public var library: Library?
@NSManaged public var originalFileName: String?
@NSManaged public var isFinished: Bool
}
@@ -24,10 +24,6 @@ public class Playlist: LibraryItem {
return book.artwork
}

override var isCompleted: Bool {
return round(self.totalProgress()) >= round(self.totalDuration())
}

// MARK: - Init
convenience init(title: String, books: [Book], context: NSManagedObjectContext) {
@@ -61,7 +57,7 @@ public class Playlist: LibraryItem {
return totalDuration
}

func totalProgress() -> Double {
override var progress: Double {
guard let books = self.books?.array as? [Book] else {
return 0.0
}
@@ -81,6 +77,12 @@ public class Playlist: LibraryItem {
return totalProgress / totalDuration
}

func updateCompletionState() {
guard let books = self.books?.array as? [Book] else { return }
print(!books.contains(where: { !$0.isFinished }))
self.isFinished = !books.contains(where: { !$0.isFinished })
}

func hasBooks() -> Bool {
guard let books = self.books else {
return false
@@ -133,7 +135,7 @@ public class Playlist: LibraryItem {
guard let books = self.books else { return nil }

for item in books {
guard let book = item as? Book, !book.isCompleted else { continue }
guard let book = item as? Book, !book.isFinished else { continue }

return book
}
@@ -119,7 +119,7 @@ class PlayerManager: NSObject {

// Once book a book is finished, ask for a review
UserDefaults.standard.set(true, forKey: "ask_review")
NotificationCenter.default.post(name: .bookEnd, object: nil)
self.markAsCompleted(true)
}

if let currentChapter = book.currentChapter,
@@ -407,6 +407,19 @@ extension PlayerManager {
userInfo: userInfo)
}
}

func markAsCompleted(_ flag: Bool) {
guard let book = self.currentBook else { return }

book.markAsFinished(flag)
DataManager.saveContext()

NotificationCenter.default.post(name: .bookEnd,
object: nil,
userInfo: [
"fileURL": book.fileURL
])
}
}

// MARK: - AVAudioPlayer Delegate
@@ -254,12 +254,11 @@ class PlayerViewController: UIViewController, UIGestureRecognizerDelegate {
PlayerManager.shared.jumpTo(0.0)
}))

actionSheet.addAction(UIAlertAction(title: "Mark as Finished", style: .default, handler: { _ in
PlayerManager.shared.pause()
// Player resets back to 0.0 if currentTime is set to player's duration
PlayerManager.shared.jumpTo(0.1, fromEnd: true)
let markTitle = self.currentBook.isFinished ? "Mark as Unfinished" : "Mark as Finished"

self.requestReview()
actionSheet.addAction(UIAlertAction(title: markTitle, style: .default, handler: { _ in
PlayerManager.shared.pause()
PlayerManager.shared.markAsCompleted(!self.currentBook.isFinished)
}))

actionSheet.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
@@ -52,21 +52,21 @@ class PlaylistTests: XCTestCase {

let playlist = generatePlaylist(title: "playlist", books: [book1, book2])

let emptyProgress = playlist.totalProgress()
let emptyProgress = playlist.progress

XCTAssert(emptyProgress == 0.0)

book1.currentTime = 50
book2.currentTime = 50

let halfProgress = playlist.totalProgress()
let halfProgress = playlist.progress

XCTAssert(halfProgress == 0.5)

book1.currentTime = 100
book2.currentTime = 100

let completedProgress = playlist.totalProgress()
let completedProgress = playlist.progress

XCTAssert(completedProgress == 1.0)
}

0 comments on commit 6463875

Please sign in to comment.
You can’t perform that action at this time.