Skip to content
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
10 changes: 8 additions & 2 deletions shared/spec/PRODUCT-SPEC.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,8 +149,14 @@ pickers. Save (blank text silently ignored), Delete (confirm first), Cancel
(light) / 深色 (dark), persisted in config `theme`; follow-system tracks
OS personalization live. Windows reads the persisted language and theme
before first window activation (no temporary English/light frame); the
backend settings RPC remains authoritative once connected. macOS follows the system appearance at launch
and live; its Settings toggle is a per-session override. Plus 检查更新… /
backend settings RPC remains authoritative once connected. macOS follows
the system appearance at launch and live; its Settings toggle is a
per-session override. Async persistence
acknowledgements must **not** overwrite local settings changed since the
request began (including `last-selected-list-id`, theme and language).
The locally selected list remains authoritative through overlapping
preferences saves; the backend result confirms persistence or an error.
Plus 检查更新… /
Check for Updates… (manual online-update check; auto-check runs at
launch and every 4 h — contract: `UPDATE.md`).
- Help: About — `Taskly v<version>` + `© 2026 Taskly Team` +
Expand Down
13 changes: 7 additions & 6 deletions windows/MainWindow.xaml.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1936,12 +1936,13 @@ winrt::fire_and_forget MainWindow::SaveSettingAsync(std::string const& key,
key, value,
[dispatcher, weak](rivet_app::Result<rivet_app::Settings> result) {
try {
auto const settings = result.get();
dispatcher.TryEnqueue([weak, settings] {
if (auto window = weak.get()) {
window->settings_ = settings;
}
});
// SaveSettingAsync is a persistence acknowledgement, not a fresh
// snapshot of the UI's current intent. Each caller already
// updates its own language/theme/selected-list state before the
// RPC, and another setting may change while this call is running.
// Applying the whole returned struct here can roll those newer
// values back when callbacks arrive out of order.
(void)result.get();
} catch (std::exception const& e) {
auto message = std::string(e.what());
dispatcher.TryEnqueue([weak, message = std::move(message)] {
Expand Down
Loading