Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Changing theme causes Race Timer widget to lose track of is start/pause state #334

Merged
merged 1 commit into from
Mar 21, 2024
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
49 changes: 36 additions & 13 deletions src/app/core/services/timers.service.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { Injectable } from '@angular/core';
import { Injectable, ɵisComponentDefPendingResolution } from '@angular/core';

import { BehaviorSubject, Observable } from 'rxjs';


interface IKipTimer {
currentValue: BehaviorSubject<number>;
timeoutID: ReturnType<typeof setInterval>|null;
timeoutID: ReturnType<typeof setInterval> | null;
intervalMS: number;
}

Expand All @@ -20,11 +20,23 @@ export class TimersService {

kipTimers: IKipTimers = {};

constructor() {
constructor() {

}

createTimer(timerName: string, count: number, timerInterval: number): Observable<number> {
/**
* Create service timer. The timer notification schedules is based on the timerInterval value and
* the number of count to apply. Adjust the interval according to the use case and reduce
* unnecessary app events. A timerInterval of 1000 ms with count of 60 is 60 * 1000ms =
* 1 minutes and would generate a Subject event and Observer processing every second.
*
* @param {string} timerName Used as the ID id the timer
* @param {number} count Number of steps to execute. This number is a factor of timerInterval. Use negative values to countdown
* @param {number} timerInterval Count interval in milliseconds
* @return {*} {Observable<number>} Timer count value as a number
* @memberof TimersService
*/
public createTimer(timerName: string, count: number, timerInterval: number): Observable<number> {
// return if exists
if (timerName in this.kipTimers) {
return this.kipTimers[timerName].currentValue.asObservable();
Expand All @@ -39,35 +51,46 @@ export class TimersService {
}


startTimer(timerName: string) {

public startTimer(timerName: string) {
if (!this.kipTimers.hasOwnProperty(timerName)) { return; }

if (this.kipTimers[timerName].timeoutID !== null) { return ; } // already running

this.kipTimers[timerName].timeoutID = setInterval(()=>{
if (this.kipTimers[timerName].timeoutID !== null) { return } // already running

this.kipTimers[timerName].timeoutID = setInterval(() => {
this.kipTimers[timerName].currentValue.next(this.kipTimers[timerName].currentValue.value + 1)
}, this.kipTimers[timerName].intervalMS);

}

stopTimer(timerName: string) {
public stopTimer(timerName: string) {
if (!this.kipTimers.hasOwnProperty(timerName)) { return; }
if (this.kipTimers[timerName].timeoutID === null) { return; } // already Stopped
clearInterval(this.kipTimers[timerName].timeoutID);
this.kipTimers[timerName].timeoutID = null;
}


setTimer(timerName: string, timerValue: number) {
public setTimer(timerName: string, timerValue: number) {
if (!this.kipTimers.hasOwnProperty(timerName)) { return; }
this.kipTimers[timerName].currentValue.next(timerValue);
}


deleteTimer(timerName: string) {
public deleteTimer(timerName: string) {
if (!this.kipTimers.hasOwnProperty(timerName)) { return; }
this.stopTimer(timerName);
delete this.kipTimers[timerName];
}


public isRunning(timerName: string) : boolean {
let running: boolean = false;
if (timerName in this.kipTimers) {
running = this.kipTimers[timerName].timeoutID === null ? false : true;
};

return running;
}


}
69 changes: 34 additions & 35 deletions src/app/widgets/widget-race-timer/widget-race-timer.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export class WidgetRaceTimerComponent extends BaseWidgetComponent implements OnI
flashOn: boolean = false;
flashInterval;
timerRunning: boolean = false;
readonly timeName: string = "race";
private warnColor: string = null;
private warmContrast: string = null;
private textColor: string = null;
Expand Down Expand Up @@ -53,19 +54,11 @@ export class WidgetRaceTimerComponent extends BaseWidgetComponent implements OnI
// this.resizeWidget();
}

ngOnDestroy() {
this.unsubscribeTimer();
if (this.flashInterval) {
clearInterval(this.flashInterval);
this.flashInterval = null;
}
}

onResized(event: ResizedEvent) {
this.resizeWidget();
}

resizeWidget() {
private resizeWidget() {
let rect = this.canvasEl.nativeElement.getBoundingClientRect();

if (rect.height < 50) { return; }
Expand All @@ -82,12 +75,11 @@ export class WidgetRaceTimerComponent extends BaseWidgetComponent implements OnI

}

subscribeTimer() {
this.unsubscribeTimer();

let length = (this.widgetProperties.config.timerLength*-1)*10;
private subscribeTimer() {
this.timerRunning = this.TimersService.isRunning(this.timeName);
const length = (this.widgetProperties.config.timerLength * -1) * 10;

this.timerSub = this.TimersService.createTimer("race", -3000, 100).subscribe(
this.timerSub = this.TimersService.createTimer(this.timeName, -3000, 100).subscribe(
newValue => {
this.dataValue = newValue;

Expand Down Expand Up @@ -119,56 +111,49 @@ export class WidgetRaceTimerComponent extends BaseWidgetComponent implements OnI
);
}

unsubscribeTimer() {
if (this.timerSub !== null) {
this.timerSub.unsubscribe();
this.timerSub = null;
}
}

startTimer() {
this.TimersService.startTimer("race");
public startTimer() {
this.TimersService.startTimer(this.timeName);
this.timerRunning = true;
}

resetTimer() {
public resetTimer() {
this.unsubscribeTimer();
this.TimersService.deleteTimer("race");
this.TimersService.deleteTimer(this.timeName);
this.timerRunning = false;
this.subscribeTimer();
}

pauseTimer() {
this.TimersService.stopTimer("race");
public pauseTimer() {
this.TimersService.stopTimer(this.timeName);
this.timerRunning = false;
}

roundToMin() {
public roundToMin() {
let v = this.dataValue;
if (this.dataValue < 0) { v = v *-1} // always positive
if (this.dataValue < 0) { v = v * -1} // always positive
var seconds = v % 600;

if (this.dataValue > 0) {
if (seconds > 300) {
this.TimersService.setTimer("race", this.dataValue + (600 - seconds));
this.TimersService.setTimer(this.timeName, this.dataValue + (600 - seconds));
} else {
this.TimersService.setTimer("race", this.dataValue - seconds);
this.TimersService.setTimer(this.timeName, this.dataValue - seconds);
}
} else {
if (seconds > 300) {
this.TimersService.setTimer("race", this.dataValue - (600 - seconds));
this.TimersService.setTimer(this.timeName, this.dataValue - (600 - seconds));
} else {
this.TimersService.setTimer("race", this.dataValue + seconds);
this.TimersService.setTimer(this.timeName, this.dataValue + seconds);
}
}
}

addOneMin() {
this.TimersService.setTimer("race", this.dataValue + 600);
this.TimersService.setTimer(this.timeName, this.dataValue + 600);
}

remOneMin() {
this.TimersService.setTimer("race", this.dataValue - 600);
this.TimersService.setTimer(this.timeName, this.dataValue - 600);
}

private getColors(themeColor: string) {
Expand Down Expand Up @@ -205,6 +190,20 @@ export class WidgetRaceTimerComponent extends BaseWidgetComponent implements OnI
}
}

private unsubscribeTimer() {
if (!this.timerSub?.closed) {
this.timerSub.unsubscribe();
}
}

ngOnDestroy() {
this.unsubscribeTimer();
if (this.flashInterval) {
clearInterval(this.flashInterval);
this.flashInterval = null;
}
}

/* ******************************************************************************************* */
/* ******************************************************************************************* */
/* ******************************************************************************************* */
Expand Down