about summary refs log tree commit diff
path: root/app/javascript/flavours/glitch/components
diff options
context:
space:
mode:
Diffstat (limited to 'app/javascript/flavours/glitch/components')
-rw-r--r--app/javascript/flavours/glitch/components/modal_root.js15
-rw-r--r--app/javascript/flavours/glitch/components/poll.js28
-rw-r--r--app/javascript/flavours/glitch/components/status.js17
3 files changed, 52 insertions, 8 deletions
diff --git a/app/javascript/flavours/glitch/components/modal_root.js b/app/javascript/flavours/glitch/components/modal_root.js
index e73ef8d12..f9877d5ea 100644
--- a/app/javascript/flavours/glitch/components/modal_root.js
+++ b/app/javascript/flavours/glitch/components/modal_root.js
@@ -62,15 +62,22 @@ export default class ModalRoot extends React.PureComponent {
     } else if (!nextProps.children) {
       this.setState({ revealed: false });
     }
-    if (!nextProps.children && !!this.props.children) {
-      this.activeElement.focus({ preventScroll: true });
-      this.activeElement = null;
-    }
   }
 
   componentDidUpdate (prevProps) {
     if (!this.props.children && !!prevProps.children) {
       this.getSiblings().forEach(sibling => sibling.removeAttribute('inert'));
+
+      // Because of the wicg-inert polyfill, the activeElement may not be
+      // immediately selectable, we have to wait for observers to run, as
+      // described in https://github.com/WICG/inert#performance-and-gotchas
+      Promise.resolve().then(() => {
+        this.activeElement.focus({ preventScroll: true });
+        this.activeElement = null;
+      }).catch((error) => {
+        console.error(error);
+      });
+
       this.handleModalClose();
     }
     if (this.props.children) {
diff --git a/app/javascript/flavours/glitch/components/poll.js b/app/javascript/flavours/glitch/components/poll.js
index 2d2a7cbe0..62965df94 100644
--- a/app/javascript/flavours/glitch/components/poll.js
+++ b/app/javascript/flavours/glitch/components/poll.js
@@ -67,9 +67,7 @@ class Poll extends ImmutablePureComponent {
     }
   }
 
-  handleOptionChange = e => {
-    const { target: { value } } = e;
-
+  _toggleOption = value => {
     if (this.props.poll.get('multiple')) {
       const tmp = { ...this.state.selected };
       if (tmp[value]) {
@@ -83,8 +81,20 @@ class Poll extends ImmutablePureComponent {
       tmp[value] = true;
       this.setState({ selected: tmp });
     }
+  }
+
+  handleOptionChange = ({ target: { value } }) => {
+    this._toggleOption(value);
   };
 
+  handleOptionKeyPress = (e) => {
+    if (e.key === 'Enter' || e.key === ' ') {
+      this._toggleOption(e.target.getAttribute('data-index'));
+      e.stopPropagation();
+      e.preventDefault();
+    }
+  }
+
   handleVote = () => {
     if (this.props.disabled) {
       return;
@@ -135,7 +145,17 @@ class Poll extends ImmutablePureComponent {
             disabled={disabled}
           />
 
-          {!showResults && <span className={classNames('poll__input', { checkbox: poll.get('multiple'), active })} />}
+          {!showResults && (
+            <span
+              className={classNames('poll__input', { checkbox: poll.get('multiple'), active })}
+              tabIndex='0'
+              role={poll.get('multiple') ? 'checkbox' : 'radio'}
+              onKeyPress={this.handleOptionKeyPress}
+              aria-checked={active}
+              aria-label={option.get('title')}
+              data-index={optionIndex}
+            />
+          )}
           {showResults && <span className='poll__number'>
             {!!voted && <Icon id='check' className='poll__vote__mark' title={intl.formatMessage(messages.voted)} />}
             {Math.round(percent)}%
diff --git a/app/javascript/flavours/glitch/components/status.js b/app/javascript/flavours/glitch/components/status.js
index e7bf1f4d0..23cdc0167 100644
--- a/app/javascript/flavours/glitch/components/status.js
+++ b/app/javascript/flavours/glitch/components/status.js
@@ -376,6 +376,22 @@ class Status extends ImmutablePureComponent {
     this.props.onOpenVideo(media, startTime);
   }
 
+  handleHotkeyOpenMedia = e => {
+    const { status, onOpenMedia, onOpenVideo } = this.props;
+
+    e.preventDefault();
+
+    if (status.get('media_attachments').size > 0) {
+      if (status.getIn(['media_attachments', 0, 'type']) === 'audio') {
+        // TODO: toggle play/paused?
+      } else if (status.getIn(['media_attachments', 0, 'type']) === 'video') {
+        onOpenVideo(status.getIn(['media_attachments', 0]), 0);
+      } else {
+        onOpenMedia(status.get('media_attachments'), 0);
+      }
+    }
+  }
+
   handleHotkeyReply = e => {
     e.preventDefault();
     this.props.onReply(this.props.status, this.context.router.history);
@@ -503,6 +519,7 @@ class Status extends ImmutablePureComponent {
       bookmark: this.handleHotkeyBookmark,
       toggleCollapse: this.handleHotkeyCollapse,
       toggleSensitive: this.handleHotkeyToggleSensitive,
+      openMedia: this.handleHotkeyOpenMedia,
     };
 
     if (hidden) {