Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Schedule UI #51

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@ let package = Package(
dependencies: [
.package(url: "https://github.com/StanfordSpezi/SpeziFoundation", from: "2.0.0"),
.package(url: "https://github.com/StanfordSpezi/Spezi", from: "1.8.0"),
.package(url: "https://github.com/StanfordSpezi/SpeziViews", from: "1.7.0"),
.package(url: "https://github.com/StanfordSpezi/SpeziViews", from: "1.7.1"),
.package(url: "https://github.com/StanfordSpezi/SpeziStorage", from: "1.1.2"),
.package(url: "https://github.com/StanfordSpezi/SpeziNotifications.git", from: "1.0.2"),
.package(url: "https://github.com/apple/swift-algorithms.git", from: "1.2.0"),
.package(url: "https://github.com/swiftlang/swift-syntax", from: "600.0.0-prerelease-2024-08-14"),
.package(url: "https://github.com/swiftlang/swift-syntax", from: "600.0.0"),
.package(url: "https://github.com/pointfreeco/swift-snapshot-testing.git", from: "1.17.2")
] + swiftLintPackage(),
targets: [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,13 @@ extension Schedule {
}
}

static func notificationMatchingHint( // swiftlint:disable:this function_parameter_count function_default_parameter_at_end
static func notificationMatchingHint( // swiftlint:disable:this function_parameter_count
forMatchingInterval interval: Int,
calendar: Calendar,
hour: Int,
minute: Int,
second: Int,
weekday: Int? = nil,
weekday: Int? = nil, // swiftlint:disable:this function_default_parameter_at_end
consider duration: Duration
) -> NotificationMatchingHint? {
guard interval == 1 else {
Expand Down
12 changes: 6 additions & 6 deletions Sources/SpeziScheduler/Schedule/Schedule.swift
Original file line number Diff line number Diff line change
Expand Up @@ -259,12 +259,12 @@ extension Schedule {
/// - end: Optional end date of the schedule. Otherwise, it repeats indefinitely.
/// - duration: The duration of a single occurrence. By default one hour.
/// - Returns: Returns the schedule that repeats daily.
public static func daily( // swiftlint:disable:this function_default_parameter_at_end
public static func daily(
calendar: Calendar = .current,
interval: Int = 1,
interval: Int = 1, // swiftlint:disable:this function_default_parameter_at_end
hour: Int,
minute: Int,
second: Int = 0,
second: Int = 0, // swiftlint:disable:this function_default_parameter_at_end
startingAt start: Date,
end: Calendar.RecurrenceRule.End = .never,
duration: Duration = .tillEndOfDay
Expand Down Expand Up @@ -308,13 +308,13 @@ extension Schedule {
/// - end: Optional end date of the schedule. Otherwise, it repeats indefinitely.
/// - duration: The duration of a single occurrence. By default one hour.
/// - Returns: Returns the schedule that repeats weekly.
public static func weekly( // swiftlint:disable:this function_default_parameter_at_end
public static func weekly(
calendar: Calendar = .current,
interval: Int = 1,
weekday: Locale.Weekday? = nil,
weekday: Locale.Weekday? = nil, // swiftlint:disable:this function_default_parameter_at_end
hour: Int,
minute: Int,
second: Int = 0,
second: Int = 0, // swiftlint:disable:this function_default_parameter_at_end
startingAt start: Date,
end: Calendar.RecurrenceRule.End = .never,
duration: Duration = .tillEndOfDay
Expand Down
23 changes: 23 additions & 0 deletions Sources/SpeziScheduler/Schedule/Weekday+CaseIterable.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//
// This source file is part of the Stanford Spezi open-source project
//
// SPDX-FileCopyrightText: 2024 Stanford University and the project authors (see CONTRIBUTORS.md)
//
// SPDX-License-Identifier: MIT
//

import Foundation


extension Locale.Weekday: @retroactive CaseIterable {
/// All cases that respects the first weekday of the current locale.
public static let allCases: [Locale.Weekday] = {
(Calendar.current.firstWeekday..<(Calendar.current.firstWeekday + 7))
.map { integer in
((integer - 1) % 7) + 1
}
.compactMap { ordinal in
Locale.Weekday(ordinal: ordinal)
}
}()
}
36 changes: 35 additions & 1 deletion Sources/SpeziScheduler/Schedule/Weekday+Ordinal.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ import Foundation


extension Locale.Weekday {
var ordinal: Int {
/// Retrieve the ordinal of the weekday.
public var ordinal: Int {
switch self {
case .sunday:
1
Expand All @@ -30,4 +31,37 @@ extension Locale.Weekday {
preconditionFailure("A new weekday appeared we don't know about: \(self)")
}
}

/// Initialize the weekday from it's ordinal representation.
/// - Parameter ordinal: The ordinal. A value between 1 and 7.
public init?(ordinal: Int) {
switch ordinal {
case 1:
self = .sunday
case 2:
self = .monday
case 3:
self = .tuesday
case 4:
self = .wednesday
case 5:
self = .thursday
case 6:
self = .friday
case 7:
self = .saturday
default:
return nil
}
}

/// Get the weekday from a date.
/// - Parameter date: The date.
public init(from date: Date) {
let weekdayOrdinal = Calendar.current.component(.weekday, from: date)
guard let weekday = Locale.Weekday(ordinal: weekdayOrdinal) else {
preconditionFailure("Failed to derive weekday from ordinal \(weekdayOrdinal)")
}
self = weekday
}
}
8 changes: 4 additions & 4 deletions Sources/SpeziScheduler/Scheduler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -219,11 +219,11 @@ public final class Scheduler {
/// - contextClosure: The closure that allows to customize the ``Task/Context`` that is stored with the task.
/// - Returns: Returns the latest version of the `task` and if the task was updated or created indicated by `didChange`.
@discardableResult
public func createOrUpdateTask( // swiftlint:disable:this function_default_parameter_at_end function_body_length
public func createOrUpdateTask( // swiftlint:disable:this function_body_length
id: String,
title: String.LocalizationValue,
instructions: String.LocalizationValue,
category: Task.Category? = nil,
category: Task.Category? = nil, // swiftlint:disable:this function_default_parameter_at_end
schedule: Schedule,
completionPolicy: AllowedCompletionPolicy = .sameDay,
scheduleNotifications: Bool = false,
Expand Down Expand Up @@ -593,11 +593,11 @@ extension Scheduler {
return try context.fetchCount(descriptor) > 0
}

private func queryTasks( // swiftlint:disable:this function_default_parameter_at_end
private func queryTasks(
with basePredicate: Predicate<Task>,
combineWith userPredicate: Predicate<Task>,
sortBy sortDescriptors: [SortDescriptor<Task>],
fetchLimit: Int? = nil,
fetchLimit: Int? = nil, // swiftlint:disable:this function_default_parameter_at_end
prefetchOutcomes: Bool
) throws -> [Task] {
var descriptor = FetchDescriptor<Task>(
Expand Down
8 changes: 4 additions & 4 deletions Sources/SpeziSchedulerMacros/SpeziSchedulerDiagnostic.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,10 @@ struct SpeziSchedulerDiagnostic: DiagnosticMessage {


extension Diagnostic {
init<S: SyntaxProtocol>( // swiftlint:disable:this function_default_parameter_at_end
init<S: SyntaxProtocol>(
syntax: S,
message: String,
domain: String = "SpeziScheduler",
domain: String = "SpeziScheduler", // swiftlint:disable:this function_default_parameter_at_end
id: SpeziSchedulerDiagnostic.ID,
severity: SwiftDiagnostics.DiagnosticSeverity = .error
) {
Expand All @@ -48,10 +48,10 @@ extension Diagnostic {


extension DiagnosticsError {
init<S: SyntaxProtocol>( // swiftlint:disable:this function_default_parameter_at_end
init<S: SyntaxProtocol>(
syntax: S,
message: String,
domain: String = "SpeziScheduler",
domain: String = "SpeziScheduler", // swiftlint:disable:this function_default_parameter_at_end
id: SpeziSchedulerDiagnostic.ID,
severity: SwiftDiagnostics.DiagnosticSeverity = .error
) {
Expand Down
Loading