Skip to content

Commit

Permalink
Handle TimerCategoryToggle state changes
Browse files Browse the repository at this point in the history
  • Loading branch information
isiahmanns committed Sep 14, 2023
1 parent 261ae98 commit 6300d2e
Show file tree
Hide file tree
Showing 14 changed files with 138 additions and 54 deletions.
10 changes: 7 additions & 3 deletions Hourglass/Hourglass.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
258302EE29C36A0000D37115 /* Notifications.swift in Sources */ = {isa = PBXBuildFile; fileRef = 258302ED29C36A0000D37115 /* Notifications.swift */; };
258CB4C529C2E4D800812DA4 /* UserNotificationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 258CB4C429C2E4D800812DA4 /* UserNotificationManager.swift */; };
258D5ABC2AB12F4D005CD49F /* TimerCategoryToggle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 258D5ABB2AB12F4D005CD49F /* TimerCategoryToggle.swift */; };
258D5ABE2AB262C2005CD49F /* TimerCategoryTogglePresenterModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 258D5ABD2AB262C2005CD49F /* TimerCategoryTogglePresenterModel.swift */; };
25937DBA29B1B4E900A15F0B /* TimerModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 25937DB929B1B4E900A15F0B /* TimerModel.swift */; };
25AF8B902A2EAA93000A3F5F /* Mixpanel in Frameworks */ = {isa = PBXBuildFile; productRef = 25AF8B8F2A2EAA93000A3F5F /* Mixpanel */; };
25AF8B922A2EAD3C000A3F5F /* AnalyticsManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 25AF8B912A2EAD3C000A3F5F /* AnalyticsManager.swift */; };
Expand Down Expand Up @@ -106,6 +107,7 @@
258302ED29C36A0000D37115 /* Notifications.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Notifications.swift; sourceTree = "<group>"; };
258CB4C429C2E4D800812DA4 /* UserNotificationManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserNotificationManager.swift; sourceTree = "<group>"; };
258D5ABB2AB12F4D005CD49F /* TimerCategoryToggle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimerCategoryToggle.swift; sourceTree = "<group>"; };
258D5ABD2AB262C2005CD49F /* TimerCategoryTogglePresenterModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimerCategoryTogglePresenterModel.swift; sourceTree = "<group>"; };
25937DB929B1B4E900A15F0B /* TimerModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimerModel.swift; sourceTree = "<group>"; };
25AF8B912A2EAD3C000A3F5F /* AnalyticsManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsManager.swift; sourceTree = "<group>"; };
25AF8B942A2F92BA000A3F5F /* MixpanelEngine.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MixpanelEngine.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -213,12 +215,13 @@
path = Managers;
sourceTree = "<group>";
};
2507BB5829C92067004478BE /* Data Models */ = {
2507BB5829C92067004478BE /* Presenter Models */ = {
isa = PBXGroup;
children = (
25937DB929B1B4E900A15F0B /* TimerModel.swift */,
258D5ABD2AB262C2005CD49F /* TimerCategoryTogglePresenterModel.swift */,
);
path = "Data Models";
path = "Presenter Models";
sourceTree = "<group>";
};
253816D129A5D88C007BD118 = {
Expand Down Expand Up @@ -253,7 +256,7 @@
25EB6DAB29B027AB005BC143 /* ViewModel.swift */,
2507BB5529C91D95004478BE /* Views */,
2507BB5729C92054004478BE /* Managers */,
2507BB5829C92067004478BE /* Data Models */,
2507BB5829C92067004478BE /* Presenter Models */,
2507BB5629C91DDB004478BE /* Utilities */,
253816E129A5D88C007BD118 /* Assets.xcassets */,
253816E629A5D88C007BD118 /* Hourglass.entitlements */,
Expand Down Expand Up @@ -543,6 +546,7 @@
2570F7352A0BDA5F0031B0BB /* RestSettingsFlow.swift in Sources */,
258302EA29C331CC00D37115 /* SettingsManager.swift in Sources */,
2570F7382A1472160031B0BB /* TimerHistory.xcdatamodeld in Sources */,
258D5ABE2AB262C2005CD49F /* TimerCategoryTogglePresenterModel.swift in Sources */,
2507BB4729C7A77F004478BE /* SettingsKeys.swift in Sources */,
254C4F062A33C74900217448 /* AnalyticsDataType.swift in Sources */,
25458EE129C6A69F00A118C0 /* Constants.swift in Sources */,
Expand Down
1 change: 1 addition & 0 deletions Hourglass/Hourglass/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ extension AppDelegate: WindowCoordinator {
aboutWindow.makeKeyAndOrderFront(nil)
}

// TODO: - Remove
func showPopoverIfNeeded() {
// Note: Fixes bug where tapping the status item wouldn't close the popover on the first time after an alert popup.
if !popover.isShown {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"colors" : [
{
"color" : {
"color-space" : "srgb",
"components" : {
"alpha" : "1.000",
"blue" : "0x60",
"green" : "0x60",
"red" : "0x60"
}
},
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"colors" : [
{
"color" : {
"color-space" : "srgb",
"components" : {
"alpha" : "1.000",
"blue" : "0x1E",
"green" : "0x1E",
"red" : "0x1E"
}
},
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
1 change: 1 addition & 0 deletions Hourglass/Hourglass/Managers/AnalyticsManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ enum AnalyticsEngine: AnalyticsEngineType {
}
}

// TODO: - Add event for timer category toggle
enum AnalyticsEvent {
case timerDidComplete(Timer.Model)
case timerWasCancelled(Timer.Model)
Expand Down
2 changes: 2 additions & 0 deletions Hourglass/Hourglass/Managers/DataManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@ import Foundation

protocol DataManaging {
var timerModels: [Timer.Model.ID: Timer.Model] { get }
var timerCategoryTogglePresenterModel: TimerCategoryToggle.PresenterModel { get }
}

class DataManager: DataManaging {
static let shared = DataManager(timerLengths: Constants.timerLengths,
store: CoreDataStore.shared,
timerEventProvider: TimerManager.shared)
let timerModels: [Timer.Model.ID: Timer.Model]
let timerCategoryTogglePresenterModel: TimerCategoryToggle.PresenterModel = .init()
private let timerEvents: [HourglassEventKey.Timer: TimerEvent]
private let store: CoreDataStore
private var cancellables: Set<AnyCancellable> = []
Expand Down
15 changes: 12 additions & 3 deletions Hourglass/Hourglass/Managers/TimerModelStateManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ class TimerModelStateManager {

private let analyticsManager: AnalyticsManager
private let timerModels: [Timer.Model.ID: Timer.Model]
private let timerCategoryTogglePresenterModel: TimerCategoryToggle.PresenterModel
private let timerEvents: [HourglassEventKey.Timer: TimerEvent]
private let settingsManager: SettingsManager
weak var delegate: (EventNotifying & TimerHandling)?
Expand Down Expand Up @@ -60,6 +61,7 @@ class TimerModelStateManager {
timerEventProvider: TimerEventProviding) {
self.analyticsManager = analyticsManager
self.timerModels = dataManager.timerModels
self.timerCategoryTogglePresenterModel = dataManager.timerCategoryTogglePresenterModel
self.settingsManager = settingsManager
self.timerEvents = timerEventProvider.events
configureEventSubscriptions()
Expand Down Expand Up @@ -87,6 +89,13 @@ class TimerModelStateManager {
setTimers(state: .inactive)
delegate?.notifyUser(timerEvent: .timerDidComplete)

switch timerCategoryTogglePresenterModel.state {
case .focus, .focusOnly:
timerCategoryTogglePresenterModel.state = .focus
case .rest, .restOnly:
timerCategoryTogglePresenterModel.state = .rest
}

switch Timer.Model.category {
case .focus:
focusStride += 1
Expand Down Expand Up @@ -127,9 +136,9 @@ class TimerModelStateManager {
analyticsManager.logEvent(.enforceRestThresholdSet(newValue))
}

// TODO: - Refactor
settingsManager.observe(\.getBackToWork) { [self] isEnabled in
if !isEnabled {
timerCategoryTogglePresenterModel.state = .focus
}

analyticsManager.logEvent(.getBackToWorkSet(isEnabled))
Expand All @@ -153,17 +162,17 @@ class TimerModelStateManager {
}
}

// TODO: - Refactor
private func enforceRestIfNeeded() {
if let enforceRestThreshold, focusStride == enforceRestThreshold {
delegate?.notifyUser(progressEvent: .enforceRestThresholdMet)
timerCategoryTogglePresenterModel.state = .restOnly
}
}

// TODO: - Refactor
private func enforceFocusIfNeeded() {
if getBackToWorkIsEnabled {
delegate?.notifyUser(progressEvent: .getBackToWork)
timerCategoryTogglePresenterModel.state = .focusOnly
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import Combine

extension TimerCategoryToggle {
class PresenterModel: ObservableObject {
@Published var state: State {
didSet {
switch state {
case .focus, .focusOnly:
Timer.Model.category = .focus
case .rest, .restOnly:
Timer.Model.category = .rest
}
}
}

init(state: State = .focus) {
self.state = state
}
}

enum State {
case focus
case rest
case focusOnly
case restOnly
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import Foundation

// TODO: - Import Combine
// TODO: - Refactor to use PresenterModel naming pattern
enum Timer {
class Model: Identifiable, ObservableObject {
let length: Int
Expand Down
27 changes: 8 additions & 19 deletions Hourglass/Hourglass/Utilities/Color.swift
Original file line number Diff line number Diff line change
@@ -1,25 +1,14 @@
import SwiftUI

extension Color {
private enum Token: String {
case background
case onBackgroundPrimary
case onBackgroundSecondary
case surface
case onSurface
case accent

var color: Color {
Color(self.rawValue)
}
}

enum Hourglass {
static let background = Token.background.color
static let onBackgroundPrimary = Token.onBackgroundPrimary.color
static let onBackgroundSecondary = Token.onBackgroundSecondary.color
static let surface = Token.surface.color
static let onSurface = Token.onSurface.color
static let accent = Token.accent.color
static let background = Color("background")
static let onBackgroundPrimary = Color("onBackgroundPrimary")
static let onBackgroundSecondary = Color("onBackgroundSecondary")
static let surface = Color("surface")
static let onSurface = Color("onSurface")
static let accent = Color("accent")
static let toggleSelection = Color("toggleSelection")
static let toggleBackground = Color("toggleBackground")
}
}
5 changes: 4 additions & 1 deletion Hourglass/Hourglass/ViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,17 @@ protocol TimerHandling: AnyObject {
func resetActiveTimer()
}

// TODO: - Split root view model into domain specific groups of responsibilities
class ViewModel: ObservableObject {
private let analyticsManager: AnalyticsManager
let timerModels: [Timer.Model.ID: Timer.Model]
let timerCategoryTogglePresenterModel: TimerCategoryToggle.PresenterModel
private let timerManager: TimerManager
private let userNotificationManager: NotificationManager
private let settingsManager: SettingsManager
weak var windowCoordinator: WindowCoordinator?

private var activeTimerModel: Timer.Model? {
var activeTimerModel: Timer.Model? {
guard let activeTimerModelId = timerManager.activeTimerModelId else { return nil }
return timerModels[activeTimerModelId]
}
Expand All @@ -35,6 +37,7 @@ class ViewModel: ObservableObject {

self.analyticsManager = analyticsManager
self.timerModels = dataManager.timerModels
self.timerCategoryTogglePresenterModel = dataManager.timerCategoryTogglePresenterModel
self.settingsManager = settingsManager
self.timerManager = timerManager
self.userNotificationManager = userNotificationManager
Expand Down
3 changes: 2 additions & 1 deletion Hourglass/Hourglass/Views/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ struct ContentView: View {
HStack {
Logo(size: 28)
Spacer()
TimerCategoryToggle()
TimerCategoryToggle(viewModel: viewModel,
presenterModel: viewModel.timerCategoryTogglePresenterModel)
Spacer()
SettingsMenu(viewModel: viewModel)
}
Expand Down
2 changes: 1 addition & 1 deletion Hourglass/Hourglass/Views/TimerButton.swift
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ extension TimerButton {
EmptyView()
case .active:
Circle()
.stroke(Color.Hourglass.accent, lineWidth: 4.0)
.stroke(Color.Hourglass.accent, lineWidth: 2.6)
}
}

Expand Down
Loading

0 comments on commit 6300d2e

Please sign in to comment.