Skip to content

Commit

Permalink
extract countdown logic into dedicated component
Browse files Browse the repository at this point in the history
  • Loading branch information
Joao Leonardo Pereira committed Jul 19, 2024
1 parent c450c74 commit 0c09e6a
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
</ion-row>
<ion-row>
<ion-col size="12">
<h2>{{timer}}s</h2>
<app-countdown-timer #countdownTimer [seconds]="tokenCountdown" (timerEnd)="timerEnd()"></app-countdown-timer>
</ion-col>
</ion-row>
</ng-container>
Expand Down
56 changes: 33 additions & 23 deletions src/app/components/account-detail/account-detail.component.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,28 @@
import { Component, Input } from '@angular/core';
import { Component, Input, ViewChild } from '@angular/core';
import { ToastController } from '@ionic/angular';
import { Account2FA } from 'src/app/models/account2FA.model';
import { OtpService } from 'src/app/services/otp.service';
import { CountdownTimerComponent } from '../countdown-timer/countdown-timer.component';
import { debounceTime, pipe } from 'rxjs';

@Component({
selector: 'app-account-detail',
templateUrl: './account-detail.component.html',
styleUrls: ['./account-detail.component.scss'],
})
export class AccountDetailComponent {
@ViewChild(CountdownTimerComponent) countdownTimer!: CountdownTimerComponent;

private timerRefreshInterval: any
private _account?: Account2FA
timer: number = 0
private _token = '000 000'

private _tokenCountdown = 30
private debounceTimeout: any
@Input() set account(value: Account2FA | undefined) {
this._account = value
this.updateTokenCountdown()
this.updateCode()
this.updateTimer()
}

get account(): Account2FA | undefined {
return this._account
}
Expand Down Expand Up @@ -54,6 +57,17 @@ export class AccountDetailComponent {
return this._token
}

private set tokenCountdown(value: number) {
this._tokenCountdown = value
setTimeout(() => {
this.countdownTimer?.startTimer()
}, 50);
}

get tokenCountdown(): number {
return this._tokenCountdown
}

async copyCode(evt: any) {
if(!this.account) {
return
Expand All @@ -70,24 +84,11 @@ export class AccountDetailComponent {
await toast.present()
}

updateTimer() {
if(this.timerRefreshInterval) {
clearInterval(this.timerRefreshInterval)
}
if(this.account) {
this.timer = this.account.getNextRollingTimeLeft()
this.timerRefreshInterval = setInterval(() => {
if(!this.account) {
clearInterval(this.timerRefreshInterval)
this.timer = NaN
} else {
this.timer = this.account.getNextRollingTimeLeft()
if (this.timer == this.account.interval) { // new code needed
this.updateCode()
}
}
}, 500) // for precision purposes update every 500ms
}
timerEnd() {
setTimeout(() => {
this.updateCode()
this.updateTokenCountdown()
}, 1000);
}

updateCode() {
Expand All @@ -96,4 +97,13 @@ export class AccountDetailComponent {
this.token = this.otpService.generateTOTP(this.account.secret, this.account.interval)
}
}

private updateTokenCountdown() {
if(!this.debounceTimeout) {
this.debounceTimeout = setTimeout(() => {
this.tokenCountdown = this.account?.getNextRollingTimeLeft() || this.account?.interval || 30
this.debounceTimeout = undefined
}, 150)
}
}
}
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
<p>
countdown-timer works!
</p>
<h2>{{timerLabel}}s</h2>
51 changes: 48 additions & 3 deletions src/app/components/countdown-timer/countdown-timer.component.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,59 @@
import { Component, OnInit } from '@angular/core';
import { Component, EventEmitter, Input, Output } from '@angular/core';

@Component({
selector: 'app-countdown-timer',
templateUrl: './countdown-timer.component.html',
styleUrls: ['./countdown-timer.component.scss'],
})
export class CountdownTimerComponent implements OnInit {
export class CountdownTimerComponent {
private timerRefreshInterval: any
private _timerStartTime = 0
private _seconds = 0
@Input() set seconds(value: number) {
this._seconds = value
this.timerLabel = value
this.stopTimer()
}
get seconds(): number {
return this._seconds
}

@Output() timerEnd = new EventEmitter<void>();

timerLabel: number = 0;

constructor() { }

ngOnInit() {}
public startTimer() {
this.setupTimerInterval()
}

private stopTimer() {
if(this.timerRefreshInterval) {
clearInterval(this.timerRefreshInterval)
}
}

private setupTimerInterval() {
if(this.timerRefreshInterval) {
clearInterval(this.timerRefreshInterval)
}

this.timerLabel = this.seconds // reset timer label
this._timerStartTime = Date.now() // reset timer start time

this.timerRefreshInterval = setInterval(() => {
this.updateTimerLabel()
if(this.timerLabel <= 0) {
clearInterval(this.timerRefreshInterval)
this.timerEnd.emit()
}
}, 250) // for precision purposes check every 250ms
}

private updateTimerLabel() {
const elapsedTime = Math.ceil((Date.now() - this._timerStartTime)/1000)
this.timerLabel = this.seconds - elapsedTime
}

}
4 changes: 2 additions & 2 deletions src/app/home/home.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { AccountFilterPipe } from '../pipes/account-filter.pipe';
import { NgxScannerQrcodeModule } from 'ngx-scanner-qrcode';
import { AccountListComponent } from '../components/account-list/account-list.component';
import { AccountDetailComponent } from '../components/account-detail/account-detail.component';
import { CountdownTimerComponent } from '../components/countdown-timer/countdown-timer.component';


@NgModule({
Expand All @@ -20,8 +21,7 @@ import { AccountDetailComponent } from '../components/account-detail/account-det
HomePageRoutingModule,
AccountFilterPipe,
NgxScannerQrcodeModule,

],
declarations: [HomePage, AccountListComponent, AccountDetailComponent]
declarations: [HomePage, AccountListComponent, AccountDetailComponent, CountdownTimerComponent]
})
export class HomePageModule {}
2 changes: 1 addition & 1 deletion src/app/models/account2FA.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ export class Account2FA implements IAccount2FA {
}

getNextRollingTimeLeft(): number {
return (this.interval || 30) - (Math.floor(Date.now() / 1000) % (this.interval || 30));
return this.interval - (Math.ceil(Date.now() / 1000) % this.interval);
}

typeErased(): Object {
Expand Down

0 comments on commit 0c09e6a

Please sign in to comment.