klembot / twinejs

Twine, a tool for telling interactive, nonlinear stories
https://twinery.org
GNU General Public License v3.0
2k stars 295 forks source link

Pop-up message for new built-in story format versions #124

Closed klembot closed 6 years ago

klembot commented 9 years ago

Originally reported by: Leon Arnott (Bitbucket: L, GitHub: Unknown)


The next version of Harlowe will have slight backwards-incompatibilities with the previous version, so I'm wondering how to communicate to present users that this new version is available, and whether their H1.0.1 stories should or should not be automatically promoted to use H2.0.0.

I think that, on upgrading to a new version (determined by saving a "last version opened" LocalStorage bit, I guess) and opening a story, a pop-up message over the story menu should appear, warning authors that a new version of Harlowe/Snowman is present, with both bugfixes and API changes, and they can switch to it now (if they haven't been upgraded automatically) or switch back to the previous version (if they have).

Ideally I'd like this to be in place in time for the next Harlowe version (which I'm working to get out within the next week or three).


klembot commented 7 years ago

Original comment by Chris Klimas (Bitbucket: klembot, GitHub: klembot):


Closing this since we've decided to handle this to allow multiple story format versions, and allow users to upgrade when they're ready.

klembot commented 9 years ago

Original comment by Chris Klimas (Bitbucket: klembot, GitHub: klembot):


I agree that the story format JSON ought to be a remote file, so format authors can release as they like. The endgame for this is likely some sort of story format registry a la addons.mozilla.org, but that is a project unto itself.

One of my goals with the local app versions is to automatically cache story formats for the user, so users would not need to download files and copy them to magic locations in order to get a new release going. In the meanwhile, I think the logical thing to do would be for local apps to package all releases of a built-in story format. I'm happy to do Twine app releases that are solely story format version updates in the meanwhile as well (though we're still in a state where minor bugfixes are relatively steady, anyway).

That reminds me of one key part of my proposal that I left out.

klembot commented 9 years ago

Original comment by greyelf (Bitbucket: greyelf, GitHub: greyelf):


If a user is running Twine locally I believe there a need to distinguish between where a story format file is loaded from (locally or hosted) and where to look for an update (generally hosted). This would allow the user the option to copy a story format file like SugarCube's to their storyformats directory while still being able to check if there is an update.

klembot commented 9 years ago

Original comment by Chris Klimas (Bitbucket: klembot, GitHub: klembot):


Using a standard versioning scheme seems good to me, generally speaking.

My proposal is crystallizing in my head:

General principles

  1. We want to encourage users to upgrade, but let someone who isn't ready to deal with a change pause things until they are ready.
  2. We want to encourage users to move all their work to a single release of a story format.
  3. A story format is a set of releases. They act as a bundle; you either have access to them all, or not at all.

Story format changes

We change things so that a story format will be stored in a JSON file that looks a bit like package.json in npm. This file includes the user-visible name, license, author, URL, etc. that are properties in the current setStoryFormat() call. It contains a new property, releases. This is a object with props like:

#!javascript
{
    [
    {
       "version": "1.0",
       "url": "http://mysite/myformat/1.0.js",
       "changes": "<p>Initial version.</p>",
       "promptUpgrade": false
    },
    {
        "version": "1.0.1",
        "url": "http://mysite/myformat/1.0.1.js",
        "changes": "<ul><li>Fixed a bug.</li></ul>"
        "promptUpgrade": false
    },
    {
        "version": "2.0",
        "url": "http://mysite/myformat/2.0.js",
        "changes": "<ul><li>Revised CSS.</li><li>Visit the <a href=\"...\">project page</a> for more information.</li></ul>",
        "promptUpgrade": true
    }
    ]
}

An array is used here so it's dead easy for the editor to understand the sequence of releases. The URL property points to the JSONP for that release; it would load that particular version of the story format only, and contain no supplementary information.

What a user sees

The editor stores what release of a story format each particular story is linked to. This information would also be published with the story. When opening a story that is not using the most current release:

If the user opens the Story Format menu item, it would show them the version the story is currently on, and give them a drop-down menu of releases to choose from.

The editor also remembers the last version of a story format the user has chosen. When creating a new story:

If the user opens the Story Formats link in the story list, it would show them the release they're using for new stories, and have the same drop-down menu of releases as above.

If a user has never used a story format before, then the editor defaults the user to the latest. Likewise if a story has no version information, it too is defaulted to the latest when importing.

klembot commented 9 years ago

Original comment by greyelf (Bitbucket: greyelf, GitHub: greyelf):


Is this not similar to the version issues that tools like nodejs's NPM have to solve, expect in the reverse. In NPM's case the package.json defines which version(s) of a package is required as a minimum to resolve the projects needs.

In the story format's case could it not define which previous version(s) of itself it is considered compatible with, thus helping with the situation of a imported story needing a particular previous version.

klembot commented 9 years ago

Original comment by Thomas M. Edwards (Bitbucket: tmedwards, GitHub: tmedwards):


I have to agree with Leon here. The story formats define language and behavior, so they're not really comparable to fonts.

Chris Klimas> I strongly believe that allowing the user to have multiple versions of the same format should be a last resort. I believe we shouldn't ask users to become story format janitors.

There's no real other option, however.

That said, I believe that most of the multiple story format version issues you have (Chris) could/should be addressed by the UI. For example, by default, show only the version with the greatest major number (while keeping previous major versions around for existing/imported projects is important, there's no reason to advertise them unduly).

The point about using only the name of the story format not really being sufficient to identify it has already been raised here (and also in our e-mails). My suggestion is to:

  1. Require SemVer for story format versions
  2. Add something like a major property to the story format object, which is the major version number (we shouldn't need more than that for versioning, so the version property can remain the displayed version string). You could make version an object with all of the appropriate properties (e.g. major, minor, patch, and extra), but that's really overkill for this situation. What should not be done is trying to parse version information out of the version string.
  3. Use both the name and major version together as the story format's identity (both internally and in published projects/archives).

As to the versions.json file, are you talking about something hosted on the story format side? If so, I have to point out that its location is another point of failure (still, I suppose that could be mitigated by strongly suggesting that it be hosted someplace unlikely to disappear/move, e.g. in their remote repo, if they're using someplace like GitHub or Bitbucket).

klembot commented 9 years ago

Original comment by Leon Arnott (Bitbucket: L, GitHub: Unknown):


My apologies, BC = backwards compatible. Was kind of rushed and bothered while writing that.

The thing about story formats in Twine 2 is that they singly define the runtime programming language and DOM used by the story. This wasn't quite the case for Twine 1's Jonah/Sugarcube, which use the same TiddlyWiki fork language (although the DOM and CSS divergence is significant in itself) but has been the case for Twine 2 since the inclusion of both Harlowe and Snowman.

Story formats, then, are really not comparable to fonts (which don't really have an "API" per se), and are more comparable to, say, Python or Node runtime libs. You can't, without proper examination, switch out a 2.4 runtime with 2.7 and expect no change in the client program's behaviour.

This analogy provides potential answers to these questions. Importing a story that requires harlowe-2.0 while you lack it should have the same result as trying to, say, compile Twine 1 without Python 2.7: "no go - please obtain the format separately". It also, unfortunately, suggests that prior version persistence is unavoidable, when and if breaking changes are made: upgrading really shouldn't just silently delete the version they were using, and nor should it temporarily/permanently preclude them from using the latest version in a different story.

(It sounds like the solution to most of these problems is "avoid releasing BC-breaking versions", which is something I've been keeping mindful of. But, from the end-user's perspective, even a simple bugfix constitutes a break to BC if it alters the final running of a game - I recall a situation where changing the doctype from HTML4 to HTML5 changed the vertical padding between <img> elements in Sugarcane, affecting a story. My interpretation of which bugs are genuine BC changes, as required by SemVer, is thus fairly judicial.)

Of course, I realise that one thing authors shouldn't need is having to micromanage these formats, keeping track of which one has which legacy feature, and is used by which story, and so forth. I feel like this is more of a UI issue, though - if the previous versions are kept as discreet as possible, and if each of them has readable compat. notes accessible from the story format panel, the burden of version-tracking can be reduced. This could be done by extending format.js again, or by a versions.json file (the prospect of which I'm liking a good deal).

klembot commented 9 years ago

Original comment by Chris Klimas (Bitbucket: klembot, GitHub: klembot):


First of all, I realized that for some reason Bitbucket is marking everyone's comments on this as potential spam, which is not really helping. In the future, I'll try to approve things ASAP so there is no potential confusion.

Could you clarify what you mean by "BC behaviour"?

My original thought when working on this part of the design was to mimic Twine 1, and to treat story formats akin to fonts. If you have a format named Harlowe installed and I have one with the same name installed, I thought it shouldn't care too deeply about that. It sounds like this latter assumption has turned out to be partly incorrect, and the reality is "it shouldn't care, except if there is a breaking change between the version currently installed and the one the story needs."

This sometimes-matters, sometimes-doesn't situation makes it difficult to suggest rules for this. If I import a story using harlowe-2.0 and I only have harlowe-1.0.1 installed (for example), what should the editor do? How about the opposite situation?

I strongly believe that allowing the user to have multiple versions of the same format should be a last resort. I believe we shouldn't ask users to become story format janitors.

As a small point, I'm not terribly fond of the concept of the editor probing for new versions on its own. What happens if Harlowe 3.0 gets hosted at another web site? You also strand anyone who misses, say, two minor point releases in a row. Finally, practically speaking, there's a time penalty for attempting to load a nonexistent format in some browsers right now. I believe that not all browsers fire an error event when a Githubissues.

  • Githubissues is a development platform for aggregating issues.