diff --git a/app/soapbox/features/placeholder/components/placeholder_media_gallery.js b/app/soapbox/features/placeholder/components/placeholder_media_gallery.js
new file mode 100644
index 000000000..d44261e6c
--- /dev/null
+++ b/app/soapbox/features/placeholder/components/placeholder_media_gallery.js
@@ -0,0 +1,96 @@
+import React from 'react';
+import ImmutablePropTypes from 'react-immutable-proptypes';
+import { Map as ImmutableMap } from 'immutable';
+import PropTypes from 'prop-types';
+
+export default class PlaceholderMediaGallery extends React.Component {
+
+ static propTypes = {
+ media: ImmutablePropTypes.map.isRequired,
+ defaultWidth: PropTypes.number,
+ }
+
+ state = {
+ width: this.props.defaultWidth,
+ };
+
+ handleRef = (node) => {
+ if (node) {
+ this.setState({
+ width: node.offsetWidth,
+ });
+ }
+ }
+
+ getSizeData = size => {
+ const { defaultWidth } = this.props;
+ const width = this.state.width || defaultWidth;
+
+ const style = {};
+ let itemsDimensions = [];
+
+ if (size === 1) {
+ style.height = width * 9 / 16;
+
+ itemsDimensions = [
+ { w: '100%', h: '100%' },
+ ];
+ } else if (size === 2) {
+ style.height = width / 2;
+
+ itemsDimensions = [
+ { w: '50%', h: '100%', r: '2px' },
+ { w: '50%', h: '100%', l: '2px' },
+ ];
+ } else if (size === 3) {
+ style.height = width;
+
+ 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) {
+ style.height = width;
+
+ 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' },
+ ];
+ }
+
+ return ImmutableMap({
+ style,
+ itemsDimensions,
+ size,
+ width,
+ });
+ }
+
+ renderItem = (dimensions, i) => {
+ const width = dimensions.w;
+ const height = dimensions.h;
+ const top = dimensions.t || 'auto';
+ const right = dimensions.r || 'auto';
+ const bottom = dimensions.b || 'auto';
+ const left = dimensions.l || 'auto';
+ const float = dimensions.float || 'left';
+ const position = dimensions.pos || 'relative';
+
+ return
;
+ }
+
+ render() {
+ const { media } = this.props;
+ const sizeData = this.getSizeData(media.size);
+
+ return (
+
+ {media.take(4).map((_, i) => this.renderItem(sizeData.get('itemsDimensions')[i], i))}
+
+ );
+ }
+
+}
diff --git a/app/soapbox/features/placeholder/components/placeholder_status_content.js b/app/soapbox/features/placeholder/components/placeholder_status_content.js
index f3f4e951c..b51fa44c1 100644
--- a/app/soapbox/features/placeholder/components/placeholder_status_content.js
+++ b/app/soapbox/features/placeholder/components/placeholder_status_content.js
@@ -13,7 +13,7 @@ export default class PlaceholderStatusContent extends React.Component {
const { maxLength, minLength } = this.props;
const length = randomIntFromInterval(maxLength, minLength);
- return(
+ return (
{generateText(length)}
diff --git a/app/soapbox/features/ui/components/pending_status.js b/app/soapbox/features/ui/components/pending_status.js
index 13daa5928..638b896c9 100644
--- a/app/soapbox/features/ui/components/pending_status.js
+++ b/app/soapbox/features/ui/components/pending_status.js
@@ -10,9 +10,9 @@ import { Link, NavLink } from 'react-router-dom';
import { getDomain } from 'soapbox/utils/accounts';
import Avatar from 'soapbox/components/avatar';
import DisplayName from 'soapbox/components/display_name';
-import AttachmentThumbs from 'soapbox/components/attachment_thumbs';
import PollPreview from './poll_preview';
import PlaceholderCard from 'soapbox/features/placeholder/components/placeholder_card';
+import PlaceholderMediaGallery from '../../placeholder/components/placeholder_media_gallery';
const shouldHaveCard = pendingStatus => {
return Boolean(pendingStatus.get('content').match(/https?:\/\/\S*/));
@@ -34,8 +34,7 @@ class PendingStatus extends ImmutablePureComponent {
if (status.get('media_attachments') && !status.get('media_attachments').isEmpty()) {
return (
-
);
diff --git a/app/soapbox/features/ui/util/pending_status_builder.js b/app/soapbox/features/ui/util/pending_status_builder.js
index 191a99f1d..241abdbdb 100644
--- a/app/soapbox/features/ui/util/pending_status_builder.js
+++ b/app/soapbox/features/ui/util/pending_status_builder.js
@@ -22,7 +22,7 @@ export const buildStatus = (state, pendingStatus, idempotencyKey) => {
in_reply_to_account_id: null,
in_reply_to_id: pendingStatus.get('in_reply_to_id'),
language: null,
- media_attachments: [], // TODO: render pending thumbs
+ media_attachments: pendingStatus.get('media_ids').map(id => ({ id })),
mentions: [],
muted: false,
pinned: false,
diff --git a/app/styles/placeholder.scss b/app/styles/placeholder.scss
index ded87f579..37ed8ee58 100644
--- a/app/styles/placeholder.scss
+++ b/app/styles/placeholder.scss
@@ -1,7 +1,8 @@
.placeholder-status,
.placeholder-hashtag,
.notification--placeholder,
-.status-card--placeholder {
+.status-card--placeholder,
+.media-gallery--placeholder {
position: relative;
&::before {
@@ -120,3 +121,11 @@
opacity: 0.1;
}
}
+
+.media-gallery.media-gallery--placeholder {
+ background: none;
+
+ .media-gallery__item {
+ background-color: var(--brand-color--faint);
+ }
+}