Newer
Older
reroad-test / 2020-ryusei / aframe-master / src / components / scene / device-orientation-permission-ui.js
@ryusei ryusei on 22 Oct 2020 6 KB パノラマ表示
/* global DeviceOrientationEvent, location  */
var registerComponent = require('../../core/component').registerComponent;
var utils = require('../../utils/');
var bind = utils.bind;

var constants = require('../../constants/');

var MODAL_CLASS = 'a-modal';
var DIALOG_CLASS = 'a-dialog';
var DIALOG_TEXT_CLASS = 'a-dialog-text';
var DIALOG_TEXT_CONTAINER_CLASS = 'a-dialog-text-container';
var DIALOG_BUTTONS_CONTAINER_CLASS = 'a-dialog-buttons-container';
var DIALOG_BUTTON_CLASS = 'a-dialog-button';
var DIALOG_ALLOW_BUTTON_CLASS = 'a-dialog-allow-button';
var DIALOG_DENY_BUTTON_CLASS = 'a-dialog-deny-button';
var DIALOG_OK_BUTTON_CLASS = 'a-dialog-ok-button';

/**
 * UI for enabling device motion permission
 */
module.exports.Component = registerComponent('device-orientation-permission-ui', {
  schema: {enabled: {default: true}},

  init: function () {
    var self = this;

    if (!this.data.enabled) { return; }

    if (location.hostname !== 'localhost' &&
        location.hostname !== '127.0.0.1' &&
        location.protocol === 'http:') {
      this.showHTTPAlert();
    }

    // Show alert on iPad if Safari is on desktop mode.
    if (utils.device.isMobileDeviceRequestingDesktopSite()) {
      this.showMobileDesktopModeAlert();
      return;
    }

    // Browser doesn't support or doesn't require permission to DeviceOrientationEvent API.
    if (typeof DeviceOrientationEvent === 'undefined' || !DeviceOrientationEvent.requestPermission) {
      this.permissionGranted = true;
      return;
    }

    this.onDeviceMotionDialogAllowClicked = bind(this.onDeviceMotionDialogAllowClicked, this);
    this.onDeviceMotionDialogDenyClicked = bind(this.onDeviceMotionDialogDenyClicked, this);
    // Show dialog only if permission has not yet been granted.
    DeviceOrientationEvent.requestPermission().catch(function () {
      self.devicePermissionDialogEl = createPermissionDialog(
        'This immersive website requires access to your device motion sensors.',
        self.onDeviceMotionDialogAllowClicked,
        self.onDeviceMotionDialogDenyClicked);
      self.el.appendChild(self.devicePermissionDialogEl);
    }).then(function () {
      self.el.emit('deviceorientationpermissiongranted');
      self.permissionGranted = true;
    });
  },

  remove: function () {
    // This removes the modal screen
    if (this.devicePermissionDialogEl) { this.el.removeChild(this.devicePermissionDialogEl); }
  },

  onDeviceMotionDialogDenyClicked: function () {
    this.remove();
  },

  showMobileDesktopModeAlert: function () {
    var self = this;
    var safariIpadAlertEl = createAlertDialog(
      'Set your browser to request the mobile version of the site and reload the page to enjoy immersive mode.',
      function () { self.el.removeChild(safariIpadAlertEl); });
    this.el.appendChild(safariIpadAlertEl);
  },

  showHTTPAlert: function () {
    var self = this;
    var httpAlertEl = createAlertDialog(
      'Access this site over HTTPS to enter VR mode and grant access to the device sensors.',
      function () { self.el.removeChild(httpAlertEl); });
    this.el.appendChild(httpAlertEl);
  },

  /**
   * Enable device motion permission when clicked.
   */
  onDeviceMotionDialogAllowClicked: function () {
    var self = this;
    this.el.emit('deviceorientationpermissionrequested');
    DeviceOrientationEvent.requestPermission().then(function (response) {
      if (response === 'granted') {
        self.el.emit('deviceorientationpermissiongranted');
        self.permissionGranted = true;
      } else {
        self.el.emit('deviceorientationpermissionrejected');
      }
      self.remove();
    }).catch(console.error);
  }
});

/**
 * Create a modal dialog that request users permission to access the Device Motion API.
 *
 * @param {function} onAllowClicked - click event handler
 * @returns {Element} Wrapper <div>.
 */
function createPermissionDialog (text, onAllowClicked, onDenyClicked) {
  var buttonsContainer;
  var denyButton;
  var acceptButton;

  buttonsContainer = document.createElement('div');
  buttonsContainer.classList.add(DIALOG_BUTTONS_CONTAINER_CLASS);

  // Buttons
  denyButton = document.createElement('button');
  denyButton.classList.add(DIALOG_BUTTON_CLASS, DIALOG_DENY_BUTTON_CLASS);
  denyButton.setAttribute(constants.AFRAME_INJECTED, '');
  denyButton.innerHTML = 'Deny';
  buttonsContainer.appendChild(denyButton);

  acceptButton = document.createElement('button');
  acceptButton.classList.add(DIALOG_BUTTON_CLASS, DIALOG_ALLOW_BUTTON_CLASS);
  acceptButton.setAttribute(constants.AFRAME_INJECTED, '');
  acceptButton.innerHTML = 'Allow';
  buttonsContainer.appendChild(acceptButton);

  // Ask for sensor events to be used
  acceptButton.addEventListener('click', function (evt) {
    evt.stopPropagation();
    onAllowClicked();
  });

  denyButton.addEventListener('click', function (evt) {
    evt.stopPropagation();
    onDenyClicked();
  });

  return createDialog(text, buttonsContainer);
}

function createAlertDialog (text, onOkClicked) {
  var buttonsContainer;
  var okButton;

  buttonsContainer = document.createElement('div');
  buttonsContainer.classList.add(DIALOG_BUTTONS_CONTAINER_CLASS);

  // Buttons
  okButton = document.createElement('button');
  okButton.classList.add(DIALOG_BUTTON_CLASS, DIALOG_OK_BUTTON_CLASS);
  okButton.setAttribute(constants.AFRAME_INJECTED, '');
  okButton.innerHTML = 'Close';
  buttonsContainer.appendChild(okButton);

  // Ask for sensor events to be used
  okButton.addEventListener('click', function (evt) {
    evt.stopPropagation();
    onOkClicked();
  });

  return createDialog(text, buttonsContainer);
}

function createDialog (text, buttonsContainerEl) {
  var modalContainer;
  var dialog;
  var dialogTextContainer;
  var dialogText;

  modalContainer = document.createElement('div');
  modalContainer.classList.add(MODAL_CLASS);
  modalContainer.setAttribute(constants.AFRAME_INJECTED, '');

  dialog = document.createElement('div');
  dialog.className = DIALOG_CLASS;
  dialog.setAttribute(constants.AFRAME_INJECTED, '');
  modalContainer.appendChild(dialog);

  dialogTextContainer = document.createElement('div');
  dialogTextContainer.classList.add(DIALOG_TEXT_CONTAINER_CLASS);
  dialog.appendChild(dialogTextContainer);

  dialogText = document.createElement('div');
  dialogText.classList.add(DIALOG_TEXT_CLASS);
  dialogText.innerHTML = text;
  dialogTextContainer.appendChild(dialogText);

  dialog.appendChild(buttonsContainerEl);

  return modalContainer;
}