[WebODF] Undo & Operation groups

Philip Peitsch philip.peitsch at gmail.com
Tue Jan 21 06:56:36 CET 2014


On 21 January 2014 01:39, Friedrich W. H. Kossebau <friedrich at kogmbh.com> wrote:
>
> Am Freitag, 17. Januar 2014, 22:39:37 schrieb Philip Peitsch:
> > Greetings webodfers,
> >
> > I'm spending some time in the next 3 weeks improving the behaviour of
> > undo slightly. I am specifically looking at fixing how undo states
> > are created to group things more intuitively for the user.
>
> Currently I see two places for grouping operations together (just stating,
> guess everyone sees the same):
>
> a) when creating a set of operations based on a single state of the document,
> where the parameters of the (n+1)-th op could depend on the effects of the n-
> th op. The set needs to be passed as one group, to be also applied in the same
> order. Once they are serialized, the grouping has no more meaning.
>
> b) in the UI logic, because UI actions are often not directly mapped to a
> single operation, but multiple ones (UI actions could be seen as CISC,
> translated to operations which could be seen as RISC). To stay consistent in
> the UI, possible listings of what actions different users did and also the
> option to undo/redo those actions would be always described in the UI action
> terms. So this grouping (info) has to stay also when serialized, because it
> will be used later. User-defined macros could be seen similar to UI actions,
> just that they extend the "CISC" set.
>
> Any c) etc.?


This all makes sense to me. We've already started encountering issues
with the UI actions not being easily discernable from their group. Gazing
into my crystal ball, I predict a coming feature eventually that changes
session.enqueue to take a localizable string describe the group alongside
the array of operations. That sounds like next month's problem however!

>
>
> > I have two ideas for how to do this cleanly.
> > ...
> >   from multiple groups?
>
> From above use-cases for groups I would think:
> * UI-action groups are permanent
> * UI-action groups cannot be modified after being streamed (ignoring OT-
> modification here)
> * UI-action groups should be known remotely as well, ideally by a defined
> action set (but not required). A known UI action set would help with display
> (think action name translation). But custom macro names have translation
> issues in any case. Being known e.g. allows users do see in UI action terms
> what other users are doing (and undo that)
> * a group start/end could be marked by setting start/end tag in the specs. If
> we also support nested groups (e.g. created by macros calling other macros)
> those tags would need to support that. Another option would be to have a tree
> structure in the serialization to express that, but I do not see a real gain,
> as some clients might just not care.
> * at least with the idea of UI-action groups I see no reason to support
> interleaving, also no sense. Hm, comes the need e.g. from grouping consecutive
> insert operations by one user?

+1. This also aligns with my own thoughts on the matter.

>
> Related thought:
> Grouped actions possibly need some kind of local lock, to make sure all
> operations belonging to the same UI action end up being applied/routed without
> other ops sneaking in. E.g. some UI action could be done in an interactive
> way, with intermediate steps already applied. That could also be useful for
> grouping related operations into one, like the consecutive inserting. Because
> in the timespan where one is quickly typing a word updates from other users
> might be not wanted as well, so such a lock could be synced with the timeout
> for when inserts will no longer be auto-grouped?

This makes sense for other times as well. E.g., updates arriving while selecting
with a mouse will likely break the selection or move the view around. Updates
arriving while the view is scrolling might have similar issues. I agree that we
will (eventually) need some predictable critical regions during which remote
updates cannot be received or processed.

For now, if I stick with option 1, we can avoid answering these questions.

>
> Open problem:
> Given that at least with the OT approach different clients have different
> (groups of) operations applied, and usually not only in a different order. So
> they would also have different Undo stacks.
> So should the history be normalized somehow?
> What to do about groups whose operations are transformed completely into noops
> so would be currently just be forgotten?

The likely implementation of collaborative undo is going to be
inverse-ops. In this
case, all the normal OT behaviours remain, and all the undo stack is
decide which
inverse-ops to send to other clients. (Of course, I reserve my rights
to change my
mind on this fictional implementation at any time in the future...)

The undo history being different per user is only an issue if the
users are sitting
side-by-side and expect undo to perform the same action on both machines. I
don't think there is any technical issue with the undo stacks being
different per
client, but there will potentially be some significant user-experience bugs.

>
> So somehow I prefer option 1) for now, until there is a grand plan compiled.
> Unless we are quick enough with compiling one now.

I am in agreement with you for this. Option 1 is the least code impact at the
moment, and allows me to avoid the inherent monsters lurking within the
"collaborative undo" feature for a few weeks longer :-).

Based on this, I'll roll code for option 1 and get it up for review soon. We
can then extend or modify as desired.

As ever, thanks for your comprehensive feedback!


-- 
Philip Peitsch
Mob: 0439 810 260


More information about the WebODF mailing list