From 7ba5ef99a3bc1fa79634dab83f2bc1ad0d9559b1 Mon Sep 17 00:00:00 2001 From: Gianni Carlo Date: Sat, 6 Apr 2019 14:46:45 -0500 Subject: [PATCH] Add playback time tracker (local) --- BookPlayer.xcodeproj/project.pbxproj | 8 ++++++ .../DataManagement/DataManager+CoreData.swift | 28 +++++++++++++++++++ .../Audiobook Player.xcdatamodel/contents | 7 ++++- .../Models/PlaybackRecord+CoreDataClass.swift | 18 ++++++++++++ .../PlaybackRecord+CoreDataProperties.swift | 25 +++++++++++++++++ BookPlayer/Player/PlayerManager.swift | 3 +- BookPlayer/Services/UserActivityManager.swift | 18 ++++++++++++ 7 files changed, 104 insertions(+), 3 deletions(-) create mode 100644 BookPlayer/Models/PlaybackRecord+CoreDataClass.swift create mode 100644 BookPlayer/Models/PlaybackRecord+CoreDataProperties.swift diff --git a/BookPlayer.xcodeproj/project.pbxproj b/BookPlayer.xcodeproj/project.pbxproj index e8d3b72ab..78f494a87 100644 --- a/BookPlayer.xcodeproj/project.pbxproj +++ b/BookPlayer.xcodeproj/project.pbxproj @@ -14,6 +14,8 @@ 4112AFD6223AD27D00BFEA55 /* Sentry.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4112AFD5223AD27D00BFEA55 /* Sentry.framework */; }; 412451841D489204008AC0E5 /* Crashlytics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 412451821D489204008AC0E5 /* Crashlytics.framework */; }; 413616401D2E21F000E48944 /* LibraryViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4136163F1D2E21F000E48944 /* LibraryViewController.swift */; }; + 413C7D9022580A0F009F3658 /* PlaybackRecord+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 413C7D8E22580A0F009F3658 /* PlaybackRecord+CoreDataClass.swift */; }; + 413C7D9122580A0F009F3658 /* PlaybackRecord+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 413C7D8F22580A0F009F3658 /* PlaybackRecord+CoreDataProperties.swift */; }; 4142964421F21D95004356DA /* BulkControlsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4142964321F21D95004356DA /* BulkControlsView.swift */; }; 4142964621F21DAE004356DA /* BulkControlsView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4142964521F21DAE004356DA /* BulkControlsView.xib */; }; 4142964921F2E2BA004356DA /* ThemeCellView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4142964721F2E2BA004356DA /* ThemeCellView.swift */; }; @@ -185,6 +187,8 @@ 4112AFD5223AD27D00BFEA55 /* Sentry.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Sentry.framework; path = Carthage/Build/iOS/Sentry.framework; sourceTree = ""; }; 412451821D489204008AC0E5 /* Crashlytics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Crashlytics.framework; sourceTree = ""; }; 4136163F1D2E21F000E48944 /* LibraryViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LibraryViewController.swift; sourceTree = ""; }; + 413C7D8E22580A0F009F3658 /* PlaybackRecord+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PlaybackRecord+CoreDataClass.swift"; sourceTree = ""; }; + 413C7D8F22580A0F009F3658 /* PlaybackRecord+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PlaybackRecord+CoreDataProperties.swift"; sourceTree = ""; }; 4142964321F21D95004356DA /* BulkControlsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BulkControlsView.swift; sourceTree = ""; }; 4142964521F21DAE004356DA /* BulkControlsView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = BulkControlsView.xib; sourceTree = ""; }; 4142964721F2E2BA004356DA /* ThemeCellView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThemeCellView.swift; sourceTree = ""; }; @@ -644,6 +648,8 @@ isa = PBXGroup; children = ( 4165EDF920A743D500616EDF /* BookPlayer.xcdatamodeld */, + 413C7D8E22580A0F009F3658 /* PlaybackRecord+CoreDataClass.swift */, + 413C7D8F22580A0F009F3658 /* PlaybackRecord+CoreDataProperties.swift */, 41839AB120AA8B960047E55D /* Theme+CoreDataClass.swift */, 41839AB220AA8B960047E55D /* Theme+CoreDataProperties.swift */, 41839AB520AA8C970047E55D /* Book+CoreDataClass.swift */, @@ -1057,7 +1063,9 @@ 410D0FED1EDCF4B000A52EB9 /* SettingsViewController.swift in Sources */, 41B2A5DE21CAF20E00917584 /* ThemesViewController.swift in Sources */, C398559C20C492FF00BE9EC0 /* AddButton.swift in Sources */, + 413C7D9022580A0F009F3658 /* PlaybackRecord+CoreDataClass.swift in Sources */, 4175E1242206CF9600FB7B71 /* DataManager+CoreData.swift in Sources */, + 413C7D9122580A0F009F3658 /* PlaybackRecord+CoreDataProperties.swift in Sources */, C3EC372E206EE0650094B4E8 /* SleepTimer.swift in Sources */, 4165EE1220A7D1E100616EDF /* RootViewController.swift in Sources */, 4165EE0820A743D500616EDF /* Playlist+CoreDataProperties.swift in Sources */, diff --git a/BookPlayer/Library/DataManagement/DataManager+CoreData.swift b/BookPlayer/Library/DataManagement/DataManager+CoreData.swift index 62060e353..e362593aa 100644 --- a/BookPlayer/Library/DataManagement/DataManager+CoreData.swift +++ b/BookPlayer/Library/DataManagement/DataManager+CoreData.swift @@ -262,4 +262,32 @@ extension DataManager { item.markAsFinished(asFinished) self.saveContext() } + + // MARK: - TimeRecord + + class func getPlaybackRecord() -> PlaybackRecord { + let calendar = Calendar.current + + let today = Date() + let dateFrom = calendar.startOfDay(for: today) + let dateTo = calendar.date(byAdding: .day, value: 1, to: dateFrom)! + + // Set predicate as date being today's date + let fromPredicate = NSPredicate(format: "%@ >= %@", today as NSDate, dateFrom as NSDate) + let toPredicate = NSPredicate(format: "%@ < %@", today as NSDate, dateTo as NSDate) + let datePredicate = NSCompoundPredicate(andPredicateWithSubpredicates: [fromPredicate, toPredicate]) + + let context = self.persistentContainer.viewContext + let fetch: NSFetchRequest = PlaybackRecord.fetchRequest() + fetch.predicate = datePredicate + + let record = try? context.fetch(fetch).first + + return record ?? PlaybackRecord.create(in: context) + } + + class func recordTime(_ playbackRecord: PlaybackRecord) { + playbackRecord.time += 1 + self.saveContext() + } } diff --git a/BookPlayer/Models/BookPlayer.xcdatamodeld/Audiobook Player.xcdatamodel/contents b/BookPlayer/Models/BookPlayer.xcdatamodeld/Audiobook Player.xcdatamodel/contents index c86e668b1..3e1726b15 100644 --- a/BookPlayer/Models/BookPlayer.xcdatamodeld/Audiobook Player.xcdatamodel/contents +++ b/BookPlayer/Models/BookPlayer.xcdatamodeld/Audiobook Player.xcdatamodel/contents @@ -1,5 +1,5 @@ - + @@ -32,6 +32,10 @@ + + + + @@ -57,5 +61,6 @@ + \ No newline at end of file diff --git a/BookPlayer/Models/PlaybackRecord+CoreDataClass.swift b/BookPlayer/Models/PlaybackRecord+CoreDataClass.swift new file mode 100644 index 000000000..408e62669 --- /dev/null +++ b/BookPlayer/Models/PlaybackRecord+CoreDataClass.swift @@ -0,0 +1,18 @@ +// +// PlaybackRecord+CoreDataClass.swift +// BookPlayer +// +// Created by Gianni Carlo on 4/5/19. +// Copyright © 2019 Tortuga Power. All rights reserved. +// +// + +import CoreData +import Foundation + +public class PlaybackRecord: NSManagedObject { + public override func awakeFromInsert() { + super.awakeFromInsert() + setPrimitiveValue(Date(), forKey: "date") + } +} diff --git a/BookPlayer/Models/PlaybackRecord+CoreDataProperties.swift b/BookPlayer/Models/PlaybackRecord+CoreDataProperties.swift new file mode 100644 index 000000000..dd53c3ad9 --- /dev/null +++ b/BookPlayer/Models/PlaybackRecord+CoreDataProperties.swift @@ -0,0 +1,25 @@ +// +// PlaybackRecord+CoreDataProperties.swift +// BookPlayer +// +// Created by Gianni Carlo on 4/5/19. +// Copyright © 2019 Tortuga Power. All rights reserved. +// +// + +import CoreData +import Foundation + +extension PlaybackRecord { + @nonobjc public class func fetchRequest() -> NSFetchRequest { + return NSFetchRequest(entityName: "PlaybackRecord") + } + + @nonobjc public class func create(in context: NSManagedObjectContext) -> PlaybackRecord { + // swiftlint:disable force_cast + return NSEntityDescription.insertNewObject(forEntityName: "PlaybackRecord", into: context) as! PlaybackRecord + } + + @NSManaged public var date: Date + @NSManaged public var time: Double +} diff --git a/BookPlayer/Player/PlayerManager.swift b/BookPlayer/Player/PlayerManager.swift index 5016e6f2b..a1d7fa2fb 100644 --- a/BookPlayer/Player/PlayerManager.swift +++ b/BookPlayer/Player/PlayerManager.swift @@ -81,8 +81,6 @@ class PlayerManager: NSObject { // Set speed for player audioplayer.rate = self.speed - UserActivityManager.shared.resumePlaybackActivity() - NotificationCenter.default.post(name: .bookReady, object: nil, userInfo: ["book": book]) completion(true) @@ -105,6 +103,7 @@ class PlayerManager: NSObject { book.percentCompleted = book.percentage DataManager.saveContext() + UserActivityManager.shared.recordTime() // Notify if isPercentageDifferent { diff --git a/BookPlayer/Services/UserActivityManager.swift b/BookPlayer/Services/UserActivityManager.swift index deacf2988..3f7fc19f1 100644 --- a/BookPlayer/Services/UserActivityManager.swift +++ b/BookPlayer/Services/UserActivityManager.swift @@ -13,6 +13,7 @@ class UserActivityManager { static let shared = UserActivityManager() var currentActivity: NSUserActivity + var playbackRecord: PlaybackRecord? private init() { let activity = NSUserActivity(activityType: Constants.UserActivityPlayback) @@ -29,9 +30,26 @@ class UserActivityManager { func resumePlaybackActivity() { self.currentActivity.becomeCurrent() + + if self.playbackRecord == nil { + self.playbackRecord = DataManager.getPlaybackRecord() + } + + guard let record = self.playbackRecord else { return } + + guard !Calendar.current.isDate(record.date, inSameDayAs: Date()) else { return } + + self.playbackRecord = DataManager.getPlaybackRecord() } func stopPlaybackActivity() { self.currentActivity.resignCurrent() + self.playbackRecord = nil + } + + func recordTime() { + guard let record = self.playbackRecord else { return } + + DataManager.recordTime(record) } }