Closed axd1967 closed 2 weeks ago
Maybe a separate issue: state name handling is sufficient for most use cases, but a bit awkward when trying to apply versioning schemes by duplicating states and using (semver) version strings.
I see no immediate solution for this.
Your first suggestion sounds reasonable. I don't see how the second is different, though; could you elaborate?
The "current state" (shown at the top of the state list) should be distinct from a recorded state. Now there is no way to save the current state; what is possible is to duplicate a recorded state.
The "current state" should never modify a recorded state, but exist as a separate, "modified" state. But the user should have the option to overwrite an existing state anyway (eg by specifying an existing saved state).
So what would be needed is for the states menu to have the option "Save current as new state" and prefill in the name box with the existing state name, appended with e.g. a '*' (rather than 'copy' because it might no longer be an identical copy); it is up to the user to choose whether to overwrite an existing state.
This should simplify sharing states.
Currently, I think the workaround is this: before doing anything with the calculator, duplicate the recorded state into <current state name>+"*"
and revert to it.
this discussion is probably to be moved into a separate issue.
also, state names could be sortable in "semver" fashion : e.g. mystate v0.2
should be before mystate v0.11
. Workaround is to use fixed fields in version names...
I implemented pre-population of the text field for Rename.
Regarding the behavior of Duplicate, you said: "Now there is no way to save the current state; what is possible is to duplicate a recorded state." But that is incorrect; when Duplicate is applied to the currently active state, the duplicate that is created is a dump of the current state as it exists in memory. It is not a copy of the state file as it currently exists on disk. But if the app is exited immediately after creating the duplicate, the current state will also be written back to disk, overwriting the file that was most recently loaded. Thus, if state foo is active, and Duplicate is performed on that state, foo copy will be created, and when the app is then exited, foo is updated, and after all this, foo and foo copy will be identical.
(An alternative is to apply versioning of the .f42 state files with e.g. Git; but this is not easily done on Android).
when Duplicate is applied to the currently active state, the duplicate that is created is a dump of the current state as it exists in memory. It is not a copy of the state file as it currently exists on disk. But if the app is exited immediately after creating the duplicate, the current state will also be written back to disk, overwriting the file that was most recently loaded. Thus, if state foo is active, and Duplicate is performed on that state, foo copy will be created, and when the app is then exited, foo is updated, and after all this, foo and foo copy will be identical.
I think here is the confusion: foo
and foo copy
should not be the same after the session has ended. Of course the running state should be preserved, but not in a recorded state.
A Revert action does not guarantee that the reverted state is identical after every Revert action.
Currently, although the user presses Duplicate after selecting a recorded state from the state menu, it is not the selected state but the state in memory that is duplicated if that is the current state , otherwise the selected state. And that difference in behaviour is the problem.
One would expect the selected object to be duplicated (i.e. the state as it was recorded when the Duplicate button was pressed), which has or has not changed in memory while that state was active.
The current (running) state should be a copy that contains modified data wrt the saved state, and should not touch the saved state. That way, there is always a guarantee that reverting a saved state will always revert to the moment where the state was saved.
When the sessions is ended, the currently modified state should be stored in a separate state, such as <current state name>*
. When pressing Save (an action that does not exists yet), the user will be able to save the current state as a new state, or overwrite a recorded state.
IMHO it should always be the selected state that should be duplicated, and a separate action should allow to save the current state.
In other words, every time the user presses "revert", the machine should go back to the same state, regardless of what happened after the state was saved. Now there is no such guarantee, as the saved (current) state is overwritten at the end of every session. It should be saved in a separate, "running" state.
In other words, Duplicate is not a good action to save the current state; it should simply make a copy of the recorded state, not of the running state. A separate action should read "Save current..." and there the user could choose whether to create a new state, or overwrite an existing state.
So, what we need is
Once a state is created, it should become read-only unless the user decided to overwrite it. This guarantees that a revert action always goes back to the same state. (Which is currently not the case.)
Here is an example where the complication arises:
It might not be the exact place in code where the problem appears, I just did a quick search.
Quickly browsing the sourcecode it appears that there are several places where this test is made to see whether we are dealing with the currently active state or not. I suspect this is part of the ensuing confusion. (And there seems to be a scary amount of copy-pasted code, such as the string "We're naming duplicates by appending " copy" or " copy NNN" to the name"...)
Also, the recorded .f42 states should live in a subdirectory, eg "states/
" rather than next to other F42 config files such as skins/
, state
, print
, ...,
I think the existing semantics of the state system are fine for almost everyone. All these changes to support state versioning in the app are too elaborate and too niche for my liking. I'll leave it with the Rename changes I already made, and close this issue.
A common use case is to rename or duplicate a state with a version string appended. (So backspace can be used to erase/edit a few chars.)
Current behaviour is to present an empty edit field, while the current state name might be a very good candidate.