Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 66 additions & 37 deletions asset/javascript/TimeController.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,13 @@ function TimerController(reference) {

function bindFullscreenEvents() {
document.addEventListener('fullscreenchange', handleButtonFullscreenChange);
document.addEventListener('visibilitychange', handleVisibilityChange);
}

function handleVisibilityChange() {
if (document.hidden) return;

updatePageTitle();
}

function validateInput(input, maxValue) {
Expand Down Expand Up @@ -161,6 +168,8 @@ function TimerController(reference) {

if (!canStart) return;

reference.classList.remove('inverted');
countdownContainerReference.classList.remove('inverted');
startButton.hideElement();
pauseButton.showElement();
stopButton.showElement();
Expand All @@ -177,27 +186,28 @@ function TimerController(reference) {
TimerStatus.isCountdown(lastTimerStatus) ||
TimerStatus.isPaused(lastTimerStatus);

if (canStart) {
let seconds = getInputsValueAsSeconds();
seconds--;
if (seconds <= 10) {
lastTimerStatus = TimerStatus.COUNTDOWN;
playCountdownSound();
if (!canStart) {
clearInterval(timerIntervalId);
return;
}

if (!preventOpenCountdown) executeCountdown(seconds);
}
let seconds = getInputsValueAsSeconds();
seconds--;
if (seconds <= 10) {
lastTimerStatus = TimerStatus.COUNTDOWN;
playCountdownSound();

setInputValues(seconds);
if (!preventOpenCountdown) executeCountdown(seconds);
}

if (seconds == 0) {
preventOpenCountdown = false;
lastTimerStatus = TimerStatus.STOPPED;
setInputValues(seconds);

showDefaultButtons();
playStopSound();
clearInterval(timerIntervalId);
}
} else {
if (seconds == 0) {
preventOpenCountdown = false;
lastTimerStatus = TimerStatus.STOPPED;

showDefaultButtons();
playStopSound();
clearInterval(timerIntervalId);
}
}, DEFAULT_INTERVAL);
Expand All @@ -220,14 +230,15 @@ function TimerController(reference) {
const fade = setInterval(() => {
if (stopSound.volume > 0.05) {
stopSound.volume -= 0.05;
} else {
stopSound.volume = 0;
stopSound.pause();
stopSound.currentTime = 0;
clearInterval(fade);
setInputValues(DEFAULT_SECONDS);
preventOpenCountdown = false;
return;
}

stopSound.volume = 0;
stopSound.pause();
stopSound.currentTime = 0;
clearInterval(fade);
setInputValues(DEFAULT_SECONDS);
preventOpenCountdown = false;
}, 200);
}, 3000);
}
Expand All @@ -236,39 +247,48 @@ function TimerController(reference) {
countdownContainerReference.showElement();
countdownNumber.textContent = seconds;

countdownContainerReference.classList.toggle('even');
countdownContainerReference.classList.toggle('odd');

if (seconds % 2 === 0) {
countdownContainerReference.classList.add('even');
countdownContainerReference.classList.remove('odd');
reference.classList.add('inverted');
countdownContainerReference.classList.add('inverted');

return;
}

countdownContainerReference.classList.add('odd');
countdownContainerReference.classList.remove('even');
reference.classList.remove('inverted');
countdownContainerReference.classList.remove('inverted');
}

function stop() {
if (TimerStatus.isStopped(lastTimerStatus)) return;

preventOpenCountdown = false;
lastTimerStatus = TimerStatus.STOPPED;
reference.classList.remove('inverted');
countdownContainerReference.classList.remove('inverted');
showDefaultButtons();
setInputValues(DEFAULT_SECONDS);
clearInterval(timerIntervalId);
}

function pause() {
if (lastTimerStatus === TimerStatus.RUNNING || lastTimerStatus === TimerStatus.COUNTDOWN) {
lastTimerStatus = TimerStatus.PAUSED;
startButton.showElement();
pauseButton.hideElement();
clearInterval(timerIntervalId);
}
const shouldNotPause = lastTimerStatus !== TimerStatus.RUNNING && lastTimerStatus !== TimerStatus.COUNTDOWN;
if (shouldNotPause) return;

lastTimerStatus = TimerStatus.PAUSED;

startButton.showElement();
pauseButton.hideElement();

clearInterval(timerIntervalId);
}

function isInFullscreen() {
return !!document.fullscreenElement
return !!document.fullscreenElement;
}

function handleButtonFullscreenChange() {
if (isInFullscreen()) {
exitFullscreenButton.showElement();
Expand All @@ -291,6 +311,8 @@ function TimerController(reference) {

function closeCountdownContainer() {
preventOpenCountdown = true;
reference.classList.remove('inverted');
countdownContainerReference.classList.remove('inverted');
countdownContainerReference.hideElement();
countdownContainerReference.classList.remove('even', 'odd');
countdownNumber.textContent = '';
Expand Down Expand Up @@ -347,6 +369,13 @@ function TimerController(reference) {
hourInput.value = formatTimeUnit(hours);
minuteInput.value = formatTimeUnit(minutes);
secondInput.value = formatTimeUnit(seconds);

updatePageTitle();
}

function updatePageTitle() {
const { seconds, minutes, hours } = getInputValues();
document.title = `${formatTimeUnit(hours)}:${formatTimeUnit(minutes)}:${formatTimeUnit(seconds)} - Timer <Codecon>`;
}

init();
Expand All @@ -358,4 +387,4 @@ document.addEventListener('DOMContentLoaded', function () {
window.timerController = timerController;
});

export default TimerController;
export default TimerController;
28 changes: 19 additions & 9 deletions asset/javascript/__tests__/TimerIntegration.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ describe('TimerController Integration', () => {

beforeEach(() => {
mockReference = {
classList: {
add: jest.fn(),
remove: jest.fn(),
contains: jest.fn(),
toggle: jest.fn(),
},
querySelector: jest.fn(selector => {
if (selector === '.js-stopwatch-action-buttons') {
return mockElement();
Expand All @@ -25,21 +31,25 @@ describe('TimerController Integration', () => {

it('deve iniciar, pausar e parar o timer corretamente', () => {
const timerController = new TimerController(mockReference);

const startButton = mockReference.querySelector('.js-stopwatch-action-buttons').querySelector('.js-start-button');

const startButton = mockReference
.querySelector('.js-stopwatch-action-buttons')
.querySelector('.js-start-button');
expect(startButton.addEventListener).toHaveBeenCalledWith('click', expect.any(Function));

const startHandler = startButton.addEventListener.mock.calls[0][1];
startHandler();

expect(startButton.hideElement).toHaveBeenCalled();

const pauseButton = mockReference.querySelector('.js-stopwatch-action-buttons').querySelector('.js-pause-button');

const pauseButton = mockReference
.querySelector('.js-stopwatch-action-buttons')
.querySelector('.js-pause-button');
expect(pauseButton.addEventListener).toHaveBeenCalledWith('click', expect.any(Function));

const pauseHandler = pauseButton.addEventListener.mock.calls[0][1];
pauseHandler();

expect(pauseButton.hideElement).toHaveBeenCalled();
});
});
});
Loading