Skip to content

Commit b4a4f3e

Browse files
committed
toggle duration of graph day/week/month, keep up to a month worth, and rev version to 0.3
1 parent 81b95f8 commit b4a4f3e

File tree

4 files changed

+72
-25
lines changed

4 files changed

+72
-25
lines changed

Keyjam.xcodeproj/project.pbxproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@
264264
"$(inherited)",
265265
"@executable_path/../Frameworks",
266266
);
267-
MARKETING_VERSION = 0.2;
267+
MARKETING_VERSION = 0.3;
268268
PRODUCT_BUNDLE_IDENTIFIER = com.mattorb.Keyjam;
269269
PRODUCT_NAME = "$(TARGET_NAME)";
270270
SWIFT_EMIT_LOC_STRINGS = YES;
@@ -291,7 +291,7 @@
291291
"$(inherited)",
292292
"@executable_path/../Frameworks",
293293
);
294-
MARKETING_VERSION = 0.2;
294+
MARKETING_VERSION = 0.3;
295295
PRODUCT_BUNDLE_IDENTIFIER = com.mattorb.Keyjam;
296296
PRODUCT_NAME = "$(TARGET_NAME)";
297297
SWIFT_EMIT_LOC_STRINGS = YES;

Keyjam/KeyjamMenuBar.swift

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ struct KeyjamMenuBar: Scene {
66
@Environment(StreakRepository.self) var keyCount
77
@Environment(StreakCoordinator.self) var coordinator
88

9+
@State private var selectedTimeScope: StreakChartTimeScope = .day
910
@State private var launchAtLogin = false
1011
@State private var newAppName: String = ""
1112
@AppStorage(Settings.trackedApps) private var trackedApps: [String] = []
@@ -26,7 +27,18 @@ struct KeyjamMenuBar: Scene {
2627
}
2728

2829
private var recentStreakEvents: [StreakEvent] {
29-
keyCount.getRecentStreakEvents()
30+
// Convert TimeScope to days for the repository method
31+
let days: Int
32+
switch selectedTimeScope {
33+
case .day:
34+
days = 1
35+
case .week:
36+
days = 7
37+
case .month:
38+
days = 30
39+
}
40+
41+
return keyCount.getRecentStreakEvents(days: days)
3042
}
3143

3244
private var streakStats: String {
@@ -80,12 +92,20 @@ struct KeyjamMenuBar: Scene {
8092
Text("Statistics")
8193
.font(.headline)
8294

83-
Text("Current key streak: \(keyCount.keyCount)")
95+
HStack {
96+
Text("Current key streak: \(keyCount.keyCount)")
97+
Spacer()
98+
if !recentStreakEvents.isEmpty {
99+
Text("Highest: \(recentStreakEvents.map { $0.streakCount }.max() ?? 0)")
100+
.foregroundColor(Color.teal)
101+
}
102+
}
103+
84104
Text(streakStats)
85105
.font(.caption)
86106
.foregroundColor(.secondary)
87107

88-
StreakChartView(streakEvents: recentStreakEvents)
108+
StreakChartView(streakEvents: recentStreakEvents, timeScope: $selectedTimeScope)
89109
.padding(.vertical, 5)
90110
}
91111
}

Keyjam/streak/StreakChartView.swift

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import SwiftUI
44
// MARK: - Main View
55
struct StreakChartView: View {
66
let streakEvents: [StreakEvent]
7+
@Binding var timeScope: StreakChartTimeScope
78
@State private var selectedEvent: StreakEvent?
89
@State private var hoverLocation: CGPoint?
910
@State private var chartSize: CGSize = .zero
@@ -30,9 +31,15 @@ struct StreakChartView: View {
3031
Spacer()
3132

3233
if !streakEvents.isEmpty {
33-
Text("Highest: \(maxStreakCount)")
34-
.font(.caption)
35-
.foregroundColor(Color.teal)
34+
Picker("", selection: $timeScope) {
35+
ForEach(StreakChartTimeScope.allCases) { scope in
36+
Text(scope.rawValue).tag(scope)
37+
}
38+
}
39+
.pickerStyle(.menu)
40+
.labelsHidden()
41+
.frame(width: 70)
42+
.controlSize(.small)
3643
}
3744
}
3845
}
@@ -401,19 +408,25 @@ enum TrendDirection {
401408
VStack(spacing: 20) {
402409
Text("Upward Trend")
403410
.font(.headline)
404-
StreakChartView(streakEvents: createSampleData(startValue: 10, endValue: 50, count: 10, now: Date(), calendar: Calendar.current))
405-
.padding()
406-
.background(Color.primary.opacity(0.1))
407-
.cornerRadius(8)
408-
.shadow(radius: 2)
411+
StreakChartView(
412+
streakEvents: createSampleData(startValue: 10, endValue: 50, count: 10, now: Date(), calendar: Calendar.current),
413+
timeScope: .constant(.day)
414+
)
415+
.padding()
416+
.background(Color.primary.opacity(0.1))
417+
.cornerRadius(8)
418+
.shadow(radius: 2)
409419

410420
Text("Downward Trend")
411421
.font(.headline)
412-
StreakChartView(streakEvents: createSampleData(startValue: 50, endValue: 10, count: 10, now: Date(), calendar: Calendar.current))
413-
.padding()
414-
.background(Color.primary.opacity(0.1))
415-
.cornerRadius(8)
416-
.shadow(radius: 2)
422+
StreakChartView(
423+
streakEvents: createSampleData(startValue: 50, endValue: 10, count: 10, now: Date(), calendar: Calendar.current),
424+
timeScope: .constant(.day)
425+
)
426+
.padding()
427+
.background(Color.primary.opacity(0.1))
428+
.cornerRadius(8)
429+
.shadow(radius: 2)
417430
}
418431
.padding()
419432
}
@@ -441,3 +454,11 @@ private func createSampleData(
441454

442455
return sampleData.sorted { $0.timestamp < $1.timestamp }
443456
}
457+
458+
enum StreakChartTimeScope: String, CaseIterable, Identifiable {
459+
case day = "Day"
460+
case week = "Week"
461+
case month = "Month"
462+
463+
var id: String { rawValue }
464+
}

Keyjam/streak/StreakRepository.swift

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ final class StreakRepository {
66
private(set) var mouseBreak: Int = 0
77
private(set) var streakEvents: [StreakEvent] = []
88

9-
private let maxStoredEvents = 100
9+
// Maximum age of stored events (one month)
10+
private let maxEventAge: TimeInterval = 30 * 24 * 60 * 60 // 30 days in seconds
1011

1112
init() {
1213
loadStreakEvents()
@@ -36,24 +37,29 @@ final class StreakRepository {
3637
let event = StreakEvent(streakCount: count)
3738
streakEvents.append(event)
3839

39-
// Limit the number of stored events
40-
if streakEvents.count > maxStoredEvents {
41-
streakEvents.sort { $0.timestamp > $1.timestamp } // Sort by timestamp descending
42-
streakEvents = Array(streakEvents.prefix(maxStoredEvents))
43-
}
40+
// Clean up old events
41+
removeExpiredEvents()
4442

4543
saveStreakEvents()
4644
}
4745

46+
private func removeExpiredEvents() {
47+
let cutoffDate = Date().addingTimeInterval(-maxEventAge)
48+
streakEvents = streakEvents.filter { $0.timestamp >= cutoffDate }
49+
}
50+
4851
private func loadStreakEvents() {
4952
streakEvents = FileManager.loadStreakEvents()
53+
54+
// Remove any expired events during load
55+
removeExpiredEvents()
5056
}
5157

5258
private func saveStreakEvents() {
5359
FileManager.saveStreakEvents(streakEvents)
5460
}
5561

56-
// Returns streak events for the last 7 days
62+
// Returns streak events for the specified time period
5763
func getRecentStreakEvents(days: Int = 7) -> [StreakEvent] {
5864
let calendar = Calendar.current
5965
let startDate = calendar.date(byAdding: .day, value: -days, to: Date()) ?? Date()

0 commit comments

Comments
 (0)