Render attachments grouped by date

This commit is contained in:
Daniel Gasienica 2018-04-12 20:56:05 -04:00
parent e34347f290
commit d7b21ef5dc
7 changed files with 104 additions and 32 deletions

View file

@ -650,7 +650,8 @@
// Lightbox - or do we use the lightbox already in the app?
const props = {
number: 10,
media: [],
documents: [],
};
const view = new window.Whisper.ReactWrapper({

View file

@ -1,8 +1,10 @@
import React from 'react';
import { ImageThumbnail } from './ImageThumbnail';
import { DocumentListEntry } from './DocumentListEntry';
import { ImageThumbnail } from './ImageThumbnail';
import { Message } from './propTypes/Message';
import { missingCaseError } from '../../../missingCaseError';
const styles = {
container: {
@ -29,15 +31,34 @@ interface Props {
export class AttachmentListSection extends React.Component<Props, {}> {
public renderItems() {
const { i18n, messages, type } = this.props;
const Component = type === 'media' ? ImageThumbnail : DocumentListEntry;
return messages.map((message) => (
<Component
key={message.id}
i18n={i18n}
message={message}
/>
));
return messages.map((message) => {
const { attachments } = message;
const firstAttachment = attachments[0];
switch (type) {
case 'media':
return (
<ImageThumbnail
key={message.id}
i18n={i18n}
message={message}
/>
);
case 'documents':
return (
<DocumentListEntry
key={message.id}
i18n={i18n}
fileSize={firstAttachment.size}
fileName={firstAttachment.fileName}
timestamp={message.received_at}
/>
);
default:
return missingCaseError(type);
}
});
}
public render() {

View file

@ -7,7 +7,7 @@ import formatFileSize from 'filesize';
interface Props {
fileName: string | null;
fileName?: string;
fileSize?: number;
i18n: (key: string, values?: Array<string>) => string;
timestamp: number;

View file

@ -8,28 +8,38 @@ interface Props {
i18n: (value: string) => string;
}
const size = {
width: 94,
height: 94,
};
const styles = {
container: {
...size,
backgroundColor: '#f3f3f3',
marginRight: 4,
marginBottom: 4,
width: 94,
height: 94,
},
image: {
...size,
backgroundSize: 'cover',
},
};
export class ImageThumbnail extends React.Component<Props, {}> {
public renderContent() {
const { i18n, message } = this.props;
const {/* i18n, */message } = this.props;
if (!message.imageUrl) {
if (!message.objectURL) {
return <LoadingIndicator />;
}
return (
<img
src={message.imageUrl}
alt={`${i18n('messageCaption')}: ${message.body}`}
<div
style={{
...styles.container,
...styles.image,
backgroundImage: `url("${message.objectURL}")`,
}}
/>
);
}

View file

@ -10,24 +10,26 @@ const createRandomMessage = (props) => {
id: _.random(now).toString(),
received_at: _.random(now - YEAR_MS, now),
attachments: [{
fileName,
data: null,
fileName,
size: _.random(1000, 1000 * 1000 * 50),
}],
// TODO: Revisit
imageUrl: 'https://placekitten.com/94/94',
objectURL: `https://placekitten.com/${_.random(50, 150)}/${_.random(50, 150)}`,
...props,
};
};
const startTime = Date.now();
const messages = _.sortBy(
_.range(30).map(createRandomMessage),
_.range(25).map(createRandomMessage),
message => -message.received_at
);
<MediaGallery
i18n={(key) => key}
messages={messages}
i18n={window.i18n}
media={messages}
documents={messages}
/>
```

View file

@ -1,20 +1,26 @@
import React from 'react';
import moment from 'moment';
import { map } from 'lodash';
import { AttachmentListSection } from './AttachmentListSection';
import { groupMessagesByDate } from './groupMessagesByDate';
import { Message } from './propTypes/Message';
type AttachmentType = 'media' | 'documents';
interface Props {
documents: Array<Message>;
i18n: (key: string, values?: Array<string>) => string;
messages: Array<Message>;
media: Array<Message>;
}
interface State {
selectedTab: AttachmentType;
}
const MONTH_FORMAT = 'MMMM YYYY';
const COLOR_GREY = '#f3f3f3';
const tabStyle = {
@ -76,6 +82,10 @@ export class MediaGallery extends React.Component<Props, State> {
selectedTab: 'media',
};
private handleTabSelect = (event: TabSelectEvent): void => {
this.setState({selectedTab: event.type});
}
public render() {
const { selectedTab } = this.state;
@ -96,17 +106,44 @@ export class MediaGallery extends React.Component<Props, State> {
/>
</div>
<div style={styles.attachmentsContainer}>
<AttachmentListSection
type={selectedTab}
i18n={this.props.i18n}
messages={this.props.messages}
/>
{this.renderSections()}
</div>
</div>
);
}
private handleTabSelect = (event: TabSelectEvent): void => {
this.setState({selectedTab: event.type});
private renderSections() {
const { i18n, media, documents } = this.props;
const { selectedTab } = this.state;
const messages = selectedTab === 'media' ? media : documents;
const type = selectedTab;
if (!messages || messages.length === 0) {
// return <LoadingIndicator />;
return null;
}
const now = Date.now();
const groups = groupMessagesByDate(now, messages);
return map(groups, (annotations) => {
const first = annotations[0];
const date = moment(first.message.received_at);
const header = first.label === 'yearMonth'
? date.format(MONTH_FORMAT)
: i18n(first.label);
const groupMessages = map(annotations, 'message');
return (
<AttachmentListSection
key={header}
header={header}
i18n={i18n}
type={type}
messages={groupMessages}
/>
);
});
}
}

View file

@ -5,8 +5,9 @@ export interface Message {
attachments: Array<{
data?: ArrayBuffer;
fileName?: string;
size?: number;
}>;
// TODO: Revisit
imageUrl: string;
objectURL?: string;
}