From 80182eda622e1317bffb6729259b8a81d84251a2 Mon Sep 17 00:00:00 2001 From: ThibG Date: Tue, 21 Apr 2020 15:13:26 +0200 Subject: Fix and refactor keyboard navigation in dropdown menus (#13528) Fixes #13527 - Fixes caught keyboard events being needlessly propagated - Let up/down arrows wrap around like the tab key does - Refactor common code --- .../mastodon/components/dropdown_menu.js | 29 ++++++------------ .../compose/components/privacy_dropdown.js | 35 +++++++--------------- 2 files changed, 19 insertions(+), 45 deletions(-) (limited to 'app/javascript') diff --git a/app/javascript/mastodon/components/dropdown_menu.js b/app/javascript/mastodon/components/dropdown_menu.js index a4f262285..31c02d735 100644 --- a/app/javascript/mastodon/components/dropdown_menu.js +++ b/app/javascript/mastodon/components/dropdown_menu.js @@ -68,20 +68,14 @@ class DropdownMenu extends React.PureComponent { handleKeyDown = e => { const items = Array.from(this.node.getElementsByTagName('a')); const index = items.indexOf(document.activeElement); - let element; + let element = null; switch(e.key) { case 'ArrowDown': - element = items[index+1]; - if (element) { - element.focus(); - } + element = items[index+1] || items[0]; break; case 'ArrowUp': - element = items[index-1]; - if (element) { - element.focus(); - } + element = items[index-1] || items[items.length-1]; break; case 'Tab': if (e.shiftKey) { @@ -89,28 +83,23 @@ class DropdownMenu extends React.PureComponent { } else { element = items[index+1] || items[0]; } - if (element) { - element.focus(); - e.preventDefault(); - e.stopPropagation(); - } break; case 'Home': element = items[0]; - if (element) { - element.focus(); - } break; case 'End': element = items[items.length-1]; - if (element) { - element.focus(); - } break; case 'Escape': this.props.onClose(); break; } + + if (element) { + element.focus(); + e.preventDefault(); + e.stopPropagation(); + } } handleItemKeyPress = e => { diff --git a/app/javascript/mastodon/features/compose/components/privacy_dropdown.js b/app/javascript/mastodon/features/compose/components/privacy_dropdown.js index de030b7a2..57588fe96 100644 --- a/app/javascript/mastodon/features/compose/components/privacy_dropdown.js +++ b/app/javascript/mastodon/features/compose/components/privacy_dropdown.js @@ -50,7 +50,7 @@ class PrivacyDropdownMenu extends React.PureComponent { const index = items.findIndex(item => { return (item.value === value); }); - let element; + let element = null; switch(e.key) { case 'Escape': @@ -60,18 +60,10 @@ class PrivacyDropdownMenu extends React.PureComponent { this.handleClick(e); break; case 'ArrowDown': - element = this.node.childNodes[index + 1]; - if (element) { - element.focus(); - this.props.onChange(element.getAttribute('data-index')); - } + element = this.node.childNodes[index + 1] || this.node.firstChild; break; case 'ArrowUp': - element = this.node.childNodes[index - 1]; - if (element) { - element.focus(); - this.props.onChange(element.getAttribute('data-index')); - } + element = this.node.childNodes[index - 1] || this.node.lastChild; break; case 'Tab': if (e.shiftKey) { @@ -79,28 +71,21 @@ class PrivacyDropdownMenu extends React.PureComponent { } else { element = this.node.childNodes[index + 1] || this.node.firstChild; } - if (element) { - element.focus(); - this.props.onChange(element.getAttribute('data-index')); - e.preventDefault(); - e.stopPropagation(); - } break; case 'Home': element = this.node.firstChild; - if (element) { - element.focus(); - this.props.onChange(element.getAttribute('data-index')); - } break; case 'End': element = this.node.lastChild; - if (element) { - element.focus(); - this.props.onChange(element.getAttribute('data-index')); - } break; } + + if (element) { + element.focus(); + this.props.onChange(element.getAttribute('data-index')); + e.preventDefault(); + e.stopPropagation(); + } } handleClick = e => { -- cgit From c5c8f680317a182c4794505007ef227a4294a18e Mon Sep 17 00:00:00 2001 From: Irie Aoi Date: Thu, 23 Apr 2020 22:49:33 +0900 Subject: Set max-width and max-height to gif video (#13533) --- app/javascript/styles/mastodon/components.scss | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'app/javascript') diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss index 26774ab43..beb3b3cfd 100644 --- a/app/javascript/styles/mastodon/components.scss +++ b/app/javascript/styles/mastodon/components.scss @@ -5575,6 +5575,13 @@ a.status-card.compact:hover { } } +.gifv { + video { + max-width: 100vw; + max-height: 80vh; + } +} + .directory { &__list { width: 100%; -- cgit From c955f98d36868e85b0f1939a3a1c58c00babd4e8 Mon Sep 17 00:00:00 2001 From: ThibG Date: Sat, 25 Apr 2020 12:16:05 +0200 Subject: Fix expanded video player issues (#13541) Fixes #13536 - Expanding a paused video doesn't autoplay anymore - Default volume level for the expanded video inherited from the original video Position/playing state/volume are carried over from the original video player to the modal, but they're not reported back to the modal as it would require deeper changes. --- app/javascript/mastodon/components/status.js | 6 +++--- app/javascript/mastodon/containers/status_container.js | 4 ++-- .../features/status/components/detailed_status.js | 4 ++-- .../status/containers/detailed_status_container.js | 4 ++-- app/javascript/mastodon/features/status/index.js | 6 +++--- .../mastodon/features/ui/components/video_modal.js | 13 ++++++++++--- app/javascript/mastodon/features/video/index.js | 17 ++++++++++++++++- 7 files changed, 38 insertions(+), 16 deletions(-) (limited to 'app/javascript') diff --git a/app/javascript/mastodon/components/status.js b/app/javascript/mastodon/components/status.js index 075ee1b87..9e4442cef 100644 --- a/app/javascript/mastodon/components/status.js +++ b/app/javascript/mastodon/components/status.js @@ -176,8 +176,8 @@ class Status extends ImmutablePureComponent { return
; } - handleOpenVideo = (media, startTime) => { - this.props.onOpenVideo(media, startTime); + handleOpenVideo = (media, options) => { + this.props.onOpenVideo(media, options); } handleHotkeyOpenMedia = e => { @@ -190,7 +190,7 @@ class Status extends ImmutablePureComponent { 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); + onOpenVideo(status.getIn(['media_attachments', 0]), { startTime: 0 }); } else { onOpenMedia(status.get('media_attachments'), 0); } diff --git a/app/javascript/mastodon/containers/status_container.js b/app/javascript/mastodon/containers/status_container.js index 2ba3a3123..decf7279f 100644 --- a/app/javascript/mastodon/containers/status_container.js +++ b/app/javascript/mastodon/containers/status_container.js @@ -150,8 +150,8 @@ const mapDispatchToProps = (dispatch, { intl }) => ({ dispatch(openModal('MEDIA', { media, index })); }, - onOpenVideo (media, time) { - dispatch(openModal('VIDEO', { media, time })); + onOpenVideo (media, options) { + dispatch(openModal('VIDEO', { media, options })); }, onBlock (status) { diff --git a/app/javascript/mastodon/features/status/components/detailed_status.js b/app/javascript/mastodon/features/status/components/detailed_status.js index 7a82fa13a..4201b237e 100644 --- a/app/javascript/mastodon/features/status/components/detailed_status.js +++ b/app/javascript/mastodon/features/status/components/detailed_status.js @@ -48,8 +48,8 @@ export default class DetailedStatus extends ImmutablePureComponent { e.stopPropagation(); } - handleOpenVideo = (media, startTime) => { - this.props.onOpenVideo(media, startTime); + handleOpenVideo = (media, options) => { + this.props.onOpenVideo(media, options); } handleExpandedToggle = () => { diff --git a/app/javascript/mastodon/features/status/containers/detailed_status_container.js b/app/javascript/mastodon/features/status/containers/detailed_status_container.js index 333c295dc..6d5c33240 100644 --- a/app/javascript/mastodon/features/status/containers/detailed_status_container.js +++ b/app/javascript/mastodon/features/status/containers/detailed_status_container.js @@ -129,8 +129,8 @@ const mapDispatchToProps = (dispatch, { intl }) => ({ dispatch(openModal('MEDIA', { media, index })); }, - onOpenVideo (media, time) { - dispatch(openModal('VIDEO', { media, time })); + onOpenVideo (media, options) { + dispatch(openModal('VIDEO', { media, options })); }, onBlock (status) { diff --git a/app/javascript/mastodon/features/status/index.js b/app/javascript/mastodon/features/status/index.js index c058120d6..179df53a1 100644 --- a/app/javascript/mastodon/features/status/index.js +++ b/app/javascript/mastodon/features/status/index.js @@ -277,8 +277,8 @@ class Status extends ImmutablePureComponent { this.props.dispatch(openModal('MEDIA', { media, index })); } - handleOpenVideo = (media, time) => { - this.props.dispatch(openModal('VIDEO', { media, time })); + handleOpenVideo = (media, options) => { + this.props.dispatch(openModal('VIDEO', { media, options })); } handleHotkeyOpenMedia = e => { @@ -290,7 +290,7 @@ class Status extends ImmutablePureComponent { if (status.getIn(['media_attachments', 0, 'type']) === 'audio') { // TODO: toggle play/paused? } else if (status.getIn(['media_attachments', 0, 'type']) === 'video') { - this.handleOpenVideo(status.getIn(['media_attachments', 0]), 0); + this.handleOpenVideo(status.getIn(['media_attachments', 0]), { startTime: 0 }); } else { this.handleOpenMedia(status.get('media_attachments'), 0); } diff --git a/app/javascript/mastodon/features/ui/components/video_modal.js b/app/javascript/mastodon/features/ui/components/video_modal.js index f37fc796f..e28bd5b49 100644 --- a/app/javascript/mastodon/features/ui/components/video_modal.js +++ b/app/javascript/mastodon/features/ui/components/video_modal.js @@ -14,7 +14,11 @@ export default class VideoModal extends ImmutablePureComponent { static propTypes = { media: ImmutablePropTypes.map.isRequired, status: ImmutablePropTypes.map, - time: PropTypes.number, + options: PropTypes.shape({ + startTime: PropTypes.number, + autoPlay: PropTypes.bool, + defaultVolume: PropTypes.number, + }), onClose: PropTypes.func.isRequired, }; @@ -52,7 +56,8 @@ export default class VideoModal extends ImmutablePureComponent { } render () { - const { media, status, time, onClose } = this.props; + const { media, status, onClose } = this.props; + const options = this.props.options || {}; return (
@@ -61,7 +66,9 @@ export default class VideoModal extends ImmutablePureComponent { preview={media.get('preview_url')} blurhash={media.get('blurhash')} src={media.get('url')} - startTime={time} + startTime={options.startTime} + autoPlay={options.autoPlay} + defaultVolume={options.defaultVolume} onCloseVideo={onClose} detailed alt={media.get('description')} diff --git a/app/javascript/mastodon/features/video/index.js b/app/javascript/mastodon/features/video/index.js index 42ded9d21..95e107618 100644 --- a/app/javascript/mastodon/features/video/index.js +++ b/app/javascript/mastodon/features/video/index.js @@ -109,6 +109,8 @@ class Video extends React.PureComponent { intl: PropTypes.object.isRequired, blurhash: PropTypes.string, link: PropTypes.node, + autoPlay: PropTypes.bool, + defaultVolume: PropTypes.number, }; state = { @@ -367,6 +369,13 @@ class Video extends React.PureComponent { handleLoadedData = () => { if (this.props.startTime) { this.video.currentTime = this.props.startTime; + } + + if (this.props.defaultVolume !== undefined) { + this.video.volume = this.props.defaultVolume; + } + + if (this.props.autoPlay) { this.video.play(); } } @@ -393,8 +402,14 @@ class Video extends React.PureComponent { height, }); + const options = { + startTime: this.video.currentTime, + autoPlay: !this.state.paused, + defaultVolume: this.state.volume, + }; + this.video.pause(); - this.props.onOpenVideo(media, this.video.currentTime); + this.props.onOpenVideo(media, options); } handleCloseVideo = () => { -- cgit From be637146f310d7ec3a49d01e850959514e9e4964 Mon Sep 17 00:00:00 2001 From: ThibG Date: Sat, 25 Apr 2020 12:27:29 +0200 Subject: Fix uninformative error message when uploading unsupported image files (#13540) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Attempting to upload image files that the browser is unable to load results in “Oops! An unexpected error occurred.” This commit changes the error handling so that an unprocessable image results in the file being sent anyway, which might cover a few corner cases, and provide a slightly better error message. --- app/javascript/mastodon/utils/resize_image.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app/javascript') diff --git a/app/javascript/mastodon/utils/resize_image.js b/app/javascript/mastodon/utils/resize_image.js index 710a08f7c..6c1cb61a2 100644 --- a/app/javascript/mastodon/utils/resize_image.js +++ b/app/javascript/mastodon/utils/resize_image.js @@ -138,7 +138,7 @@ const resizeImage = (img, type = 'image/png') => new Promise((resolve, reject) = .catch(reject); }); -export default inputFile => new Promise((resolve, reject) => { +export default inputFile => new Promise((resolve) => { if (!inputFile.type.match(/image.*/) || inputFile.type === 'image/gif') { resolve(inputFile); return; @@ -153,5 +153,5 @@ export default inputFile => new Promise((resolve, reject) => { resizeImage(img, inputFile.type) .then(resolve) .catch(() => resolve(inputFile)); - }).catch(reject); + }).catch(() => resolve(inputFile)); }); -- cgit