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

Allow days to be sorted with today at the top #94

Merged
merged 1 commit into from
Apr 20, 2024
Merged
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
33 changes: 27 additions & 6 deletions Tickmate/Tickmate/Controllers/TrackController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -201,18 +201,39 @@ class TrackController: NSObject, ObservableObject {
return (weekday, dateFormatter.string(from: date))
}

func weekend(day: Int) -> Bool {
func isWeekEnd(day: Int) -> Bool {
// The Swift % operator doesn't calculate
// the modulo from negative numbers,
// so we're adding 7 and %ing again.
(weekday - day % 7 + 7) % 7 + 1 == weekStartDay
}

private func isWeekStart(day: Int) -> Bool {
(weekday - day % 7 + 6) % 7 + 1 == weekStartDay
}

func insets(day: Int) -> Edge.Set? {
weekend(day: day)
? .bottom
: (weekday - day % 7 + 6) % 7 + 1 == weekStartDay
? .top : nil
let todayAtTop = UserDefaults(suiteName: groupID)?.bool(forKey: Defaults.todayAtTop.rawValue) ?? false
var after: Edge.Set { todayAtTop ? .top : .bottom }
var before: Edge.Set { todayAtTop ? .bottom : .top }

if isWeekEnd(day: day) {
return after
} else if isWeekStart(day: day) {
return before
} else {
return .none
}
}

func shouldShowSeparatorBelow(day: Int) -> Bool {
let todayAtTop = UserDefaults(suiteName: groupID)?.bool(forKey: Defaults.todayAtTop.rawValue) ?? false

if todayAtTop {
return isWeekStart(day: day)
} else {
return isWeekEnd(day: day)
}
}

//MARK: Track CRUD
Expand Down Expand Up @@ -300,7 +321,7 @@ class TrackController: NSObject, ObservableObject {
}
}

// TODO: Update this to instead save _now_, but prevent a second save from happening for 5 seconds (or whatever interval)
// TODO: Update this and the below to instead save _now_, but prevent a second save from happening for 5 seconds (or whatever interval)
/// Schedule a Core Data save on the current view context.
///
/// Call this function when you want to save a small change when other small changes may happen soon after.
Expand Down
3 changes: 2 additions & 1 deletion Tickmate/Tickmate/Model/Defaults.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Defaults.swift
// Tickmate
//
// Created by Isaac Lyons on 3/9/21.
// Created by Elaine Lyons on 3/9/21.
//

import Foundation
Expand All @@ -23,4 +23,5 @@ enum Defaults: String {
case appGroupDatabaseMigration // Bool
case userDefaultsMigration // Bool App Group
case lastUpdateTime // String App Group
case todayAtTop // Bool App Group
}
2 changes: 1 addition & 1 deletion Tickmate/Tickmate/TickmateApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// TickmateApp.swift
// Tickmate
//
// Created by Isaac Lyons on 2/19/21.
// Created by Elaine Lyons on 2/19/21.
//

import SwiftUI
Expand Down
15 changes: 15 additions & 0 deletions Tickmate/Tickmate/Views/SettingsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ struct SettingsView: View {
@AppStorage(Defaults.weekStartDay.rawValue, store: UserDefaults(suiteName: groupID))
private var weekStartDay = 2

@AppStorage(Defaults.todayAtTop.rawValue, store: UserDefaults(suiteName: groupID))
private var todayAtTop = false

@AppStorage(Defaults.weekSeparatorSpaces.rawValue) private var weekSeparatorSpaces: Bool = true
@AppStorage(Defaults.weekSeparatorLines.rawValue) private var weekSeparatorLines: Bool = true
@AppStorage(Defaults.relativeDates.rawValue) private var relativeDates = true
Expand Down Expand Up @@ -50,6 +53,15 @@ struct SettingsView: View {
}
}

Section {
Picker("Put today at the", selection: $todayAtTop) {
Text("top")
.tag(true)
Text("bottom")
.tag(false)
}
}

Section {
Toggle(isOn: $relativeDates) {
TextWithCaption(text: "Use relative dates", caption: "Today, Yesterday")
Expand Down Expand Up @@ -167,6 +179,9 @@ struct SettingsView: View {
}
.onChange(of: customDayStart, perform: updateCustomDayStart)
.onChange(of: timeOffset, perform: updateCustomDayStart)
.onChange(of: todayAtTop) { _ in
trackController.scheduleTimelineRefresh()
}
.onChange(of: weekStartDay) { value in
trackController.weekStartDay = value
}
Expand Down
6 changes: 3 additions & 3 deletions Tickmate/Tickmate/Views/TickView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ struct DayRow<C: RandomAccessCollection>: View where C.Element == Track {
}

@ViewBuilder
private var backgroud: some View {
if lines && trackController.weekend(day: day) {
private var background: some View {
if lines && trackController.shouldShowSeparatorBelow(day: day) {
VStack {
Spacer()
Capsule()
Expand Down Expand Up @@ -70,7 +70,7 @@ struct DayRow<C: RandomAccessCollection>: View where C.Element == Track {
.opacity(0)
}
}
.listRowBackground(backgroud)
.listRowBackground(background)
.id(day)
}
}
Expand Down
29 changes: 19 additions & 10 deletions Tickmate/Tickmate/Views/TicksView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ struct TicksView: View {
fetchRequest.wrappedValue
}

@AppStorage(Defaults.todayAtTop.rawValue, store: UserDefaults(suiteName: groupID))
private var todayAtTop = false
@AppStorage(Defaults.weekSeparatorLines.rawValue) private var weekSeparatorLines: Bool = true
@AppStorage(Defaults.weekSeparatorSpaces.rawValue) private var weekSeparatorSpaces: Bool = true

Expand Down Expand Up @@ -122,24 +124,31 @@ struct TicksView: View {

ScrollViewReader { proxy in
List {
Button("Go to bottom") {
proxy.scrollTo(0)
if !todayAtTop {
Button("Go to bottom") {
proxy.scrollTo(0)
}
}

ForEach(0..<365) { dayComplement in
DayRow(364 - dayComplement, tracks: tracks, spaces: weekSeparatorSpaces, lines: weekSeparatorLines)
.listRowInsets(.init(top: 4, leading: 0, bottom: 4, trailing: 0))
#if os(iOS)
.padding(.horizontal)
#endif
ForEach(0..<365) { row in
DayRow(
todayAtTop ? row : 364 - row,
tracks: tracks,
spaces: weekSeparatorSpaces,
lines: weekSeparatorLines
)
.listRowInsets(.init(top: 4, leading: 0, bottom: 4, trailing: 0))
#if os(iOS)
.padding(.horizontal)
#endif
}
}
.listStyle(PlainListStyle())
.introspect(.list, on: .iOS(.v14, .v15)) { tableView in
tableView.scrollsToTop = false
tableView.scrollsToTop = todayAtTop
}
.introspect(.list, on: .iOS(.v16, .v17)) { collectionView in
collectionView.scrollsToTop = false
collectionView.scrollsToTop = todayAtTop
}
.padding(0)
.onAppear {
Expand Down
21 changes: 16 additions & 5 deletions Tickmate/TicksWidget/TicksWidget.swift
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,9 @@ struct TicksWidgetEntryView : View {
@Environment(\.colorScheme) private var colorScheme
@Environment(\.widgetFamily) private var widgetFamily

@AppStorage(Defaults.todayAtTop.rawValue, store: UserDefaults(suiteName: groupID))
private var todayAtTop = false

//MARK: Properties

var entry: Provider.Entry
Expand Down Expand Up @@ -206,6 +209,14 @@ struct TicksWidgetEntryView : View {
: min(entry.configuration.numDays?.intValue ?? defaultNumDays, maxNumDays)
}

struct Row: Identifiable {
var id: Int { value }
var value: Int
}
var rows: [Row] {
(0..<numDays).map(Row.init(value:))
}

var defaultNumTracks: Int {
switch widgetFamily {
case .systemSmall:
Expand Down Expand Up @@ -273,13 +284,13 @@ struct TicksWidgetEntryView : View {
Divider()
}

ForEach(0..<numDays) { dayComplement in
let day = numDays - 1 - dayComplement
ForEach(rows) { row in
let day = todayAtTop ? row.value : (numDays - 1 - row.value)
DayRow(day, tracks: tracks, spaces: false, lines: false, widget: true, compact: compact)

if dayComplement < numDays - 1 {
if entry.configuration.weekSeparators?.boolValue ?? true
&& entry.trackController.weekend(day: day) {
if row.value < numDays - 1 {
if entry.configuration.weekSeparators?.boolValue ?? true,
entry.trackController.shouldShowSeparatorBelow(day: day) {
Capsule()
.foregroundColor(.gray)
.frame(height: 2)
Expand Down