SPB Git forge

spb/admin-ka

Public
41commits 1branches 0releases
172.9 MBsize
maindefault branch
19 days agolast push
JavaScript 65.5% Python 17.8% CSS 13% HTML 3.7%
18.6 KB · 573 lines javascript
Raw Blame History
1"use strict";23Object.defineProperty(exports, "__esModule", {4  value: true5});6exports["default"] = void 0;7function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }8function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }9function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }10function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }11function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }12function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }13/*14 * noVNC: HTML5 VNC client15 * Copyright (C) 2020 The noVNC authors16 * Licensed under MPL 2.0 (see LICENSE.txt)17 *18 * See README.md for usage and integration instructions.19 *20 */2122var GH_NOGESTURE = 0;23var GH_ONETAP = 1;24var GH_TWOTAP = 2;25var GH_THREETAP = 4;26var GH_DRAG = 8;27var GH_LONGPRESS = 16;28var GH_TWODRAG = 32;29var GH_PINCH = 64;30var GH_INITSTATE = 127;31var GH_MOVE_THRESHOLD = 50;32var GH_ANGLE_THRESHOLD = 90; // Degrees3334// Timeout when waiting for gestures (ms)35var GH_MULTITOUCH_TIMEOUT = 250;3637// Maximum time between press and release for a tap (ms)38var GH_TAP_TIMEOUT = 1000;3940// Timeout when waiting for longpress (ms)41var GH_LONGPRESS_TIMEOUT = 1000;4243// Timeout when waiting to decide between PINCH and TWODRAG (ms)44var GH_TWOTOUCH_TIMEOUT = 50;45var GestureHandler = exports["default"] = /*#__PURE__*/function () {46  function GestureHandler() {47    _classCallCheck(this, GestureHandler);48    this._target = null;49    this._state = GH_INITSTATE;50    this._tracked = [];51    this._ignored = [];52    this._waitingRelease = false;53    this._releaseStart = 0.0;54    this._longpressTimeoutId = null;55    this._twoTouchTimeoutId = null;56    this._boundEventHandler = this._eventHandler.bind(this);57  }58  return _createClass(GestureHandler, [{59    key: "attach",60    value: function attach(target) {61      this.detach();62      this._target = target;63      this._target.addEventListener('touchstart', this._boundEventHandler);64      this._target.addEventListener('touchmove', this._boundEventHandler);65      this._target.addEventListener('touchend', this._boundEventHandler);66      this._target.addEventListener('touchcancel', this._boundEventHandler);67    }68  }, {69    key: "detach",70    value: function detach() {71      if (!this._target) {72        return;73      }74      this._stopLongpressTimeout();75      this._stopTwoTouchTimeout();76      this._target.removeEventListener('touchstart', this._boundEventHandler);77      this._target.removeEventListener('touchmove', this._boundEventHandler);78      this._target.removeEventListener('touchend', this._boundEventHandler);79      this._target.removeEventListener('touchcancel', this._boundEventHandler);80      this._target = null;81    }82  }, {83    key: "_eventHandler",84    value: function _eventHandler(e) {85      var fn;86      e.stopPropagation();87      e.preventDefault();88      switch (e.type) {89        case 'touchstart':90          fn = this._touchStart;91          break;92        case 'touchmove':93          fn = this._touchMove;94          break;95        case 'touchend':96        case 'touchcancel':97          fn = this._touchEnd;98          break;99      }100      for (var i = 0; i < e.changedTouches.length; i++) {101        var touch = e.changedTouches[i];102        fn.call(this, touch.identifier, touch.clientX, touch.clientY);103      }104    }105  }, {106    key: "_touchStart",107    value: function _touchStart(id, x, y) {108      // Ignore any new touches if there is already an active gesture,109      // or we're in a cleanup state110      if (this._hasDetectedGesture() || this._state === GH_NOGESTURE) {111        this._ignored.push(id);112        return;113      }114115      // Did it take too long between touches that we should no longer116      // consider this a single gesture?117      if (this._tracked.length > 0 && Date.now() - this._tracked[0].started > GH_MULTITOUCH_TIMEOUT) {118        this._state = GH_NOGESTURE;119        this._ignored.push(id);120        return;121      }122123      // If we're waiting for fingers to release then we should no longer124      // recognize new touches125      if (this._waitingRelease) {126        this._state = GH_NOGESTURE;127        this._ignored.push(id);128        return;129      }130      this._tracked.push({131        id: id,132        started: Date.now(),133        active: true,134        firstX: x,135        firstY: y,136        lastX: x,137        lastY: y,138        angle: 0139      });140      switch (this._tracked.length) {141        case 1:142          this._startLongpressTimeout();143          break;144        case 2:145          this._state &= ~(GH_ONETAP | GH_DRAG | GH_LONGPRESS);146          this._stopLongpressTimeout();147          break;148        case 3:149          this._state &= ~(GH_TWOTAP | GH_TWODRAG | GH_PINCH);150          break;151        default:152          this._state = GH_NOGESTURE;153      }154    }155  }, {156    key: "_touchMove",157    value: function _touchMove(id, x, y) {158      var touch = this._tracked.find(function (t) {159        return t.id === id;160      });161162      // If this is an update for a touch we're not tracking, ignore it163      if (touch === undefined) {164        return;165      }166167      // Update the touches last position with the event coordinates168      touch.lastX = x;169      touch.lastY = y;170      var deltaX = x - touch.firstX;171      var deltaY = y - touch.firstY;172173      // Update angle when the touch has moved174      if (touch.firstX !== touch.lastX || touch.firstY !== touch.lastY) {175        touch.angle = Math.atan2(deltaY, deltaX) * 180 / Math.PI;176      }177      if (!this._hasDetectedGesture()) {178        // Ignore moves smaller than the minimum threshold179        if (Math.hypot(deltaX, deltaY) < GH_MOVE_THRESHOLD) {180          return;181        }182183        // Can't be a tap or long press as we've seen movement184        this._state &= ~(GH_ONETAP | GH_TWOTAP | GH_THREETAP | GH_LONGPRESS);185        this._stopLongpressTimeout();186        if (this._tracked.length !== 1) {187          this._state &= ~GH_DRAG;188        }189        if (this._tracked.length !== 2) {190          this._state &= ~(GH_TWODRAG | GH_PINCH);191        }192193        // We need to figure out which of our different two touch gestures194        // this might be195        if (this._tracked.length === 2) {196          // The other touch is the one where the id doesn't match197          var prevTouch = this._tracked.find(function (t) {198            return t.id !== id;199          });200201          // How far the previous touch point has moved since start202          var prevDeltaMove = Math.hypot(prevTouch.firstX - prevTouch.lastX, prevTouch.firstY - prevTouch.lastY);203204          // We know that the current touch moved far enough,205          // but unless both touches moved further than their206          // threshold we don't want to disqualify any gestures207          if (prevDeltaMove > GH_MOVE_THRESHOLD) {208            // The angle difference between the direction of the touch points209            var deltaAngle = Math.abs(touch.angle - prevTouch.angle);210            deltaAngle = Math.abs((deltaAngle + 180) % 360 - 180);211212            // PINCH or TWODRAG can be eliminated depending on the angle213            if (deltaAngle > GH_ANGLE_THRESHOLD) {214              this._state &= ~GH_TWODRAG;215            } else {216              this._state &= ~GH_PINCH;217            }218            if (this._isTwoTouchTimeoutRunning()) {219              this._stopTwoTouchTimeout();220            }221          } else if (!this._isTwoTouchTimeoutRunning()) {222            // We can't determine the gesture right now, let's223            // wait and see if more events are on their way224            this._startTwoTouchTimeout();225          }226        }227        if (!this._hasDetectedGesture()) {228          return;229        }230        this._pushEvent('gesturestart');231      }232      this._pushEvent('gesturemove');233    }234  }, {235    key: "_touchEnd",236    value: function _touchEnd(id, x, y) {237      // Check if this is an ignored touch238      if (this._ignored.indexOf(id) !== -1) {239        // Remove this touch from ignored240        this._ignored.splice(this._ignored.indexOf(id), 1);241242        // And reset the state if there are no more touches243        if (this._ignored.length === 0 && this._tracked.length === 0) {244          this._state = GH_INITSTATE;245          this._waitingRelease = false;246        }247        return;248      }249250      // We got a touchend before the timer triggered,251      // this cannot result in a gesture anymore.252      if (!this._hasDetectedGesture() && this._isTwoTouchTimeoutRunning()) {253        this._stopTwoTouchTimeout();254        this._state = GH_NOGESTURE;255      }256257      // Some gestures don't trigger until a touch is released258      if (!this._hasDetectedGesture()) {259        // Can't be a gesture that relies on movement260        this._state &= ~(GH_DRAG | GH_TWODRAG | GH_PINCH);261        // Or something that relies on more time262        this._state &= ~GH_LONGPRESS;263        this._stopLongpressTimeout();264        if (!this._waitingRelease) {265          this._releaseStart = Date.now();266          this._waitingRelease = true;267268          // Can't be a tap that requires more touches than we current have269          switch (this._tracked.length) {270            case 1:271              this._state &= ~(GH_TWOTAP | GH_THREETAP);272              break;273            case 2:274              this._state &= ~(GH_ONETAP | GH_THREETAP);275              break;276          }277        }278      }279280      // Waiting for all touches to release? (i.e. some tap)281      if (this._waitingRelease) {282        // Were all touches released at roughly the same time?283        if (Date.now() - this._releaseStart > GH_MULTITOUCH_TIMEOUT) {284          this._state = GH_NOGESTURE;285        }286287        // Did too long time pass between press and release?288        if (this._tracked.some(function (t) {289          return Date.now() - t.started > GH_TAP_TIMEOUT;290        })) {291          this._state = GH_NOGESTURE;292        }293        var touch = this._tracked.find(function (t) {294          return t.id === id;295        });296        touch.active = false;297298        // Are we still waiting for more releases?299        if (this._hasDetectedGesture()) {300          this._pushEvent('gesturestart');301        } else {302          // Have we reached a dead end?303          if (this._state !== GH_NOGESTURE) {304            return;305          }306        }307      }308      if (this._hasDetectedGesture()) {309        this._pushEvent('gestureend');310      }311312      // Ignore any remaining touches until they are ended313      for (var i = 0; i < this._tracked.length; i++) {314        if (this._tracked[i].active) {315          this._ignored.push(this._tracked[i].id);316        }317      }318      this._tracked = [];319      this._state = GH_NOGESTURE;320321      // Remove this touch from ignored if it's in there322      if (this._ignored.indexOf(id) !== -1) {323        this._ignored.splice(this._ignored.indexOf(id), 1);324      }325326      // We reset the state if ignored is empty327      if (this._ignored.length === 0) {328        this._state = GH_INITSTATE;329        this._waitingRelease = false;330      }331    }332  }, {333    key: "_hasDetectedGesture",334    value: function _hasDetectedGesture() {335      if (this._state === GH_NOGESTURE) {336        return false;337      }338      // Check to see if the bitmask value is a power of 2339      // (i.e. only one bit set). If it is, we have a state.340      if (this._state & this._state - 1) {341        return false;342      }343344      // For taps we also need to have all touches released345      // before we've fully detected the gesture346      if (this._state & (GH_ONETAP | GH_TWOTAP | GH_THREETAP)) {347        if (this._tracked.some(function (t) {348          return t.active;349        })) {350          return false;351        }352      }353      return true;354    }355  }, {356    key: "_startLongpressTimeout",357    value: function _startLongpressTimeout() {358      var _this = this;359      this._stopLongpressTimeout();360      this._longpressTimeoutId = setTimeout(function () {361        return _this._longpressTimeout();362      }, GH_LONGPRESS_TIMEOUT);363    }364  }, {365    key: "_stopLongpressTimeout",366    value: function _stopLongpressTimeout() {367      clearTimeout(this._longpressTimeoutId);368      this._longpressTimeoutId = null;369    }370  }, {371    key: "_longpressTimeout",372    value: function _longpressTimeout() {373      if (this._hasDetectedGesture()) {374        throw new Error("A longpress gesture failed, conflict with a different gesture");375      }376      this._state = GH_LONGPRESS;377      this._pushEvent('gesturestart');378    }379  }, {380    key: "_startTwoTouchTimeout",381    value: function _startTwoTouchTimeout() {382      var _this2 = this;383      this._stopTwoTouchTimeout();384      this._twoTouchTimeoutId = setTimeout(function () {385        return _this2._twoTouchTimeout();386      }, GH_TWOTOUCH_TIMEOUT);387    }388  }, {389    key: "_stopTwoTouchTimeout",390    value: function _stopTwoTouchTimeout() {391      clearTimeout(this._twoTouchTimeoutId);392      this._twoTouchTimeoutId = null;393    }394  }, {395    key: "_isTwoTouchTimeoutRunning",396    value: function _isTwoTouchTimeoutRunning() {397      return this._twoTouchTimeoutId !== null;398    }399  }, {400    key: "_twoTouchTimeout",401    value: function _twoTouchTimeout() {402      if (this._tracked.length === 0) {403        throw new Error("A pinch or two drag gesture failed, no tracked touches");404      }405406      // How far each touch point has moved since start407      var avgM = this._getAverageMovement();408      var avgMoveH = Math.abs(avgM.x);409      var avgMoveV = Math.abs(avgM.y);410411      // The difference in the distance between where412      // the touch points started and where they are now413      var avgD = this._getAverageDistance();414      var deltaTouchDistance = Math.abs(Math.hypot(avgD.first.x, avgD.first.y) - Math.hypot(avgD.last.x, avgD.last.y));415      if (avgMoveV < deltaTouchDistance && avgMoveH < deltaTouchDistance) {416        this._state = GH_PINCH;417      } else {418        this._state = GH_TWODRAG;419      }420      this._pushEvent('gesturestart');421      this._pushEvent('gesturemove');422    }423  }, {424    key: "_pushEvent",425    value: function _pushEvent(type) {426      var detail = {427        type: this._stateToGesture(this._state)428      };429430      // For most gesture events the current (average) position is the431      // most useful432      var avg = this._getPosition();433      var pos = avg.last;434435      // However we have a slight distance to detect gestures, so for the436      // first gesture event we want to use the first positions we saw437      if (type === 'gesturestart') {438        pos = avg.first;439      }440441      // For these gestures, we always want the event coordinates442      // to be where the gesture began, not the current touch location.443      switch (this._state) {444        case GH_TWODRAG:445        case GH_PINCH:446          pos = avg.first;447          break;448      }449      detail['clientX'] = pos.x;450      detail['clientY'] = pos.y;451452      // FIXME: other coordinates?453454      // Some gestures also have a magnitude455      if (this._state === GH_PINCH) {456        var distance = this._getAverageDistance();457        if (type === 'gesturestart') {458          detail['magnitudeX'] = distance.first.x;459          detail['magnitudeY'] = distance.first.y;460        } else {461          detail['magnitudeX'] = distance.last.x;462          detail['magnitudeY'] = distance.last.y;463        }464      } else if (this._state === GH_TWODRAG) {465        if (type === 'gesturestart') {466          detail['magnitudeX'] = 0.0;467          detail['magnitudeY'] = 0.0;468        } else {469          var movement = this._getAverageMovement();470          detail['magnitudeX'] = movement.x;471          detail['magnitudeY'] = movement.y;472        }473      }474      var gev = new CustomEvent(type, {475        detail: detail476      });477      this._target.dispatchEvent(gev);478    }479  }, {480    key: "_stateToGesture",481    value: function _stateToGesture(state) {482      switch (state) {483        case GH_ONETAP:484          return 'onetap';485        case GH_TWOTAP:486          return 'twotap';487        case GH_THREETAP:488          return 'threetap';489        case GH_DRAG:490          return 'drag';491        case GH_LONGPRESS:492          return 'longpress';493        case GH_TWODRAG:494          return 'twodrag';495        case GH_PINCH:496          return 'pinch';497      }498      throw new Error("Unknown gesture state: " + state);499    }500  }, {501    key: "_getPosition",502    value: function _getPosition() {503      if (this._tracked.length === 0) {504        throw new Error("Failed to get gesture position, no tracked touches");505      }506      var size = this._tracked.length;507      var fx = 0,508        fy = 0,509        lx = 0,510        ly = 0;511      for (var i = 0; i < this._tracked.length; i++) {512        fx += this._tracked[i].firstX;513        fy += this._tracked[i].firstY;514        lx += this._tracked[i].lastX;515        ly += this._tracked[i].lastY;516      }517      return {518        first: {519          x: fx / size,520          y: fy / size521        },522        last: {523          x: lx / size,524          y: ly / size525        }526      };527    }528  }, {529    key: "_getAverageMovement",530    value: function _getAverageMovement() {531      if (this._tracked.length === 0) {532        throw new Error("Failed to get gesture movement, no tracked touches");533      }534      var totalH, totalV;535      totalH = totalV = 0;536      var size = this._tracked.length;537      for (var i = 0; i < this._tracked.length; i++) {538        totalH += this._tracked[i].lastX - this._tracked[i].firstX;539        totalV += this._tracked[i].lastY - this._tracked[i].firstY;540      }541      return {542        x: totalH / size,543        y: totalV / size544      };545    }546  }, {547    key: "_getAverageDistance",548    value: function _getAverageDistance() {549      if (this._tracked.length === 0) {550        throw new Error("Failed to get gesture distance, no tracked touches");551      }552553      // Distance between the first and last tracked touches554555      var first = this._tracked[0];556      var last = this._tracked[this._tracked.length - 1];557      var fdx = Math.abs(last.firstX - first.firstX);558      var fdy = Math.abs(last.firstY - first.firstY);559      var ldx = Math.abs(last.lastX - first.lastX);560      var ldy = Math.abs(last.lastY - first.lastY);561      return {562        first: {563          x: fdx,564          y: fdy565        },566        last: {567          x: ldx,568          y: ldy569        }570      };571    }572  }]);573}();