picostitch
crafting (and) JavaScript

Camera Permission Detector in a Webapp

Did you ever decline the camera permission on a website, and then you were wondering why the camera dialog didn't show up? I had this too and thought it is a bug in the browser. But actually it's a safety feature, so the website can't just ask for the camera permission continuously and annoy you. Still detecting missing permissions makes sense to hint the user to enable the camera.

Here is how I did it.

// camera.js

/**
 * Detect if the camera permission are missing.
 * This assumes when the permissions are missing, the <input type=file capture=...>
 * will not show the camera dialog, and the too fast blur and unblur events are measured.
 * And if the events are too fast, the permission error alert is shown.
 * This seems to work quite well.
 * 
 * @param {HTMLInputElement} $input - The input element to detect the missing permissions, normally a <input type=file capture=...>.
 * @param {string} permissionErrorMessage - The error message to show when the permissions are missing.
 */
export const missingPermissionAlert = ($input, permissionErrorMessage) => {
  $input.addEventListener('click', () => {
    const eventTimes = [];
    window.addEventListener('blur', () => eventTimes.push(new Date().getTime()));
    window.addEventListener('focus', () => eventTimes.push(new Date().getTime()));
    setTimeout(() => {
      // Calculate the time here, since the setTimeout is just put on the callstack, but not executed exactly after the given time.
      // It might be just called when the camera dialog closes, that's why the time is calculated manually.
      const diff = eventTimes[1] - eventTimes[0];
      const didTheCameraDisappearTooFast = eventTimes.length === 2 && diff < 300;
      if (didTheCameraDisappearTooFast) {
        showPermissionError();
      }
    }, 300);
  });

  const showPermissionError = () => {
    alert(permissionErrorMessage);
  };
};

You can use it as is and throw it in your page, no framework or setup needed, just the reference to the input element and the error message as pure text.

<input type="file" accept="image/*" capture="environment" id="camera-input" />
<script type="module">
  import { missingPermissionAlert } from './camera.js';
  missingPermissionAlert(document.getElementById('camera-input'), 'Please enable the camera permissions to take a picture.');
</script>

Have fun and give me feedback if you have a better way to detect missing permissions, or if there is anything wrong with this approach.