Page 1 of 1

Countdown widget

Posted: 01 Nov 2019 19:02
by Gen
Hi,

Hoping someone can assist with a flow I'm struggling to make work. I've searched the forum but still haven't managed to make it work.

I'm trying to create a widget overlay that displays a countdown, the duration of which will be pulled from a speech input value. For example speech input = "2 minutes 30 seconds". The widget will then display: "02:30" and start to countdown the seconds. The input can also be in hours, minutes and seconds.

I'm struggling to take the input value and convert it to a date format to be displayed on the widget .

Thanks,
Gen

Re: Countdown widget

Posted: 01 Nov 2019 21:50
by Horschte
Maybe that brings you a little bit further:

Code: Select all

speech_minutes = 2;
speech_seconds = 30;

now = getDate();
dateNew = addMinutes(now, speech_minutes);
dateNew = addSeconds(dateNew, speech_seconds);

date_diff = dateNew - now;

//02:30
dateFormatted = "{date_diff,dateformat,mm:ss}";
Now you can make a loop, pause for 1 second and substract 1 second from date_diff

Code: Select all

date_diff = addSeconds(date_diff, -1);

//02:29
dateFormatted = "{date_diff,dateformat,mm:ss}";

Re: Countdown widget

Posted: 02 Nov 2019 23:02
by Gen
Hi,

Thanks for your help!

It definitely brings me closer but now I'm struggling to work with hours.

Using your code, if I change dateFormatted to "{date_diff,dateformat,HH:mm:ss}" for some reason it always adds an extra hour. So with the code as is it should display "00:02:30" but it shows "01:02:30". I tried using addHour -1 but it doesn't seem to have an effect.

I would like it to display HH:mm while dateFormatted > 1 hour else mm:ss

Re: Countdown widget

Posted: 03 Nov 2019 16:00
by Horschte

Code: Select all

speech_hours = 0;
speech_minutes = 2;
speech_seconds = 30;

now = getDate();
dateNew = addMinutes(now, speech_minutes);
dateNew = addSeconds(dateNew, speech_seconds);
dateNew = addHours(dateNew, speech_hours-1);

date_diff = dateNew - now;

if(speech_hours < 1){
  dateFormatted = "{date_diff,dateformat,'00':mm:ss}";
}
else{
  dateFormatted = "{date_diff,dateformat,HH:mm:ss}";
}

Re: Countdown widget

Posted: 03 Nov 2019 18:40
by Desmanto
@Gen : Are you living in country where the timezone is UTC + 1? Because when showing time from number, will always get added with your timezone. If you want to show it properly, you should use 0 based timezone, which is UTC.

Code: Select all

dateFormatted = "{date_diff,dateformat,timezone,UTC,HH:mm:ss}";
For the input dialog, if you don't care about the seconds, you can just use input dialog - time. You don't have to convert the string to time first anymore, since the result is already in time. The value have been added with the timezone, so you have to deduct it back. Or simply minus the time with 00:00:00 based of it, you shoudl get the raw difference.

Using loop with sleep 1 second, you can set the widget text for each loop to count until 0.

Re: Countdown widget

Posted: 03 Nov 2019 20:45
by Gen
Hi,

@Desmanto I live in London so I'm currently in GMT but it changes to BST.

Ah I didn't realise there's a "time" speech input type. That would probably have worked but I've managed to achieve the result that I wanted with a script (thank you both for your help!) already and it supports seconds also.

FYI here's the script. As far as I've tested (with hours, minutes etc) it works with no issues. If you see any potential issues or any way I can improve it, please let me know.

Speech input stores input in {value} and then leads to script. Format of time as recognised by speech input varies e.g "1-hour 30 minutes" / "1 hour 30-minutes" hence the first section to replace the values which will be recognised by the getDurationMillis command.

I've also managed to offset the 1 hour difference by using addHour - 1. I guess when we change to BST this will be one hour off again.

Currently it seems in terms of values 00:00:00 is value = -3600000 and 01:00:00 is value = 0 them anything higher than 1 hour is value > 0.

Code: Select all

value=replace(value, "-hours", "h");
value=replace(value, "-hour", "h");
value=replace(value, " hours", "h");
value=replace(value, " hour", "h");
value=replace(value, "-minutes", "m");
value=replace(value, "-minute", "m");
value=replace(value, " minutes", "m");
value=replace(value, " minute", "m");
value=replace(value, "-seconds", "s");
value=replace(value, "-second", "s");
value=replace(value, " seconds", "s");
value=replace(value, " second", "s");

value = addHours((getDurationMillis(value)), -1);

while (value != -3600000) {
  sleep("1s");
  value = addSeconds(value, -1);
  if (value > 0) {
    global_countdown = "{value,dateformat,HH:mm}";
  }
  else {
    global_countdown = "{value,dateformat,mm:ss}";
  }
}
By the way, is there a better way to implement the "replace" section? Maybe a map?

Re: Countdown widget

Posted: 05 Nov 2019 17:32
by Desmanto
Yes, you can use regex to replaceAll(). But since hour, minute and second can be there or not (it can be just 1-hour 30 minutes, without seconds), so replaceAll will get null value when using optional capture. In this case, we better just use regular findAll() and multiply the capture group directlty to convert it to time.

Code: Select all

value = "1-hour 30 minutes";
find = findAll(value, '(?:(\\d+).?hours?)?(?: (\\d+).?minutes?)?(?: (\\d+).?seconds?)?', true);
dur = convertNull(find[0][1], 0) * 3600000 + convertNull(find[0][2], 0) * 60000 + convertNull(find[0][3], 0);
The regex part is very confusing if you never use it before. You might want to look at the youtube : https://www.youtube.com/watch?v=sa-TUpSx1JA

After we get the capture part of each hour minute second, we convert it to the duration by multiplying with each multiplier. convertNull() is to ensure if the value is not there, it will be converted to 0. The result of the dur is 5400000. You can just directly use this and show in the UTC format, without worrying about your timezone.

Just in case if you need to know your exact timezone, you can use the following to get the value you need to add to your time to make it UTC.

Code: Select all

tz = getDate("{0,dateformat,z}", "z");
if you are in BST, tz should -3600000. Which if you add back, will resut the time to be 00:00:00 base.

The rest is the same, you can loop subtract 1000 from the dur and store the value in the glovar. But if the value only used by one widget, it is much faster just to use setWidgetElementProperty(), to immediately apply the value to the text field in the widget. Click function and search for the setWidget.

Re: Countdown widget

Posted: 09 Nov 2019 17:07
by Gen
Awesome, thank you!

I'm almost there but now I have another issue.

I need the widget overlay to keep the screen on while its being displayed but it seems that if the duration is long, the device locks itself even though the widget overlay is still being displayed.

Is there a way to keep the device from locking as long as the widget overlay is displayed?

I tried running sleep with keep device awake checked every second while countdown hasn't reached 0 but it doesn't seem to work.

Re: Countdown widget

Posted: 10 Nov 2019 17:51
by Desmanto
Widget itself can't keep the screen on.

You have to add action at when showing the widget, Set Screen Timeout to Never. Then at the end of the timer, set back again the timeout to your default timeout.

Re: Countdown widget

Posted: 11 Nov 2019 08:07
by Gen
Ah, that works thanks!

Didn't realise there's such an action