Skip to content

Instantly share code, notes, and snippets.

@ngnam
Created May 4, 2020 06:15
Show Gist options
  • Save ngnam/c18a5680389382e3617c05c9c595b883 to your computer and use it in GitHub Desktop.
Save ngnam/c18a5680389382e3617c05c9c595b883 to your computer and use it in GitHub Desktop.
import {
Directive,
Output,
HostListener,
Input,
OnDestroy,
OnInit,
EventEmitter
} from "@angular/core";
import { Subject, interval, combineLatest } from "rxjs";
import { map, filter, takeUntil, switchMap, tap, repeat } from "rxjs/operators";
@Directive({
selector: "[longPress]",
exportAs: "longPress"
})
export class LongPressDirective implements OnInit, OnDestroy {
@Output() longPress = new EventEmitter<MouseEvent>();
@Input() pressDuration = 1000;
private readonly $mouseDown = new Subject<MouseEvent>();
private readonly $mouseUp = new Subject<MouseEvent>();
private readonly $mouseLeave = new Subject<MouseEvent>();
private readonly $destroy = new Subject();
pressing = false;
longPressing = false;
ngOnInit() {
const mouseDownInterval$ = interval(10).pipe(
map(i => i * 10),
filter(i => i > this.pressDuration),
tap(() => {
this.longPressing = true;
}),
takeUntil(this.$mouseUp),
interval$ => combineLatest([interval$, this.$mouseUp])
);
this.$mouseDown
.pipe(
tap(() => {
this.pressing = true;
this.longPressing = false;
}),
switchMap(() => mouseDownInterval$),
repeat(),
takeUntil(this.$destroy)
)
.subscribe(([, event]) => {
this.pressing = false;
this.longPressing = false;
this.longPress.emit(event);
});
}
@HostListener("mousedown", ["$event"])
onMouseDown($event: MouseEvent) {
this.$mouseDown.next($event);
}
@HostListener("mouseup", ["$event"])
onMouseUp($event: MouseEvent) {
this.$mouseUp.next($event);
}
@HostListener("mouseleave", ["$event"])
onMouseLeave($event: MouseEvent) {
this.$mouseLeave.next($event);
}
ngOnDestroy() {
this.$destroy.next();
this.$destroy.complete();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment