Compare commits

...

10 Commits

Author SHA1 Message Date
Wanja Krah
b9cbfa0d50 Package lock maintenance
Some checks failed
Build and Deploy develop / builds (push) Has been cancelled
2025-04-03 16:35:37 +02:00
32b244a42e should run on host 2024-12-28 20:41:04 +01:00
94e5973f88 docker action yaml 2024-12-28 20:32:19 +01:00
712baefa7f opzet voor gitea actions 2024-12-26 21:30:35 +01:00
dd6dbb6236 docker setup 2024-12-26 20:24:15 +01:00
170b472545 prevents the stop-sound being placed twice 2024-12-17 21:35:43 +01:00
e2232af098 fixes the end-of-timer-chime being played continiously 2024-12-17 21:29:54 +01:00
2a1a68e969 leesbare tijdseenheid in stats plus timer door laten lopen na einde 2024-12-10 18:55:32 +01:00
cf3f5b11ac correct timers 2024-12-09 21:20:09 +01:00
64ca83083e working on logging process and adding sounds 2024-12-03 11:56:54 +01:00
10 changed files with 739 additions and 323 deletions

View File

@@ -0,0 +1,39 @@
name: Build and Deploy develop
on:
push:
branches:
- develop
jobs:
builds:
runs-on: host
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: '20'
- name: Install dependencies
run: |
npm install
npm install -g @angular/cli
- name: Build Angular project
run: ng build --configuration=production
- name: Build Docker image
run: |
docker build -t 192.168.2.28:5050/tusha-fe:latest .
- name: Push Docker image
env:
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
run: |
echo "${DOCKER_PASSWORD}" | docker login -u "${DOCKER_USERNAME}" --password-stdin
docker push 192.168.2.28:5050/tusha-fe:latest

16
Dockerfile Normal file
View File

@@ -0,0 +1,16 @@
FROM node:20-bullseye as build
WORKDIR /app
COPY package*.json ./
RUN npm install
RUN npm install -g @angular/cli
COPY . ./
RUN ng build --configuration=production
FROM nginx:latest
COPY --from=build app/dist/aftas-angular /usr/share/nginx/html
EXPOSE 80

View File

@@ -126,7 +126,10 @@
} }
}, },
"cli": { "cli": {
"schematicCollections": ["@ionic/angular-toolkit"] "schematicCollections": [
"@ionic/angular-toolkit"
],
"analytics": false
}, },
"schematics": { "schematics": {
"@ionic/angular-toolkit:component": { "@ionic/angular-toolkit:component": {

867
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,29 +1,58 @@
import {FocusState} from "./focus-state"; import {FocusState} from "./focus-state";
import {state} from "@angular/animations";
export class FocusStats { export class FocusStats {
private _focusCycles: number = 0; private _focusCycles: number = 0;
private _focusTimeInMs: number = 0; private _focusTimeInMs: number = 0;
private _focusTime: string = '';
private _shortBreakCycles: number = 0; private _shortBreakCycles: number = 0;
private _longBreakCycles: number = 0; private _longBreakCycles: number = 0;
private _breakTimeInMs: number = 0; private _breakTimeInMs: number = 0;
private _breakTime: string = '';
inc(state: FocusState, deltaInMs?: number): void { inc(state: FocusState, deltaInMs?: number): void {
switch (state) { switch (state) {
case FocusState.FOCUS: case FocusState.FOCUS:
this._focusCycles++; this._focusCycles++;
this._focusTimeInMs += !!deltaInMs ? deltaInMs : 0; this._focusTimeInMs += !!deltaInMs ? deltaInMs : 0;
this.updateFocusTime();
break; break;
case FocusState.SHORT_BREAK: case FocusState.SHORT_BREAK:
this._shortBreakCycles++; this._shortBreakCycles++;
this._breakTimeInMs += !!deltaInMs ? deltaInMs : 0; this._breakTimeInMs += !!deltaInMs ? deltaInMs : 0;
this.updateBreakTime();
break; break;
case FocusState.LONG_BREAK: case FocusState.LONG_BREAK:
this._longBreakCycles++; this._longBreakCycles++;
this._breakTimeInMs += !!deltaInMs ? deltaInMs : 0; this._breakTimeInMs += !!deltaInMs ? deltaInMs : 0;
this.updateBreakTime();
break; break;
default: default:
// nothing // nothing
break;
}
}
private updateFocusTime() {
this._focusTime = this.transformTime(this._focusTimeInMs);
}
private updateBreakTime() {
this._breakTime = this.transformTime(this._breakTimeInMs);
}
private transformTime(ms: number): string {
const totalSeconds = Math.floor(ms / 1000);
const seconds = totalSeconds % 60;
const totalMinutes = Math.floor(totalSeconds / 60);
const minutes = totalMinutes % 60;
const hours = Math.floor(totalMinutes / 60);
const pad = (n: number) => n.toString().padStart(2, "0");
if (hours > 0) {
return `${pad(hours)}:${pad(minutes)}:${pad(seconds)}`;
} else {
return `${pad(minutes)}:${pad(seconds)}`;
} }
} }
@@ -31,10 +60,6 @@ export class FocusStats {
return this._focusCycles; return this._focusCycles;
} }
get focusTimeInMs(): number {
return this._focusTimeInMs;
}
get shortBreakCycles(): number { get shortBreakCycles(): number {
return this._shortBreakCycles; return this._shortBreakCycles;
} }
@@ -43,7 +68,12 @@ export class FocusStats {
return this._longBreakCycles; return this._longBreakCycles;
} }
get breakTimeInMs(): number {
return this._breakTimeInMs; get focusTime(): string {
return this._focusTime;
}
get breakTime(): string {
return this._breakTime;
} }
} }

View File

@@ -75,7 +75,7 @@
</ion-item> </ion-item>
<ion-item> <ion-item>
<ion-label> <ion-label>
<p>Focus tijd: <span>{{ ($stats | async)?.focusTimeInMs}}</span></p> <p>Focus tijd: <span>{{ ($stats | async)?.focusTime}}</span></p>
</ion-label> </ion-label>
</ion-item> </ion-item>
<ion-item> <ion-item>
@@ -90,7 +90,7 @@
</ion-item> </ion-item>
<ion-item> <ion-item>
<ion-label> <ion-label>
<p>Pauze tijd: <span>{{ ($stats | async)?.breakTimeInMs}}</span></p> <p>Pauze tijd: <span>{{ ($stats | async)?.breakTime}}</span></p>
</ion-label> </ion-label>
</ion-item> </ion-item>
</ion-list> </ion-list>

View File

@@ -32,6 +32,8 @@ export class FocusPage implements OnInit, OnDestroy {
$stats: Observable<FocusStats> = this.focusService.$stats; $stats: Observable<FocusStats> = this.focusService.$stats;
private endOfTimerChime: HTMLAudioElement; private endOfTimerChime: HTMLAudioElement;
private forcedEndOfTimerChime: HTMLAudioElement;
private windUpChime: HTMLAudioElement;
pathD: string = 'M100 10 A90 90 0 1 1 0 0'; pathD: string = 'M100 10 A90 90 0 1 1 0 0';
@@ -39,6 +41,8 @@ export class FocusPage implements OnInit, OnDestroy {
constructor(private renderer: Renderer2, private focusService: FocusService) { constructor(private renderer: Renderer2, private focusService: FocusService) {
this.endOfTimerChime = new Audio('../../../assets/race-start-beeps-125125.mp3'); this.endOfTimerChime = new Audio('../../../assets/race-start-beeps-125125.mp3');
this.forcedEndOfTimerChime = new Audio('../../../assets/hardstop.mp3');
this.windUpChime = new Audio('../../../assets/wind-up.mp3');
} }
ngOnInit() { ngOnInit() {
@@ -63,20 +67,24 @@ export class FocusPage implements OnInit, OnDestroy {
} }
private update() { private update() {
const elapsed = Math.round((Date.now() - (this.timerStarted!)) / 1000); // in seconden const elapsed = this.timerStarted ? Math.round((Date.now() - (this.timerStarted)) / 1000) : 0; // in seconden
let progress = elapsed / (this.duration * 60); // from 0 to 1 let progress = elapsed / (this.duration * 60); // from 0 to 1
if( progress === 0) { if( progress === 0) {
progress = 0.0000001; // otherwise no graph progress = 0.0000001; // otherwise no graph
} }
if (progress >= 1) { if (progress >= 1 || isNaN(progress)) {
if (this.duration === 0) {
clearInterval(this.interval);
this.timerStarted = null;
}
else if (progress === 1) {
this.endOfTimerChime.play().catch(error => {
console.error('Error playing audio:', error);
});
}
progress = 1; progress = 1;
this.endOfTimerChime.play().catch(error => {
console.error('Error playing audio:', error);
});
clearInterval(this.interval);
this.timerStarted = null;
} }
this.renderer.setStyle( this.renderer.setStyle(
@@ -95,8 +103,9 @@ export class FocusPage implements OnInit, OnDestroy {
this.pathD = 'M100 10 A90 90 0 ' + (percentage > 0.5 ? '1' : '0') + ' 1 ' + circleEndX + ' ' + circleEndY; this.pathD = 'M100 10 A90 90 0 ' + (percentage > 0.5 ? '1' : '0') + ' 1 ' + circleEndX + ' ' + circleEndY;
const twoNumbers = (n: number) => n < 10 && n >= 0 ? '0' + n.toString() : n.toString(); const twoNumbers = (n: number) => n < 10 && n >= 0 ? '0' + n.toString() : n.toString();
this.minutesText = twoNumbers(Math.max(Math.floor(timeLeft / 60), 0)); const floorPositiveCeilNegative = (n: number): number => n > 0 ? Math.floor(n) : Math.ceil(n);
this.secondsText = twoNumbers(Math.max(Math.floor(timeLeft % 60), 0)); this.minutesText = twoNumbers(Math.abs(floorPositiveCeilNegative(timeLeft / 60)));
this.secondsText = twoNumbers(Math.abs(floorPositiveCeilNegative(timeLeft % 60)));
this.dashOffset = elapsed; this.dashOffset = elapsed;
} }
@@ -121,27 +130,50 @@ export class FocusPage implements OnInit, OnDestroy {
stopTimer() { stopTimer() {
this.focusRuns = 0; this.focusRuns = 0;
this.state = FocusState.STOPPED; this.state = FocusState.STOPPED;
this.stopStatsCounter();
this.startTimer(0); this.startTimer(0);
this.forcedEndOfTimerChime.play().catch(error => {
console.error('Error playing audio:', error);
});
}
private stopStatsCounter() {
this.focusService.stopCurrent(this.timerStarted !== null);
} }
focus() { focus() {
this.windUpChime.play().catch(error => {
console.error('Error playing audio:', error);
});
this.state = FocusState.FOCUS; this.state = FocusState.FOCUS;
this.startTimer(25); this.stopStatsCounter();
this.focusService.startFocus();
this.startTimer(0.3); // 25
} }
reload() { reload() {
this.windUpChime.play().catch(error => {
console.error('Error playing audio:', error);
});
if (!!this.timerStarted) { if (!!this.timerStarted) {
this.focusRuns = 0; this.focusRuns = 0;
} }
this.state = FocusState.SHORT_BREAK; this.state = FocusState.SHORT_BREAK;
this.startTimer(5); this.stopStatsCounter();
this.focusService.startShortBreak();
this.startTimer(0.1); // 5
} }
recharge() { recharge() {
this.windUpChime.play().catch(error => {
console.error('Error playing audio:', error);
});
if (!!this.timerStarted) { if (!!this.timerStarted) {
this.focusRuns = 0; this.focusRuns = 0;
} }
this.state = FocusState.LONG_BREAK; this.state = FocusState.LONG_BREAK;
this.startTimer(15); this.stopStatsCounter();
this.focusService.startLongBreak();
this.startTimer(0.2); // 15
} }
} }

View File

@@ -37,35 +37,4 @@ export class FocusService {
this.statsSubject.next(this.localStats); this.statsSubject.next(this.localStats);
} }
} }
private formatDelta(deltaInMs: number) {
const totalSeconds = Math.floor(deltaInMs / 1000);
const hours = Math.floor(totalSeconds / 3600);
const minutes = Math.floor((totalSeconds % 3600) / 60);
const seconds = totalSeconds % 60;
const padZero = (num: number) => num.toString().padStart(2, '0');
return `${padZero(hours)}:${padZero(minutes)}:${padZero(seconds)}`;
}
getFocusCycles(): number {
return this.localStats.focusCycles;
}
getFocusTime(): string {
return this.formatDelta(this.localStats.focusTimeInMs);
}
getShortBreakCycles(): number {
return this.localStats.shortBreakCycles;
}
getLongBreakCycles(): number {
return this.localStats.longBreakCycles;
}
getBreakTime(): string {
return this.formatDelta(this.localStats.breakTimeInMs);
}
} }

BIN
src/assets/hardstop.mp3 Normal file

Binary file not shown.

BIN
src/assets/wind-up.mp3 Normal file

Binary file not shown.