stretchly icon indicating copy to clipboard operation
stretchly copied to clipboard

[Feature request]: Movement detection, user is back

Open rockrevenchy opened this issue 8 months ago • 10 comments

Version

  • [x] I'm using version 1.17.2

Existing requests

  • [x] I've checked Existing requests

Advanced Preferences

  • [x] I've checked Advanced Preferences

What operating system are you using?

Linux

Operating System Version

Ubuntu 24.04 LTS with KDE plasma 6.3.2 (Wayland) (feature request disregards the platform altho)

Problem description

So basically whenever I go on a break the countdown will do as it should but I will more often than not end up taking my time doing whatever business I went on (walking, washroom, preparing coffee, food, whatever) and then when I come back my computer basically assumed I was back and started counting down to the next break.

My current solution, tho a very lousy one, was to simply reset breaks every single time I came back to my computer rather than have it call another break shortly after I sat down.

Possible solution

The idea I was thinking of was to simply have an option to leave the overlay after the break is over and have it detect any movement, once it does, it resumes as it should

(rather than say postpone this break in the mid bottom it would just say something like "move your mouse/ click/ press any key" or something alike to resume after the break would be over)

Alternative solutions

Perhaps it could quietly do the detection after a break, if no movement is detected after the break, the timer would quietly hang.

Additional information

No response

Code of Conduct

  • [x] I agree to follow this project's Code of Conduct

rockrevenchy avatar Apr 03 '25 21:04 rockrevenchy

Hi, have you tried idle time detection? It should detect that you are not away from PC and pause breaks.

Ah, I see you are on Wayland, where it is currently not working : https://github.com/hovancik/stretchly/issues/1261

hovancik avatar Apr 24 '25 14:04 hovancik

oh interesting, sorry I assumed this was like this regardless of platform

rockrevenchy avatar Apr 24 '25 18:04 rockrevenchy

I’m also very interested in making this happen. Our initial idea was similar but focused more on a super simple version: instead of relying on movement detection (which can be tricky across platforms like Wayland), just have an optional setting where, after the break timer ends, the screen stays on until the user presses any key or clicks to confirm they're back. Only then would it exit the break screen and continue.

simonwinther avatar May 10 '25 15:05 simonwinther

I would love to implement this if I may?

simonwinther avatar May 10 '25 17:05 simonwinther

With all provided language support as well.

simonwinther avatar May 10 '25 17:05 simonwinther

This seems to be the same as https://github.com/hovancik/stretchly/issues/1001#issuecomment-1678621033, I guess we should keep only one open.

Anyway @simonsejse can you describe how you imagine this would work? I prefer to discuss that before implementation to make sure I would merge such a functionality :) I am also in the midle of big migration to ESM #1599 so not good time to start doing code changes :)

hovancik avatar May 14 '25 13:05 hovancik

here's a mockup of how i'd imagine this would look like

Image

I would think it would do the sound it does once the countdown is finished but remain as seen on the picture (or similar)

this option could remain either hidden or somewhere in the configs but probably not on by default

(the background image is because I didnt want to show my desktop mess and I didnt want to change the opacity either lol dont worry about it)

(for reference the keyboard is unicode character 🖮 other characters could do well there too such as 🖰 or 🖳 )

rockrevenchy avatar May 16 '25 01:05 rockrevenchy

That is exactly how @rockrevenchy shows it, yes. I implemented a small working version — not tested thoroughly though.

When enabled, the break screen stays after time runs out until the user presses any key or clicks as @rockrevenchy I love the unicode keyboard for an extra touch.

The following changes I made was the following:

defaultSettings.js

By default it is set to false.

requireKeyPressToContinue: true, // manual resume after microbreak

en.json

"pressAnyKeyOrClickToContinue": "Press any key or click to continue",
"settings": {
  // ...
  "requireKeyPressToContinue": "Require key press to continue",
  // ...
}

preferences.html

Enable disable checkbox in settings.

<div>
  <input type="checkbox"
         value="requireKeyPressToContinue"
         id="requireKeyPressToContinue">
  <label data-i18next="preferences.settings.requireKeyPressToContinue"
         for="requireKeyPressToContinue"></label>
</div>

main.js

Listens for 'break-renderer-waiting-for-keypress' from the renderer and cancels the scheduler’s auto-finish to pause until user interaction.


ipcMain.on('break-renderer-waiting-for-keypress', (event, breakType) => {
  const expectedRef = breakType === 'microbreak' ? 'finishMicrobreak' : 'finishBreak';

  const isActiveWindowRelevant = (breakType === 'microbreak' && microbreakWins && microbreakWins.length > 0) ||
                                (breakType === 'break' && breakWins && breakWins.length > 0);

  if (!isActiveWindowRelevant) {
    log.warn(`Stretchly: Received 'break-renderer-waiting-for-keypress' for ${breakType} but no corresponding windows are active. Ignoring stale message.`);
    return; 
  }

  if (!breakPlanner.scheduler || breakPlanner.scheduler.reference !== expectedRef) {
    log.warn(`Stretchly: Received 'break-renderer-waiting-for-keypress' for active ${breakType}, but scheduler state is unexpected. Scheduler ref: ${breakPlanner.scheduler ? breakPlanner.scheduler.reference : 'null'}. Ignoring cancel.`);
    return;
  }

  log.info(`Stretchly: ${breakType} duration visually ended in renderer, now awaiting interaction. Cancelling main process automatic finish.`);
  breakPlanner.scheduler.cancel(); 
});

microbreaks.js

After the timer ends, this checks requireKeyPressToContinue. If enabled, it hides controls and waits for a key press or mouse click before sending finish-microbreak. Otherwise, it finishes automatically as before. After the timer ends, this checks requireKeyPressToContinue. If enabled, it hides controls, sends 'break-renderer-waiting-for-keypress' to the main process, which cancels the scheduler's auto finish. Then waits for a key press or mouse click before sending finish-microbreak. Otherwise, it finishes automatically as before.

const intervalId = window.setInterval(() => {
  ...
  if (elapsed < duration) {
    ...
  } else {
    clearInterval(intervalId);

    if (settings.get('requireKeyPressToContinue')) {
      if (progress) progress.style.display = 'none';
      if (progressTime) progressTime.style.display = 'none';
      if (postponeElement) postponeElement.style.display = 'none';
      if (closeElement) closeElement.style.display = 'none';

      if (ideaElement) {
        ideaElement.innerHTML = i18next.t('break.pressAnyKeyOrClickToContinue');
        ideaElement.style.fontSize = '1.5em';
        ideaElement.style.textAlign = 'center';
      }

      ipcRenderer.send('break-renderer-waiting-for-keypress', 'microbreak');

      const onInteraction = () => {
        document.removeEventListener('keydown', onInteraction);
        document.removeEventListener('mousedown', onInteraction);
        ipcRenderer.send('finish-microbreak', true, true);
      };

      document.addEventListener('keydown', onInteraction);
      document.addEventListener('mousedown', onInteraction);
    } else {
      ipcRenderer.send('finish-break', true, true);
    }
  }
  ...
}, 100);

If requireKeyPressToContinue is enabled, the microbreak screen will stay up after the timer ends and only go away once the user presses any key or clicks. This prevents auto-starting the next break cycle before you're actually back.

It’s not visually as polished as what @rockrevenchy showed above, but it works well enough for a functional version

Image 1

Image

Image 2

Image

Image 3

Image

And if you click keyboard or mouse it ends as you see on third picture.

simonwinther avatar May 16 '25 12:05 simonwinther

The important thing is that the next break counter does not start before you are back at the computer and interacting with it.

simonwinther avatar May 16 '25 13:05 simonwinther

Any update on this?

simonwinther avatar Jun 01 '25 19:06 simonwinther

I'll take that as a no lol

rockrevenchy avatar Jun 29 '25 08:06 rockrevenchy

This seems to be the same as #1001 (comment), I guess we should keep only one open.

Anyway @simonsejse can you describe how you imagine this would work? I prefer to discuss that before implementation to make sure I would merge such a functionality :) I am also in the midle of big migration to ESM #1599 so not good time to start doing code changes :)

I am still working on rewrite to ESM

hovancik avatar Jun 30 '25 05:06 hovancik

Now that the ESM migration (#1599) is in trunk, a gentle request to consider incorporating the suggestion from @rockrevenchy

I suspect there are going to be increasingly more number of people on Wayland where movement detection doesn't work as well. See #1261

Having a 'Click here to resume' button also seems like a portable solution that ought to work nicely across environments.

balajeerc avatar Oct 22 '25 06:10 balajeerc

Hey, so thinking about this now and I am beggining to think this is a bit different: "Don't stop break unless user says so."

So basically, we should not have countdown of time till end of break, but "yourbreak is going on for X:XX:XX, click here to finish it"

hovancik avatar Oct 25 '25 14:10 hovancik

Yeah, exactly I think just having a simple button you can click would already solve the problem, but ideally it would detect any key press or mouse movement instead.

The version I made earlier worked fine in my virtual machine, but I haven’t tested it properly on a real Ubuntu/Wayland setup yet. Still, I think key or mouse detection would be the nicest option.

Basically, once the timer hits zero, it shouldn’t automatically start the next break cycle. Instead, it should wait until it detects that the user is back, either by pressing a key, moving the mouse, or clicking somewhere.

To give a bit of context: I like having short breaks every 10 minutes or so (just to stretch for 30 seconds), and then longer breaks every 20–30 minutes. But if I take a long break and, say, go to the bathroom, especially the one further away (which Stretchly actually recommends 😄), it can easily take longer than 5 minutes. When I get back, the next timer has already started counting, so I’ve technically “lost” a few minutes of focus time.

That’s why I think it’d be better if the timer only starts again once I’m actually back. And yeah, if movement or key detection is too complex, a simple “Click to continue” button would also be totally fine, but I don’t think the detection part would be that hard to do.

simonwinther avatar Oct 25 '25 14:10 simonwinther

When I get back, the next timer has already started counting, so I’ve technically “lost” a few minutes of focus time.

Yeah my own dirty solution was to bind the reset timer to an easy to access key combination and always hit it when i came back, but that's a risky solution, a easy to reset the timer button is not a great thing to have to really be responsible, it's easy to get the habit to hit it whenever it annoys me slightly haha

(Also i still use a Wayland Ubuntu variant as a daily driver, i could further test on bare metal as needed)

rockrevenchy avatar Oct 29 '25 14:10 rockrevenchy

Yeah, my own dirty solution was to bind the reset timer to an easy-to-access key combination and always hit it when I came back.

That’s actually quite smart; I’ve just been doing it manually with the mouse, which ergonomically is just annoying to repeat every time, so your solution is definitely better. I might use that until (hopefully) this feature request has been implemented. And I don’t mind being the one to look into it, I already have, as seen here haha.

simonwinther avatar Oct 29 '25 14:10 simonwinther

Awesome! Quick question, when is the next release, just an approximation if possible? Is it months away? Or just a couple?

simonwinther avatar Nov 11 '25 13:11 simonwinther

Hey, sorry for delay, I wanted to merge #1670 but I guess I'll make a release and add that later.

hovancik avatar Nov 11 '25 14:11 hovancik

Thanks for the quick reply! No worries at all. Finishing up #1670 first makes perfect sense (so you don't need to have two releases in a row). I was just curious about the rough timing, and your answer was exactly what I needed. Thanks again!😆

simonwinther avatar Nov 13 '25 05:11 simonwinther