Skip to content

Commit 6ee234e

Browse files
committed
widget ui fixes
1 parent b8ed823 commit 6ee234e

File tree

5 files changed

+117
-126
lines changed

5 files changed

+117
-126
lines changed
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"images" : [
3+
{
4+
"filename" : "taskwarrior.png",
5+
"idiom" : "universal",
6+
"scale" : "1x"
7+
},
8+
{
9+
"idiom" : "universal",
10+
"scale" : "2x"
11+
},
12+
{
13+
"idiom" : "universal",
14+
"scale" : "3x"
15+
}
16+
],
17+
"info" : {
18+
"author" : "xcode",
19+
"version" : 1
20+
}
21+
}
30.6 KB
Loading

ios/TaskWarriorWidgets/TaskWarriorWidgets.swift

Lines changed: 86 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,8 @@ struct TaskProvider: AppIntentTimelineProvider {
7676
struct TaskWidgetEntryView: View {
7777
var entry: TaskProvider.Entry
7878
@Environment(\.widgetFamily) var family
79-
80-
// Parse tasks from JSON
79+
80+
// 1. DATA PARSING
8181
var parsedTasks: [Task] {
8282
guard let data = entry.tasks.data(using: .utf8) else { return [] }
8383
do {
@@ -97,7 +97,6 @@ struct TaskWidgetEntryView: View {
9797
return []
9898
}
9999

100-
// Sort tasks by priority: H > M > L > None
101100
var sortedTasks: [Task] {
102101
return parsedTasks.sorted { task1, task2 in
103102
let priorityOrder = ["H": 0, "M": 1, "L": 2, "N": 3]
@@ -111,179 +110,150 @@ struct TaskWidgetEntryView: View {
111110
entry.themeMode == "dark"
112111
}
113112

113+
// 2. MAIN BODY LAYOUT
114114
var body: some View {
115115
ZStack {
116+
// Background Layer
116117
(isDarkMode ? Color.black : Color(white: 0.95))
117118
.ignoresSafeArea()
118119

119-
VStack(alignment: .leading, spacing: 8) {
120+
// Content Layer
121+
VStack(spacing: 0) {
122+
123+
// --- TOP BAR (Pinned) ---
120124
headerView
125+
.padding(.top, 12)
126+
.padding(.horizontal, 16)
127+
.padding(.bottom, 8) // Slightly tighter to fit content
121128

129+
// --- LIST AREA ---
122130
if parsedTasks.isEmpty {
123131
emptyStateView
124132
} else {
125-
switch family {
126-
case .systemSmall:
127-
smallTaskList
128-
case .systemMedium:
129-
mediumTaskList
130-
case .systemLarge:
131-
largeTaskList
132-
default:
133-
mediumTaskList
133+
VStack(alignment: .leading, spacing: 0) {
134+
switch family {
135+
case .systemMedium:
136+
mediumTaskList
137+
case .systemLarge:
138+
largeTaskList
139+
default:
140+
mediumTaskList
141+
}
134142
}
143+
.padding(.horizontal, 12)
135144
}
145+
146+
// --- BOTTOM SPACER ---
147+
Spacer()
136148
}
137-
.padding(family == .systemLarge ? 12 : 10)
138149
}
139150
.colorScheme(isDarkMode ? .dark : .light)
140151
}
141152

153+
// 3. SUBVIEWS
154+
142155
var headerView: some View {
143156
HStack {
144-
HStack(spacing: 4) {
145-
Image(systemName: "checkmark.circle.fill")
146-
.foregroundColor(.blue)
147-
.imageScale(family == .systemSmall ? .small : .medium)
148-
Text("Taskwarrior")
149-
.font(family == .systemSmall ? .caption.bold() : .headline)
157+
HStack(spacing: 6) {
158+
Image("taskwarrior")
159+
.resizable()
160+
.aspectRatio(contentMode: .fit)
161+
.frame(width: 30, height: 30)
162+
163+
150164
}
151165
Spacer()
152-
Image(systemName: "plus.circle.fill")
153-
.foregroundColor(.blue)
154-
.imageScale(family == .systemSmall ? .medium : .large)
155-
.widgetURL(URL(string: "taskwarrior://addClicked"))
166+
Text("Taskwarrior")
167+
.font(.headline)
168+
Spacer()
169+
170+
// Add Button
171+
Link(destination: URL(string: "taskwarrior://addclicked")!) {
172+
Image(systemName: "plus.circle.fill")
173+
.foregroundColor(.blue)
174+
.font(.system(size: 26))
175+
}
156176
}
157-
.padding(.bottom, 8)
158177
}
159178

160179
var emptyStateView: some View {
161-
VStack(spacing: 4) {
180+
VStack(spacing: 6) {
181+
Spacer()
162182
Image(systemName: "checkmark.circle")
163-
.font(.title2)
164-
.foregroundColor(.secondary)
165-
Text("No tasks available")
183+
.font(.largeTitle)
184+
.foregroundColor(.secondary.opacity(0.5))
185+
Text("No tasks pending")
166186
.font(.caption)
167187
.foregroundColor(.secondary)
168-
.multilineTextAlignment(.center)
188+
Spacer()
169189
}
170-
.frame(maxWidth: .infinity, maxHeight: .infinity)
171190
}
172191

173-
// Small widget list with deeplinks (shows 3 tasks)
174-
var smallTaskList: some View {
175-
VStack(spacing: 4) {
176-
ForEach(Array(sortedTasks.prefix(3))) { task in
177-
smallTaskRow(task: task)
178-
.widgetURL(URL(string: "taskwarrior://cardClicked?uuid=\(task.uuid)"))
179-
}
180-
if sortedTasks.count > 3 {
181-
Text("+\(sortedTasks.count - 3) more")
182-
.font(.caption2)
183-
.foregroundColor(.secondary)
184-
.frame(maxWidth: .infinity, alignment: .center)
185-
}
186-
}
187-
}
192+
// -- List Variations --
188193

189-
// Medium widget
194+
// MEDIUM: With urgency text removed, we can fit 3 items comfortably
190195
var mediumTaskList: some View {
191-
VStack(spacing: 4) {
192-
ForEach(Array(sortedTasks.prefix(3))) { task in
193-
mediumTaskRow(task: task)
194-
.widgetURL(URL(string: "taskwarrior://cardClicked?uuid=\(task.uuid)"))
196+
VStack(spacing: 4) { // Compact spacing
197+
ForEach(Array(sortedTasks.prefix(2))) { task in
198+
taskRow(task: task)
199+
.widgetURL(URL(string: "taskwarrior://cardclicked?uuid=\(task.uuid)"))
195200
}
196201

197-
if sortedTasks.count > 3 {
198-
Text("+\(sortedTasks.count - 3) more tasks")
202+
if sortedTasks.count > 2 {
203+
Text("+\(sortedTasks.count - 2) more")
199204
.font(.caption2)
200205
.foregroundColor(.secondary)
201206
.frame(maxWidth: .infinity, alignment: .center)
202-
.padding(.top, 2)
207+
.padding(.trailing, 4)
203208
}
204209
}
205210
}
206211

207-
// Large widget
212+
// LARGE: With urgency text removed, we can fit 6 items
208213
var largeTaskList: some View {
209-
VStack(spacing: 6) {
210-
// Display only top 4 tasks by priority
211-
ForEach(Array(sortedTasks.prefix(4))) { task in
212-
largeTaskRow(task: task)
213-
.widgetURL(URL(string: "taskwarrior://cardClicked?uuid=\(task.uuid)"))
214+
VStack(spacing: 7) {
215+
ForEach(Array(sortedTasks.prefix(6))) { task in
216+
taskRow(task: task)
217+
.widgetURL(URL(string: "taskwarrior://cardclicked?uuid=\(task.uuid)"))
214218
}
215219

216-
if sortedTasks.count > 4 {
217-
Text("+\(sortedTasks.count - 4) more tasks")
220+
if sortedTasks.count > 6 {
221+
Text("+\(sortedTasks.count - 6) more tasks")
218222
.font(.caption)
219223
.foregroundColor(.secondary)
220224
.frame(maxWidth: .infinity, alignment: .center)
221-
.padding(.top, 4)
225+
.padding(.top, 2)
222226
}
223227
}
224228
}
225229

226-
func smallTaskRow(task: Task) -> some View {
227-
HStack(spacing: 6) {
228-
Circle()
229-
.fill(task.priorityColor)
230-
.frame(width: 8, height: 8)
231-
Text(task.description)
232-
.font(.caption2)
233-
.lineLimit(1)
234-
.truncationMode(.tail)
235-
Spacer()
236-
}
237-
.padding(.vertical, 4)
238-
.padding(.horizontal, 6)
239-
.background(
240-
RoundedRectangle(cornerRadius: 4)
241-
.fill(Color(UIColor.secondarySystemBackground))
242-
)
243-
}
230+
// -- Row Designs --
244231

245-
func mediumTaskRow(task: Task) -> some View {
246-
HStack(spacing: 8) {
247-
Circle()
232+
// Unified Row Design (Clean, Single Line)
233+
func taskRow(task: Task) -> some View {
234+
HStack(spacing: 10) {
235+
// Colored Bar
236+
Capsule()
248237
.fill(task.priorityColor)
249-
.frame(width: 8, height: 8)
238+
.frame(width: 10, height: 10) // Smaller height since text is single line
239+
240+
// Description (Single line, centered vertically)
250241
Text(task.description)
251-
.font(.caption)
242+
.font(.subheadline)
243+
.fontWeight(.medium)
252244
.lineLimit(1)
253-
.truncationMode(.tail)
254-
Spacer()
255-
}
256-
.padding(.vertical, 5)
257-
.padding(.horizontal, 8)
258-
.background(
259-
RoundedRectangle(cornerRadius: 6)
260-
.fill(Color(UIColor.secondarySystemBackground))
261-
)
262-
}
263-
264-
func largeTaskRow(task: Task) -> some View {
265-
HStack(spacing: 10) {
266-
Circle()
267-
.fill(task.priorityColor)
268-
.frame(width: 10, height: 10)
269-
VStack(alignment: .leading, spacing: 2) {
270-
Text(task.description)
271-
.font(.subheadline)
272-
.lineLimit(1)
273-
.truncationMode(.tail)
274-
Text(task.urgency)
275-
.font(.caption2)
276-
.foregroundColor(.secondary)
277-
}
245+
.foregroundColor(.primary)
246+
278247
Spacer()
279248
}
280-
.padding(.vertical, 6)
281-
.padding(.horizontal, 8)
249+
// Compact Padding to fit more items
250+
.padding(.vertical, 8)
251+
.padding(.horizontal, 12)
282252
.background(
283-
RoundedRectangle(cornerRadius: 8)
253+
RoundedRectangle(cornerRadius: 12)
284254
.fill(Color(UIColor.secondarySystemBackground))
285255
)
286-
.widgetURL(URL(string: "taskwarrior://cardClicked?uuid=\(task.uuid)"))
256+
.fixedSize(horizontal: false, vertical: true)
287257
}
288258
}
289259

@@ -296,7 +266,7 @@ struct TasksWidget: Widget {
296266
}
297267
.configurationDisplayName("Tasks")
298268
.description("Shows your pending tasks")
299-
.supportedFamilies([.systemSmall, .systemMedium, .systemLarge])
269+
.supportedFamilies([.systemMedium, .systemLarge])
300270
.contentMarginsDisabled()
301271
}
302272
}
@@ -310,10 +280,4 @@ struct TasksWidget: Widget {
310280
themeMode: "light",
311281
configuration: ConfigurationAppIntent()
312282
)
313-
TaskWidgetEntry(
314-
date: .now,
315-
tasks: "[{\"description\":\"Critical bug fix\",\"urgency\":\"urgency: 6.5\",\"uuid\":\"abc\",\"priority\":\"H\"}, {\"description\":\"Update docs\",\"urgency\":\"urgency: 2.8\",\"uuid\":\"def\",\"priority\":\"M\"}, {\"description\":\"Review PR\",\"urgency\":\"urgency: 4.5\",\"uuid\":\"ghi\",\"priority\":\"H\"}, {\"description\":\"Fix typos\",\"urgency\":\"urgency: 1.2\",\"uuid\":\"jkl\",\"priority\":\"L\"}, {\"description\":\"Add tests\",\"urgency\":\"urgency: 3.8\",\"uuid\":\"mno\",\"priority\":\"M\"}, {\"description\":\"Refactor code\",\"urgency\":\"urgency: 2.5\",\"uuid\":\"pqr\",\"priority\":\"N\"}]",
316-
themeMode: "dark",
317-
configuration: ConfigurationAppIntent()
318-
)
319283
}

lib/app/modules/home/controllers/home_controller.dart

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ class HomeController extends GetxController {
8787
taskdb.open();
8888
getUniqueProjects();
8989
_loadTaskChampion();
90-
if (Platform.isAndroid) {
90+
if (Platform.isAndroid || Platform.isIOS) {
9191
handleHomeWidgetClicked();
9292
}
9393
fetchTasksFromDB();
@@ -102,9 +102,9 @@ class HomeController extends GetxController {
102102
selectedSort,
103103
selectedTags,
104104
tasks,
105-
tasksFromReplica
105+
tasksFromReplica,
106106
], (_) {
107-
if (Platform.isAndroid|| Platform.isIOS) {
107+
if (Platform.isAndroid || Platform.isIOS) {
108108
WidgetController widgetController = Get.put(WidgetController());
109109
widgetController.fetchAllData();
110110

@@ -116,7 +116,7 @@ class HomeController extends GetxController {
116116
"TW3") {
117117
refreshTaskWithNewProfile();
118118
}
119-
if (Platform.isAndroid) {
119+
if (Platform.isAndroid || Platform.isIOS) {
120120
WidgetController widgetController = Get.put(WidgetController());
121121
widgetController.fetchAllData();
122122
widgetController.updateWidget();

lib/app/modules/home/views/add_task_bottom_sheet_new.dart

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,12 @@ class AddTaskBottomSheet extends StatelessWidget {
363363
}
364364

365365
void onSaveButtonClicked(BuildContext context) async {
366+
if (Platform.isAndroid || Platform.isIOS) {
367+
WidgetController widgetController = Get.put(WidgetController());
368+
widgetController.fetchAllData();
369+
370+
widgetController.update();
371+
}
366372
if (homeController.formKey.currentState!.validate()) {
367373
try {
368374
var task = taskParser(homeController.namecontroller.text)

0 commit comments

Comments
 (0)