Skip to content

Commit

Permalink
move deferral to its own sheet v1 - standardMode only
Browse files Browse the repository at this point in the history
  • Loading branch information
erikng committed Aug 16, 2021
1 parent 9745e46 commit 9f7f1d8
Show file tree
Hide file tree
Showing 9 changed files with 137 additions and 49 deletions.
5 changes: 4 additions & 1 deletion Nudge.xcodeproj/project.pbxproj
Expand Up @@ -13,6 +13,7 @@
5836861425DACFE90004514C /* Logger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5836861325DACFE90004514C /* Logger.swift */; };
5836861C25DAD01C0004514C /* SoftwareUpdate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5836861B25DAD01C0004514C /* SoftwareUpdate.swift */; };
5870FF6225CFE5EC0036D203 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 5870FF6425CFE5EC0036D203 /* Localizable.strings */; };
636B9C0226CACCAB0007BE3B /* DeferView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 636B9C0126CACCAB0007BE3B /* DeferView.swift */; };
636C4B4A25D1BECE0004A791 /* DefaultPreferencesNudge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 636C4B4925D1BECE0004A791 /* DefaultPreferencesNudge.swift */; };
636C4B7625D4306A0004A791 /* UILogic.swift in Sources */ = {isa = PBXBuildFile; fileRef = 636C4B7525D4306A0004A791 /* UILogic.swift */; };
639B6B0F25DC9ED300E38EC1 /* com.github.macadmins.Nudge.mobileconfig in Resources */ = {isa = PBXBuildFile; fileRef = 639B6B0E25DC9ED300E38EC1 /* com.github.macadmins.Nudge.mobileconfig */; };
Expand Down Expand Up @@ -60,6 +61,7 @@
5836861B25DAD01C0004514C /* SoftwareUpdate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SoftwareUpdate.swift; sourceTree = "<group>"; };
5870FF6325CFE5EC0036D203 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; };
5870FF6825CFE5FA0036D203 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/Localizable.strings; sourceTree = "<group>"; };
636B9C0126CACCAB0007BE3B /* DeferView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeferView.swift; sourceTree = "<group>"; };
636C4B4925D1BECE0004A791 /* DefaultPreferencesNudge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultPreferencesNudge.swift; sourceTree = "<group>"; };
636C4B7525D4306A0004A791 /* UILogic.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UILogic.swift; sourceTree = "<group>"; };
639B6B0E25DC9ED300E38EC1 /* com.github.macadmins.Nudge.mobileconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = com.github.macadmins.Nudge.mobileconfig; sourceTree = "<group>"; };
Expand Down Expand Up @@ -150,6 +152,7 @@
children = (
63D7D0E225C9E9A400236281 /* Main.swift */,
63D7D0E425C9E9A400236281 /* ContentView.swift */,
636B9C0126CACCAB0007BE3B /* DeferView.swift */,
639B6B5725DF377B00E38EC1 /* DeviceInfo.swift */,
639B6B5625DF376300E38EC1 /* StandardMode */,
639B6B5525DF375800E38EC1 /* SimpleMode */,
Expand All @@ -169,7 +172,6 @@
isa = PBXGroup;
children = (
63D7D12625C9F1EE00236281 /* StandardMode.swift */,
639B6B5725DF377B00E38EC1 /* DeviceInfo.swift */,
639B6B5F25DF37F000E38EC1 /* ScreenShotZoom.swift */,
639B6BA125DF41DB00E38EC1 /* LeftSide.swift */,
639B6BA625DF432D00E38EC1 /* RightSide.swift */,
Expand Down Expand Up @@ -391,6 +393,7 @@
639B6B3B25DF200C00E38EC1 /* Preferences.swift in Sources */,
63D7D0E325C9E9A400236281 /* Main.swift in Sources */,
639B6B6025DF37F000E38EC1 /* ScreenShotZoom.swift in Sources */,
636B9C0226CACCAB0007BE3B /* DeferView.swift in Sources */,
639B6BA225DF41DB00E38EC1 /* LeftSide.swift in Sources */,
639B6BA725DF432D00E38EC1 /* RightSide.swift in Sources */,
);
Expand Down
9 changes: 7 additions & 2 deletions Nudge/UI/ContentView.swift
Expand Up @@ -10,14 +10,19 @@ import SwiftUI
// https://stackoverflow.com/a/66039864
// https://gist.github.com/steve228uk/c960b4880480c6ed186d

class ViewState: ObservableObject {
@Published var shouldExit = false
}

// BackgroundView
struct BackgroundView: View {
@State var simpleModePreview: Bool
@StateObject var viewState = ViewState()
var body: some View {
if simpleMode() || simpleModePreview {
SimpleMode()
SimpleMode(viewObserved: viewState)
} else {
StandardMode()
StandardMode(viewObserved: viewState)
}
}
}
Expand Down
95 changes: 95 additions & 0 deletions Nudge/UI/DeferView.swift
@@ -0,0 +1,95 @@
//
// DeferView.swift
// Nudge
//
// Created by Erik Gomez on 8/16/21.
//

import Foundation
import SwiftUI

// Sheet view for Device Information
struct DeferView: View {
@ObservedObject var viewObserved: ViewState
@Environment(\.presentationMode) var presentationMode
@Environment(\.colorScheme) var colorScheme

@State var nudgeCustomEventDate = Date()

var body: some View {
VStack(alignment: .center) {
HStack {
Button(
action: {
self.presentationMode.wrappedValue.dismiss()})
{
Image(systemName: "xmark.circle")
.resizable()
.frame(width: 20, height: 20)
.foregroundColor(.red)
}
.keyboardShortcut(.escape)
.buttonStyle(.plain)
.help("Click to close".localized(desiredLanguage: getDesiredLanguage()))
.onHover { inside in
if inside {
NSCursor.pointingHand.push()
} else {
NSCursor.pop()
}
}
.frame(width: 30, height: 30)
Spacer()
}
DatePicker("", selection: $nudgeCustomEventDate, in: limitRange, displayedComponents: [.date])
.datePickerStyle(.graphical)
.labelsHidden()
.frame(width: 150, height: 150, alignment: .center)
.clipped()
DatePicker("", selection: $nudgeCustomEventDate, in: limitRange, displayedComponents: [.hourAndMinute])
.datePickerStyle(.stepperField)
.labelsHidden()
.frame(maxWidth: 75)
Divider()
HStack {
Button {
nudgeDefaults.set(nudgeCustomEventDate, forKey: "deferRunUntil")
userHasClickedDeferralQuitButton(deferralTime: nudgeCustomEventDate)
viewObserved.shouldExit.toggle()
self.presentationMode.wrappedValue.dismiss()
} label: {
Text("Defer")
.frame(minWidth: 35)
}
}
}
.frame(width: 280, height: 280)
}
var limitRange: ClosedRange<Date> {
let daysRemaining = Utils().getNumberOfDaysBetween()
if daysRemaining > 0 {
// Do not let the user defer past the point of the approachingWindowTime
return Date()...Calendar.current.date(byAdding: .day, value: daysRemaining-(imminentWindowTime / 24), to: Date())!
} else {
return Date()...Calendar.current.date(byAdding: .day, value: 0, to: Date())!
}
}
}

#if DEBUG
// Xcode preview for both light and dark mode
struct DeviceViewPreview: PreviewProvider {
static var previews: some View {
Group {
ForEach(["en", "es"], id: \.self) { id in
DeferView(viewObserved: ViewState())
.preferredColorScheme(.light)
.environment(\.locale, .init(identifier: id))
}
DeferView(viewObserved: ViewState())
.preferredColorScheme(.dark)
}
}
}
#endif

4 changes: 2 additions & 2 deletions Nudge/UI/Main.swift
Expand Up @@ -50,7 +50,7 @@ class AppDelegate: NSObject, NSApplicationDelegate {

// Only exit if primaryQuitButton is clicked
func applicationShouldTerminate(_ sender: NSApplication) -> NSApplication.TerminateReply {
if shouldExit {
if nudgePrimaryState.shouldExit {
return NSApplication.TerminateReply.terminateNow
} else {
let msg = "Nudge detected an attempt to close the application."
Expand Down Expand Up @@ -86,7 +86,7 @@ class AppDelegate: NSObject, NSApplicationDelegate {
if Utils().requireMajorUpgrade() && fetchMajorUpgradeSuccessful == false && majorUpgradeAppPathExists == false {
let msg = "Unable to fetch major upgrade and application missing, exiting Nudge"
uiLog.notice("\(msg, privacy: .public)")
shouldExit = true
nudgePrimaryState.shouldExit.toggle()
AppKit.NSApp.terminate(nil)
}
}
Expand Down
5 changes: 3 additions & 2 deletions Nudge/UI/SimpleMode/SimpleMode.swift
Expand Up @@ -10,6 +10,7 @@ import SwiftUI

// SimpleMode
struct SimpleMode: View {
@ObservedObject var viewObserved: ViewState
// Get the color scheme so we can dynamically change properties
@Environment(\.colorScheme) var colorScheme
@Environment(\.openURL) var openURL
Expand Down Expand Up @@ -288,11 +289,11 @@ struct SimpleModePreviews: PreviewProvider {
static var previews: some View {
Group {
ForEach(["en", "es"], id: \.self) { id in
SimpleMode()
SimpleMode(viewObserved: ViewState())
.preferredColorScheme(.light)
.environment(\.locale, .init(identifier: id))
}
SimpleMode()
SimpleMode(viewObserved: ViewState())
.preferredColorScheme(.dark)
}
}
Expand Down
55 changes: 19 additions & 36 deletions Nudge/UI/StandardMode/RightSide.swift
Expand Up @@ -10,20 +10,21 @@ import SwiftUI

// StandardModeRightSide
struct StandardModeRightSide: View {
@ObservedObject var viewObserved: ViewState
// Get the color scheme so we can dynamically change properties
@Environment(\.colorScheme) var colorScheme
@Environment(\.openURL) var openURL

// State variables
@State var allowButtons = true
@State var hasClickedCustomDeferralButton = false
@State var hasClickedSecondaryQuitButton = false
@State var requireDualQuitButtons = false
@State var nudgeEventDate = Date()
@State var nudgeCustomEventDate = Date()

// Modal view for screenshot and device info
// Modal view for screenshot and deferral info
@State var showSSDetail = false
@State var showDeferView = false

// Get the screen frame
var screen = NSScreen.main?.visibleFrame
Expand Down Expand Up @@ -217,13 +218,12 @@ struct StandardModeRightSide: View {
}

// primaryQuitButton
if requireDualQuitButtons == false || self.hasClickedSecondaryQuitButton {
if requireDualQuitButtons == false {
HStack(spacing: 20) {
if allowUserQuitDeferrals && hasClickedCustomDeferralButton == false {
if allowUserQuitDeferrals {
Menu("Defer") {
Button {
// Always go back a day to trigger Nudge every time user hits this button
nudgeDefaults.set(Calendar.current.date(byAdding: .minute, value: -(1440), to: nudgeEventDate), forKey: "deferRunUntil")
nudgeDefaults.set(Calendar.current.date(byAdding: .minute, value: (0), to: nudgeEventDate), forKey: "deferRunUntil")
Utils().userInitiatedExit()
} label: {
Text(primaryQuitButtonText)
Expand All @@ -250,8 +250,9 @@ struct StandardModeRightSide: View {
}
}
if Utils().allowCustomDeferral() {
Divider()
Button {
hasClickedCustomDeferralButton = true
self.showDeferView.toggle()
} label: {
Text("Custom")
.frame(minWidth: 35)
Expand All @@ -260,30 +261,22 @@ struct StandardModeRightSide: View {
}
.frame(maxWidth: 100)
} else {
if hasClickedCustomDeferralButton == false {
Button {
Utils().userInitiatedExit()
} label: {
Text(primaryQuitButtonText)
.frame(minWidth: 35)
}
}
}
if hasClickedCustomDeferralButton {
DatePicker("Please enter a time", selection: $nudgeCustomEventDate, in: limitRange)
.labelsHidden()
.frame(maxWidth: 150)
Button {
nudgeDefaults.set(nudgeCustomEventDate, forKey: "deferRunUntil")
userHasClickedDeferralQuitButton(deferralTime: nudgeCustomEventDate)
Utils().userInitiatedExit()
} label: {
Text("Defer")
Text(primaryQuitButtonText)
.frame(minWidth: 35)
}
}
}
.frame(maxHeight: 30)
.sheet(isPresented: $showDeferView) {
if viewObserved.shouldExit {
Utils().userInitiatedExit()
}
} content: {
DeferView(viewObserved: viewObserved)
}

}
}
}
Expand All @@ -298,16 +291,6 @@ struct StandardModeRightSide: View {
}
}

var limitRange: ClosedRange<Date> {
let daysRemaining = Utils().getNumberOfDaysBetween()
if daysRemaining > 0 {
// Do not let the user defer past the point of the approachingWindowTime
return Date()...Calendar.current.date(byAdding: .day, value: daysRemaining-(imminentWindowTime / 24), to: Date())!
} else {
return Date()...Calendar.current.date(byAdding: .day, value: 0, to: Date())!
}
}

func updateUI() {
if Utils().requireDualQuitButtons() || hasLoggedDeferralCountPastThresholdDualQuitButtons {
self.requireDualQuitButtons = true
Expand All @@ -324,11 +307,11 @@ struct StandardModeRightSidePreviews: PreviewProvider {
static var previews: some View {
Group {
ForEach(["en", "es"], id: \.self) { id in
StandardModeRightSide()
StandardModeRightSide(viewObserved: ViewState())
.preferredColorScheme(.light)
.environment(\.locale, .init(identifier: id))
}
StandardModeRightSide()
StandardModeRightSide(viewObserved: ViewState())
.preferredColorScheme(.dark)
}
}
Expand Down
7 changes: 4 additions & 3 deletions Nudge/UI/StandardMode/StandardMode.swift
Expand Up @@ -10,6 +10,7 @@ import SwiftUI

// Standard Mode
struct StandardMode: View {
@ObservedObject var viewObserved: ViewState
// Nudge UI
var body: some View {
HStack {
Expand All @@ -25,7 +26,7 @@ struct StandardMode: View {
.frame(height: 525)

// Right side of Nudge
StandardModeRightSide()
StandardModeRightSide(viewObserved: viewObserved)
}
.frame(width: 900, height: 450)
}
Expand All @@ -37,11 +38,11 @@ struct StandardModePreviews: PreviewProvider {
static var previews: some View {
Group {
ForEach(["en", "es"], id: \.self) { id in
StandardMode()
StandardMode(viewObserved: ViewState())
.preferredColorScheme(.light)
.environment(\.locale, .init(identifier: id))
}
StandardMode()
StandardMode(viewObserved: ViewState())
.preferredColorScheme(.dark)
}
}
Expand Down
2 changes: 1 addition & 1 deletion Nudge/Utilities/Preferences.swift
Expand Up @@ -10,7 +10,7 @@ import Foundation
let nudgeJSONPreferences = Utils().getNudgeJSONPreferences()
let nudgeDefaults = UserDefaults.standard
let language = NSLocale.current.languageCode!
var shouldExit = false
var nudgePrimaryState = ViewState()
let deferRunUntil = UserDefaults.standard.object(forKey: "deferRunUntil") as? Date

// Get the language
Expand Down
4 changes: 2 additions & 2 deletions Nudge/Utilities/Utils.swift
Expand Up @@ -96,7 +96,7 @@ struct Utils {
func exitNudge() {
let msg = "Nudge is terminating due to condition met"
uiLog.notice("\(msg, privacy: .public)")
shouldExit = true
nudgePrimaryState.shouldExit.toggle()
AppKit.NSApp.terminate(nil)
}

Expand Down Expand Up @@ -391,7 +391,7 @@ struct Utils {
func userInitiatedExit() {
let msg = "User clicked primaryQuitButton"
uiLog.notice("\(msg, privacy: .public)")
shouldExit = true
nudgePrimaryState.shouldExit.toggle()
AppKit.NSApp.terminate(nil)
}

Expand Down

0 comments on commit 9f7f1d8

Please sign in to comment.