fix message layout
Signed-off-by: eternal-flame-AD <yume@yumechi.jp>
This commit is contained in:
parent
73d42c5857
commit
d929e66aa2
|
|
@ -11,6 +11,7 @@ import {Markdown} from '../common/Markdown';
|
||||||
import * as config from '../config';
|
import * as config from '../config';
|
||||||
import {IMessageExtras} from '../types';
|
import {IMessageExtras} from '../types';
|
||||||
import {contentType, RenderMode} from './extras';
|
import {contentType, RenderMode} from './extras';
|
||||||
|
import {makeIntlFormatter} from 'react-timeago/defaultFormatter';
|
||||||
|
|
||||||
const PREVIEW_LENGTH = 500;
|
const PREVIEW_LENGTH = 500;
|
||||||
|
|
||||||
|
|
@ -39,14 +40,34 @@ const useStyles = makeStyles()((theme: Theme) => ({
|
||||||
width: 32,
|
width: 32,
|
||||||
height: 32,
|
height: 32,
|
||||||
},
|
},
|
||||||
|
[theme.breakpoints.down('sm')]: {
|
||||||
|
display: 'none',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
appName: {
|
||||||
|
opacity: 0.7,
|
||||||
},
|
},
|
||||||
date: {
|
date: {
|
||||||
[theme.breakpoints.down('md')]: {
|
[theme.breakpoints.down('md')]: {
|
||||||
order: 1,
|
|
||||||
flexBasis: '100%',
|
|
||||||
opacity: 0.7,
|
opacity: 0.7,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
messageWrapper: {
|
||||||
|
display: 'grid',
|
||||||
|
gridTemplateColumns: '70px 1fr',
|
||||||
|
[theme.breakpoints.down('sm')]: {
|
||||||
|
gridTemplateColumns: '1fr',
|
||||||
|
},
|
||||||
|
gap: 16,
|
||||||
|
width: '100%',
|
||||||
|
},
|
||||||
|
actionsWrapper: {
|
||||||
|
flex: 1,
|
||||||
|
display: 'flex',
|
||||||
|
justifyContent: 'flex-end',
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'flex-start',
|
||||||
|
},
|
||||||
imageWrapper: {
|
imageWrapper: {
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
},
|
},
|
||||||
|
|
@ -81,6 +102,7 @@ interface IProps {
|
||||||
date: string;
|
date: string;
|
||||||
content: string;
|
content: string;
|
||||||
priority: number;
|
priority: number;
|
||||||
|
appName: string;
|
||||||
fDelete: VoidFunction;
|
fDelete: VoidFunction;
|
||||||
extras?: IMessageExtras;
|
extras?: IMessageExtras;
|
||||||
expanded: boolean;
|
expanded: boolean;
|
||||||
|
|
@ -105,6 +127,7 @@ const Message = ({
|
||||||
priority,
|
priority,
|
||||||
content,
|
content,
|
||||||
extras,
|
extras,
|
||||||
|
appName,
|
||||||
onExpand,
|
onExpand,
|
||||||
expanded: initialExpanded,
|
expanded: initialExpanded,
|
||||||
}: IProps) => {
|
}: IProps) => {
|
||||||
|
|
@ -140,56 +163,73 @@ const Message = ({
|
||||||
borderLeftWidth: 6,
|
borderLeftWidth: 6,
|
||||||
borderLeftStyle: 'solid',
|
borderLeftStyle: 'solid',
|
||||||
}}>
|
}}>
|
||||||
<div style={{display: 'flex', width: '100%'}}>
|
<div className={classes.messageWrapper}>
|
||||||
<div className={classes.imageWrapper}>
|
{image !== null ? (
|
||||||
{image !== null ? (
|
<img
|
||||||
<img
|
src={config.get('url') + image}
|
||||||
src={config.get('url') + image}
|
alt={`${appName} logo`}
|
||||||
alt="app logo"
|
width="70"
|
||||||
width="70"
|
height="70"
|
||||||
height="70"
|
className={classes.image}
|
||||||
className={classes.image}
|
/>
|
||||||
/>
|
) : null}
|
||||||
) : null}
|
<div style={{width: '100%'}}>
|
||||||
</div>
|
<div style={{display: 'flex', width: '100%'}}>
|
||||||
<div className={classes.messageContentWrapper}>
|
<div className={classes.messageContentWrapper}>
|
||||||
<div className={classes.header}>
|
<div className={classes.header}>
|
||||||
<Typography className={`${classes.headerTitle} title`} variant="h5">
|
<Typography
|
||||||
{title}
|
className={`${classes.headerTitle} title`}
|
||||||
</Typography>
|
variant="h5">
|
||||||
<Typography variant="body1" className={classes.date}>
|
{title}
|
||||||
<TimeAgo date={date} />
|
</Typography>
|
||||||
</Typography>
|
</div>
|
||||||
<IconButton
|
<div className={classes.appName}>
|
||||||
onClick={fDelete}
|
<Typography variant="body1" className={classes.date}>
|
||||||
className={`${classes.trash} delete`}
|
{appName}
|
||||||
size="large">
|
</Typography>
|
||||||
<Delete />
|
</div>
|
||||||
</IconButton>
|
</div>
|
||||||
|
<div className={classes.actionsWrapper}>
|
||||||
|
<Typography variant="body1" className={classes.date}>
|
||||||
|
<TimeAgo
|
||||||
|
date={date}
|
||||||
|
formatter={makeIntlFormatter({
|
||||||
|
style: 'narrow',
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
</Typography>
|
||||||
|
<IconButton
|
||||||
|
onClick={fDelete}
|
||||||
|
className={`${classes.trash} delete`}
|
||||||
|
size="large">
|
||||||
|
<Delete />
|
||||||
|
</IconButton>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
<Typography
|
<Typography
|
||||||
component="div"
|
component="div"
|
||||||
ref={setPreviewRef}
|
ref={setPreviewRef}
|
||||||
className={`${classes.content} content ${
|
className={`${classes.content} content ${
|
||||||
isOverflowing && expanded ? 'expanded' : ''
|
isOverflowing && expanded ? 'expanded' : ''
|
||||||
}`}>
|
}`}>
|
||||||
{renderContent()}
|
{renderContent()}
|
||||||
</Typography>
|
</Typography>
|
||||||
|
</div>
|
||||||
|
{isOverflowing && (
|
||||||
|
<Button
|
||||||
|
style={{marginTop: 16}}
|
||||||
|
onClick={togglePreviewHeight}
|
||||||
|
variant="contained"
|
||||||
|
color="primary"
|
||||||
|
size="large"
|
||||||
|
fullWidth={true}
|
||||||
|
startIcon={expanded ? <ExpandLess /> : <ExpandMore />}>
|
||||||
|
{expanded ? 'Read Less' : 'Read More'}
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{isOverflowing && (
|
|
||||||
<Button
|
|
||||||
style={{marginTop: 16}}
|
|
||||||
onClick={togglePreviewHeight}
|
|
||||||
variant="contained"
|
|
||||||
color="primary"
|
|
||||||
size="large"
|
|
||||||
fullWidth={true}
|
|
||||||
startIcon={expanded ? <ExpandLess /> : <ExpandMore />}>
|
|
||||||
{expanded ? 'Read Less' : 'Read More'}
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
</Container>
|
</Container>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@ const Messages = observer(() => {
|
||||||
onExpand={(expanded) => (expandedState.current[message.id] = expanded)}
|
onExpand={(expanded) => (expandedState.current[message.id] = expanded)}
|
||||||
title={message.title}
|
title={message.title}
|
||||||
date={message.date}
|
date={message.date}
|
||||||
|
appName={appStore.getName(message.appid)}
|
||||||
expanded={expandedState.current[message.id] ?? false}
|
expanded={expandedState.current[message.id] ?? false}
|
||||||
content={message.message}
|
content={message.message}
|
||||||
image={message.image}
|
image={message.image}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,19 @@
|
||||||
declare module 'react-timeago' {
|
declare module 'react-timeago' {
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
|
export type FormatterOptions = {
|
||||||
|
style?: 'long' | 'short' | 'narrow';
|
||||||
|
};
|
||||||
|
export type Formatter = (options: FormatterOptions) => React.ReactNode;
|
||||||
|
|
||||||
export interface ITimeAgoProps {
|
export interface ITimeAgoProps {
|
||||||
date: string;
|
date: string;
|
||||||
|
formatter?: Formatter;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class TimeAgo extends React.Component<ITimeAgoProps, unknown> {}
|
export default class TimeAgo extends React.Component<ITimeAgoProps, unknown> {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
declare module 'react-timeago/defaultFormatter' {
|
||||||
|
declare function makeIntlFormatter(options: FormatterOptions): Formatter;
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue