Sugarcube 2.36.1: Dialog box flashes when its contents are changed

Twine Version: tweego, version 2.1.1+81d1d71 (I assume that means Twine 2?)
Story Format: sugarcube-2.36.1

I’ve tried to use the <<repeat>> macro inside of a passage which is used inside of a Dialog to display a timer. The timer’s contents are changed using the <<replace>> macro every second to display the remaining seconds left on the timer. However, this causes elements inside of the passage to flash when the content of the passage is changed. You can see an example that I’ve made to isolate the issue here:

dialog-chromium

Note that on the second iteration, it looks like it wasn’t flashing - that’s because the gif wasn’t capturing at enough frames to display it. It did flash on my screen.

For context, the initial effect I was trying to achieve was an error dialog with a counting timer, and multiple buttons you could press to help resolve the error. If there’s a better way to achieve this without transitioning out of the passage, I’m open to suggestions.

I’ve uploaded a minimal example here: https://github.com/MoyTW/TwineFlashingDialogExample and include the full source of the example below.

:: StoryTitle
Flashing Dialog Timer Example


:: StoryData
{
	"ifid": "532D481D-F971-4209-ACED-33CFD818D24B"
}


:: Start
<<button 'Show Blinking Dialog'>>
  <<script>>
    Dialog.setup('Timer Dialog');
    Dialog.wiki(Story.get('BlinkingDialogPassage').processText());
    Dialog.open();
  <</script>>
<</button>>
<<script>>
  // Clean up the timers on dialog closed so you don't spawn new timers every open.
  // If there's a nicer way to do it advice would be welcome!
  $(document).on(':dialogclosed', function (ev) {
    const timers = Macro.get('repeat').timers
    for (let timerId of timers) {
      clearInterval(timerId);
      timers.delete(timerId);
    }
  })
<</script>>


:: BlinkingDialogPassage
<<set _currentTime to 1>>\
Current time is @@#time-display;_currentTime@@

<<button 'Example button (nonfunctional)'>><</button>>
<<silently>>
  <<repeat 1s>>
    <<set _currentTime to _currentTime + 1>>

    /* It does not blink without this replace */
    <<replace '#time-display'>>_currentTime<</replace>>

    /* Using run & a selector also causes it to blink */
    /* <<run $('#time-display').text(State.temporary.currentTime)>> */
  <</repeat>>
<</silently>>

Thanks!

Looks like it’s caused by a MutationObserver on the dialog box which is updating the size of the dialog box every time you you change its content, despite the size of the dialog box not actually changing. See the SugarCube dialog.js source.

It could probably be fixed by having SugarCube only update the size of the dialog box if the dimensions would actually change, which (unless you want to patch the code yourself) means contacting the author of SugarCube, @TheMadExile, to modify that.

I’d recommend creating a SugarCube issue bug report up at GitHub to get that fixed. Feel free to reference my comment here.

I’ll also note that the problem was more pronounced for me on Firefox than on Chrome or Opera.

If you don’t want to wait for a fix, your best option is probably to simply create your own dialog box. Take a look at the dialog.js source I linked to above, and it should help show you how to do that.

Hope that helps! :slight_smile:

Yeah, thanks, that helped! I cloned the repo and wrote a patch that seems to have resolved that locally.

I can file a bug, but do you know if the maintainer takes PRs? I can put up a PR for it or post my code or something if that’d be useful.

For the record, here’s the change I made: Modify _resizeHandler to resize selectively · MoyTW/sugarcube-2@19bf58e · GitHub

I believe that they do take pull requests (PRs), just make sure you explain it in an issue you report.

Glad you got it working! :slight_smile: