Open Staninna opened 11 months ago
You're absolutely right! So I dove into the prototype code for you to see what would have to be done, and I found something! In this post I'll describe a way to communicate and a problem I noticed.
Looking at the system again, I feel it's currently technically possible, however the whole way of setting interaction data not very intuitive.
It should be possible for the interaction screen (on a user's phone) to postMessage just like the slide would. This is because the interaction screen is the same webpage as the slide on the monitor, except it has #interaction-{local_user_id}
as the anchor.
Sending any message from the slide, or any client will cause a message to be sent to the API and sent back to any listening slide/client:
// untested psuedo-code
window.parent.postMessage({
type: 'requestSetInteractionData',
data: {
user_quiz_actions: {
"tl10": [ "a", "c", "b" ],
"staninna": [ "c", "b", "a" ],
},
},
}, '*');
The slide (or any other user interaction screen) could listen for it, similar to how the slide listens in the betting example, but then in the interaction screen:
// untested psuedo-code
function interactionScreen(localId) {
window.addEventListener('message', function(event) {
if (event.data.type === 'onInteractionData') {
const interactionData = event.data.data;
const localAnswers = interactionData.user_quiz_actions[localId];
document.querySelector('#yourAnswers').innerText = localAnswers.join(', ');
}
});
}
Both the slide and all connected interaction screens (users) would get that data update.
If you have trouble implementing this let me know and I'll help out!
Here's a sketch showing how the same slide displays different content based on whether it's on the screen or on a user's phone. (I doubt it makes the situation much clearer, but I drew it already so just dumping it here)
Although the above should work, it's not at all safe. Seeing how a user could modify (and thus cheat) the data in any way. Since the server blindly accepts any requestSetInteractionData
and sets it in the database as the data. A user could set the contents of user_quiz_actions
to anything. They could change answers after they've been submitted, submit answers for the other user, etc.
If things work as I describe, then I'd like to turn this issue into a bug/security fix, there must be some way to set data from the slide authoritatively (so the slide can later know for sure it was the one to set data).
A low-effort fix that I'm thinking could resolve this is as follows (contains psuedo-code):
X-Secret-Tick-Key
with every request. The API could use this to authorize the slide and know that it was legit. If a slide then sets interaction data like requestSetInteractionData({ data.any_key: 10 })
the API would allow it, since the slide can write anywhere.requestSetInteractionData({ data.users.tl10.answers: ['a', 'b'] })
. This would work, but only the screen shown to me.data.any_key
), the API would reject it, since the screen can only write to data.users.tl10
.Let me know if you manage to implement bidirectional communication. Especially let me know if you have suggestions on how to improve the system, so we get the right tools to make cool stuff.
Thanks for the tips. I'll give this a shot soon and let you know how it goes. Appreciate the help!
I played a bit around, but I can't get it to work, here is my current draft: gist
Your code looks like it should work based on what I explained, but now looking at it again I've made a mistake: https://github.com/curio-team/narrowblast/blob/1bde5753138fca76543b02ad70cfaf3c747497ea/resources/views/app/slides/iframe-scripts.blade.php#L373C21-L373C52
This code finds the iframe to send the interaction data to by checking the data.publicPath
, which only points to the slide URL (which doesn't end in #interaction-etc
). If you were to trim the hash off (data.publicPath.split('#')[0]
) in the location I linked, I feel that your code might work.
I woke up thinking it might possibly be more complicated than I made it out to be. I'll try find some time this weekend to actually run, test and change the code. Instead of trying to read it and deduce it's workings. I'll let you know if I find something
The way invites work now doesn't let data move between the client and the server (slide). This makes it hard for interactive stuff like games or quizzes to work properly. Even though it's in early development, it's important to let the client and server talk using for example JSON.