Permalink
Browse files

Merge pull request #296 from TortugaPower/develop

App Store release 3.2.1
  • Loading branch information...
GianniCarlo committed Dec 20, 2018
2 parents 94ba279 + f163ae6 commit 6be02e1b427ee9e5a6620821fd35605d586fcd0b
@@ -14,7 +14,7 @@ extension Notification.Name {
public static let importOperation = Notification.Name("com.tortugapower.audiobookplayer.operation.new")
public static let requestReview = Notification.Name("com.tortugapower.audiobookplayer.requestreview")
public static let updatePercentage = Notification.Name("com.tortugapower.audiobookplayer.book.percentage")
public static let updateChapter = Notification.Name("com.tortugapower.audiobookplayer.book.chapter")
public static let chapterChange = Notification.Name("com.tortugapower.audiobookplayer.book.chapter")
public static let bookReady = Notification.Name("com.tortugapower.audiobookplayer.book.ready")
public static let bookPlayed = Notification.Name("com.tortugapower.audiobookplayer.book.play")
public static let bookPaused = Notification.Name("com.tortugapower.audiobookplayer.book.pause")
@@ -42,7 +42,7 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>3.2.0</string>
<string>3.2.1</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleURLTypes</key>
@@ -59,7 +59,7 @@
</dict>
</array>
<key>CFBundleVersion</key>
<string>9</string>
<string>2</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>LSSupportsOpeningDocumentsInPlace</key>
@@ -259,40 +259,20 @@ class BaseListViewController: UIViewController {
let alert = UIAlertController(title: "Sort Files by", message: nil, preferredStyle: .actionSheet)

alert.addAction(UIAlertAction(title: "Title", style: .default, handler: { _ in
do {
try self.sort(by: .metadataTitle)
self.tableView.reloadData()
} catch {
self.displaySortFailureAlert()
}
self.sort(by: .metadataTitle)
self.tableView.reloadData()
}))

alert.addAction(UIAlertAction(title: "Original File Name", style: .default, handler: { _ in
do {
try self.sort(by: .fileName)
self.tableView.reloadData()
} catch {
self.displaySortFailureAlert()
}
self.sort(by: .fileName)
self.tableView.reloadData()
}))

alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
return alert
}

func sort(by sortType: PlayListSortOrder) throws {
fatalError()
}

private func displaySortFailureAlert() {
let alert = UIAlertController(title: "Error",
message: "Sorting is unsupported. Please re-import files",
preferredStyle: .alert)

alert.addAction(UIAlertAction(title: "Ok", style: .cancel, handler: nil))

self.present(alert, animated: true, completion: nil)
}
func sort(by sortType: PlayListSortOrder) {}
}

// MARK: - TableView DataSource
@@ -357,8 +357,8 @@ class LibraryViewController: BaseListViewController, UIGestureRecognizerDelegate
}

// Sorting
override func sort(by sortType: PlayListSortOrder) throws {
try library.sort(by: sortType)
override func sort(by sortType: PlayListSortOrder) {
library.sort(by: sortType)
}
}

@@ -102,8 +102,8 @@ class PlaylistViewController: BaseListViewController {

// MARK: - Methods
override func sort(by sortType: PlayListSortOrder) throws {
try self.playlist.sort(by: sortType)
override func sort(by sortType: PlayListSortOrder) {
self.playlist.sort(by: sortType)
}
}

@@ -20,17 +20,7 @@ public class Book: LibraryItem {
return self.title + "." + self.ext
}

var currentChapter: Chapter? {
guard let chapters = self.chapters?.array as? [Chapter], !chapters.isEmpty else {
return nil
}

for chapter in chapters where chapter.start <= self.currentTime && chapter.end > self.currentTime {
return chapter
}

return nil
}
var currentChapter: Chapter?

var displayTitle: String {
return self.title
@@ -72,6 +62,8 @@ public class Book: LibraryItem {
self.addToChapters(chapter)
}
}

self.currentChapter = self.chapters?.array.first as? Chapter
}

convenience init(from bookUrl: FileItem, context: NSManagedObjectContext) {
@@ -113,6 +105,24 @@ public class Book: LibraryItem {
}
}

public override func awakeFromFetch() {
super.awakeFromFetch()

self.updateCurrentChapter()
}

func updateCurrentChapter() {
guard let chapters = self.chapters?.array as? [Chapter], !chapters.isEmpty else {
return
}

guard let currentChapter = (chapters.first { (chapter) -> Bool in
chapter.start <= self.currentTime && chapter.end > self.currentTime
}) else { return }

self.currentChapter = currentChapter
}

override func getBookToPlay() -> Book? {
return self
}
@@ -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="18A391" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="14460.32" systemVersion="18B75" 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"/>
@@ -33,6 +33,7 @@
<attribute name="identifier" attributeType="String" 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"/>
<attribute name="title" attributeType="String" syncable="YES"/>
<relationship name="library" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Library" inverseName="items" inverseEntity="Library" syncable="YES"/>
</entity>
@@ -45,7 +46,7 @@
<element name="Book" positionX="-65" positionY="329" width="128" height="135"/>
<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="148"/>
<element name="LibraryItem" positionX="-63" positionY="-18" width="128" height="180"/>
<element name="Playlist" positionX="16" positionY="207" width="128" height="73"/>
</elements>
</model>
@@ -81,9 +81,9 @@ public class Library: NSManagedObject {
}

extension Library: Sortable {
func sort(by sortType: PlayListSortOrder) throws {
func sort(by sortType: PlayListSortOrder) {
guard let items = items else { return }
self.items = try BookSortService.sort(items, by: sortType)
self.items = BookSortService.sort(items, by: sortType)
DataManager.saveContext()
}
}
@@ -21,6 +21,7 @@ extension LibraryItem {
@NSManaged public var identifier: String!
@NSManaged public var title: String!
@NSManaged public var percentCompleted: Double
@NSManaged public var speed: Float
@NSManaged public var library: Library?
@NSManaged public var originalFileName: String?
}
@@ -167,9 +167,9 @@ public class Playlist: LibraryItem {
}

extension Playlist: Sortable {
func sort(by sortType: PlayListSortOrder) throws {
func sort(by sortType: PlayListSortOrder) {
guard let books = books else { return }
self.books = try BookSortService.sort(books, by: sortType)
self.books = BookSortService.sort(books, by: sortType)
DataManager.saveContext()
}
}
@@ -14,12 +14,22 @@ class ChaptersViewController: UITableViewController {

var currentChapter: Chapter!
var didSelectChapter: ((_ selectedChapter: Chapter) -> Void)?
var scrolledToCurrentChapter = false

override func viewDidLoad() {
super.viewDidLoad()

self.tableView.tableFooterView = UIView()
self.tableView.reloadData()
}

override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()

guard !self.scrolledToCurrentChapter, let index = self.chapters.firstIndex(of: self.currentChapter) else { return }

self.scrolledToCurrentChapter = true
let indexPath = IndexPath(row: index, section: 0)
self.tableView.scrollToRow(at: indexPath, at: .top, animated: false)
}

@IBAction func done(_ sender: UIBarButtonItem?) {
@@ -15,7 +15,7 @@ import MediaPlayer
class PlayerManager: NSObject {
static let shared = PlayerManager()

static let speedOptions: [Float] = [2.5, 2, 1.5, 1.25, 1, 0.75]
static let speedOptions: [Float] = [2.5, 2, 1.75, 1.5, 1.25, 1, 0.75]

private var audioPlayer: AVAudioPlayer?

@@ -113,7 +113,7 @@ class PlayerManager: NSObject {

// stop timer if the book is finished
if Int(audioplayer.currentTime) == Int(audioplayer.duration) {
if self.timer != nil && self.timer.isValid {
if self.timer != nil, self.timer.isValid {
self.timer.invalidate()
}

@@ -122,6 +122,12 @@ class PlayerManager: NSObject {
NotificationCenter.default.post(name: .bookEnd, object: nil)
}

if let currentChapter = book.currentChapter,
book.currentTime > currentChapter.end || book.currentTime < currentChapter.start {
book.updateCurrentChapter()
NotificationCenter.default.post(name: .chapterChange, object: nil, userInfo: nil)
}

let userInfo = [
"time": currentTime,
"fileURL": book.fileURL
@@ -159,21 +165,21 @@ class PlayerManager: NSObject {
}

set {
guard let player = self.audioPlayer else {
return
}
guard let player = self.audioPlayer else { return }

player.currentTime = newValue

self.currentBook?.currentTime = newValue
}
}

var speed: Float {
get {
guard let currentBook = self.currentBook else {
return 1.0
}

let useGlobalSpeed = UserDefaults.standard.bool(forKey: Constants.UserDefaults.globalSpeedEnabled.rawValue)
let globalSpeed = UserDefaults.standard.float(forKey: "global_speed")
let localSpeed = UserDefaults.standard.float(forKey: currentBook!.identifier + "_speed")
let localSpeed = currentBook.playlist?.speed ?? currentBook.speed
let speed = useGlobalSpeed ? globalSpeed : localSpeed

return speed > 0 ? speed : 1.0
@@ -184,7 +190,9 @@ class PlayerManager: NSObject {
return
}

UserDefaults.standard.set(newValue, forKey: currentBook.identifier + "_speed")
currentBook.playlist?.speed = newValue
currentBook.speed = newValue
DataManager.saveContext()

// set global speed
if UserDefaults.standard.bool(forKey: Constants.UserDefaults.globalSpeedEnabled.rawValue) {
@@ -230,9 +238,7 @@ class PlayerManager: NSObject {
// MARK: - Seek Controls
func jumpTo(_ time: Double, fromEnd: Bool = false) {
guard let player = self.audioPlayer else {
return
}
guard let player = self.audioPlayer else { return }

player.currentTime = min(max(fromEnd ? player.duration - time : time, 0), player.duration)

@@ -244,9 +250,7 @@ class PlayerManager: NSObject {
}

func jumpBy(_ direction: Double) {
guard let player = self.audioPlayer else {
return
}
guard let player = self.audioPlayer else { return }

player.currentTime += direction

@@ -367,9 +371,7 @@ class PlayerManager: NSObject {

// Toggle play/pause of book
func playPause(autoplayed _: Bool = false) {
guard let audioplayer = self.audioPlayer else {
return
}
guard let audioplayer = self.audioPlayer else { return }

// Pause player if it's playing
if audioplayer.isPlaying {
@@ -61,6 +61,13 @@ final class SleepTimer {
}))
}

self.alert.addAction(UIAlertAction(title: "End of current chapter", style: .default) { _ in
self.cancel()
self.alert.message = "Sleeping when the chapter ends"
NotificationCenter.default.addObserver(self, selector: #selector(self.end), name: .chapterChange, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(self.end), name: .bookChange, object: nil)
})

self.alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
}

@@ -80,6 +87,8 @@ final class SleepTimer {
self.alert.message = defaultMessage

self.timer?.invalidate()
NotificationCenter.default.removeObserver(self, name: .bookEnd, object: nil)
NotificationCenter.default.removeObserver(self, name: .chapterChange, object: nil)
}

private func cancel() {
@@ -96,12 +105,16 @@ final class SleepTimer {
self.alert.message = "Sleeping in \(self.durationFormatter.string(from: self.timeLeft)!)"

if self.timeLeft <= 0 {
self.timer?.invalidate()

self.onEnd?(false)
self.end()
}
}

@objc private func end() {
self.reset()

self.onEnd?(false)
}

// MARK: Public methods
func actionSheet(onStart: @escaping SleepTimerStart, onProgress: @escaping SleepTimerProgress, onEnd: @escaping SleepTimerEnd) -> UIAlertController {
Oops, something went wrong.

0 comments on commit 6be02e1

Please sign in to comment.