-
Notifications
You must be signed in to change notification settings - Fork 56
feat: Implement local-first tracking for unsynced tasks #181
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: Implement local-first tracking for unsynced tasks #181
Conversation
Adds visual indicators for tasks modified locally but not yet synced with the backend. Implementation details: - Uses `localStorage` to track dirty UUIDs (keeps IndexedDB schema clean). - Adds "Unsynced" badge to task rows. - Adds a notification counter badge to the Sync button. - Masks temporary negative IDs with a dash in the UI. - Updates tasks optimistically for instant UI feedback. - Clears unsynced status automatically upon successful sync.
its-me-abhishek
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still, imho using IndexedDB, or any type of extra storage to store UUIDs of unsynced tasks is a waste of resources.
It would be just better if only a singular state is used inside the Tasks component to do this instead.
With just another addition that the tasks are automatically synced on the first load - which is yet to be done, as discussed.
| } from './hooks'; | ||
| import { debounce } from '@/components/utils/utils'; | ||
|
|
||
| const STORAGE_KEY = 'ccsync_unsynced_uuids'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this will fail in multi-user setups
|
Please check it out and revert these changes |
|
Okay, thank you for the clarification, I completely understand the goal now. You're absolutely right about the localStorage key failing in multi-user setups. That's a bug I missed. My goal was to make the 'Unsynced' badge persist on page refresh, but I see your point now: if the app will auto-sync on load, that persistence isn't necessary. So, just to confirm the new plan:
This is a much simpler change. Does this sound correct? |
|
yeah, this makes sense! please go ahead with it |
|
Hey! @its-me-abhishek I'm closing this PR because it has become quite outdated and cluttered after the recent architectural changes. This should make it easier to review without going through old or irrelevant changes. Once this new PR is merged, I will open a separate PR for the fuzzy search feature as discussed, so each change stays well-scoped and easy to review. Thanks for your understanding - trying to keep the contributions clean and maintainable! |
Description
This PR implements a "local-first" architecture for task modifications. When a task is added, edited, completed, or deleted, the change is saved immediately to the local IndexedDB (Dexie) and reflected in the UI instantly, rather than waiting for the backend response.
Architecture Decision:
To ensure the main database schema remains pure and to avoid migration risks, this implementation uses
localStorageto track the UUIDs of modified tasks. This ensures the "Unsynced" status persists across page reloads without polluting the core data model.Key Changes
handleAddTask,handleSaveClick, and other modification handlers now update the local DB andlocalStorageimmediately before triggering the background API call.getUnsyncedFromStorageandsaveUnsyncedToStoragehelpers to initialize React state and persist dirty items.-in the ID column for newly created local tasks (hiding the temporary negative ID) for a cleaner look.syncTasksWithTwAndDbto automatically clear thelocalStoragetracking upon a successful full sync.Tasks.test.tsxto mocklocalStorageand validate the badge visibility, ID formatting, and pagination logic.Checklist
npx prettier --write .(for formatting)gofmt -w .(for Go backend)npm test(for JS/TS testing)Additional Notes
Video: Link to see changes