Media Gallery: Support for dark theme
This commit is contained in:
parent
3c69886320
commit
7e2d7b5e60
10 changed files with 236 additions and 190 deletions
|
@ -1682,6 +1682,147 @@
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Module: Media Gallery
|
||||||
|
|
||||||
|
.module-media-gallery {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex-grow: 1;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.module-media-gallery__tab-container {
|
||||||
|
display: flex;
|
||||||
|
flex-grow: 0;
|
||||||
|
flex-shrink: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.module-media-gallery__tab {
|
||||||
|
width: 100%;
|
||||||
|
background-color: $color-light-02;
|
||||||
|
padding: 20px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.module-media-gallery__tab--active {
|
||||||
|
border-bottom: 2px solid $color-signal-blue;
|
||||||
|
}
|
||||||
|
|
||||||
|
.module-media-gallery__content {
|
||||||
|
display: flex;
|
||||||
|
flex-grow: 1;
|
||||||
|
overflow-y: auto;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.module-media-gallery__sections {
|
||||||
|
display: flex;
|
||||||
|
flex-grow: 1;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Module: Attachment Section
|
||||||
|
|
||||||
|
.module-attachment-section {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.module-attachment-section__header {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: normal;
|
||||||
|
line-height: 28px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.module-attachment-section__items {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: flex-start;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Module: Document List Item
|
||||||
|
|
||||||
|
.module-document-list-item {
|
||||||
|
width: 100%;
|
||||||
|
height: 72px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.module-document-list-item--with-separator {
|
||||||
|
border-bottom: 1px solid $color-light-02;
|
||||||
|
}
|
||||||
|
|
||||||
|
.module-document-list-item__content {
|
||||||
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
align-items: center;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.module-document-list-item__icon {
|
||||||
|
flex-shrink: 0;
|
||||||
|
|
||||||
|
width: 48px;
|
||||||
|
height: 48px;
|
||||||
|
@include color-svg('../images/file.svg', $color-light-35);
|
||||||
|
}
|
||||||
|
|
||||||
|
.module-document-list-item__metadata {
|
||||||
|
display: inline-flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex-grow: 1;
|
||||||
|
flex-shrink: 0;
|
||||||
|
margin-left: 8px;
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.module-document-list-item__file-name {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.module-document-list-item__file-size {
|
||||||
|
display: inline-block;
|
||||||
|
margin-top: 8px;
|
||||||
|
font-size: 80%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.module-document-list-item__date {
|
||||||
|
display: inline-block;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Module: Media Grid Item
|
||||||
|
|
||||||
|
.module-media-grid-item {
|
||||||
|
height: 94px;
|
||||||
|
width: 94px;
|
||||||
|
cursor: pointer;
|
||||||
|
background-color: $color-light-10;
|
||||||
|
margin-right: 4px;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
.module-media-grid-item__image {
|
||||||
|
height: 94px;
|
||||||
|
width: 94px;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Module: Empty State
|
||||||
|
|
||||||
|
.module-empty-state {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
flex-grow: 1;
|
||||||
|
font-size: 28px;
|
||||||
|
color: $color-light-45;
|
||||||
|
}
|
||||||
|
|
||||||
// Third-party module: react-contextmenu
|
// Third-party module: react-contextmenu
|
||||||
|
|
||||||
.react-contextmenu {
|
.react-contextmenu {
|
||||||
|
|
|
@ -1263,6 +1263,38 @@ body.dark-theme {
|
||||||
background-color: $color-core-red;
|
background-color: $color-core-red;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Module: Media Gallery
|
||||||
|
|
||||||
|
.module-media-gallery__tab {
|
||||||
|
background-color: $color-dark-85;
|
||||||
|
}
|
||||||
|
|
||||||
|
.module-media-gallery__tab--active {
|
||||||
|
border-bottom: 2px solid $color-signal-blue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Module: Document List Item
|
||||||
|
|
||||||
|
.module-document-list-item--with-separator {
|
||||||
|
border-bottom: 1px solid $color-dark-70;
|
||||||
|
}
|
||||||
|
|
||||||
|
.module-document-list-item__icon {
|
||||||
|
@include color-svg('../images/file.svg', $color-dark-60);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Module: Media Grid Item
|
||||||
|
|
||||||
|
.module-media-grid-item {
|
||||||
|
background-color: $color-dark-85;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Module: Empty State
|
||||||
|
|
||||||
|
.module-empty-state {
|
||||||
|
color: $color-dark-55;
|
||||||
|
}
|
||||||
|
|
||||||
// Third-party module: react-contextmenu
|
// Third-party module: react-contextmenu
|
||||||
|
|
||||||
.react-contextmenu {
|
.react-contextmenu {
|
||||||
|
|
|
@ -5,13 +5,24 @@ import React from 'react';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import is from '@sindresorhus/is';
|
import is from '@sindresorhus/is';
|
||||||
|
|
||||||
import * as Colors from './styles/Colors';
|
|
||||||
import * as GoogleChrome from '../util/GoogleChrome';
|
import * as GoogleChrome from '../util/GoogleChrome';
|
||||||
import * as MIME from '../types/MIME';
|
import * as MIME from '../types/MIME';
|
||||||
import { colorSVG } from '../styles/colorSVG';
|
|
||||||
|
|
||||||
import { Localizer } from '../types/Util';
|
import { Localizer } from '../types/Util';
|
||||||
|
|
||||||
|
const Colors = {
|
||||||
|
TEXT_SECONDARY: '#bbb',
|
||||||
|
ICON_SECONDARY: '#ccc',
|
||||||
|
};
|
||||||
|
|
||||||
|
const colorSVG = (url: string, color: string) => {
|
||||||
|
return {
|
||||||
|
WebkitMask: `url(${url}) no-repeat center`,
|
||||||
|
WebkitMaskSize: '100%',
|
||||||
|
backgroundColor: color,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
close: () => void;
|
close: () => void;
|
||||||
contentType: MIME.MIMEType | undefined;
|
contentType: MIME.MIMEType | undefined;
|
||||||
|
|
|
@ -6,27 +6,10 @@ import { ItemClickEvent } from './types/ItemClickEvent';
|
||||||
import { MediaGridItem } from './MediaGridItem';
|
import { MediaGridItem } from './MediaGridItem';
|
||||||
import { Message } from './types/Message';
|
import { Message } from './types/Message';
|
||||||
import { missingCaseError } from '../../../util/missingCaseError';
|
import { missingCaseError } from '../../../util/missingCaseError';
|
||||||
|
import { Localizer } from '../../../types/Util';
|
||||||
const styles = {
|
|
||||||
container: {
|
|
||||||
width: '100%',
|
|
||||||
},
|
|
||||||
header: {
|
|
||||||
fontSize: 14,
|
|
||||||
fontWeight: 'normal',
|
|
||||||
lineHeight: '28px',
|
|
||||||
} as React.CSSProperties,
|
|
||||||
itemContainer: {
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'row',
|
|
||||||
flexWrap: 'wrap',
|
|
||||||
justifyContent: 'flex-start',
|
|
||||||
alignItems: 'flex-start',
|
|
||||||
} as React.CSSProperties,
|
|
||||||
};
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
i18n: (value: string) => string;
|
i18n: Localizer;
|
||||||
header?: string;
|
header?: string;
|
||||||
type: AttachmentType;
|
type: AttachmentType;
|
||||||
messages: Array<Message>;
|
messages: Array<Message>;
|
||||||
|
@ -38,9 +21,11 @@ export class AttachmentSection extends React.Component<Props> {
|
||||||
const { header } = this.props;
|
const { header } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={styles.container}>
|
<div className="module-attachment-section">
|
||||||
<h2 style={styles.header}>{header}</h2>
|
<h2 className="module-attachment-section__header">{header}</h2>
|
||||||
<div style={styles.itemContainer}>{this.renderItems()}</div>
|
<div className="module-attachment-section__items">
|
||||||
|
{this.renderItems()}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -61,6 +46,7 @@ export class AttachmentSection extends React.Component<Props> {
|
||||||
key={message.id}
|
key={message.id}
|
||||||
message={message}
|
message={message}
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
|
i18n={i18n}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
case 'documents':
|
case 'documents':
|
||||||
|
@ -69,7 +55,6 @@ export class AttachmentSection extends React.Component<Props> {
|
||||||
key={message.id}
|
key={message.id}
|
||||||
fileName={firstAttachment.fileName}
|
fileName={firstAttachment.fileName}
|
||||||
fileSize={firstAttachment.size}
|
fileSize={firstAttachment.size}
|
||||||
i18n={i18n}
|
|
||||||
shouldShowSeparator={shouldShowSeparator}
|
shouldShowSeparator={shouldShowSeparator}
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
timestamp={message.received_at}
|
timestamp={message.received_at}
|
||||||
|
|
|
@ -1,14 +1,12 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
// tslint:disable-next-line:match-default-export-name
|
// tslint:disable-next-line:match-default-export-name
|
||||||
import formatFileSize from 'filesize';
|
import formatFileSize from 'filesize';
|
||||||
|
|
||||||
import { Localizer } from '../../../types/Util';
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
// Required
|
// Required
|
||||||
i18n: Localizer;
|
|
||||||
timestamp: number;
|
timestamp: number;
|
||||||
|
|
||||||
// Optional
|
// Optional
|
||||||
|
@ -18,49 +16,6 @@ interface Props {
|
||||||
shouldShowSeparator?: boolean;
|
shouldShowSeparator?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const styles = {
|
|
||||||
container: {
|
|
||||||
width: '100%',
|
|
||||||
height: 72,
|
|
||||||
},
|
|
||||||
containerSeparator: {
|
|
||||||
borderBottomWidth: 1,
|
|
||||||
borderBottomColor: '#ccc',
|
|
||||||
borderBottomStyle: 'solid',
|
|
||||||
},
|
|
||||||
itemContainer: {
|
|
||||||
cursor: 'pointer',
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'row',
|
|
||||||
flexWrap: 'nowrap',
|
|
||||||
alignItems: 'center',
|
|
||||||
height: '100%',
|
|
||||||
} as React.CSSProperties,
|
|
||||||
itemMetadata: {
|
|
||||||
display: 'inline-flex',
|
|
||||||
flexDirection: 'column',
|
|
||||||
flexGrow: 1,
|
|
||||||
flexShrink: 0,
|
|
||||||
marginLeft: 8,
|
|
||||||
marginRight: 8,
|
|
||||||
} as React.CSSProperties,
|
|
||||||
itemDate: {
|
|
||||||
display: 'inline-block',
|
|
||||||
flexShrink: 0,
|
|
||||||
},
|
|
||||||
itemIcon: {
|
|
||||||
flexShrink: 0,
|
|
||||||
},
|
|
||||||
itemFileName: {
|
|
||||||
fontWeight: 'bold',
|
|
||||||
} as React.CSSProperties,
|
|
||||||
itemFileSize: {
|
|
||||||
display: 'inline-block',
|
|
||||||
marginTop: 8,
|
|
||||||
fontSize: '80%',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
export class DocumentListItem extends React.Component<Props> {
|
export class DocumentListItem extends React.Component<Props> {
|
||||||
public static defaultProps: Partial<Props> = {
|
public static defaultProps: Partial<Props> = {
|
||||||
shouldShowSeparator: true,
|
shouldShowSeparator: true,
|
||||||
|
@ -71,10 +26,12 @@ export class DocumentListItem extends React.Component<Props> {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
style={{
|
className={classNames(
|
||||||
...styles.container,
|
'module-document-list-item',
|
||||||
...(shouldShowSeparator ? styles.containerSeparator : {}),
|
shouldShowSeparator
|
||||||
}}
|
? 'module-document-list-item--with-separator'
|
||||||
|
: null
|
||||||
|
)}
|
||||||
>
|
>
|
||||||
{this.renderContent()}
|
{this.renderContent()}
|
||||||
</div>
|
</div>
|
||||||
|
@ -82,28 +39,24 @@ export class DocumentListItem extends React.Component<Props> {
|
||||||
}
|
}
|
||||||
|
|
||||||
private renderContent() {
|
private renderContent() {
|
||||||
const { fileName, fileSize, timestamp, i18n } = this.props;
|
const { fileName, fileSize, timestamp } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
style={styles.itemContainer}
|
className="module-document-list-item__content"
|
||||||
role="button"
|
role="button"
|
||||||
onClick={this.props.onClick}
|
onClick={this.props.onClick}
|
||||||
>
|
>
|
||||||
<img
|
<div className="module-document-list-item__icon" />
|
||||||
alt={i18n('fileIconAlt')}
|
<div className="module-document-list-item__metadata">
|
||||||
src="images/file.svg"
|
<span className="module-document-list-item__file-name">
|
||||||
width="48"
|
{fileName}
|
||||||
height="48"
|
</span>
|
||||||
style={styles.itemIcon}
|
<span className="module-document-list-item__file-size">
|
||||||
/>
|
|
||||||
<div style={styles.itemMetadata}>
|
|
||||||
<span style={styles.itemFileName}>{fileName}</span>
|
|
||||||
<span style={styles.itemFileSize}>
|
|
||||||
{typeof fileSize === 'number' ? formatFileSize(fileSize) : ''}
|
{typeof fileSize === 'number' ? formatFileSize(fileSize) : ''}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div style={styles.itemDate}>
|
<div className="module-document-list-item__date">
|
||||||
{moment(timestamp).format('ddd, MMM D, Y')}
|
{moment(timestamp).format('ddd, MMM D, Y')}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -3,28 +3,14 @@
|
||||||
*/
|
*/
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import * as Colors from '../../styles/Colors';
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
label: string;
|
label: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const styles = {
|
|
||||||
container: {
|
|
||||||
display: 'flex',
|
|
||||||
justifyContent: 'center',
|
|
||||||
alignItems: 'center',
|
|
||||||
flexGrow: 1,
|
|
||||||
|
|
||||||
fontSize: 28,
|
|
||||||
color: Colors.TEXT_SECONDARY,
|
|
||||||
} as React.CSSProperties,
|
|
||||||
};
|
|
||||||
|
|
||||||
export class EmptyState extends React.Component<Props> {
|
export class EmptyState extends React.Component<Props> {
|
||||||
public render() {
|
public render() {
|
||||||
const { label } = this.props;
|
const { label } = this.props;
|
||||||
|
|
||||||
return <div style={styles.container}>{label}</div>;
|
return <div className="module-empty-state">{label}</div>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
|
|
||||||
|
@ -9,10 +10,11 @@ import { groupMessagesByDate } from './groupMessagesByDate';
|
||||||
import { ItemClickEvent } from './types/ItemClickEvent';
|
import { ItemClickEvent } from './types/ItemClickEvent';
|
||||||
import { Message } from './types/Message';
|
import { Message } from './types/Message';
|
||||||
import { missingCaseError } from '../../../util/missingCaseError';
|
import { missingCaseError } from '../../../util/missingCaseError';
|
||||||
|
import { Localizer } from '../../../types/Util';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
documents: Array<Message>;
|
documents: Array<Message>;
|
||||||
i18n: (key: string, values?: Array<string>) => string;
|
i18n: Localizer;
|
||||||
media: Array<Message>;
|
media: Array<Message>;
|
||||||
onItemClick?: (event: ItemClickEvent) => void;
|
onItemClick?: (event: ItemClickEvent) => void;
|
||||||
}
|
}
|
||||||
|
@ -22,49 +24,6 @@ interface State {
|
||||||
}
|
}
|
||||||
|
|
||||||
const MONTH_FORMAT = 'MMMM YYYY';
|
const MONTH_FORMAT = 'MMMM YYYY';
|
||||||
const COLOR_GRAY = '#f3f3f3';
|
|
||||||
|
|
||||||
const tabStyle = {
|
|
||||||
width: '100%',
|
|
||||||
backgroundColor: COLOR_GRAY,
|
|
||||||
padding: 20,
|
|
||||||
textAlign: 'center',
|
|
||||||
};
|
|
||||||
|
|
||||||
const styles = {
|
|
||||||
container: {
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'column',
|
|
||||||
flexGrow: 1,
|
|
||||||
width: '100%',
|
|
||||||
height: '100%',
|
|
||||||
} as React.CSSProperties,
|
|
||||||
tabContainer: {
|
|
||||||
display: 'flex',
|
|
||||||
flexGrow: 0,
|
|
||||||
flexShrink: 0,
|
|
||||||
cursor: 'pointer',
|
|
||||||
width: '100%',
|
|
||||||
},
|
|
||||||
tab: {
|
|
||||||
default: tabStyle,
|
|
||||||
active: {
|
|
||||||
...tabStyle,
|
|
||||||
borderBottom: '2px solid #08f',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
contentContainer: {
|
|
||||||
display: 'flex',
|
|
||||||
flexGrow: 1,
|
|
||||||
overflowY: 'auto',
|
|
||||||
padding: 20,
|
|
||||||
} as React.CSSProperties,
|
|
||||||
sectionContainer: {
|
|
||||||
display: 'flex',
|
|
||||||
flexGrow: 1,
|
|
||||||
flexDirection: 'column',
|
|
||||||
} as React.CSSProperties,
|
|
||||||
};
|
|
||||||
|
|
||||||
interface TabSelectEvent {
|
interface TabSelectEvent {
|
||||||
type: AttachmentType;
|
type: AttachmentType;
|
||||||
|
@ -89,7 +48,10 @@ const Tab = ({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
style={isSelected ? styles.tab.active : styles.tab.default}
|
className={classNames(
|
||||||
|
'module-media-gallery__tab',
|
||||||
|
isSelected ? 'module-media-gallery__tab--active' : null
|
||||||
|
)}
|
||||||
onClick={handleClick}
|
onClick={handleClick}
|
||||||
role="tab"
|
role="tab"
|
||||||
>
|
>
|
||||||
|
@ -107,8 +69,8 @@ export class MediaGallery extends React.Component<Props, State> {
|
||||||
const { selectedTab } = this.state;
|
const { selectedTab } = this.state;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={styles.container}>
|
<div className="module-media-gallery">
|
||||||
<div style={styles.tabContainer}>
|
<div className="module-media-gallery__tab-container">
|
||||||
<Tab
|
<Tab
|
||||||
label="Media"
|
label="Media"
|
||||||
type="media"
|
type="media"
|
||||||
|
@ -122,7 +84,9 @@ export class MediaGallery extends React.Component<Props, State> {
|
||||||
onSelect={this.handleTabSelect}
|
onSelect={this.handleTabSelect}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div style={styles.contentContainer}>{this.renderSections()}</div>
|
<div className="module-media-gallery__content">
|
||||||
|
{this.renderSections()}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -176,6 +140,6 @@ export class MediaGallery extends React.Component<Props, State> {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
return <div style={styles.sectionContainer}>{sections}</div>;
|
return <div className="module-media-gallery__sections">{sections}</div>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,52 +1,38 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { Message } from './types/Message';
|
import { Message } from './types/Message';
|
||||||
|
import { Localizer } from '../../../types/Util';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
message: Message;
|
message: Message;
|
||||||
onClick?: () => void;
|
onClick?: () => void;
|
||||||
|
i18n: Localizer;
|
||||||
}
|
}
|
||||||
|
|
||||||
const size = {
|
|
||||||
width: 94,
|
|
||||||
height: 94,
|
|
||||||
};
|
|
||||||
const styles = {
|
|
||||||
container: {
|
|
||||||
...size,
|
|
||||||
cursor: 'pointer',
|
|
||||||
backgroundColor: '#f3f3f3',
|
|
||||||
marginRight: 4,
|
|
||||||
marginBottom: 4,
|
|
||||||
},
|
|
||||||
image: {
|
|
||||||
...size,
|
|
||||||
backgroundSize: 'cover',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
export class MediaGridItem extends React.Component<Props> {
|
export class MediaGridItem extends React.Component<Props> {
|
||||||
public renderContent() {
|
public renderContent() {
|
||||||
const { message } = this.props;
|
const { message, i18n } = this.props;
|
||||||
|
|
||||||
if (!message.objectURL) {
|
if (!message.objectURL) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<img
|
||||||
style={{
|
alt={i18n('lightboxImageAlt')}
|
||||||
...styles.container,
|
className="module-media-grid-item__image"
|
||||||
...styles.image,
|
src={message.objectURL}
|
||||||
backgroundImage: `url("${message.objectURL}")`,
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public render() {
|
public render() {
|
||||||
return (
|
return (
|
||||||
<div style={styles.container} role="button" onClick={this.props.onClick}>
|
<div
|
||||||
|
className="module-media-grid-item"
|
||||||
|
role="button"
|
||||||
|
onClick={this.props.onClick}
|
||||||
|
>
|
||||||
{this.renderContent()}
|
{this.renderContent()}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
/**
|
|
||||||
* @prettier
|
|
||||||
*/
|
|
||||||
export const TEXT_SECONDARY = '#bbb';
|
|
||||||
export const ICON_SECONDARY = '#ccc';
|
|
|
@ -1,7 +0,0 @@
|
||||||
export const colorSVG = (url: string, color: string) => {
|
|
||||||
return {
|
|
||||||
WebkitMask: `url(${url}) no-repeat center`,
|
|
||||||
WebkitMaskSize: '100%',
|
|
||||||
backgroundColor: color,
|
|
||||||
};
|
|
||||||
};
|
|
Loading…
Reference in a new issue