From b8e790c3c22693271a4fd74ce34067c462ebf8a3 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Sun, 1 Nov 2020 16:25:02 +0100 Subject: Fix crash when viewing a profile with a filtered out pinned toot --- app/javascript/flavours/glitch/containers/status_container.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/javascript/flavours/glitch') diff --git a/app/javascript/flavours/glitch/containers/status_container.js b/app/javascript/flavours/glitch/containers/status_container.js index ac423c58d..7782246a6 100644 --- a/app/javascript/flavours/glitch/containers/status_container.js +++ b/app/javascript/flavours/glitch/containers/status_container.js @@ -55,7 +55,7 @@ const makeMapStateToProps = () => { let account = undefined; let prepend = undefined; - if (props.featured) { + if (props.featured && status) { account = status.get('account'); prepend = 'featured'; } else if (reblogStatus !== null && typeof reblogStatus === 'object') { -- cgit From 3b96141633421a0f80e8fb89cfeff549c9c3a3d1 Mon Sep 17 00:00:00 2001 From: Mélanie Chauvel Date: Tue, 27 Oct 2020 03:05:50 +0100 Subject: [Glitch] Make “Mark media as sensitive” properly translatable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Port c5704e75ae1f64742d59747fd931ffcca7a4887d to glitch-soc Signed-off-by: Thibaut Girka --- .../containers/sensitive_button_container.js | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) (limited to 'app/javascript/flavours/glitch') diff --git a/app/javascript/flavours/glitch/features/compose/containers/sensitive_button_container.js b/app/javascript/flavours/glitch/features/compose/containers/sensitive_button_container.js index fa1ae8821..9c23d3f47 100644 --- a/app/javascript/flavours/glitch/features/compose/containers/sensitive_button_container.js +++ b/app/javascript/flavours/glitch/features/compose/containers/sensitive_button_container.js @@ -6,8 +6,14 @@ import { changeComposeSensitivity } from 'flavours/glitch/actions/compose'; import { injectIntl, defineMessages, FormattedMessage } from 'react-intl'; const messages = defineMessages({ - marked: { id: 'compose_form.sensitive.marked', defaultMessage: 'Media is marked as sensitive' }, - unmarked: { id: 'compose_form.sensitive.unmarked', defaultMessage: 'Media is not marked as sensitive' }, + marked: { + id: 'compose_form.sensitive.marked', + defaultMessage: '{count, plural, one {Media is marked as sensitive} other {Media is marked as sensitive}}', + }, + unmarked: { + id: 'compose_form.sensitive.unmarked', + defaultMessage: '{count, plural, one {Media is not marked as sensitive} other {Media is not marked as sensitive}}', + }, }); const mapStateToProps = state => { @@ -16,6 +22,7 @@ const mapStateToProps = state => { return { active: state.getIn(['compose', 'sensitive']) || (spoilersAlwaysOn && spoilerText && spoilerText.length > 0), disabled: state.getIn(['compose', 'spoiler']), + mediaCount: state.getIn(['compose', 'media_attachments']).size, }; }; @@ -32,16 +39,17 @@ class SensitiveButton extends React.PureComponent { static propTypes = { active: PropTypes.bool, disabled: PropTypes.bool, + mediaCount: PropTypes.number, onClick: PropTypes.func.isRequired, intl: PropTypes.object.isRequired, }; render () { - const { active, disabled, onClick, intl } = this.props; + const { active, disabled, mediaCount, onClick, intl } = this.props; return (
-
); -- cgit From 37dfb9dddcc816744d1ab269dd879451addb1be4 Mon Sep 17 00:00:00 2001 From: fuyu <54523771+mfmfuyu@users.noreply.github.com> Date: Fri, 30 Oct 2020 21:09:20 +0900 Subject: [Glitch] Fix wrong seek bar width on media player Port 8d7fbe7dd9b0a64915a96d342579ab80951be840 to glitch-soc Signed-off-by: Thibaut Girka --- app/javascript/flavours/glitch/features/audio/index.js | 4 ++-- app/javascript/flavours/glitch/features/video/index.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'app/javascript/flavours/glitch') diff --git a/app/javascript/flavours/glitch/features/audio/index.js b/app/javascript/flavours/glitch/features/audio/index.js index 6d09ac8d2..412c561a0 100644 --- a/app/javascript/flavours/glitch/features/audio/index.js +++ b/app/javascript/flavours/glitch/features/audio/index.js @@ -252,7 +252,7 @@ class Audio extends React.PureComponent { handleTimeUpdate = () => { this.setState({ currentTime: this.audio.currentTime, - duration: Math.floor(this.audio.duration), + duration: this.audio.duration, }); } @@ -460,7 +460,7 @@ class Audio extends React.PureComponent { {formatTime(Math.floor(currentTime))} / - {formatTime(this.state.duration || Math.floor(this.props.duration))} + {formatTime(Math.floor(this.state.duration || this.props.duration))} diff --git a/app/javascript/flavours/glitch/features/video/index.js b/app/javascript/flavours/glitch/features/video/index.js index 95bee1331..21d327823 100644 --- a/app/javascript/flavours/glitch/features/video/index.js +++ b/app/javascript/flavours/glitch/features/video/index.js @@ -211,7 +211,7 @@ class Video extends React.PureComponent { handleTimeUpdate = () => { this.setState({ currentTime: this.video.currentTime, - duration: Math.floor(this.video.duration), + duration:this.video.duration, }); } @@ -568,7 +568,7 @@ class Video extends React.PureComponent { {formatTime(Math.floor(currentTime))} / - {formatTime(duration)} + {formatTime(Math.floor(duration))} )} -- cgit From adfaf9551c817da83d955ac55e6791bb12ea894e Mon Sep 17 00:00:00 2001 From: ThibG Date: Sun, 1 Nov 2020 18:31:39 +0100 Subject: [Glitch] Fix some account media gallery items having empty labels Port 9d023ed4f6d8a69699d14479d5e12132ea4f4cd2 to glitch-soc Signed-off-by: Thibaut Girka --- .../flavours/glitch/features/account_gallery/components/media_item.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/javascript/flavours/glitch') diff --git a/app/javascript/flavours/glitch/features/account_gallery/components/media_item.js b/app/javascript/flavours/glitch/features/account_gallery/components/media_item.js index 781bd4e03..7457980d2 100644 --- a/app/javascript/flavours/glitch/features/account_gallery/components/media_item.js +++ b/app/javascript/flavours/glitch/features/account_gallery/components/media_item.js @@ -122,7 +122,7 @@ export default class MediaItem extends ImmutablePureComponent {
{content} - {label} + {label && {label}}
); } -- cgit From 578e757d090b349fa996df6d3be7607b9216c563 Mon Sep 17 00:00:00 2001 From: Mélanie Chauvel Date: Tue, 27 Oct 2020 02:58:47 +0100 Subject: [Glitch] Make click area of video/audio player buttons bigger in WebUI Port a5afbb62d25306dc9d28fa8d0e85edf02c63d2a3 to glitch-soc Signed-off-by: Thibaut Girka --- .../flavours/glitch/features/audio/index.js | 10 +++++--- .../flavours/glitch/features/video/index.js | 12 ++++----- .../flavours/glitch/styles/components/media.scss | 30 ++++++++-------------- 3 files changed, 23 insertions(+), 29 deletions(-) (limited to 'app/javascript/flavours/glitch') diff --git a/app/javascript/flavours/glitch/features/audio/index.js b/app/javascript/flavours/glitch/features/audio/index.js index 412c561a0..c050a63a9 100644 --- a/app/javascript/flavours/glitch/features/audio/index.js +++ b/app/javascript/flavours/glitch/features/audio/index.js @@ -444,14 +444,14 @@ class Audio extends React.PureComponent {
- - + +
@@ -465,7 +465,9 @@ class Audio extends React.PureComponent {
- + + +
diff --git a/app/javascript/flavours/glitch/features/video/index.js b/app/javascript/flavours/glitch/features/video/index.js index 21d327823..d22bc1d56 100644 --- a/app/javascript/flavours/glitch/features/video/index.js +++ b/app/javascript/flavours/glitch/features/video/index.js @@ -551,8 +551,8 @@ class Video extends React.PureComponent {
- - + +
@@ -576,10 +576,10 @@ class Video extends React.PureComponent {
- {(!onCloseVideo && !editable && !fullscreen && !this.props.alwaysVisible) && } - {(!fullscreen && onOpenVideo) && } - {onCloseVideo && } - + {(!onCloseVideo && !editable && !fullscreen && !this.props.alwaysVisible) && } + {(!fullscreen && onOpenVideo) && } + {onCloseVideo && } +
diff --git a/app/javascript/flavours/glitch/styles/components/media.scss b/app/javascript/flavours/glitch/styles/components/media.scss index 58bdb642f..f504fa91e 100644 --- a/app/javascript/flavours/glitch/styles/components/media.scss +++ b/app/javascript/flavours/glitch/styles/components/media.scss @@ -385,7 +385,6 @@ } .video-player__controls { - padding: 0 15px; padding-top: 10px; background: transparent; } @@ -512,7 +511,8 @@ &__buttons-bar { display: flex; justify-content: space-between; - padding-bottom: 10px; + padding-bottom: 8px; + margin: 0 -5px; .video-player__download__icon { color: inherit; @@ -536,22 +536,13 @@ overflow: hidden; text-overflow: ellipsis; - &.left { - button { - padding-left: 0; - } - } - - &.right { - button { - padding-right: 0; - } - } + .player-button { + display: inline-block; + outline: 0; - button { flex: 0 0 auto; background: transparent; - padding: 2px 10px; + padding: 5px; font-size: 16px; border: 0; color: rgba($white, 0.75); @@ -569,6 +560,7 @@ flex: 0 1 auto; overflow: hidden; text-overflow: ellipsis; + margin: 0 5px; } &__time-sep, @@ -688,7 +680,7 @@ display: block; position: absolute; height: 4px; - top: 10px; + top: 14px; } &__progress, @@ -697,7 +689,7 @@ position: absolute; height: 4px; border-radius: 4px; - top: 10px; + top: 14px; background: lighten($ui-highlight-color, 8%); } @@ -712,7 +704,7 @@ border-radius: 50%; width: 12px; height: 12px; - top: 6px; + top: 10px; margin-left: -6px; background: lighten($ui-highlight-color, 8%); box-shadow: 1px 2px 6px rgba($base-shadow-color, 0.2); @@ -736,7 +728,7 @@ &.detailed, &.fullscreen { .video-player__buttons { - button { + .player-button { padding-top: 10px; padding-bottom: 10px; } -- cgit From 078744f210add1edc988142fad3815d4fb92de01 Mon Sep 17 00:00:00 2001 From: Mélanie Chauvel Date: Tue, 27 Oct 2020 03:00:47 +0100 Subject: [Glitch] Make visibility icon clickable as part of the time of a toot Port 1d07f51039625c2eafa7eb0b1b6d5a7f8cf00e41 to glitch-soc Signed-off-by: Thibaut Girka --- .../flavours/glitch/features/ui/components/boost_modal.js | 5 +++-- app/javascript/flavours/glitch/styles/components/modal.scss | 4 +--- app/javascript/flavours/glitch/styles/statuses.scss | 7 +++---- 3 files changed, 7 insertions(+), 9 deletions(-) (limited to 'app/javascript/flavours/glitch') diff --git a/app/javascript/flavours/glitch/features/ui/components/boost_modal.js b/app/javascript/flavours/glitch/features/ui/components/boost_modal.js index 8092e862f..12ad426c8 100644 --- a/app/javascript/flavours/glitch/features/ui/components/boost_modal.js +++ b/app/javascript/flavours/glitch/features/ui/components/boost_modal.js @@ -78,9 +78,10 @@ class BoostModal extends ImmutablePureComponent {
- + + +
-
diff --git a/app/javascript/flavours/glitch/styles/components/modal.scss b/app/javascript/flavours/glitch/styles/components/modal.scss index 85f216887..7abe8818b 100644 --- a/app/javascript/flavours/glitch/styles/components/modal.scss +++ b/app/javascript/flavours/glitch/styles/components/modal.scss @@ -427,10 +427,8 @@ .status__visibility-icon { color: $dark-text-color; - float: right; font-size: 14px; - margin-left: 4px; - margin-right: 4px; + padding: 0 4px; } .status__display-name { diff --git a/app/javascript/flavours/glitch/styles/statuses.scss b/app/javascript/flavours/glitch/styles/statuses.scss index 982a1ab9a..58f74f954 100644 --- a/app/javascript/flavours/glitch/styles/statuses.scss +++ b/app/javascript/flavours/glitch/styles/statuses.scss @@ -201,19 +201,18 @@ display: initial; } - .status__relative-time, - .status__visibility-icon { + .status__relative-time { color: $dark-text-color; float: right; font-size: 14px; width: auto; margin: initial; padding: initial; + padding-bottom: 1px; } .status__visibility-icon { - margin-left: 4px; - margin-right: 4px; + padding: 0 4px; } .status__info .status__display-name { -- cgit From f5df3d1ae25846bb4f651c531c5e5c9bffebeaae Mon Sep 17 00:00:00 2001 From: mayaeh Date: Tue, 27 Oct 2020 21:34:02 +0900 Subject: [Glitch] Fix width of content text fluctuating over time Port 2ae751f19d48c12e70a445ce1d01149866b56ce8 to glitch-soc Signed-off-by: Thibaut Girka --- app/javascript/flavours/glitch/styles/components/status.scss | 1 + 1 file changed, 1 insertion(+) (limited to 'app/javascript/flavours/glitch') diff --git a/app/javascript/flavours/glitch/styles/components/status.scss b/app/javascript/flavours/glitch/styles/components/status.scss index 554ea8cd5..94b9a1e99 100644 --- a/app/javascript/flavours/glitch/styles/components/status.scss +++ b/app/javascript/flavours/glitch/styles/components/status.scss @@ -55,6 +55,7 @@ font-weight: 400; overflow: visible; padding-top: 5px; + clear: both; &:focus { outline: 0; -- cgit From 40af1cf65bdbe9e6ef5f480b6e03cb1be7db5774 Mon Sep 17 00:00:00 2001 From: Mashiro Date: Tue, 3 Nov 2020 04:16:38 +0800 Subject: [Glitch] Add expand/compress image button on image view box Port 6a2db10f767879b9072b6c020ebadac4f985ed34 to glitch-soc Signed-off-by: Thibaut Girka --- .../glitch/features/ui/components/image_loader.js | 4 + .../glitch/features/ui/components/media_modal.js | 24 +- .../features/ui/components/zoomable_image.js | 299 +++++++++++++++++++-- .../flavours/glitch/styles/components/index.scss | 14 + .../flavours/glitch/styles/components/modal.scss | 15 ++ 5 files changed, 335 insertions(+), 21 deletions(-) (limited to 'app/javascript/flavours/glitch') diff --git a/app/javascript/flavours/glitch/features/ui/components/image_loader.js b/app/javascript/flavours/glitch/features/ui/components/image_loader.js index 5e1cf75af..c6f16a792 100644 --- a/app/javascript/flavours/glitch/features/ui/components/image_loader.js +++ b/app/javascript/flavours/glitch/features/ui/components/image_loader.js @@ -13,6 +13,7 @@ export default class ImageLoader extends React.PureComponent { width: PropTypes.number, height: PropTypes.number, onClick: PropTypes.func, + zoomButtonHidden: PropTypes.bool, } static defaultProps = { @@ -151,6 +152,9 @@ export default class ImageLoader extends React.PureComponent { alt={alt} src={src} onClick={onClick} + width={width} + height={height} + zoomButtonHidden={this.props.zoomButtonHidden} /> )}
diff --git a/app/javascript/flavours/glitch/features/ui/components/media_modal.js b/app/javascript/flavours/glitch/features/ui/components/media_modal.js index aa6554107..e37df7208 100644 --- a/app/javascript/flavours/glitch/features/ui/components/media_modal.js +++ b/app/javascript/flavours/glitch/features/ui/components/media_modal.js @@ -35,23 +35,39 @@ class MediaModal extends ImmutablePureComponent { state = { index: null, navigationHidden: false, + zoomButtonHidden: false, }; handleSwipe = (index) => { this.setState({ index: index % this.props.media.size }); } + handleTransitionEnd = () => { + this.setState({ + zoomButtonHidden: false, + }); + } + handleNextClick = () => { - this.setState({ index: (this.getIndex() + 1) % this.props.media.size }); + this.setState({ + index: (this.getIndex() + 1) % this.props.media.size, + zoomButtonHidden: true, + }); } handlePrevClick = () => { - this.setState({ index: (this.props.media.size + this.getIndex() - 1) % this.props.media.size }); + this.setState({ + index: (this.props.media.size + this.getIndex() - 1) % this.props.media.size, + zoomButtonHidden: true, + }); } handleChangeIndex = (e) => { const index = Number(e.currentTarget.getAttribute('data-index')); - this.setState({ index: index % this.props.media.size }); + this.setState({ + index: index % this.props.media.size, + zoomButtonHidden: true, + }); } handleKeyDown = (e) => { @@ -128,6 +144,7 @@ class MediaModal extends ImmutablePureComponent { alt={image.get('description')} key={image.get('url')} onClick={this.toggleNavigation} + zoomButtonHidden={this.state.zoomButtonHidden} /> ); } else if (image.get('type') === 'video') { @@ -191,6 +208,7 @@ class MediaModal extends ImmutablePureComponent { style={swipeableViewsStyle} containerStyle={containerStyle} onChangeIndex={this.handleSwipe} + onTransitionEnd={this.handleTransitionEnd} index={index} > {content} diff --git a/app/javascript/flavours/glitch/features/ui/components/zoomable_image.js b/app/javascript/flavours/glitch/features/ui/components/zoomable_image.js index 3f6562bc9..004913480 100644 --- a/app/javascript/flavours/glitch/features/ui/components/zoomable_image.js +++ b/app/javascript/flavours/glitch/features/ui/components/zoomable_image.js @@ -1,8 +1,16 @@ import React from 'react'; import PropTypes from 'prop-types'; +import IconButton from 'flavours/glitch/components/icon_button'; +import { defineMessages, injectIntl } from 'react-intl'; + +const messages = defineMessages({ + compress: { id: 'lightbox.compress', defaultMessage: 'Compress image view box' }, + expand: { id: 'lightbox.expand', defaultMessage: 'Expand image view box' }, +}); const MIN_SCALE = 1; const MAX_SCALE = 4; +const NAV_BAR_HEIGHT = 66; const getMidpoint = (p1, p2) => ({ x: (p1.clientX + p2.clientX) / 2, @@ -14,7 +22,77 @@ const getDistance = (p1, p2) => const clamp = (min, max, value) => Math.min(max, Math.max(min, value)); -export default class ZoomableImage extends React.PureComponent { +// Normalizing mousewheel speed across browsers +// copy from: https://github.com/facebookarchive/fixed-data-table/blob/master/src/vendor_upstream/dom/normalizeWheel.js +const normalizeWheel = event => { + // Reasonable defaults + const PIXEL_STEP = 10; + const LINE_HEIGHT = 40; + const PAGE_HEIGHT = 800; + + let sX = 0, + sY = 0, // spinX, spinY + pX = 0, + pY = 0; // pixelX, pixelY + + // Legacy + if ('detail' in event) { + sY = event.detail; + } + if ('wheelDelta' in event) { + sY = -event.wheelDelta / 120; + } + if ('wheelDeltaY' in event) { + sY = -event.wheelDeltaY / 120; + } + if ('wheelDeltaX' in event) { + sX = -event.wheelDeltaX / 120; + } + + // side scrolling on FF with DOMMouseScroll + if ('axis' in event && event.axis === event.HORIZONTAL_AXIS) { + sX = sY; + sY = 0; + } + + pX = sX * PIXEL_STEP; + pY = sY * PIXEL_STEP; + + if ('deltaY' in event) { + pY = event.deltaY; + } + if ('deltaX' in event) { + pX = event.deltaX; + } + + if ((pX || pY) && event.deltaMode) { + if (event.deltaMode === 1) { // delta in LINE units + pX *= LINE_HEIGHT; + pY *= LINE_HEIGHT; + } else { // delta in PAGE units + pX *= PAGE_HEIGHT; + pY *= PAGE_HEIGHT; + } + } + + // Fall-back if spin cannot be determined + if (pX && !sX) { + sX = (pX < 1) ? -1 : 1; + } + if (pY && !sY) { + sY = (pY < 1) ? -1 : 1; + } + + return { + spinX: sX, + spinY: sY, + pixelX: pX, + pixelY: pY, + }; +}; + +export default @injectIntl +class ZoomableImage extends React.PureComponent { static propTypes = { alt: PropTypes.string, @@ -22,6 +100,8 @@ export default class ZoomableImage extends React.PureComponent { width: PropTypes.number, height: PropTypes.number, onClick: PropTypes.func, + zoomButtonHidden: PropTypes.bool, + intl: PropTypes.object.isRequired, } static defaultProps = { @@ -32,6 +112,22 @@ export default class ZoomableImage extends React.PureComponent { state = { scale: MIN_SCALE, + zoomMatrix: { + type: null, // 'full-width' 'full-height' + rate: null, // full screen scale rate + clientWidth: null, + clientHeight: null, + offsetWidth: null, + offsetHeight: null, + clientHeightFixed: null, + scrollTop: null, + scrollLeft: null, + }, + zoomState: 'expand', // 'expand' 'compress' + navigationHidden: false, + dragPosition: { top: 0, left: 0, x: 0, y: 0 }, + dragged: false, + lockScroll: { x: 0, y: 0 }, } removers = []; @@ -49,17 +145,101 @@ export default class ZoomableImage extends React.PureComponent { // https://www.chromestatus.com/features/5093566007214080 this.container.addEventListener('touchmove', handler, { passive: false }); this.removers.push(() => this.container.removeEventListener('touchend', handler)); + + handler = this.mouseDownHandler; + this.container.addEventListener('mousedown', handler); + this.removers.push(() => this.container.removeEventListener('mousedown', handler)); + + handler = this.mouseWheelHandler; + this.container.addEventListener('wheel', handler); + this.removers.push(() => this.container.removeEventListener('wheel', handler)); + // Old Chrome + this.container.addEventListener('mousewheel', handler); + this.removers.push(() => this.container.removeEventListener('mousewheel', handler)); + // Old Firefox + this.container.addEventListener('DOMMouseScroll', handler); + this.removers.push(() => this.container.removeEventListener('DOMMouseScroll', handler)); + + this.initZoomMatrix(); } componentWillUnmount () { this.removeEventListeners(); } + componentDidUpdate () { + if (this.props.zoomButtonHidden) { + this.setState({ scale: MIN_SCALE }, () => { + this.container.scrollLeft = 0; + this.container.scrollTop = 0; + }); + } + + this.setState({ zoomState: this.state.scale >= this.state.zoomMatrix.rate ? 'compress' : 'expand' }); + + if (this.state.scale === 1) { + this.container.style.removeProperty('cursor'); + } + } + removeEventListeners () { this.removers.forEach(listeners => listeners()); this.removers = []; } + mouseWheelHandler = e => { + e.preventDefault(); + + const event = normalizeWheel(e); + + if (this.state.zoomMatrix.type === 'full-width') { + // full width, scroll vertical + this.container.scrollTop = this.container.scrollTop + event.pixelY; + } else { + // full height, scroll horizontal + this.container.scrollLeft = this.container.scrollLeft + event.pixelY; + } + } + + mouseDownHandler = e => { + this.container.style.cursor = 'grabbing'; + this.container.style.userSelect = 'none'; + + this.setState({ dragPosition: { + left: this.container.scrollLeft, + top: this.container.scrollTop, + // Get the current mouse position + x: e.clientX, + y: e.clientY, + } }); + + this.image.addEventListener('mousemove', this.mouseMoveHandler); + this.image.addEventListener('mouseup', this.mouseUpHandler); + } + + mouseMoveHandler = e => { + const dx = e.clientX - this.state.dragPosition.x; + const dy = e.clientY - this.state.dragPosition.y; + + if ((this.state.dragPosition.left - dx) >= this.state.lockScroll.x) { + this.container.scrollLeft = this.state.dragPosition.left - dx; + } + + if ((this.state.dragPosition.top - dy) >= this.state.lockScroll.y) { + this.container.scrollTop = this.state.dragPosition.top - dy; + } + + this.setState({ dragged: true }); + } + + mouseUpHandler = () => { + this.container.style.cursor = 'grab'; + this.container.style.removeProperty('user-select'); + + this.image.removeEventListener('mousemove', this.mouseMoveHandler); + this.image.removeEventListener('mouseup', this.mouseUpHandler); + } + handleTouchStart = e => { if (e.touches.length !== 2) return; @@ -80,7 +260,8 @@ export default class ZoomableImage extends React.PureComponent { const distance = getDistance(...e.touches); const midpoint = getMidpoint(...e.touches); - const scale = clamp(MIN_SCALE, MAX_SCALE, this.state.scale * distance / this.lastDistance); + const _MAX_SCALE = Math.max(MAX_SCALE, this.state.zoomMatrix.rate); + const scale = clamp(MIN_SCALE, _MAX_SCALE, this.state.scale * distance / this.lastDistance); this.zoom(scale, midpoint); @@ -110,8 +291,72 @@ export default class ZoomableImage extends React.PureComponent { handleClick = e => { // don't propagate event to MediaModal e.stopPropagation(); + const dragged = this.state.dragged; + this.setState({ dragged: false }); + if (dragged) return; const handler = this.props.onClick; if (handler) handler(); + this.setState({ navigationHidden: !this.state.navigationHidden }); + } + + handleMouseDown = e => { + e.preventDefault(); + } + + initZoomMatrix = () => { + const { width, height } = this.props; + const { clientWidth, clientHeight } = this.container; + const { offsetWidth, offsetHeight } = this.image; + const clientHeightFixed = clientHeight - NAV_BAR_HEIGHT; + + const type = width/height < clientWidth / clientHeightFixed ? 'full-width' : 'full-height'; + const rate = type === 'full-width' ? clientWidth / offsetWidth : clientHeightFixed / offsetHeight; + const scrollTop = type === 'full-width' ? (clientHeight - offsetHeight) / 2 - NAV_BAR_HEIGHT : (clientHeightFixed - offsetHeight) / 2; + const scrollLeft = (clientWidth - offsetWidth) / 2; + + this.setState({ + zoomMatrix: { + type: type, + rate: rate, + clientWidth: clientWidth, + clientHeight: clientHeight, + offsetWidth: offsetWidth, + offsetHeight: offsetHeight, + clientHeightFixed: clientHeightFixed, + scrollTop: scrollTop, + scrollLeft: scrollLeft, + }, + }); + } + + handleZoomClick = e => { + e.preventDefault(); + e.stopPropagation(); + + const { scale, zoomMatrix } = this.state; + + if ( scale >= zoomMatrix.rate ) { + this.setState({ scale: MIN_SCALE }, () => { + this.container.scrollLeft = 0; + this.container.scrollTop = 0; + this.setState({ lockScroll: { + x: 0, + y: 0, + } }); + }); + } else { + this.setState({ scale: zoomMatrix.rate }, () => { + this.container.scrollLeft = zoomMatrix.scrollLeft; + this.container.scrollTop = zoomMatrix.scrollTop; + this.setState({ lockScroll: { + x: zoomMatrix.scrollLeft, + y: zoomMatrix.scrollTop, + } }); + }); + } + + this.container.style.cursor = 'grab'; + this.container.style.removeProperty('user-select'); } setContainerRef = c => { @@ -123,29 +368,47 @@ export default class ZoomableImage extends React.PureComponent { } render () { - const { alt, src } = this.props; + const { alt, src, width, height, intl } = this.props; const { scale } = this.state; const overflow = scale === 1 ? 'hidden' : 'scroll'; + const zoomButtonSshouldHide = !this.state.navigationHidden && !this.props.zoomButtonHidden ? '' : 'media-modal__zoom-button--hidden'; + const zoomButtonTitle = this.state.zoomState === 'compress' ? intl.formatMessage(messages.compress) : intl.formatMessage(messages.expand); return ( -
- {alt} + -
+
+ {alt} +
+ ); } diff --git a/app/javascript/flavours/glitch/styles/components/index.scss b/app/javascript/flavours/glitch/styles/components/index.scss index 0614278e2..3e67754c5 100644 --- a/app/javascript/flavours/glitch/styles/components/index.scss +++ b/app/javascript/flavours/glitch/styles/components/index.scss @@ -425,6 +425,20 @@ align-items: center; justify-content: center; flex-direction: column; + scrollbar-width: none; /* Firefox */ + -ms-overflow-style: none; /* IE 10+ */ + + * { + scrollbar-width: none; /* Firefox */ + -ms-overflow-style: none; /* IE 10+ */ + } + + &::-webkit-scrollbar, + *::-webkit-scrollbar { + width: 0; + height: 0; + background: transparent; /* Chrome/Safari/Webkit */ + } .image-loader__preview-canvas { max-width: $media-modal-media-max-width; diff --git a/app/javascript/flavours/glitch/styles/components/modal.scss b/app/javascript/flavours/glitch/styles/components/modal.scss index 7abe8818b..bc0965864 100644 --- a/app/javascript/flavours/glitch/styles/components/modal.scss +++ b/app/javascript/flavours/glitch/styles/components/modal.scss @@ -40,6 +40,21 @@ z-index: 9999; } +.media-modal__zoom-button { + position: absolute; + right: 64px; + top: 8px; + z-index: 100; + pointer-events: auto; + transition: opacity 0.3s linear; + will-change: opacity; +} + +.media-modal__zoom-button--hidden { + pointer-events: none; + opacity: 0; +} + .onboarding-modal, .error-modal, .embed-modal { -- cgit From dc86d814d93b9bb564ab35728c6d9fb65d064ca3 Mon Sep 17 00:00:00 2001 From: Mashiro Date: Tue, 3 Nov 2020 13:06:45 +0800 Subject: [Glitch] add mouse scroll lock in image expand view Port f645dad661ba033efdcdd6ca7597e7b8bc7f4f51 to glitch-soc Signed-off-by: Thibaut Girka --- .../features/ui/components/zoomable_image.js | 40 ++++++++++++---------- 1 file changed, 21 insertions(+), 19 deletions(-) (limited to 'app/javascript/flavours/glitch') diff --git a/app/javascript/flavours/glitch/features/ui/components/zoomable_image.js b/app/javascript/flavours/glitch/features/ui/components/zoomable_image.js index 004913480..2efc70890 100644 --- a/app/javascript/flavours/glitch/features/ui/components/zoomable_image.js +++ b/app/javascript/flavours/glitch/features/ui/components/zoomable_image.js @@ -194,11 +194,14 @@ class ZoomableImage extends React.PureComponent { if (this.state.zoomMatrix.type === 'full-width') { // full width, scroll vertical - this.container.scrollTop = this.container.scrollTop + event.pixelY; + this.container.scrollTop = Math.max(this.container.scrollTop + event.pixelY, this.state.lockScroll.y); } else { // full height, scroll horizontal - this.container.scrollLeft = this.container.scrollLeft + event.pixelY; + this.container.scrollLeft = Math.max(this.container.scrollLeft + event.pixelY, this.state.lockScroll.x); } + + // lock horizontal scroll + this.container.scrollLeft = Math.max(this.container.scrollLeft + event.pixelX, this.state.lockScroll.x); } mouseDownHandler = e => { @@ -221,13 +224,8 @@ class ZoomableImage extends React.PureComponent { const dx = e.clientX - this.state.dragPosition.x; const dy = e.clientY - this.state.dragPosition.y; - if ((this.state.dragPosition.left - dx) >= this.state.lockScroll.x) { - this.container.scrollLeft = this.state.dragPosition.left - dx; - } - - if ((this.state.dragPosition.top - dy) >= this.state.lockScroll.y) { - this.container.scrollTop = this.state.dragPosition.top - dy; - } + this.container.scrollLeft = Math.max(this.state.dragPosition.left - dx, this.state.lockScroll.x); + this.container.scrollTop = Math.max(this.state.dragPosition.top - dy, this.state.lockScroll.y); this.setState({ dragged: true }); } @@ -336,22 +334,26 @@ class ZoomableImage extends React.PureComponent { const { scale, zoomMatrix } = this.state; if ( scale >= zoomMatrix.rate ) { - this.setState({ scale: MIN_SCALE }, () => { - this.container.scrollLeft = 0; - this.container.scrollTop = 0; - this.setState({ lockScroll: { + this.setState({ + scale: MIN_SCALE, + lockScroll: { x: 0, y: 0, - } }); + }, + }, () => { + this.container.scrollLeft = 0; + this.container.scrollTop = 0; }); } else { - this.setState({ scale: zoomMatrix.rate }, () => { - this.container.scrollLeft = zoomMatrix.scrollLeft; - this.container.scrollTop = zoomMatrix.scrollTop; - this.setState({ lockScroll: { + this.setState({ + scale: zoomMatrix.rate, + lockScroll: { x: zoomMatrix.scrollLeft, y: zoomMatrix.scrollTop, - } }); + }, + }, () => { + this.container.scrollLeft = zoomMatrix.scrollLeft; + this.container.scrollTop = zoomMatrix.scrollTop; }); } -- cgit From a48dbc78f829874190ba062635881a7444d1e5f9 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Wed, 4 Nov 2020 15:12:06 +0100 Subject: Fix hiding video breaking playback Also make the video player code closer to upstream --- .../flavours/glitch/features/video/index.js | 28 ++++++++++++---------- 1 file changed, 16 insertions(+), 12 deletions(-) (limited to 'app/javascript/flavours/glitch') diff --git a/app/javascript/flavours/glitch/features/video/index.js b/app/javascript/flavours/glitch/features/video/index.js index d22bc1d56..870812856 100644 --- a/app/javascript/flavours/glitch/features/video/index.js +++ b/app/javascript/flavours/glitch/features/video/index.js @@ -281,9 +281,9 @@ class Video extends React.PureComponent { togglePlay = () => { if (this.state.paused) { - this.video.play(); + this.setState({ paused: false }, () => this.video.play()); } else { - this.video.pause(); + this.setState({ paused: true }, () => this.video.pause()); } } @@ -381,13 +381,16 @@ class Video extends React.PureComponent { } toggleMute = () => { - this.video.muted = !this.video.muted; - this.setState({ muted: this.video.muted }); + const muted = !this.video.muted; + + this.setState({ muted }, () => { + this.video.muted = muted; + }); } toggleReveal = () => { if (this.state.revealed) { - this.video.pause(); + this.setState({ paused: true }); } if (this.props.onToggleVisibility) { @@ -475,13 +478,6 @@ class Video extends React.PureComponent { return (
); } - let warning; - if (sensitive) { - warning = ; - } else { - warning = ; - } - let preload; if (this.props.currentTime || fullscreen || dragging) { @@ -492,6 +488,14 @@ class Video extends React.PureComponent { preload = 'none'; } + let warning; + + if (sensitive) { + warning = ; + } else { + warning = ; + } + return (
Date: Wed, 4 Nov 2020 15:26:58 +0100 Subject: Fix unsightly re-layout delay for media previews --- app/javascript/flavours/glitch/components/media_gallery.js | 1 + 1 file changed, 1 insertion(+) (limited to 'app/javascript/flavours/glitch') diff --git a/app/javascript/flavours/glitch/components/media_gallery.js b/app/javascript/flavours/glitch/components/media_gallery.js index 96042f07a..890a422d3 100644 --- a/app/javascript/flavours/glitch/components/media_gallery.js +++ b/app/javascript/flavours/glitch/components/media_gallery.js @@ -297,6 +297,7 @@ class MediaGallery extends React.PureComponent { this._setDimensions(); } }, 250, { + leading: true, trailing: true, }); -- cgit