Porting timer widget from the Touch Bar to a floating menu

Here is a simple timer example:
timer_example.bttpreset (46.2 KB)

The time is input in this format (examples):

1min

1h

1h 10min 5s

10min

30s

image

function parseDuration(duration) {
    const units = {
        h: 3600,
        min: 60,
        s: 1
    };
    
    // Regex to match the number followed by the unit (h, min, s)
    const regex = /(\d+)(h|min|s)/g;
    let totalSeconds = 0;
    let match;

    while ((match = regex.exec(duration)) !== null) {
        const value = parseInt(match[1], 10);
        const unit = match[2];
        totalSeconds += value * units[unit];
    }

    return totalSeconds;
}

function formatDuration(seconds) {
    const hours = Math.floor(seconds / 3600);
    const minutes = Math.floor((seconds % 3600) / 60);
    const secs = seconds % 60;

    // Pad with zeros to ensure two digits for minutes and seconds
    const formattedHours = String(hours).padStart(2, '0');
    const formattedMinutes = String(minutes).padStart(2, '0');
    const formattedSeconds = String(secs).padStart(2, '0');

    return `${formattedHours}:${formattedMinutes}:${formattedSeconds}`;
}

async function startTimer() {
	let duration = await get_string_variable("timerTime");
 	let durationInSeconds = parseDuration(duration);
	timer(durationInSeconds);
}

async function timer(durationInSeconds = 10) {

	if(durationInSeconds == 0) {
		const updateDescription = {"BTTMenuItemText": "Time is up!", "BTTMenuItemBackgroundColor": "233, 0, 0, 255"};
   await update_menu_item({"item_uuid": "1D974882-9376-4B09-81FC-E427F79CBD25", "json": JSON.stringify(updateDescription), "persist": true})
   
	} else {

	const updateDescription = {"BTTMenuItemText": formatDuration(durationInSeconds), "BTTMenuItemBackgroundColor": "0, 0, 0, 255"};
   await update_menu_item({"item_uuid": "1D974882-9376-4B09-81FC-E427F79CBD25", "json": JSON.stringify(updateDescription), "persist": true})
   

   setTimeout(() => {
   	timer(durationInSeconds-1);	
   }, 1000);

}
	return "done"
}