Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

174
Views
Resume video if user is inactive/idle for 30 seconds (RxJs)

Let me explain functionality a bit. My goal is when the video is playing if a user clicks on the video it will be paused then he might do something along the way. In the meantime I need to detect if a user is idle for 30 sec. If so then automatically resume the video again.

I have implemented using the javascript basic setTimeout functionality. Let me share the code below

@HostListener('window:click', ['$event'])
onClick: (event) => {
    // stop the video
    this.activity = setTimeout(() => { /* resume */ } , 30000)
}


@HostListener('window:mousemove', ['$event'])
onMouseMove: (event) => {
    clearTimeout(this.activity)
    this.activity = setTimeout(() => { /* resume */ } , 30000)
}

Any suggestion how this can be solved using the RxJs way?

about 4 years ago · Juan Pablo Isaza
2 answers
Answer question

0

activity = new Subject<void>();

@HostListener('window:click', ['$event'])
onClick(event: any) {
    // stop the video
    interval(30000).pipe(takeUntil(this.activity)).subscribe(() => {
        /* resume */
        this.activity.next();
        this.activity.complete();
    });
}


@HostListener('window:mousemove', ['$event'])
onMouseMove(event: any) {
    this.activity.next();
    this.activity.complete();

    this.activity = new Subject<void>();

    interval(30000).pipe(takeUntil(this.activity)).subscribe(() => {
        /* resume */
        this.activity.next();
        this.activity.complete();
    });
}
about 4 years ago · Juan Pablo Isaza Report

0

This is what I came up with:

It runs outside the Angular Zone. Won't burden your app with change detection when the mouse is moving. It triggers change detection only when the video is stopped or continued.

import { DOCUMENT } from '@angular/common';
import { Inject, Injectable, NgZone } from '@angular/core';
import {
  BehaviorSubject,
  fromEvent,
  merge,
  Observable,
  of,
  Subject,
} from 'rxjs';
import {
  distinctUntilChanged,
  mapTo,
  startWith,
  switchMapTo,
  debounceTime,
  takeUntil,
} from 'rxjs/operators';

@Injectable({ providedIn: 'root' })
export class VideoService {
  private readonly onDestroy = new Subject<void>();
  readonly isPlaying$: Observable<boolean> = new BehaviorSubject(true);

  constructor(
    @Inject(DOCUMENT) private readonly document: Document,
    private readonly ngZone: NgZone
  ) {
    // Run the whole logic outside of angular, so it won't burdent the app
    this.ngZone.runOutsideAngular(() => {
      fromEvent(this.document, 'click', { passive: true })
        .pipe(
          // On every click we create a merge observable, and unsubscribe from the previous one if exists
          switchMapTo(
            // We merge two observables
            merge(
              // one that sets the playing to false instantly
              of(false),
              // Subscribe to the documents mousemove
              fromEvent(this.document, 'mousemove', { passive: true }).pipe(
                // we start the stream with a value, so after the clicking it will go back to playing without moving the cursor.
                startWith(null),
                // With debounceTime we wait for no mousemove
                debounceTime(1000),
                // All values are mapped to true
                mapTo(true)
              )
            )
          ),
          distinctUntilChanged(),
          takeUntil(this.onDestroy)
        )
        .subscribe((value) =>
          // when we get a different value run it in the zone, so Angular will know to run change detection.
          this.ngZone.run(() => {
            (this.isPlaying$ as BehaviorSubject<boolean>).next(value);
          })
        );
    });
  }

  ngOnDestroy() {
    this.onDestroy.next();
    this.onDestroy.complete();
  }
}

Running example

I'm interested in other solutions, as mine does not seems to be simple. I feel it can be done simpler too.

about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!