<commit_before>import {BehaviorSubject} from "rxjs/BehaviorSubject";
import {Observable} from "rxjs/Observable";
import {Subject} from "rxjs/Subject";

import "rxjs/add/observable/timer";

import "rxjs/add/operator/bufferWhen";
import "rxjs/add/operator/filter";
import "rxjs/add/operator/map";
import "rxjs/add/operator/merge";
import "rxjs/add/operator/scan";
import "rxjs/add/operator/switchMap";

import {IPinch} from "../Viewer";

interface IPinchOperation {
    (pinch: IPinch): IPinch;
}

export class TouchService {
    private _element: HTMLElement;

    private _activeSubject$: BehaviorSubject<boolean>;
    private _active$: Observable<boolean>;

    private _touchStart$: Observable<TouchEvent>;
    private _touchMove$: Observable<TouchEvent>;
    private _touchEnd$: Observable<TouchEvent>;
    private _touchCancel$: Observable<TouchEvent>;

    private _singleTouchDrag$: Observable<TouchEvent>;
    private _singleTouchDragStart$: Observable<TouchEvent>;
    private _singleTouchDragEnd$: Observable<TouchEvent>;
    private _singleTouchMove$: Observable<TouchEvent>;

    private _pinchOperation$: Subject<IPinchOperation>;
    private _pinch$: Observable<IPinch>;
    private _pinchStart$: Observable<TouchEvent>;
    private _pinchEnd$: Observable<TouchEvent>;
    private _pinchChange$: Observable<IPinch>;

    private _doubleTap$: Observable<TouchEvent>;

    constructor(element: HTMLElement) {
        this._element = element;

        this._activeSubject$ = new BehaviorSubject<boolean>(false);

        this._active$ = this._activeSubject$
            .distinctUntilChanged()
            .publishReplay(1)
            .refCount();

        this._touchStart$ = Observable.fromEvent<TouchEvent>(element, "touchstart");
        this._touchMove$ = Observable.fromEvent<TouchEvent>(element, "touchmove");
        this._touchEnd$ = Observable.fromEvent<TouchEvent>(element, "touchend");
        this._touchCancel$ = Observable.fromEvent<TouchEvent>(element, "touchcancel");

        const tapStart$: Observable<TouchEvent> = this._touchStart$
            .filter(
                (te: TouchEvent): boolean => {
                    return te.touches.length === 1 && te.targetTouches.length === 1;
                })
            .share();

        this._doubleTap$ = tapStart$
            .bufferWhen(
                (): Observable<number> => {
                    return tapStart$
                        .first()
                        .switchMap(
                            (event: TouchEvent): Observable<number | TouchEvent> => {
                                return Observable
                                    .timer(300)
                                    .merge(tapStart$)
                                    .take(1);
                            });
                })
            .filter(
                (events: TouchEvent[]): boolean => {
                    return events.length === 2;
                })
            .map(
                (events: TouchEvent[]): TouchEvent => {
                    return events[events.length - 1];
                })
            .share();

        this._singleTouchMove$ = this._touchMove$
            .filter(
                (te: TouchEvent): boolean => {
                    return te.touches.length === 1 && te.targetTouches.length === 1;
                })
            .share();

        let singleTouchStart$: Observable<TouchEvent> = Observable
            .merge<TouchEvent>(
                this._touchStart$,
                this._touchEnd$,
                this._touchCancel$)
            .filter(
                (te: TouchEvent): boolean => {
                    return te.touches.length === 1 && te.targetTouches.length === 1;
                });<commit_msg>Prevent default on double tap to avoid browser zoom.<commit_after>import {BehaviorSubject} from "rxjs/BehaviorSubject";
import {Observable} from "rxjs/Observable";
import {Subject} from "rxjs/Subject";

import "rxjs/add/observable/timer";

import "rxjs/add/operator/bufferWhen";
import "rxjs/add/operator/filter";
import "rxjs/add/operator/map";
import "rxjs/add/operator/merge";
import "rxjs/add/operator/scan";
import "rxjs/add/operator/switchMap";

import {IPinch} from "../Viewer";

interface IPinchOperation {
    (pinch: IPinch): IPinch;
}

export class TouchService {
    private _element: HTMLElement;

    private _activeSubject$: BehaviorSubject<boolean>;
    private _active$: Observable<boolean>;

    private _touchStart$: Observable<TouchEvent>;
    private _touchMove$: Observable<TouchEvent>;
    private _touchEnd$: Observable<TouchEvent>;
    private _touchCancel$: Observable<TouchEvent>;

    private _singleTouchDrag$: Observable<TouchEvent>;
    private _singleTouchDragStart$: Observable<TouchEvent>;
    private _singleTouchDragEnd$: Observable<TouchEvent>;
    private _singleTouchMove$: Observable<TouchEvent>;

    private _pinchOperation$: Subject<IPinchOperation>;
    private _pinch$: Observable<IPinch>;
    private _pinchStart$: Observable<TouchEvent>;
    private _pinchEnd$: Observable<TouchEvent>;
    private _pinchChange$: Observable<IPinch>;

    private _doubleTap$: Observable<TouchEvent>;

    constructor(element: HTMLElement) {
        this._element = element;

        this._activeSubject$ = new BehaviorSubject<boolean>(false);

        this._active$ = this._activeSubject$
            .distinctUntilChanged()
            .publishReplay(1)
            .refCount();

        this._touchStart$ = Observable.fromEvent<TouchEvent>(element, "touchstart");
        this._touchMove$ = Observable.fromEvent<TouchEvent>(element, "touchmove");
        this._touchEnd$ = Observable.fromEvent<TouchEvent>(element, "touchend");
        this._touchCancel$ = Observable.fromEvent<TouchEvent>(element, "touchcancel");

        const tapStart$: Observable<TouchEvent> = this._touchStart$
            .filter(
                (te: TouchEvent): boolean => {
                    return te.touches.length === 1 && te.targetTouches.length === 1;
                })
            .share();

        this._doubleTap$ = tapStart$
            .bufferWhen(
                (): Observable<number> => {
                    return tapStart$
                        .first()
                        .switchMap(
                            (event: TouchEvent): Observable<number | TouchEvent> => {
                                return Observable
                                    .timer(300)
                                    .merge(tapStart$)
                                    .take(1);
                            });
                })
            .filter(
                (events: TouchEvent[]): boolean => {
                    return events.length === 2;
                })
            .map(
                (events: TouchEvent[]): TouchEvent => {
                    return events[events.length - 1];
                })
            .share();

        this._doubleTap$
            .subscribe(
                (event: TouchEvent): void => {
                    event.preventDefault();
                });

        this._singleTouchMove$ = this._touchMove$
            .filter(
                (te: TouchEvent): boolean => {
                    return te.touches.length === 1 && te.targetTouches.length === 1;
                })
            .share();

        let singleTouchStart$: Observable<TouchEvent> = Observable
            .merge<TouchEvent>(
                this._touchStart$,
                this._touchEnd$,
                this._touchCancel$)
            .filter(
                (te: TouchEvent): boolean => {
                    return te.touches.length === 1 && te.targetTouches.length === 1;
                });
{'fraction_non_alphanumeric': 0.11571428571428571, 'fraction_numerical': 0.0033766233766233766, 'mean_word_length': 1.95170563434266, 'pattern_counts': {'":': 0, '<': 55, '<?xml version=': 0, '>': 70, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '329186', 'n_tokens_mistral': 2007, 'n_tokens_neox': 1899, 'n_words': 390}