Repository navigation
[Mobile] Offline support and sync - #36
Merged
Merged
Conversation
Closes #18. React Query already knows how to pause a mutation and replay it, so the work is telling it the truth about a phone. Its online default listens for a browser event that does not exist here, so NetInfo drives onlineManager instead -- without that, a phone in a tunnel fires requests that time out one by one rather than queueing anything. It watches isInternetReachable rather than isConnected, because a captive portal is "connected" and is exactly the case that hangs. Queued mutations are registered by key rather than passed inline. A persisted mutation is only data, and setMutationDefaults is what turns it back into something runnable after the app has been killed -- which is the difference between a queue and a list of regrets. A queued move captures the issue's updated_at when it is made, and refuses on replay if somebody else moved the card meanwhile. Applying it blindly would undo their work. Moving it to where it was already going is not a conflict, so that case still applies. Conflicts are surfaced, not resolved: the server's version and the queued one are both somebody's intent, and choosing between them is not a decision to make on their behalf. The banner stays up while queued work is still going out after a connection returns. "Back online" with three unsent changes is not the same as up to date. Only three mutations queue -- moving a card, commenting, creating an issue. They are the ones worth doing without a connection; everything else asks for one. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #18.
React Query already knows how to pause a mutation and replay it, so the work is telling it the truth about a phone. Its online default listens for a browser event that does not exist here, so NetInfo drives
onlineManager— without that, a phone in a tunnel fires requests that time out one by one rather than queueing anything. It watchesisInternetReachablerather thanisConnected, because a captive portal is "connected" and is exactly the case that hangs.Queued mutations are registered by key rather than passed inline. A persisted mutation is only data, and
setMutationDefaultsis what turns it back into something runnable after the app has been killed — the difference between a queue and a list of regrets.Conflicts
A queued move captures the issue's
updated_atwhen it is made and refuses on replay if somebody else moved the card meanwhile; applying it blindly would undo their work. Moving it to where it was already going is not a conflict, so that case still applies.Conflicts are surfaced, not resolved — the server's version and the queued one are both somebody's intent, and choosing between them is not a decision to make on their behalf.
The banner stays up while queued work is still going out after a connection returns. "Back online" with three unsent changes is not the same as up to date.
Only three mutations queue: moving a card, commenting, creating an issue. Those are the ones worth doing without a connection; everything else asks for one.
Verification
6 unit tests covering the conflict rule in both directions. The offline behaviour itself is unverified on hardware — nobody has watched a phone lose signal, move a card and come back. That needs a device.