Skip to content

Commit

Permalink
Add contextual menu to countdowns
Browse files Browse the repository at this point in the history
  • Loading branch information
npna committed Mar 14, 2023
1 parent bf1c18c commit 2cc964f
Show file tree
Hide file tree
Showing 9 changed files with 131 additions and 8 deletions.
8 changes: 8 additions & 0 deletions KnotClock.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
objects = {

/* Begin PBXBuildFile section */
0D803C0229C0B62100C7F4BE /* ContextualMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D803C0129C0B62100C7F4BE /* ContextualMenu.swift */; };
0D803C0429C0B7BA00C7F4BE /* HiddenCountdowns.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D803C0329C0B7BA00C7F4BE /* HiddenCountdowns.swift */; };
0DA02AE529BD1DC200CEBB8F /* ConditionalModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DA02AE429BD1DC200CEBB8F /* ConditionalModifier.swift */; };
0DCA4C0829BBAB3400F78368 /* KnotClockApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DCA4C0729BBAB3400F78368 /* KnotClockApp.swift */; };
0DCA4C0D29BBAB3400F78368 /* KnotClock.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 0DCA4C0B29BBAB3400F78368 /* KnotClock.xcdatamodeld */; };
Expand Down Expand Up @@ -43,6 +45,8 @@
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
0D803C0129C0B62100C7F4BE /* ContextualMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContextualMenu.swift; sourceTree = "<group>"; };
0D803C0329C0B7BA00C7F4BE /* HiddenCountdowns.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HiddenCountdowns.swift; sourceTree = "<group>"; };
0DA02AE429BD1DC200CEBB8F /* ConditionalModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConditionalModifier.swift; sourceTree = "<group>"; };
0DCA4C0429BBAB3400F78368 /* KnotClock.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = KnotClock.app; sourceTree = BUILT_PRODUCTS_DIR; };
0DCA4C0729BBAB3400F78368 /* KnotClockApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KnotClockApp.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -148,6 +152,7 @@
0DCA4C3929BBABD400F78368 /* MainView.swift */,
0DCA4C2A29BBABD400F78368 /* AddCountdownView.swift */,
0DCA4C2B29BBABD400F78368 /* OverrideDay.swift */,
0D803C0329C0B7BA00C7F4BE /* HiddenCountdowns.swift */,
0DCA4C2C29BBABD400F78368 /* OverviewCountdowns.swift */,
0DCA4C2D29BBABD400F78368 /* FocusModeView.swift */,
0DCA4C2E29BBABD400F78368 /* SubViews */,
Expand Down Expand Up @@ -175,6 +180,7 @@
children = (
0DCA4C2829BBABD400F78368 /* MacOSPadding.swift */,
0DE574C029BD3C5A005BDCA4 /* ApplyColorScheme.swift */,
0D803C0129C0B62100C7F4BE /* ContextualMenu.swift */,
0DCA4C2929BBABD400F78368 /* TimeSliced.swift */,
0DA02AE429BD1DC200CEBB8F /* ConditionalModifier.swift */,
);
Expand Down Expand Up @@ -316,6 +322,7 @@
0DCA4C4029BBABD400F78368 /* Preferences.swift in Sources */,
0DCA4C4429BBABD400F78368 /* CountdownsSettingsView.swift in Sources */,
0DA02AE529BD1DC200CEBB8F /* ConditionalModifier.swift in Sources */,
0D803C0429C0B7BA00C7F4BE /* HiddenCountdowns.swift in Sources */,
0DE574C129BD3C5A005BDCA4 /* ApplyColorScheme.swift in Sources */,
0DCA4C4C29BBABD400F78368 /* OverviewSingleCountdownsWithAction.swift in Sources */,
0DCA4C5229BBABD400F78368 /* FormButton.swift in Sources */,
Expand All @@ -328,6 +335,7 @@
0DCA4C4729BBABD400F78368 /* TimeSliced.swift in Sources */,
0DCA4C4F29BBABD400F78368 /* Tiny.swift in Sources */,
0DCA4C4B29BBABD400F78368 /* FocusModeView.swift in Sources */,
0D803C0229C0B62100C7F4BE /* ContextualMenu.swift in Sources */,
0DCA4C4529BBABD400F78368 /* IndicationsSettingsView.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down
17 changes: 14 additions & 3 deletions KnotClock/Classes/Countdowns.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class Countdowns: ObservableObject {
@Published private(set) var current: [Countdown] = []
@Published private(set) var upcomming: [Countdown] = []
@Published private(set) var expired: [Countdown] = []
@Published private(set) var hidden: [Countdown] = []
@Published private(set) var fullList: [Countdown] = []

@Published var alertMessage = ""
Expand All @@ -24,6 +25,7 @@ class Countdowns: ObservableObject {
@Published private(set) var notificationsTotalCount = 0

@AppStorage(K.StorageKeys.userPreferences) private var preferences = Preferences(x: DefaultUserPreferences())
@AppStorage(K.StorageKeys.overrideDay) private var overrideDay = ""
@AppStorage(K.StorageKeys.hiddenDailies) private var hiddenDailies = HideDaily(list: [HiddenDailyItem()])
@AppStorage(K.StorageKeys.fetchedTomorrowDailies) private var fetchedTomorrowDailies: Bool = false

Expand Down Expand Up @@ -56,6 +58,7 @@ class Countdowns: ObservableObject {
expired.removeAll()
current.removeAll()
upcomming.removeAll()
hidden.removeAll()
var lowestRemainingSeconds: Int? = nil

let upMax = Int(preferences.x.maxUpcomming)
Expand Down Expand Up @@ -89,6 +92,9 @@ class Countdowns: ObservableObject {
countEx += 1
expired.append(item)
}
else if item.category == .daily && isDailyHidden(item.id) {
hidden.append(Countdown(id: item.id, title: item.title, category: .daily, time: item.time, isHidden: true))
}
else if lowestRemainingSeconds == nil
{
lowestRemainingSeconds = item.remainingSeconds
Expand Down Expand Up @@ -407,13 +413,13 @@ class Countdowns: ObservableObject {
dateFormatter.dateFormat = K.dateFormat

let dateString = dateFormatter.string(from: Date())
preferences.x.overrideDay = "\(dateString)=\(weekday.lowercased())"
overrideDay = "\(dateString)=\(weekday.lowercased())"

refetchAllAndHandleNotifications()
clearAndRefetch()
}

func todayIsOverriddenAs() -> String? {
let separated = preferences.x.overrideDay.components(separatedBy: "=")
let separated = overrideDay.components(separatedBy: "=")

let dateFormatter = DateFormatter()
dateFormatter.dateFormat = K.dateFormat
Expand Down Expand Up @@ -453,6 +459,11 @@ class Countdowns: ObservableObject {
refetchAll()
}

func unhideDaily(_ id: UUID) {
hiddenDailies.list.removeAll(where: { $0.id == id })
refetchAll()
}

func isDailyHidden(_ id: UUID?) -> Bool {
if let _ = hiddenDailies.list.firstIndex(where: { $0.id == id && $0.ymd == todayYMD() }) {
return true
Expand Down
5 changes: 3 additions & 2 deletions KnotClock/Structs/Countdown.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ struct Countdown: Identifiable, Equatable {
let category: CountdownCategory
let time: Int
var isForTomorrow: Bool = false
var isHidden: Bool = false

var entityName: String {
(self.category == .daily) ? "Daily" : "Single"
Expand Down Expand Up @@ -120,11 +121,11 @@ struct Countdown: Identifiable, Equatable {
}

// Core Data
func deleteExpiredSingleHideDaily() {
func deleteExpiredSingleHideDaily(dontCheckRemainingSeconds: Bool = false) {
if category == .daily {
Countdowns.shared.hideDaily(id)
} else {
guard remainingSeconds < 0 else { return }
guard remainingSeconds < 0 || dontCheckRemainingSeconds else { return }
delete()
}
}
Expand Down
37 changes: 37 additions & 0 deletions KnotClock/Views/HiddenCountdowns.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
//
// HiddenCountdowns.swift
// KnotClock
//
// Created by NA on 3/14/23.
//

import SwiftUI

struct HiddenCountdowns: View {
@ObservedObject private var countdowns = Countdowns.shared
@Environment(\.dismiss) private var dismiss

var body: some View {
Text("Hidden non-expired daily countdowns:").bold().padding(.top)
VStack {
if countdowns.hidden.count == 0 {
Text("None!")
}

small(countdowns.hidden)

Button("Close") {
dismiss()
}
.padding(.top)
}
.padding()
.frame(minWidth: 300)
}
}

struct HiddenCountdowns_Previews: PreviewProvider {
static var previews: some View {
HiddenCountdowns()
}
}
14 changes: 13 additions & 1 deletion KnotClock/Views/MainView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@ struct MainView: View {
@State private var showAddCountdown = false
@State private var showWeeklyOverviewSheet = false
@State private var showOverrideDaySheet = false
@State private var showHiddenSheet = false
private var isInMenubar: Bool

@AppStorage(K.StorageKeys.userPreferences) var preferences = Preferences(x: DefaultUserPreferences())
@AppStorage(K.StorageKeys.userPreferences) private var preferences = Preferences(x: DefaultUserPreferences())

#if os(macOS)
@Environment(\.openWindow) private var openWindow
Expand Down Expand Up @@ -52,6 +53,9 @@ struct MainView: View {
.sheet(isPresented: $showOverrideDaySheet) {
OverrideDay()
}
.sheet(isPresented: $showHiddenSheet) {
HiddenCountdowns()
}
.onChange(of: preferences.x.refreshTimerInterval) { newValue in
countdowns.rescheduleTimer(interval: newValue)
}
Expand Down Expand Up @@ -214,6 +218,14 @@ struct MainView: View {
}
#endif

if countdowns.hidden.count > 0 {
Button {
showHiddenSheet = true
} label: {
Image(systemName: "eye.slash")
}
}

Button {
showOverrideDaySheet = true
} label: {
Expand Down
44 changes: 44 additions & 0 deletions KnotClock/Views/Modifiers/ContextualMenu.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
//
// ContextualMenu.swift
// KnotClock
//
// Created by NA on 3/14/23.
//

import SwiftUI

struct ContextualMenu: ViewModifier {
@Binding fileprivate var countdown: Countdown
@State private var showConfirmation = false

func body(content: Content) -> some View {
content.contextMenu {
if countdown.isHidden {
Button {
Countdowns.shared.unhideDaily(countdown.id)
} label: {
Label("Unhide", systemImage: "eye").labelStyle(.titleAndIcon)
}
} else {
Button {
showConfirmation = true
} label: {
Label(countdown.category == .daily ? "Hide" : "Delete", systemImage: countdown.category == .daily ? "eye.slash" : "trash").labelStyle(.titleAndIcon)
}
}
}
.confirmationDialog("Are you sure you want to \(countdown.category == .daily ? "hide" : "delete") this item?", isPresented: $showConfirmation) {
Button("Yes", role: .destructive) {
countdown.deleteExpiredSingleHideDaily(dontCheckRemainingSeconds: true)
}

Button("Cancel", role: .cancel) {}
}
}
}

extension View {
func contextualMenu(for countdown: Binding<Countdown>) -> some View {
self.modifier(ContextualMenu(countdown: countdown))
}
}
3 changes: 2 additions & 1 deletion KnotClock/Views/SubViews/CountdownViews/FullSize.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import SwiftUI

struct FullSize: View {
@AppStorage(K.StorageKeys.userPreferences) var preferences = Preferences(x: DefaultUserPreferences())
@AppStorage(K.StorageKeys.userPreferences) private var preferences = Preferences(x: DefaultUserPreferences())

@Environment(\.colorScheme) var colorScheme
@State private var countdown: Countdown
Expand Down Expand Up @@ -73,6 +73,7 @@ struct FullSize: View {
checkIsShowing()
}
.frame(minWidth: isInMenubar ? K.FrameSizes.Mac.Menubar.minWidth - K.FrameSizes.Mac.countdownVStackWidthSubtract : .none)
.contextualMenu(for: $countdown)
}

func checkIsShowing() {
Expand Down
10 changes: 9 additions & 1 deletion KnotClock/Views/SubViews/CountdownViews/Small.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import SwiftUI

struct Small: View {
@AppStorage(K.StorageKeys.userPreferences) var preferences = Preferences(x: DefaultUserPreferences())
@AppStorage(K.StorageKeys.userPreferences) private var preferences = Preferences(x: DefaultUserPreferences())
@State private var countdown: Countdown
@Environment(\.colorScheme) var colorScheme
private let remainingTime: RemainingTimeDetails
Expand All @@ -35,6 +35,13 @@ struct Small: View {

if countdown.remainingSeconds >= 0 {
timeView(remainingTime, .small, preferences)
if countdown.isHidden {
Button {
Countdowns.shared.unhideDaily(countdown.id)
} label: {
Label("Unhide", systemImage: "eye").labelStyle(.iconOnly)
}
}
} else {
Button {
countdown.deleteExpiredSingleHideDaily()
Expand All @@ -48,6 +55,7 @@ struct Small: View {
.padding(.vertical, 5)
.background(getBackgroundColor())
.cornerRadius(K.FullSizeCountdown.cornerRadius)
.contextualMenu(for: $countdown)
}

func getBackgroundColor() -> Color {
Expand Down
1 change: 1 addition & 0 deletions KnotClock/Views/SubViews/CountdownViews/Tiny.swift
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ struct Tiny: View {
.frame(width: width)
.background(.quaternary)
.cornerRadius(5)
.contextualMenu(for: $countdown)
#if os(macOS)
.popover(isPresented: $showingPopover) {
VStack {
Expand Down

0 comments on commit 2cc964f

Please sign in to comment.