Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

181
Visualizações
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 Respostas
Responde à pergunta

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 Relatório

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 Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda