klembot / twinejs

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

Shareable Twinery story links #1466

Open mmafic opened 12 months ago

mmafic commented 12 months ago

Is your feature request related to a problem? Please describe.

Something that would be extremely useful whenever you collaborate on a story with other people is to be able to upload it to a public location and share a Twinery link that would open the story in Twinery. This would eliminate extra steps of having the person download the file and import into their Twinery library. This is especially relevant if they dont have experience with Twinery and you just want to give them a quick overview or let them play it without making any changes. Also super useful on mobile devices where downloading and uploading files can sometimes be cumbersome. Having a link that would immediately open the story editor or play the story would save a lot of time and whenever you reupload the new version of the story, all they need is refresh their browser page.

Describe the solution you'd like.

What I propose is much simpler than turning Twinery into a cloud service, all that's needed is a file server (I use MinIO for my website) where you can upload the file and then share a Twinery link putting your file URL as a search parameter. I had a discussion about this in the Discord server and after seeing some general interest, I went ahead and implemented it. I was about to open a PR but then I read through the contributing rules and realized I have to open an issue first. I am happy to adapt my solution in any way necessary, and I would love to get feedback on the demo that should hopefully demonstrate what I had in mind. I tried implementing this in the most non-intrusive way possible, and it's not super complicated.

The code is deployed at https://twinery-test.pages.dev/#/.

In addition to the import from file button, there is a new import from URL button which allows you to paste a story URL and download it into your library. For now only .twee files are supported, but it can easily be extended to html files as well. I put a placeholder disclaimer w.r.t. using a third-party link to a story that can potentially be malicious, based on the feedback in the Discord server, we can change the wording to whatever makes sense.

It also allows you to preview the story, which opens it in the story editor in read-only mode. When you open a story that way, you can share the page url with other people and they will be able to open the story using that URL.

I uploaded a test story here - https://files.council.monster/test.twee.

Here are examples of shareable links (the first time you open a link with a story url you see a disclaimer, once you accept it, it wont be shown for that story URL):

Link to the editor: https://twinery-test.pages.dev/#/preview?url=https://files.council.monster/test.twee Link to play the story: https://twinery-test.pages.dev/#/preview/play?url=https://files.council.monster/test.twee Link to test the story: https://twinery-test.pages.dev/#/preview/test?url=https://files.council.monster/test.twee Link to the proof function: https://twinery-test.pages.dev/#/preview/proof?url=https://files.council.monster/test.twee

Describe alternatives you've considered.

The most user-friendly solution would probably be turning Twinery into a cloud service and hosting the files there, but that would obviously be a lot more complicated and cost money. The benefit of my solution is its simplicity; it does not require a backend as the file is downloaded by the user's browser, it works well as just an extra feature that does not interfere much with how Twinery works now. The main downside is you cannot use user-friendly file hosting solutions like google drive (although this feature can be expanded to have a google drive integration), you need to be tech-savvy enough to use something like MinIO or your own http server. Honestly, we could provide a single-click DigitalOcean deployment or something like that for MinIO in the docs to make it easier for users.

Additional context on this suggestion.

No response

Presubmission checklist

greyelf commented 12 months ago

Many Twine projects include references to media content (like Images, Audio, and Video), how would these types of files become available to those importing a project via a sharable Twinery story link?

mmafic commented 12 months ago

@greyelf same way it happens with importing from file. When we import from file, we read the contents and parse into a Story object, when we import from url, we fetch the file with an AJAX request, parse it into a Story object, the rest is the same. The only difference is that I added a preview flag on the Story object, so that components have a way of telling we need a read-only mode.

mmafic commented 12 months ago

Oh I see what you mean, they are not embedded in a story. I can prepend the base url of the story to all relative urls I suppose.

klembot commented 11 months ago

I'm very interested in finding ways to do decentralized collaboration in Twine! I need some time to think this over fully before giving all my thoughts, but I wanted to let you know I've seen this.

mmafic commented 11 months ago

@klembot do you mind if I submit the PR for the changes I've made in my demo, so that you can see the current implementation? I don't mind updating things later based on your feedback and vision.

klembot commented 11 months ago

@mmafic I'm guessing your fork has the changes in the demo? https://github.com/mmafic/twinejs/commit/d3c00542341dfa394881d8db7739673d719fd4d5

If so, I think a PR would be premature at this point.

klembot commented 11 months ago

@mmafic I think overall right now I feel this is an interesting experiment that isn't quite ready to be part of the core Twine experience. I really like the idea of decentralized collab but I think the core Twine audience is at the level of using Google Drive or Dropbox or OneDrive, not spinning up DO instances, and the workflow seems like it would mean a lot of steps for each iteration.

This is how I picture it happening for a back-and-forth collaboration, but let me know if I'm thinking about it incorrectly:

  1. I create a first draft of my story in Twine locally.
  2. I want my friend to edit it too, so I upload the file to my file server and give them a URL.
  3. They import from that URL and edit away.
  4. What do they then do with the version they have modified? What if I made changes on my end in the meantime?
  5. Each time we do a round of edits, I think we'd have to repeat steps 2-4 (whatever step 4 ends up being)? And things get really hairy if I'm on a team of 3 or 4.

You mention the preview use case too, but I feel like that's kind of limited. If I want someone to play my story, give me feedback, but not make any changes directly, I can publish to file and post that somewhere, or share it with them directly. I think that is faster than doing the upload/shareable link steps, but I totally could be thinking about this the wrong way around.

I do see some benefits in being able to distribute a version of a story in test mode, which Twine isn't able to do right now. Previewing in the editor... maybe useful? I suppose it would let people poke around the story structure without having to play through it repeatedly? There is some overlap with proofing mode / export to Twee, since those are formats someone can browse through, but obviously being able to see the structure live is nice.

Setting all of the above aside for the moment, I think the idea of import from URL is cool. The problem I see is that it won't work for a lot of use cases :(. I would love, for example, if I could import https://birdland.camp into Twine directly without having to save it locally first, but that won't work in web Twine because of CORS issues. (Think we can get around them in app Twine but I want to keep functionality as similar between the two as possible.) I also think many novice users would try to import a twinery.org edit URL like https://twinery.org/2/#/stories/307e916f-20b6-415e-9458-ecf8506350ec, which will never be able to work.

Anyway... it would be nice to test your ideas out with users, get feedback, and iterate. It would be really nice if we could figure out a way for this to be an add-on to Twine that people could optionally engage with, but I don't know if that's technically possible. Maybe we could do this via your demo app.

You mention this could be expanded to work with Google Drive etc. Could you talk about how that would work?

Finally, let me jot down a brain dump of where my thinking is on collaboration in Twine in case this inspires any ideas yourself.

  1. In 2.8 (coming later this month likely), users will be able to change their story library folder location. I'm curious if this will make life easier for people using Google Drive etc. It will not be a perfect solution, I'm certain, but it might get people 80% of the way there.

  2. I have toyed with the idea of integrating Twine with git, because there are plenty of free services that offer Git repos online, and you can even host a repo yourself, or do it all locally. Informally surveying people has told me there's a large group of Twine users who have never touched git at all before, though, so Twine would have to hide a lot of that detail away--kind of like how GitHub Desktop offers a simplified UI. The stumbling point for me has been how to resolve merge conflicts... it seems messy no matter what.

mmafic commented 11 months ago

@klembot

You are right, this is not the best solution for back-and-forth collaboration, because every time someone makes changes they would need to export the story from Twinery and re-upload it to the server. This is more useful for a scenario where you have one main script writer using Twine and several other people who suggest edits and offer feedback. The Twine project is still owned by the main writer and they are in charge of incorporating people's feedback into the story, if that makes sense. This is my use case. This functionality is especially useful to people who want to check in on the story and perhaps play, as all they need is follow the URL. You dont have to explain to them that they need to download a file and then import it in Twinery so and so; some non tech savvy people have trouble with app UI they are not familiar with, so this makes the whole process a lot more seamless with them, especially if they are using a mobile device.

Setting all of the above aside for the moment, I think the idea of import from URL is cool. The problem I see is that it won't work for a lot of use cases :(. I would love, for example, if I could import https://birdland.camp/ into Twine directly without having to save it locally first, but that won't work in web Twine because of CORS issues. (Think we can get around them in app Twine but I want to keep functionality as similar between the two as possible.)

Being able to import a third-party twine story deployment in the browser would be tricky, yes. One potential solution is to fork an existing browser extension for adding CORS headers on incoming requests (e.g. https://github.com/balvin-perrie/Access-Control-Allow-Origin---Unblock/tree/master), modify it so that it only works on the Twinery domain, and if a user inputs a URL that is not served with the right CORS policy, we redirect them to download the extension. Furthermore, the extension can detect when an importable Twine story is loaded in the current tab and add a button to import it to Twinery (just opens the import URL in a new tab). All of this is a different use-case though, since we're talking about a third party deployment and not a collaboration scenario where the story author intends for you to import their story into Twinery.

I also think many novice users would try to import a twinery.org edit URL like https://twinery.org/2/#/stories/307e916f-20b6-415e-9458-ecf8506350ec, which will never be able to work.

We can detect those and display a popup saying Twinery URLs are not importable.

You mention this could be expanded to work with Google Drive etc. Could you talk about how that would work?

Google Drive has an API for downloading and uploading files. So if a user has a public Google Drive url, I think there is a way to get a download link that you can use in an AJAX request. I think saving over the file should work too if the owner gave you edit permissions, but I haven't tested that.

In 2.8 (coming later this month likely), users will be able to change their story library folder location. I'm curious if this will make life easier for people using Google Drive etc. It will not be a perfect solution, I'm certain, but it might get people 80% of the way there.

Can you please elaborate what you mean by changing story library folder? Is this relevant to the web app or is this just for the electron version?

I have toyed with the idea of integrating Twine with git, because there are plenty of free services that offer Git repos online, and you can even host a repo yourself, or do it all locally. Informally surveying people has told me there's a large group of Twine users who have never touched git at all before, though, so Twine would have to hide a lot of that detail away--kind of like how GitHub Desktop offers a simplified UI. The stumbling point for me has been how to resolve merge conflicts... it seems messy no matter what.

I think integrating with git would be very cool, but also a lot more complicated, yeah.

klembot commented 11 months ago

@mmafic thanks, clarifying that the use case is for people to share a read-only version of a story is helpful. Two alternate ideas come to mind:

  1. Approach it from the opposite perspective. People who would want to do this would need to run their own web server (we think--see my comment below about Google Drive), and you mentioned potentially packaging something that someone could spin up on their own. What if this existed as a Docker image that runs a web server, offers a simple UI for uploading files to it, and then embeds the Twine UI in read-only mode for viewing? It's self-contained and not very different from your original idea, and we think people will need to pay the tax of running their own web server already.

  2. Or, more radically... what if there was a way to produce a standalone HTML file that displays the read-only version of the Twine UI with the story? People could still upload it to a server and make it browseable that way, or they could distribute it any other way a story normally can be.

Replying to specific parts of your last message:

One potential solution is to fork an existing browser extension for adding CORS headers

This feels out-of-scope for Twine and isn't something I'd want to maintain or provide support for, but I would be fine with others doing this.

Google Drive has an API for downloading and uploading files.

Do you know if that's possible to use without a server-side component? Last I investigated this and similar services (many years ago), this was required because you needed to use a private API key.

Can you please elaborate what you mean by changing story library folder? Is this relevant to the web app or is this just for the electron version?

This is just for the Electron version. Docs here--they will be part of the published reference when 2.8 is released.

mmafic commented 11 months ago

@klembot

Docker image makes a lot of sense to me.

This feels out-of-scope for Twine and isn't something I'd want to maintain or provide support for, but I would be fine with others doing this.

I agree. It's a tricky problem and I can't think of a better solution that doesn't involve having a server backend.

Do you know if that's possible to use without a server-side component? Last I investigated this and similar services (many years ago), this was required because you needed to use a private API key.

Yes, it is possible without a server. As a matter of fact, I went ahead and implemented it, my demo supports public Google Drive links now. Here's an example:

Google Drive URL - https://drive.google.com/file/d/1w8deghpoGdyfkAsqCNulQyUQx_bd65U3/view?usp=sharing Twinery Demo URL - https://twinery-test.pages.dev/#/preview?url=https://drive.google.com/file/d/1w8deghpoGdyfkAsqCNulQyUQx_bd65U3/view?usp=sharing

mmafic commented 11 months ago

Do you have a Discord? It might be easier and faster to discuss some specifics over Discord. My username is scrim_mm.

greyelf commented 11 months ago

@klembot said What if this existed as a Docker image that runs a web server, offers a simple UI for uploading files to it, and then embeds the Twine UI in read-only mode for viewing?

@mmafic said Docker image makes a lot of sense to me.

While a Docker container/image does sound like a potential solution for some, just remember that many Authors are likely to be using Windows, and that the process for installing Docker on Windows is a little more involved that doing the same on other Operating Systems, especially for Author's that don't have a technical / software developer background.

klembot commented 11 months ago

@mmafic I do. I sent you a friend request just now.

mmafic commented 11 months ago

@greyelf I use Windows too and installing Docker was actually easier than Linux or Mac OS, you just install it like a regular Windows program. Still, you are right, you can't really expect someone without a technical background to be comfortable using Docker.

greyelf commented 11 months ago

@mmafic

you just install it like a regular Windows program.

So you already had Hardware Virtualization enabled at a BIOS level, and depending which path you took either: WSL (2) installed or Hyper-V & Containers Windows enable?

Because the average Windows user doesn't normally have any of those things enabled or installed.

mmafic commented 11 months ago

@greyelf oh hmm, I think my laptop came with hardware virtualization enabled by default, and I did enable Hyper-V and install WSL 2, I didn't realize those were necessary