Replica add-task silently drops due and wait dates (DateTime.toString is not RFC3339)
评估
- 难度
- 3/5
- 预计耗时
- 1-2 天
- 新手友好度
- 78/100
- Issue 类型
- 缺陷
- 描述清晰度
- 描述清楚
- 活跃度
- 活跃
调研方向
Start with AddTaskBottomSheet.onSaveButtonClickedForReplica in lib/app/modules/home/views/add_task_bottom_sheet_new.dart and Replica.addTaskToReplica in lib/app/v3/champion/replica.dart, then inspect parse_datetime in rust/src/api.rs. Run the relevant Dart and Rust tests available in the repository; done means replica-created tasks retain the selected due and wait timestamps in RFC3339-compatible form.
由索引模型根据 Issue 内容生成。
描述
Description
On the TaskChampion / replica path, creating a task with a due or wait date from the Add Task sheet reports success, but the date is not stored.
The add sheet puts a Dart DateTime into the replica map. Replica.addTaskToReplica then calls .toString() on that value. Dart’s DateTime.toString() uses a space (2026-10-03 12:00:00.000Z). The Rust FFI parse_datetime only accepts RFC3339 (2026-10-03T12:00:00.000Z). Parse failure becomes None, and set_due / set_wait clear the field. The write still succeeds, so the UI shows “task added”.
The edit path already formats with toIso8601String() (which includes T), so dates set on the detail screen survive. Only create is wrong.
This is source-confirmed on main (90700d4). I could not run the Flutter app in this environment (no Flutter SDK).
Steps to reproduce
- Enable TaskChampion replica mode (
settings_taskr_repl). - Open Add Task.
- Enter a description and pick a Due (and/or Wait) date/time.
- Save. Confirm the success snackbar.
- Open the new task (or list it after refresh).
Expected behavior
The due/wait timestamp chosen in the add sheet is stored on the replica task, same as when the same date is set later on the edit screen.
Actual behavior
The task is created without due / wait. The add sheet still reports success.
Technical analysis
Create path
AddTaskBottomSheet.onSaveButtonClickedForReplica (lib/app/modules/home/views/add_task_bottom_sheet_new.dart) passes:
due: getDueDate(homeController.selectedDates)?.toUtc(),
wait: getWaitDate(homeController.selectedDates)?.toUtc(),
Replica.addTaskToReplica (lib/app/v3/champion/replica.dart) stringifies every attribute with:
map[attr] = newTask[attr].toString();
For a UTC DateTime that is 2026-10-03 12:00:00.000Z (space, not T).
FFI
parse_datetime in rust/src/api.rs:
fn parse_datetime(input: &str) -> Option<DateTime<Utc>> {
if input.trim().is_empty() {
return None;
}
input.parse::<DateTime<Utc>>().ok()
}
Empty or unparsable input → None. add_task then does t.set_due(parse_datetime(&value), …) with no error if parse fails. Rust unit fixtures correctly use 2026-09-01T09:00:00Z(withT`), so they never catch this.
Edit path (works)
TaskcDetailsController.saveTask converts with parsed.toUtc().toIso8601String() before modifyTaskInReplica. That string still goes through .toString(), but it is already RFC3339.
Impact
Users on the replica / TaskChampion path (the GSoC v3 default) lose due and wait dates at creation. Overdue highlighting, wait filtering, and sync to other Taskwarrior clients all miss those dates until the user re-enters them on the detail screen. The success snackbar hides the failure.
Possible fix
- In
addTaskToReplica(and anywhere else aDateTimeis put on the map), sendtoUtc().toIso8601String()instead oftoString(). - Optionally make
parse_datetimereject unparsable non-empty strings instead of treating them as “no date”, so a bad format cannot succeed silently. - Add a regression: add a replica task with a due string in Dart
DateTime.toString()form and assert it is stored (or that the write is refused).
Environment
- Repository: CCExtractor/taskwarrior-flutter
- Branch: main (
90700d4f08a58bcaf7e5804352a7bd565ed7ddd8) - App version in pubspec: 3.0.0+3
- Dart SDK constraint:
>=3.0.5 <4.0.0 - TaskChampion FFI:
rust/src/api.rs(taskchampion2.0.3) - Flutter app not run locally (SDK not on PATH)
- 主要语言
- Dart
- 星标
- 244
- 派生
- 180
- 平均合并
- 20 分钟
- 30 天内合并 PR
- 3
环境准备
- 没有 Dockerfile 或 Docker Compose 文件
- 有 Pull Request 模板
- 阅读贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
CCExtractor/taskwarrior-flutter 的其他 Issue
-
Fix misaligned text "Select the directory" in settings tile可能重新可做 关联的 PR 已关闭且未合并。 未关闭bug
难度 2/5 1-3 小时 新手友好度 68/100
CCExtractor/taskwarrior-flutter#639 · 2 条评论 ·
-
bug
难度 1/5 1 小时以内 新手友好度 85/100
-
Drawer should close automatically when navigating to a new screen可能重新可做 关联的 PR 已关闭且未合并。 未关闭bug
难度 2/5 1-3 小时 新手友好度 68/100
-
Sensitive Credentials Stored in Plain Text Files Without Encryption可能重新可做 @sahu-virendra-1908 于 192 天前认领,目前没有进行中的 PR。 未关闭bug
难度 5/5 一周以上 新手友好度 45/100
CCExtractor/taskwarrior-flutter#645 · 1 条评论 ·
-
Data Inconsistency When Editing Task (Missing Transaction)可能重新可做 @aryanorastar 于 52 天前认领,目前没有进行中的 PR。 未关闭bug
难度 4/5 3-5 天 新手友好度 52/100
CCExtractor/taskwarrior-flutter#643 · 1 条评论 ·
查看 CCExtractor/taskwarrior-flutter 的全部 Issue
相似的 Issue
-
难度 2/5 1-3 小时 新手友好度 72/100
OpenBikeControl/bikecontrol#404 · 1 条评论 ·
维护者通常 1 天内回复
-
[Bug]: Language picker in Settings doesn't scroll; last languages overlap the buttons可能已有人在做 关联的 PR 仍在进行中或已合并。 未关闭backlog:medium bug localization
难度 1/5 1 小时以内 新手友好度 90/100
simonoppowa/OpenNutriTracker#1331 ·
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 66/100
MunichWays/munich-ways-app#248 ·
-
难度 2/5 1-3 小时 新手友好度 72/100
-
bug Platform: Linux Platform: Windows UI: Fluent
难度 2/5 1-3 小时 新手友好度 68/100
Notsfsssf/pixez-flutter#1386 ·
维护者通常 2 天内回复