| @@ -9,6 +9,7 @@ struct ContributionGraphEntry: TimelineEntry { |
| 9 | |
9 | |
| 10 | enum State { |
10 | enum State { |
| 11 | case placeholder |
11 | case placeholder |
| |
12 | case disabled |
| 12 | case unavailable |
13 | case unavailable |
| 13 | case empty |
14 | case empty |
| 14 | case indexing |
15 | case indexing |
| @@ -41,6 +42,10 @@ struct ContributionGraphTimelineProvider: TimelineProvider { |
| 41 | } |
42 | } |
| 42 | |
43 | |
| 43 | private func loadEntry() async -> ContributionGraphEntry { |
44 | private func loadEntry() async -> ContributionGraphEntry { |
| |
45 | guard ContributionWidgetContextStore.isEnabled() else { |
| |
46 | return ContributionGraphEntry(date: .now, actor: nil, state: .disabled, weeks: []) |
| |
47 | } |
| |
48 | |
| 44 | guard let actor = ContributionWidgetContextStore.loadActor(), !actor.isEmpty else { |
49 | guard let actor = ContributionWidgetContextStore.loadActor(), !actor.isEmpty else { |
| 45 | return ContributionGraphEntry(date: .now, actor: nil, state: .unavailable, weeks: []) |
50 | return ContributionGraphEntry(date: .now, actor: nil, state: .unavailable, weeks: []) |
| 46 | } |
51 | } |
| @@ -91,6 +96,29 @@ private struct ContributionGraphWidgetView: View { |
| 91 | @Environment(\.widgetFamily) private var family |
96 | @Environment(\.widgetFamily) private var family |
| 92 | |
97 | |
| 93 | var body: some View { |
98 | var body: some View { |
| |
99 | Group { |
| |
100 | switch entry.state { |
| |
101 | case .disabled: |
| |
102 | messageView( |
| |
103 | title: "Contributions Disabled", |
| |
104 | detail: "Enable contribution graphs in Hutch settings to use this widget." |
| |
105 | ) |
| |
106 | case .unavailable: |
| |
107 | messageView( |
| |
108 | title: "Open Hutch", |
| |
109 | detail: "Sign in and open your profile to load contribution data." |
| |
110 | ) |
| |
111 | default: |
| |
112 | graphView |
| |
113 | } |
| |
114 | } |
| |
115 | .widgetURL(URL(string: "hutch://home")) |
| |
116 | .containerBackground(for: .widget) { |
| |
117 | Color(.systemBackground) |
| |
118 | } |
| |
119 | } |
| |
120 | |
| |
121 | private var graphView: some View { |
| 94 | GeometryReader { geometry in |
122 | GeometryReader { geometry in |
| 95 | let cellSize = ContributionGraphSizing.baseCellSize(availableHeight: geometry.size.height) |
123 | let cellSize = ContributionGraphSizing.baseCellSize(availableHeight: geometry.size.height) |
| 96 | let layout = ContributionGraphSizing.layout(availableSize: geometry.size, cellSize: cellSize) |
124 | let layout = ContributionGraphSizing.layout(availableSize: geometry.size, cellSize: cellSize) |
| @@ -108,17 +136,27 @@ private struct ContributionGraphWidgetView: View { |
| 108 | .frame(width: actualSize.width, height: actualSize.height) |
136 | .frame(width: actualSize.width, height: actualSize.height) |
| 109 | .frame(maxWidth: .infinity, maxHeight: .infinity) |
137 | .frame(maxWidth: .infinity, maxHeight: .infinity) |
| 110 | } |
138 | } |
| 111 | .widgetURL(URL(string: "hutch://home")) |
139 | } |
| 112 | .containerBackground(for: .widget) { |
140 | |
| 113 | Color(.systemBackground) |
141 | private func messageView(title: String, detail: String) -> some View { |
| |
142 | VStack(spacing: 6) { |
| |
143 | Text(title) |
| |
144 | .font(family == .systemSmall ? .headline : .title3.weight(.semibold)) |
| |
145 | .multilineTextAlignment(.center) |
| |
146 | Text(detail) |
| |
147 | .font(.caption) |
| |
148 | .foregroundStyle(.secondary) |
| |
149 | .multilineTextAlignment(.center) |
| 114 | } |
150 | } |
| |
151 | .padding() |
| |
152 | .frame(maxWidth: .infinity, maxHeight: .infinity) |
| 115 | } |
153 | } |
| 116 | |
154 | |
| 117 | private func displayedWeeks(columnCount: Int) -> [ContributionGraphWeek] { |
155 | private func displayedWeeks(columnCount: Int) -> [ContributionGraphWeek] { |
| 118 | var baseWeeks = switch entry.state { |
156 | var baseWeeks = switch entry.state { |
| 119 | case .populated, .indexing, .empty: |
157 | case .populated, .indexing, .empty: |
| 120 | entry.weeks |
158 | entry.weeks |
| 121 | case .placeholder, .unavailable: |
159 | case .placeholder, .disabled, .unavailable: |
| 122 | ContributionGraphSampleData.placeholderWeeks |
160 | ContributionGraphSampleData.placeholderWeeks |
| 123 | } |
161 | } |
| 124 | |
162 | |