Closed maxme closed 4 years ago
Now that https://github.com/wordpress-mobile/WordPress-FluxC-Android/pull/1255 is merged, we can start working on this one.
Subscribing @wordpress-mobile/ravenclaw
I've created a table with all the possible scenarios which we can encounter when we fetch a post from the server.
Post updated in Remote
-> PostModel.lastModified
has changed
Post's AutoSave object updated in Remote
-> meta.data.autosave.modified
has changed
hasLocalChanges
-> flag indicating that the post was modified locally, but the changes were not synced with the server at all or were just remote-auto-saved.
Green (1c, 2c, 1d)
Pink (2d)
Yellow (3c, 4c)
3d
(This case is a bit more complicated)
4d
3d
but more tricky from the UX point of view, as we should probably show both "conflict resolution" and "unpublished revision" dialogs. Let's keep it out of this discussions for now, until we resolve 3d.I think it's quite complicated even if we want to keep things simple for the first iteration. I don't think we can just ignore its complexity and implement a simple solution without fully understanding impacts of our decisions. I also feel like it might be worth having a synchronous discussion about it. Wdyt?
I wish "GitHub" had an undo action 😞 . I posted it before it was finished.
I think the most straightforward solution would be to create a local revision when we detect 2d,3d,4d and just accept the data from the server (2d,3d,4d would become 2c,3c,4c). We would never need to show the "conflict resolution" dialog and the user could always go to revision history and restore their post..... But I'm not sure whether we want to/can introduce local revisions in the first iteration.
@malinajirka - That's an awesome analysis. Nice work!
Considering it's a much wider discussion than what this issue initially proposes: would you mind posting it as a new discussion issue? (it should still reference this one)
Great work, @malinajirka! Do we have information on how often these conflicts happen?
For 3d-3, would it be possible to show a dialog like "There is a modified version on this device and on the server, which one would you like to edit?". I realize this probably requires us to have local revisions. 🤔
I might have missed this. Is it possible to compare a local modifiedDate
and remote modifiedDate
and use the one that is the latest? Do we have these fields? This could probably be an interim solution until we get the complex solution sorted out.
I don't think we can just ignore its complexity and implement a simple solution without fully understanding impacts of our decisions.
I agree.
I think an ideal solution would be to create a local revision from the local version + show the remote version of the post.
It seems like the best technical solution (needs work but should be straight forward) and the best UX solution (present the history of changes when the user needs to select a revision).
I'm also wondering if we could create a remote revision from the local revision when the network is back (I'm not sure we have an endpoint to do this).
Considering it's a much wider discussion than what this issue initially proposes: would you mind posting it as a new discussion issue? (it should still reference this one)
Sorry @diegoreymendez , I was afk on Friday and I think moving it now would just result in more chaos.
Do we have information on how often these conflicts happen?
I don't think so:(.
I'm also wondering if we could create a remote revision from the local revision when the network is back (I'm not sure we have an endpoint to do this).
AFAIK this endpoint isn't available - we have the /autosave
endpoint, but it doesn't always create a new revision and has side-effects.
The remote revisions support just "title, content and excerpt", if the local revisions would do the same I believe we wouldn't even need them, right? We already store changes made while offline. We could do the following
It wouldn't work on self-hosted sites though, so if we can make it work there introducing local revisions makes total sense.
I might have missed this. Is it possible to compare a local modifiedDate and remote modifiedDate and use the one that is the latest? Do we have these fields? This could probably be an interim solution until we get the complex solution sorted out.
I don't think we use local modified date - we use just a boolean flag "hasLocalChanges". The client's time isn't reliable in my opinion and we could quite easily lose all user changes. Wdyt?
For 3d-3, would it be possible to show a dialog like "There is a modified version on this device and on the server, which one would you like to edit?". I realize this probably requires us to have local revisions.
We basically already do that for post data conflicts (https://github.com/wordpress-mobile/WordPress-Android/pull/8989). But it gets a bit more tricky with introduction of the autosave - because you can edit one of remote post
/remote autosave
/local post
. I agree with Maxime It seems like the best technical solution (needs work but should be straight forward) and the best UX solution (present the history of changes when the user needs to select a revision).
.
Thanks for the great breakdown @malinajirka . I'm still trying to make sure I understand all the scenarios.
Relating to "present the history of changes when the user needs to select a revision". Would we present this list in a way that also allows the user to view those changes? The user might remember the content they wrote, more so than the date/device it was written on. It would be nice while in this flow to be able to go and view the different posts to make an informed decision.
I'd also just like to mention that on the iOS version of this task, the same discussion might apply https://github.com/wordpress-mobile/WordPress-iOS/issues/11650 Does all the discussion above apply to iOS as well? If so, should we get talking across both platforms so we capture the same complexity on both platforms? @diegoreymendez
Does all the discussion above apply to iOS as well?
@osullivanchris - That's one of the limitations of having these discussions in GitHub. I also think this discussion should be happening in an issue of it's own, as this discussion should be parent to this issue and not vice-versa.
In a way having the wider discussion here adds a bit of noise because regardless of what states we have to deal with, this issue (the one initially reported) has a pretty narrow and well defined scope (which means this issue should be closed once that dialog is implemented and shown, regardless of the wider discussion).
I'd like to encourage us to sum up the bigger discussion in a separate issue (thread) and let this issue have a more limited scope, as initially intended.
I've created a new discussion issue: https://github.com/wordpress-mobile/WordPress-Android/issues/10008
Please post all comments which aren't directly related to this issue ("restore more recent revision dialog) into the discussion issue and not here.
@malinajirka , should this ticket still have "needs discussion" label? Is it blocked by https://github.com/wordpress-mobile/WordPress-Android/issues/10008 ?
should this ticket still have "needs discussion" label?
I think we can remove the discussion label since we moved the discussion to #10008
Is it blocked by #10008 ?
Yes, it is blocked as the solution for #10008 will most probably affect the implementation of the dialog. Most specifically what will happen with local changes if the user clicks on "restore" - will they be stored in a local revision, thrown away or something else?
I'd suggest pausing this ticket until #10008 is resolved and hopefully the solution for this ticket will be much clearer by then.
I spent some time thinking about this, because I felt we could still do progress while avoiding to get too deep into the conflict resolution discussion.
Is there any objection with implementing this for when hasLocalChanges == false
case and leaving the rest for another issue about conflict resolution?
I think that should be fairly safe.
Also I wanted to add some documentation to aid in implementing this issue, since I actually went through the effort of looking this up today.
The service to query the latest autosave for a post is:
GET
https://public-api.wordpress.com/rest/v1.1/sites/$site_id/posts/$post_id/autosave
In iOS I think this needs to be implemented.
I spent some time thinking about this, because I felt we could still do progress while avoiding to get >too deep into the conflict resolution discussion. Is there any objection with implementing this for when hasLocalChanges == false case and leaving >the rest for another issue about conflict resolution?
Good point, I guess we could do that.
Basically the logic would be following:
hasLocalChanges == true
-> ignore autosave and just open the posthasLocalChanges == false
&& post.autosave == null
-> just open the posthasLocalChanges == false
&& post.autosave != null
-> open the post and show the dialog. If the user clicks on restore, load the autosave revision and set hasLocalChanges to true
. The only downside is that the users might expect that when the dialog is not shown, there isn't any newer version of the post. However, if hasLocalChanges == true
, there might be a newer version. But it's probably not a big deal.
The service to query the latest autosave for a post is: GET https://public-api.wordpress.com/rest/v1.1/sites/$site_id/posts/$post_id/autosave
We are currently using GET /v1.1/sites/$SITE_ID/posts?context=edit&meta=autosave
. I think we won't need to fetch an autosave for a single post. Or is there any scenario you can think of?
Either case thank you for looking this up - it's good to know that the endpoint exists even if we don't use it for this particular ticket.
The only downside is that the users might expect that when the dialog is not shown, there isn't any newer version of the post. However, if hasLocalChanges == true, there might be a newer version. But it's probably not a big deal.
I agree we shouldn't think of it as a big deal currently.
My undestanding on autosaves, from what I saw in the APIs and the logic in there is that they're not really meant to be a safe storage mechanism, but rather something quite transient. They can really be dropped in many different scenarios, and I think this in part is due to how they're currently implemented (beyond just mobile).
We are currently using GET /v1.1/sites/$SITE_ID/posts?context=edit&meta=autosave. I think we won't need to fetch an autosave for a single post. Or is there any scenario you can think of? Either case thank you for looking this up - it's good to know that the endpoint exists even if we don't use it for this particular ticket.
That's fine!
The reason I added that info is because it took me a while to actually figure out how to retrieve autosave info for a single post for my manual tests. I would have though we'd be using the single post endpoint, but this is for no particular reason. Quite honestly whatever works for us is perfectly fine. Consider this my attempt to document something I'm not sure we have implemented in iOS.
@yaelirub - If you agree with the proposal above, this issue can be moved out of discovery, and can be actively worked on. The same applies for the matching iOS issue.
The proposal is:
Is there any objection with implementing this for when hasLocalChanges == false case and leaving the rest for another issue about conflict resolution?
I agree with the proposed solution. Updating the description here and on the iOS ticket to reflect the decision.
@malinajirka , from your comments:
I think we won't need to fetch an autosave for a single post and If the user clicks on restore, load the autosave revision
How are we fetching the autosave revision if not by using the GET endpoint?
How are we fetching the autosave revision if not by using the GET endpoint?
We are using just the following endpoints:
For fetching the post list
GET /v1.1/sites/$SITE_ID/posts?context=edit&meta=autosave
For fetching a specific post
GET /v1.1/sites/$SITE_ID/posts/$POST_ID?context=edit&meta=autosave
Both contain all the autosave
data.
This issue is blocked by - https://github.com/wordpress-mobile/WordPress-Android/issues/10108. I though we'd simply show a regular system dialog. I assume we decided to consider designing our own solution so we wouldn't need to show a blocking dialog. Is that a correct assumption @yaelirub?
If that's the case I'd consider using a regular dialog in the first iteration and improving it later when we have some data about it's usage - I don't think it'll be shown that often so it might not be worth the effort. Wdyt?
cc @osullivanchris
I though we'd simply show a regular system dialog. I assume we decided to consider designing our own solution so we wouldn't need to show a blocking dialog. Is that a correct assumption @yaelirub?
Yes. I previously spoke to Megs and it sounded like we wanted to design our own. I agree that we can go a head and show a system dialog for the first iteration.
@osullivanchris, if you're good with showing a system dialog, please close https://github.com/wordpress-mobile/WordPress-Android/issues/10108.
@malinajirka , anyways, this in not blocked by the dialog design. Please proceed with the implementation.
@osullivanchris is considering showing the "version conflict" resolution flow even for this case. I'll wait for his decision before moving forward with this ticket.
Proposal captured on paCBwp-bZ-p2
After discussions with @diegoreymendez , @maxme and @osullivanchris , we are closing this issue and #10008 in favor of implementing the simple approach which will be captured in this ticket
We intend to discuss any enhancements or other proposals to better handle conflict resolution in the future.
Description
When a user opens a published post with a remote auto-save, we must show a dialog “A more recent revision of this post exists. Restore?”. Like in Calypso:
Decision
we are splitting this from the discussion on conflict resolution.
Implementation logic: hasLocalChanges == true -> ignore autosave and just open the post hasLocalChanges == false && post.autosave == null -> just open the post hasLocalChanges == false && post.autosave != null -> open the post and show the dialog. If the user clicks on restore, load the autosave revision and set hasLocalChanges to true.
Corresponding iOS Ticket
https://github.com/wordpress-mobile/WordPress-iOS/issues/11650