diff --git a/apps/rxjs/49-hold-to-save-button/src/app/app.component.ts b/apps/rxjs/49-hold-to-save-button/src/app/app.component.ts
index 8f0dbbc70..931521173 100644
--- a/apps/rxjs/49-hold-to-save-button/src/app/app.component.ts
+++ b/apps/rxjs/49-hold-to-save-button/src/app/app.component.ts
@@ -1,4 +1,24 @@
-import { ChangeDetectionStrategy, Component } from '@angular/core';
+import {
+ AfterViewInit,
+ ChangeDetectionStrategy,
+ Component,
+ DestroyRef,
+ ElementRef,
+ inject,
+ signal,
+ viewChild,
+} from '@angular/core';
+import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
+import {
+ filter,
+ fromEvent,
+ interval,
+ merge,
+ switchMap,
+ takeUntil,
+ takeWhile,
+ tap,
+} from 'rxjs';
@Component({
imports: [],
@@ -8,17 +28,52 @@ import { ChangeDetectionStrategy, Component } from '@angular/core';
`,
changeDetection: ChangeDetectionStrategy.OnPush,
})
-export class AppComponent {
+export class AppComponent implements AfterViewInit {
+ sendBtn = viewChild>('sendBtn');
+ progressBarValue = signal(0);
+ destroyRef = inject(DestroyRef);
+
+ ngAfterViewInit(): void {
+ const sendBtn = this.sendBtn();
+ if (!sendBtn) {
+ return;
+ }
+
+ const mouseDown$ = fromEvent(sendBtn.nativeElement, 'mousedown');
+ const mouseUp$ = fromEvent(sendBtn.nativeElement, 'mouseup');
+ const mouseLeave$ = fromEvent(sendBtn.nativeElement, 'mouseleave');
+
+ mouseDown$
+ .pipe(
+ switchMap(() =>
+ interval(10).pipe(
+ takeUntilDestroyed(this.destroyRef),
+ takeUntil(merge(mouseUp$, mouseLeave$)),
+ takeWhile(() => this.progressBarValue() < 100),
+ tap(() => this.progressBarValue.update((val) => val + 1)),
+ filter(() => this.progressBarValue() === 100),
+ tap(() => this.onSend()),
+ ),
+ ),
+ )
+ .subscribe();
+
+ merge(mouseUp$, mouseLeave$)
+ .pipe(takeUntilDestroyed(this.destroyRef))
+ .subscribe(() => this.progressBarValue.set(0));
+ }
+
onSend() {
console.log('Save it!');
}