@@ -222,7 +197,7 @@ class Item extends React.PureComponent {
}
return (
-
+
{visible && thumbnail}
@@ -278,7 +253,7 @@ class MediaGallery extends React.PureComponent {
}
handleRef = (node) => {
- if (node /*&& this.isStandaloneEligible()*/) {
+ if (node) {
// offsetWidth triggers a layout, so only calculate when we need to
if (this.props.cacheWidth) this.props.cacheWidth(node.offsetWidth);
@@ -288,11 +263,6 @@ class MediaGallery extends React.PureComponent {
}
}
- isStandaloneEligible() {
- const { media, standalone } = this.props;
- return standalone && media.size === 1 && media.getIn([0, 'meta', 'small', 'aspect']);
- }
-
render () {
const { media, intl, sensitive, height, defaultWidth } = this.props;
const { visible } = this.state;
@@ -302,24 +272,221 @@ class MediaGallery extends React.PureComponent {
let children, spoilerButton;
const style = {};
+ const size = media.take(4).size;
- if (this.isStandaloneEligible()) {
- if (width) {
- style.height = width / this.props.media.getIn([0, 'meta', 'small', 'aspect']);
+ const standard169 = width / (16 / 9);
+ const standard169_percent = 100 / (16 / 9);
+ const standard169_px = `${standard169}px`;
+ const panoSize = Math.floor(width / maximumAspectRatio);
+ const panoSize_px = `${Math.floor(width / maximumAspectRatio)}px`;
+ let itemsDimensions = [];
+
+ if (size == 1 && width) {
+ const aspectRatio = media.getIn([0, 'meta', 'small', 'aspect']);
+
+ if (isPanoramic(aspectRatio)) {
+ style.height = Math.floor(width / maximumAspectRatio);
+ } else if (isPortrait(aspectRatio)) {
+ style.height = Math.floor(width / minimumAspectRatio);
+ } else {
+ style.height = Math.floor(width / aspectRatio);
+ }
+ } else if (size > 1 && width) {
+ const ar1 = media.getIn([0, 'meta', 'small', 'aspect']);
+ const ar2 = media.getIn([1, 'meta', 'small', 'aspect']);
+ const ar3 = media.getIn([2, 'meta', 'small', 'aspect']);
+ const ar4 = media.getIn([3, 'meta', 'small', 'aspect']);
+
+ if (size == 2) {
+ if (isPortrait(ar1) && isPortrait(ar2)) {
+ style.height = width - (width / maximumAspectRatio);
+ } else if (isPanoramic(ar1) && isPanoramic(ar2)) {
+ style.height = panoSize * 2;
+ } else if (
+ (isPanoramic(ar1) && isPortrait(ar2)) ||
+ (isPortrait(ar1) && isPanoramic(ar2)) ||
+ (isPanoramic(ar1) && isNonConformingRatio(ar2)) ||
+ (isNonConformingRatio(ar1) && isPanoramic(ar2))
+ ) {
+ style.height = (width * 0.6) + (width / maximumAspectRatio);
+ } else {
+ style.height = width / 2;
+ }
+
+ //
+
+ if (isPortrait(ar1) && isPortrait(ar2)) {
+ itemsDimensions = [
+ { w: 50, h: '100%', r: '2px' },
+ { w: 50, h: '100%', l: '2px' }
+ ];
+ } else if (isPanoramic(ar1) && isPanoramic(ar2)) {
+ itemsDimensions = [
+ { w: 100, h: panoSize_px, b: '2px' },
+ { w: 100, h: panoSize_px, t: '2px' }
+ ];
+ } else if (
+ (isPanoramic(ar1) && isPortrait(ar2)) ||
+ (isPanoramic(ar1) && isNonConformingRatio(ar2))
+ ) {
+ itemsDimensions = [
+ { w: 100, h: `${(width / maximumAspectRatio)}px`, b: '2px' },
+ { w: 100, h: `${(width * 0.6)}px`, t: '2px' },
+ ];
+ } else if (
+ (isPortrait(ar1) && isPanoramic(ar2)) ||
+ (isNonConformingRatio(ar1) && isPanoramic(ar2))
+ ) {
+ itemsDimensions = [
+ { w: 100, h: `${(width * 0.6)}px`, b: '2px' },
+ { w: 100, h: `${(width / maximumAspectRatio)}px`, t: '2px' },
+ ];
+ } else {
+ itemsDimensions = [
+ { w: 50, h: '100%', r: '2px' },
+ { w: 50, h: '100%', l: '2px' }
+ ];
+ }
+ } else if (size == 3) {
+ if (isPanoramic(ar1) && isPanoramic(ar2) && isPanoramic(ar3)) {
+ style.height = panoSize * 3;
+ } else if (isPortrait(ar1) && isPortrait(ar2) && isPortrait(ar3)) {
+ style.height = Math.floor(width / minimumAspectRatio);
+ } else {
+ style.height = width;
+ }
+
+ //
+
+ if (isPanoramic(ar1) && isNonConformingRatio(ar2) && isNonConformingRatio(ar3)) {
+ itemsDimensions = [
+ { w: 100, h: `50%`, b: '2px' },
+ { w: 50, h: '50%', t: '2px', r: '2px' },
+ { w: 50, h: '50%', t: '2px', l: '2px' }
+ ];
+ } else if (isPanoramic(ar1) && isPanoramic(ar2) && isPanoramic(ar3)) {
+ itemsDimensions = [
+ { w: 100, h: panoSize_px, b: '4px' },
+ { w: 100, h: panoSize_px },
+ { w: 100, h: panoSize_px, t: '4px' }
+ ];
+ } else if (isPortrait(ar1) && isNonConformingRatio(ar2) && isNonConformingRatio(ar3)) {
+ itemsDimensions = [
+ { w: 50, h: `100%`, r: '2px' },
+ { w: 50, h: '50%', b: '2px', l: '2px' },
+ { w: 50, h: '50%', t: '2px', l: '2px' },
+ ];
+ } else if (isNonConformingRatio(ar1) && isNonConformingRatio(ar2) && isPortrait(ar3)) {
+ itemsDimensions = [
+ { w: 50, h: '50%', b: '2px', r: '2px' },
+ { w: 50, h: '50%', l: '-2px', b: '-2px', pos: 'absolute', float: 'none' },
+ { w: 50, h: `100%`, r: '-2px', t: '0px', b: '0px', pos: 'absolute', float: 'none' }
+ ];
+ } else if (
+ (isNonConformingRatio(ar1) && isPortrait(ar2) && isNonConformingRatio(ar3)) ||
+ (isPortrait(ar1) && isPortrait(ar2) && isPortrait(ar3))
+ ) {
+ itemsDimensions = [
+ { w: 50, h: '50%', b: '2px', r: '2px' },
+ { w: 50, h: `100%`, l: '2px', float: 'right' },
+ { w: 50, h: '50%', t: '2px', r: '2px' }
+ ];
+ } else if (
+ (isPanoramic(ar1) && isPanoramic(ar2) && isNonConformingRatio(ar3)) ||
+ (isPanoramic(ar1) && isPanoramic(ar2) && isPortrait(ar3))
+ ) {
+ itemsDimensions = [
+ { w: 50, h: panoSize_px, b: '2px', r: '2px' },
+ { w: 50, h: panoSize_px, b: '2px', l: '2px' },
+ { w: 100, h: `${width - panoSize}px`, t: '2px' }
+ ];
+ } else if (
+ (isNonConformingRatio(ar1) && isPanoramic(ar2) && isPanoramic(ar3)) ||
+ (isPortrait(ar1) && isPanoramic(ar2) && isPanoramic(ar3))
+ ) {
+ itemsDimensions = [
+ { w: 100, h: `${width - panoSize}px`, b: '2px' },
+ { w: 50, h: panoSize_px, t: '2px', r: '2px' },
+ { w: 50, h: panoSize_px, t: '2px', l: '2px' },
+ ];
+ } else {
+ itemsDimensions = [
+ { w: 50, h: '50%', b: '2px', r: '2px' },
+ { w: 50, h: '50%', b: '2px', l: '2px' },
+ { w: 100, h: `50%`, t: '2px' }
+ ];
+ }
+ } else if (size == 4) {
+ if (
+ (isPortrait(ar1) && isPortrait(ar2) && isPortrait(ar3) && isPortrait(ar4)) ||
+ (isPortrait(ar1) && isPortrait(ar2) && isPortrait(ar3) && isNonConformingRatio(ar4)) ||
+ (isPortrait(ar1) && isPortrait(ar2) && isNonConformingRatio(ar3) && isPortrait(ar4)) ||
+ (isPortrait(ar1) && isNonConformingRatio(ar2) && isPortrait(ar3) && isPortrait(ar4)) ||
+ (isNonConformingRatio(ar1) && isPortrait(ar2) && isPortrait(ar3) && isPortrait(ar4))
+ ) {
+ style.height = Math.floor(width / minimumAspectRatio);
+ } else if (isPanoramic(ar1) && isPanoramic(ar2) && isPanoramic(ar3) && isPanoramic(ar4)) {
+ style.height = panoSize * 2;
+ } else if (
+ (isPanoramic(ar1) && isPanoramic(ar2) && isNonConformingRatio(ar3) && isNonConformingRatio(ar4)) ||
+ (isNonConformingRatio(ar1) && isNonConformingRatio(ar2) && isPanoramic(ar3) && isPanoramic(ar4))
+ ) {
+ style.height = panoSize + (width / 2);
+ } else {
+ style.height = width;
+ }
+
+ //
+
+ if (isPanoramic(ar1) && isPanoramic(ar2) && isNonConformingRatio(ar3) && isNonConformingRatio(ar4)) {
+ itemsDimensions = [
+ { w: 50, h: panoSize_px, b: '2px', r: '2px' },
+ { w: 50, h: panoSize_px, b: '2px', l: '2px' },
+ { w: 50, h: `${(width / 2)}px`, t: '2px', r: '2px' },
+ { w: 50, h: `${(width / 2)}px`, t: '2px', l: '2px' },
+ ];
+ } else if (isNonConformingRatio(ar1) && isNonConformingRatio(ar2) && isPanoramic(ar3) && isPanoramic(ar4)) {
+ itemsDimensions = [
+ { w: 50, h: `${(width / 2)}px`, b: '2px', r: '2px' },
+ { w: 50, h: `${(width / 2)}px`, b: '2px', l: '2px' },
+ { w: 50, h: panoSize_px, t: '2px', r: '2px' },
+ { w: 50, h: panoSize_px, t: '2px', l: '2px' },
+ ];
+ } else if (
+ (isPortrait(ar1) && isNonConformingRatio(ar2) && isNonConformingRatio(ar3) && isNonConformingRatio(ar4)) ||
+ (isPortrait(ar1) && isPanoramic(ar2) && isPanoramic(ar3) && isPanoramic(ar4))
+ ) {
+ itemsDimensions = [
+ { w: 67, h: '100%', r: '2px' },
+ { w: 33, h: '33%', b: '4px', l: '2px' },
+ { w: 33, h: '33%', l: '2px' },
+ { w: 33, h: '33%', t: '4px', l: '2px' }
+ ];
+ } else {
+ itemsDimensions = [
+ { w: 50, h: '50%', b: '2px', r: '2px' },
+ { w: 50, h: '50%', b: '2px', l: '2px' },
+ { w: 50, h: '50%', t: '2px', r: '2px' },
+ { w: 50, h: '50%', t: '2px', l: '2px' },
+ ];
+ }
}
- } else if (width) {
- style.height = width / (16/9);
} else {
style.height = height;
}
- const size = media.take(4).size;
-
- if (this.isStandaloneEligible()) {
- children =
;
- } else {
- children = media.take(4).map((attachment, i) =>
);
- }
+ children = media.take(4).map((attachment, i) => (
+
+ ));
if (visible) {
spoilerButton =
;
diff --git a/app/javascript/gabsocial/components/status.js b/app/javascript/gabsocial/components/status.js
index 58389e1a..091ad617 100644
--- a/app/javascript/gabsocial/components/status.js
+++ b/app/javascript/gabsocial/components/status.js
@@ -344,6 +344,7 @@ class Status extends ImmutablePureComponent {
blurhash={video.get('blurhash')}
src={video.get('url')}
alt={video.get('description')}
+ aspectRatio={video.getIn(['meta', 'small', 'aspect'])}
width={this.props.cachedMediaWidth}
height={110}
inline
diff --git a/app/javascript/gabsocial/features/report/components/status_check_box.js b/app/javascript/gabsocial/features/report/components/status_check_box.js
index c29e517d..9991216d 100644
--- a/app/javascript/gabsocial/features/report/components/status_check_box.js
+++ b/app/javascript/gabsocial/features/report/components/status_check_box.js
@@ -38,6 +38,7 @@ export default class StatusCheckBox extends React.PureComponent {
blurhash={video.get('blurhash')}
src={video.get('url')}
alt={video.get('description')}
+ aspectRatio={video.getIn(['meta', 'small', 'aspect'])}
width={239}
height={110}
inline
diff --git a/app/javascript/gabsocial/features/status/components/detailed_status.js b/app/javascript/gabsocial/features/status/components/detailed_status.js
index b8f2f773..7b87b54b 100644
--- a/app/javascript/gabsocial/features/status/components/detailed_status.js
+++ b/app/javascript/gabsocial/features/status/components/detailed_status.js
@@ -111,6 +111,7 @@ export default class DetailedStatus extends ImmutablePureComponent {
blurhash={video.get('blurhash')}
src={video.get('url')}
alt={video.get('description')}
+ aspectRatio={video.getIn(['meta', 'small', 'aspect'])}
width={300}
height={150}
inline
diff --git a/app/javascript/gabsocial/features/video/index.js b/app/javascript/gabsocial/features/video/index.js
index 64a24cbe..17deea6a 100644
--- a/app/javascript/gabsocial/features/video/index.js
+++ b/app/javascript/gabsocial/features/video/index.js
@@ -8,6 +8,7 @@ import { isFullscreen, requestFullscreen, exitFullscreen } from '../ui/util/full
import { displayMedia } from '../../initial_state';
import Icon from 'gabsocial/components/icon';
import { decode } from 'blurhash';
+import { isPanoramic, isPortrait, minimumAspectRatio, maximumAspectRatio } from '../../utils/media_aspect_ratio';
const messages = defineMessages({
play: { id: 'video.play', defaultMessage: 'Play' },
@@ -107,6 +108,7 @@ class Video extends React.PureComponent {
intl: PropTypes.object.isRequired,
blurhash: PropTypes.string,
link: PropTypes.node,
+ aspectRatio: PropTypes.number,
};
state = {
@@ -373,7 +375,7 @@ class Video extends React.PureComponent {
}
render () {
- const { preview, src, inline, startTime, onOpenVideo, onCloseVideo, intl, alt, detailed, sensitive, link } = this.props;
+ const { preview, src, inline, startTime, onOpenVideo, onCloseVideo, intl, alt, detailed, sensitive, link, aspectRatio } = this.props;
const { containerWidth, currentTime, duration, volume, buffer, dragging, paused, fullscreen, hovered, muted, revealed } = this.state;
const progress = (currentTime / duration) * 100;
@@ -384,8 +386,16 @@ class Video extends React.PureComponent {
let { width, height } = this.props;
if (inline && containerWidth) {
- width = containerWidth;
- height = containerWidth / (16/9);
+ width = containerWidth;
+ const minSize = containerWidth / (16/9);
+
+ if (isPanoramic(aspectRatio)) {
+ height = Math.max(Math.floor(containerWidth / maximumAspectRatio), minSize);
+ } else if (isPortrait(aspectRatio)) {
+ height = Math.max(Math.floor(containerWidth / minimumAspectRatio), minSize);
+ } else {
+ height = Math.floor(containerWidth / aspectRatio);
+ }
playerStyle.height = height;
}
diff --git a/app/javascript/gabsocial/utils/media_aspect_ratio.js b/app/javascript/gabsocial/utils/media_aspect_ratio.js
new file mode 100644
index 00000000..0a7d740a
--- /dev/null
+++ b/app/javascript/gabsocial/utils/media_aspect_ratio.js
@@ -0,0 +1,17 @@
+export const minimumAspectRatio = .8;
+export const maximumAspectRatio = 2.8;
+
+export const isPanoramic = ar => {
+ if (isNaN(ar)) return false;
+ return ar >= maximumAspectRatio;
+}
+
+export const isPortrait = ar => {
+ if (isNaN(ar)) return false;
+ return ar <= minimumAspectRatio;
+}
+
+export const isNonConformingRatio = ar => {
+ if (isNaN(ar)) return false;
+ return !isPanoramic(ar) && !isPortrait(ar);
+}
diff --git a/app/javascript/styles/gabsocial/components.scss b/app/javascript/styles/gabsocial/components.scss
index 9d1c7899..01fabb5e 100644
--- a/app/javascript/styles/gabsocial/components.scss
+++ b/app/javascript/styles/gabsocial/components.scss
@@ -3580,13 +3580,6 @@ a.status-card.compact:hover {
position: relative;
border-radius: 4px;
overflow: hidden;
-
- &.standalone {
- .media-gallery__item-gifv-thumbnail {
- transform: none;
- top: 0;
- }
- }
}
.media-gallery__item-thumbnail {
@@ -3636,10 +3629,10 @@ a.status-card.compact:hover {
height: 100%;
object-fit: cover;
position: relative;
- top: 50%;
- transform: translateY(-50%);
width: 100%;
z-index: 1;
+ transform: none;
+ top: 0;
}
.media-gallery__item-thumbnail-label {