]> git.ipfire.org Git - thirdparty/bugzilla.git/commitdiff
Bug 1391439 - Add ability to capture and attach a screenshot through the Bugzilla UI
authorKohei Yoshino <kohei.yoshino@gmail.com>
Fri, 8 Mar 2019 16:31:47 +0000 (11:31 -0500)
committerGitHub <noreply@github.com>
Fri, 8 Mar 2019 16:31:47 +0000 (11:31 -0500)
js/attachment.js
template/en/default/attachment/createformcontents.html.tmpl

index 184945501433c873f558555958026bb9a8c009c8..4721c21c9d84ccb41afcee3fbfe5835bfc39732b 100644 (file)
@@ -301,6 +301,7 @@ Bugzilla.AttachmentForm = class AttachmentForm {
     this.$filename = document.querySelector('#att-filename');
     this.$dropbox = document.querySelector('#att-dropbox');
     this.$browse_label = document.querySelector('#att-browse-label');
+    this.$capture_label = document.querySelector('#att-capture-label');
     this.$textarea = document.querySelector('#att-textarea');
     this.$preview = document.querySelector('#att-preview');
     this.$preview_name = this.$preview.querySelector('[itemprop="name"]');
@@ -326,6 +327,7 @@ Bugzilla.AttachmentForm = class AttachmentForm {
     this.$dropbox.addEventListener('dragend', () => this.dropbox_ondragend());
     this.$dropbox.addEventListener('drop', event => this.dropbox_ondrop(event));
     this.$browse_label.addEventListener('click', () => this.$file.click());
+    this.$capture_label.addEventListener('click', () => this.capture_onclick());
     this.$textarea.addEventListener('input', () => this.textarea_oninput());
     this.$textarea.addEventListener('paste', event => this.textarea_onpaste(event));
     this.$remove_button.addEventListener('click', () => this.remove_button_onclick());
@@ -561,6 +563,50 @@ Bugzilla.AttachmentForm = class AttachmentForm {
     }
   }
 
+  /**
+   * Called whenever the Take a Screenshot button is clicked. Capture a screen, window or browser tab if the Screen
+   * Capture API is supported, then attach it as a PNG image.
+   * @see https://developer.mozilla.org/en-US/docs/Web/API/Screen_Capture_API
+   */
+  capture_onclick() {
+    if (typeof navigator.mediaDevices.getDisplayMedia !== 'function') {
+      alert('This function requires the most recent browser version such as Firefox 66 or Chrome 72.');
+      return;
+    }
+
+    const $video = document.createElement('video');
+    const $canvas = document.createElement('canvas');
+
+    navigator.mediaDevices.getDisplayMedia({ video: { displaySurface: 'window' } }).then(stream => {
+      // Render a captured screenshot on `<video>`
+      $video.srcObject = stream;
+
+      return $video.play();
+    }).then(() => {
+      const width = $canvas.width = $video.videoWidth;
+      const height = $canvas.height = $video.videoHeight;
+
+      // Draw a video frame on `<canvas>`
+      $canvas.getContext('2d').drawImage($video, 0, 0, width, height);
+
+      // Clean up `<video>`
+      $video.pause();
+      $video.srcObject.getTracks().forEach(track => track.stop());
+      $video.srcObject = null;
+
+      // Convert to PNG
+      return new Promise(resolve => $canvas.toBlob(blob => resolve(blob)));
+    }).then(blob => {
+      const [date, time] = (new Date()).toISOString().match(/^(.+)T(.+)\./).splice(1);
+      const file = new File([blob], `Screenshot on ${date} at ${time}.png`, { type: 'image/png' });
+
+      this.process_file(file);
+      this.update_ispatch(false, true);
+    }).catch(() => {
+      alert('Unable to capture a screenshot.');
+    });
+  }
+
   /**
    * Called whenever the content of the textarea is updated. Update the Content Type, `required` property, etc.
    */
index dd1c51563faad8b2cef13da8ae1df3192ec35197..14b6cbb046d38bd235e40d6628e6ac78745e4b8f 100644 (file)
     <section id="att-dropbox">
       <header>
         <span class="icon" aria-hidden="true"></span>
-        <span><label id="att-browse-label" tabindex="0" role="button">Browse a file</label>,
-          drag &amp; drop it, or paste text/link/image below.</span>
+        <span>
+          <label id="att-browse-label" tabindex="0" role="button">Browse a file</label>,
+          drag &amp; drop it, paste text/link/image below, or
+          <label id="att-capture-label" tabindex="0" role="button">take a screenshot</label>.
+        </span>
       </header>
       <div>
         <textarea hidden id="att-data" name="data_base64"