mirror of
https://github.com/stoatchat/for-legacy-web.git
synced 2026-03-06 17:11:55 +00:00
Run prettier on all files.
This commit is contained in:
@@ -1,126 +1,133 @@
|
||||
import TextFile from "./TextFile";
|
||||
import { Text } from "preact-i18n";
|
||||
import classNames from "classnames";
|
||||
import styles from "./Attachment.module.scss";
|
||||
import AttachmentActions from "./AttachmentActions";
|
||||
import { useContext, useState } from "preact/hooks";
|
||||
import { AppContext } from "../../../../context/revoltjs/RevoltClient";
|
||||
import { Attachment as AttachmentRJS } from "revolt.js/dist/api/objects";
|
||||
|
||||
import styles from "./Attachment.module.scss";
|
||||
import classNames from "classnames";
|
||||
import { Text } from "preact-i18n";
|
||||
import { useContext, useState } from "preact/hooks";
|
||||
|
||||
import { useIntermediate } from "../../../../context/intermediate/Intermediate";
|
||||
import { AppContext } from "../../../../context/revoltjs/RevoltClient";
|
||||
|
||||
import { MessageAreaWidthContext } from "../../../../pages/channels/messaging/MessageArea";
|
||||
import AttachmentActions from "./AttachmentActions";
|
||||
import TextFile from "./TextFile";
|
||||
|
||||
interface Props {
|
||||
attachment: AttachmentRJS;
|
||||
hasContent: boolean;
|
||||
attachment: AttachmentRJS;
|
||||
hasContent: boolean;
|
||||
}
|
||||
|
||||
const MAX_ATTACHMENT_WIDTH = 480;
|
||||
|
||||
export default function Attachment({ attachment, hasContent }: Props) {
|
||||
const client = useContext(AppContext);
|
||||
const { openScreen } = useIntermediate();
|
||||
const { filename, metadata } = attachment;
|
||||
const [ spoiler, setSpoiler ] = useState(filename.startsWith("SPOILER_"));
|
||||
const [ loaded, setLoaded ] = useState(false)
|
||||
const client = useContext(AppContext);
|
||||
const { openScreen } = useIntermediate();
|
||||
const { filename, metadata } = attachment;
|
||||
const [spoiler, setSpoiler] = useState(filename.startsWith("SPOILER_"));
|
||||
const [loaded, setLoaded] = useState(false);
|
||||
|
||||
const url = client.generateFileURL(attachment, { width: MAX_ATTACHMENT_WIDTH * 1.5 }, true);
|
||||
const url = client.generateFileURL(
|
||||
attachment,
|
||||
{ width: MAX_ATTACHMENT_WIDTH * 1.5 },
|
||||
true,
|
||||
);
|
||||
|
||||
|
||||
switch (metadata.type) {
|
||||
case "Image": {
|
||||
return (
|
||||
<div
|
||||
className={styles.container}
|
||||
onClick={() => spoiler && setSpoiler(false)}
|
||||
>
|
||||
{spoiler && (
|
||||
<div className={styles.overflow}>
|
||||
<span><Text id="app.main.channel.misc.spoiler_attachment" /></span>
|
||||
</div>
|
||||
)}
|
||||
<img
|
||||
src={url}
|
||||
alt={filename}
|
||||
width={metadata.width}
|
||||
height={metadata.height}
|
||||
data-spoiler={spoiler}
|
||||
data-has-content={hasContent}
|
||||
className={classNames(styles.attachment, styles.image, loaded && styles.loaded)}
|
||||
onClick={() =>
|
||||
openScreen({ id: "image_viewer", attachment })
|
||||
}
|
||||
onMouseDown={ev =>
|
||||
ev.button === 1 &&
|
||||
window.open(url, "_blank")
|
||||
}
|
||||
onLoad={() => setLoaded(true)}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
case "Audio": {
|
||||
return (
|
||||
<div
|
||||
className={classNames(styles.attachment, styles.audio)}
|
||||
data-has-content={hasContent}
|
||||
>
|
||||
<AttachmentActions attachment={attachment} />
|
||||
<audio src={url} controls />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
case "Video": {
|
||||
return (
|
||||
<div
|
||||
className={styles.container}
|
||||
onClick={() => spoiler && setSpoiler(false)}>
|
||||
{spoiler && (
|
||||
<div className={styles.overflow}>
|
||||
<span><Text id="app.main.channel.misc.spoiler_attachment" /></span>
|
||||
</div>
|
||||
)}
|
||||
<div
|
||||
data-spoiler={spoiler}
|
||||
data-has-content={hasContent}
|
||||
className={classNames(styles.attachment, styles.video)}
|
||||
>
|
||||
<AttachmentActions attachment={attachment} />
|
||||
<video
|
||||
src={url}
|
||||
width={metadata.width}
|
||||
height={metadata.height}
|
||||
className={classNames(loaded && styles.loaded)}
|
||||
controls
|
||||
onMouseDown={ev =>
|
||||
ev.button === 1 &&
|
||||
window.open(url, "_blank")
|
||||
}
|
||||
onLoadedMetadata={() => setLoaded(true)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
case 'Text': {
|
||||
return (
|
||||
<div
|
||||
className={classNames(styles.attachment, styles.text)}
|
||||
data-has-content={hasContent}
|
||||
>
|
||||
<TextFile attachment={attachment} />
|
||||
<AttachmentActions attachment={attachment} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
default: {
|
||||
return (
|
||||
<div
|
||||
className={classNames(styles.attachment, styles.file)}
|
||||
data-has-content={hasContent}
|
||||
>
|
||||
<AttachmentActions attachment={attachment} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
switch (metadata.type) {
|
||||
case "Image": {
|
||||
return (
|
||||
<div
|
||||
className={styles.container}
|
||||
onClick={() => spoiler && setSpoiler(false)}>
|
||||
{spoiler && (
|
||||
<div className={styles.overflow}>
|
||||
<span>
|
||||
<Text id="app.main.channel.misc.spoiler_attachment" />
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
<img
|
||||
src={url}
|
||||
alt={filename}
|
||||
width={metadata.width}
|
||||
height={metadata.height}
|
||||
data-spoiler={spoiler}
|
||||
data-has-content={hasContent}
|
||||
className={classNames(
|
||||
styles.attachment,
|
||||
styles.image,
|
||||
loaded && styles.loaded,
|
||||
)}
|
||||
onClick={() =>
|
||||
openScreen({ id: "image_viewer", attachment })
|
||||
}
|
||||
onMouseDown={(ev) =>
|
||||
ev.button === 1 && window.open(url, "_blank")
|
||||
}
|
||||
onLoad={() => setLoaded(true)}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
case "Audio": {
|
||||
return (
|
||||
<div
|
||||
className={classNames(styles.attachment, styles.audio)}
|
||||
data-has-content={hasContent}>
|
||||
<AttachmentActions attachment={attachment} />
|
||||
<audio src={url} controls />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
case "Video": {
|
||||
return (
|
||||
<div
|
||||
className={styles.container}
|
||||
onClick={() => spoiler && setSpoiler(false)}>
|
||||
{spoiler && (
|
||||
<div className={styles.overflow}>
|
||||
<span>
|
||||
<Text id="app.main.channel.misc.spoiler_attachment" />
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
<div
|
||||
data-spoiler={spoiler}
|
||||
data-has-content={hasContent}
|
||||
className={classNames(styles.attachment, styles.video)}>
|
||||
<AttachmentActions attachment={attachment} />
|
||||
<video
|
||||
src={url}
|
||||
width={metadata.width}
|
||||
height={metadata.height}
|
||||
className={classNames(loaded && styles.loaded)}
|
||||
controls
|
||||
onMouseDown={(ev) =>
|
||||
ev.button === 1 && window.open(url, "_blank")
|
||||
}
|
||||
onLoadedMetadata={() => setLoaded(true)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
case "Text": {
|
||||
return (
|
||||
<div
|
||||
className={classNames(styles.attachment, styles.text)}
|
||||
data-has-content={hasContent}>
|
||||
<TextFile attachment={attachment} />
|
||||
<AttachmentActions attachment={attachment} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
default: {
|
||||
return (
|
||||
<div
|
||||
className={classNames(styles.attachment, styles.file)}
|
||||
data-has-content={hasContent}>
|
||||
<AttachmentActions attachment={attachment} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,83 +1,115 @@
|
||||
import { useContext } from 'preact/hooks';
|
||||
import styles from './Attachment.module.scss';
|
||||
import IconButton from '../../../ui/IconButton';
|
||||
import {
|
||||
Download,
|
||||
LinkExternal,
|
||||
File,
|
||||
Headphone,
|
||||
Video,
|
||||
} from "@styled-icons/boxicons-regular";
|
||||
import { Attachment } from "revolt.js/dist/api/objects";
|
||||
import { determineFileSize } from '../../../../lib/fileSize';
|
||||
import { AppContext } from '../../../../context/revoltjs/RevoltClient';
|
||||
import { Download, LinkExternal, File, Headphone, Video } from '@styled-icons/boxicons-regular';
|
||||
import classNames from 'classnames';
|
||||
|
||||
import styles from "./Attachment.module.scss";
|
||||
import classNames from "classnames";
|
||||
import { useContext } from "preact/hooks";
|
||||
|
||||
import { determineFileSize } from "../../../../lib/fileSize";
|
||||
|
||||
import { AppContext } from "../../../../context/revoltjs/RevoltClient";
|
||||
|
||||
import IconButton from "../../../ui/IconButton";
|
||||
|
||||
interface Props {
|
||||
attachment: Attachment;
|
||||
attachment: Attachment;
|
||||
}
|
||||
|
||||
export default function AttachmentActions({ attachment }: Props) {
|
||||
const client = useContext(AppContext);
|
||||
const { filename, metadata, size } = attachment;
|
||||
const client = useContext(AppContext);
|
||||
const { filename, metadata, size } = attachment;
|
||||
|
||||
const url = client.generateFileURL(attachment)!;
|
||||
const open_url = `${url}/${filename}`;
|
||||
const download_url = url.replace('attachments', 'attachments/download')
|
||||
const url = client.generateFileURL(attachment)!;
|
||||
const open_url = `${url}/${filename}`;
|
||||
const download_url = url.replace("attachments", "attachments/download");
|
||||
|
||||
// for some reason revolt.js says the size is a string even though it's a number
|
||||
const filesize = determineFileSize(size);
|
||||
const filesize = determineFileSize(size);
|
||||
|
||||
switch (metadata.type) {
|
||||
case 'Image':
|
||||
return (
|
||||
<div className={classNames(styles.actions, styles.imageAction)}>
|
||||
<span className={styles.filename}>{filename}</span>
|
||||
<span className={styles.filesize}>{metadata.width + 'x' + metadata.height} ({filesize})</span>
|
||||
<a href={open_url} target="_blank" className={styles.iconType} >
|
||||
<IconButton>
|
||||
<LinkExternal size={24} />
|
||||
</IconButton>
|
||||
</a>
|
||||
<a href={download_url} className={styles.downloadIcon} download target="_blank">
|
||||
<IconButton>
|
||||
<Download size={24} />
|
||||
</IconButton>
|
||||
</a>
|
||||
</div>
|
||||
)
|
||||
case 'Audio':
|
||||
return (
|
||||
<div className={classNames(styles.actions, styles.audioAction)}>
|
||||
<Headphone size={24} className={styles.iconType} />
|
||||
<span className={styles.filename}>{filename}</span>
|
||||
<span className={styles.filesize}>{filesize}</span>
|
||||
<a href={download_url} className={styles.downloadIcon} download target="_blank">
|
||||
<IconButton>
|
||||
<Download size={24} />
|
||||
</IconButton>
|
||||
</a>
|
||||
</div>
|
||||
)
|
||||
case 'Video':
|
||||
return (
|
||||
<div className={classNames(styles.actions, styles.videoAction)}>
|
||||
<Video size={24} className={styles.iconType} />
|
||||
<span className={styles.filename}>{filename}</span>
|
||||
<span className={styles.filesize}>{metadata.width + 'x' + metadata.height} ({filesize})</span>
|
||||
<a href={download_url} className={styles.downloadIcon} download target="_blank">
|
||||
<IconButton>
|
||||
<Download size={24} />
|
||||
</IconButton>
|
||||
</a>
|
||||
</div>
|
||||
)
|
||||
default:
|
||||
return (
|
||||
<div className={styles.actions}>
|
||||
<File size={24} className={styles.iconType} />
|
||||
<span className={styles.filename}>{filename}</span>
|
||||
<span className={styles.filesize}>{filesize}</span>
|
||||
<a href={download_url} className={styles.downloadIcon} download target="_blank">
|
||||
<IconButton>
|
||||
<Download size={24} />
|
||||
</IconButton>
|
||||
</a>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
switch (metadata.type) {
|
||||
case "Image":
|
||||
return (
|
||||
<div className={classNames(styles.actions, styles.imageAction)}>
|
||||
<span className={styles.filename}>{filename}</span>
|
||||
<span className={styles.filesize}>
|
||||
{metadata.width + "x" + metadata.height} ({filesize})
|
||||
</span>
|
||||
<a
|
||||
href={open_url}
|
||||
target="_blank"
|
||||
className={styles.iconType}>
|
||||
<IconButton>
|
||||
<LinkExternal size={24} />
|
||||
</IconButton>
|
||||
</a>
|
||||
<a
|
||||
href={download_url}
|
||||
className={styles.downloadIcon}
|
||||
download
|
||||
target="_blank">
|
||||
<IconButton>
|
||||
<Download size={24} />
|
||||
</IconButton>
|
||||
</a>
|
||||
</div>
|
||||
);
|
||||
case "Audio":
|
||||
return (
|
||||
<div className={classNames(styles.actions, styles.audioAction)}>
|
||||
<Headphone size={24} className={styles.iconType} />
|
||||
<span className={styles.filename}>{filename}</span>
|
||||
<span className={styles.filesize}>{filesize}</span>
|
||||
<a
|
||||
href={download_url}
|
||||
className={styles.downloadIcon}
|
||||
download
|
||||
target="_blank">
|
||||
<IconButton>
|
||||
<Download size={24} />
|
||||
</IconButton>
|
||||
</a>
|
||||
</div>
|
||||
);
|
||||
case "Video":
|
||||
return (
|
||||
<div className={classNames(styles.actions, styles.videoAction)}>
|
||||
<Video size={24} className={styles.iconType} />
|
||||
<span className={styles.filename}>{filename}</span>
|
||||
<span className={styles.filesize}>
|
||||
{metadata.width + "x" + metadata.height} ({filesize})
|
||||
</span>
|
||||
<a
|
||||
href={download_url}
|
||||
className={styles.downloadIcon}
|
||||
download
|
||||
target="_blank">
|
||||
<IconButton>
|
||||
<Download size={24} />
|
||||
</IconButton>
|
||||
</a>
|
||||
</div>
|
||||
);
|
||||
default:
|
||||
return (
|
||||
<div className={styles.actions}>
|
||||
<File size={24} className={styles.iconType} />
|
||||
<span className={styles.filename}>{filename}</span>
|
||||
<span className={styles.filesize}>{filesize}</span>
|
||||
<a
|
||||
href={download_url}
|
||||
className={styles.downloadIcon}
|
||||
download
|
||||
target="_blank">
|
||||
<IconButton>
|
||||
<Download size={24} />
|
||||
</IconButton>
|
||||
</a>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,72 +1,93 @@
|
||||
import { Text } from "preact-i18n";
|
||||
import UserShort from "../../user/UserShort";
|
||||
import styled, { css } from "styled-components";
|
||||
import Markdown from "../../../markdown/Markdown";
|
||||
import { Reply, File } from "@styled-icons/boxicons-regular";
|
||||
import { useUser } from "../../../../context/revoltjs/hooks";
|
||||
import styled, { css } from "styled-components";
|
||||
|
||||
import { Text } from "preact-i18n";
|
||||
|
||||
import { useRenderState } from "../../../../lib/renderer/Singleton";
|
||||
|
||||
import { useUser } from "../../../../context/revoltjs/hooks";
|
||||
|
||||
import Markdown from "../../../markdown/Markdown";
|
||||
import UserShort from "../../user/UserShort";
|
||||
|
||||
interface Props {
|
||||
channel: string
|
||||
index: number
|
||||
id: string
|
||||
channel: string;
|
||||
index: number;
|
||||
id: string;
|
||||
}
|
||||
|
||||
export const ReplyBase = styled.div<{ head?: boolean, fail?: boolean, preview?: boolean }>`
|
||||
gap: 4px;
|
||||
display: flex;
|
||||
font-size: 0.8em;
|
||||
margin-left: 30px;
|
||||
user-select: none;
|
||||
margin-bottom: 4px;
|
||||
align-items: center;
|
||||
color: var(--secondary-foreground);
|
||||
export const ReplyBase = styled.div<{
|
||||
head?: boolean;
|
||||
fail?: boolean;
|
||||
preview?: boolean;
|
||||
}>`
|
||||
gap: 4px;
|
||||
display: flex;
|
||||
font-size: 0.8em;
|
||||
margin-left: 30px;
|
||||
user-select: none;
|
||||
margin-bottom: 4px;
|
||||
align-items: center;
|
||||
color: var(--secondary-foreground);
|
||||
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
|
||||
svg:first-child {
|
||||
flex-shrink: 0;
|
||||
transform: scaleX(-1);
|
||||
color: var(--tertiary-foreground);
|
||||
}
|
||||
svg:first-child {
|
||||
flex-shrink: 0;
|
||||
transform: scaleX(-1);
|
||||
color: var(--tertiary-foreground);
|
||||
}
|
||||
|
||||
${ props => props.fail && css`
|
||||
color: var(--tertiary-foreground);
|
||||
` }
|
||||
${(props) =>
|
||||
props.fail &&
|
||||
css`
|
||||
color: var(--tertiary-foreground);
|
||||
`}
|
||||
|
||||
${ props => props.head && css`
|
||||
margin-top: 12px;
|
||||
` }
|
||||
${(props) =>
|
||||
props.head &&
|
||||
css`
|
||||
margin-top: 12px;
|
||||
`}
|
||||
|
||||
${ props => props.preview && css`
|
||||
margin-left: 0;
|
||||
` }
|
||||
${(props) =>
|
||||
props.preview &&
|
||||
css`
|
||||
margin-left: 0;
|
||||
`}
|
||||
`;
|
||||
|
||||
export function MessageReply({ index, channel, id }: Props) {
|
||||
const view = useRenderState(channel);
|
||||
if (view?.type !== 'RENDER') return null;
|
||||
const view = useRenderState(channel);
|
||||
if (view?.type !== "RENDER") return null;
|
||||
|
||||
const message = view.messages.find(x => x._id === id);
|
||||
if (!message) {
|
||||
return (
|
||||
<ReplyBase head={index === 0} fail>
|
||||
<Reply size={16} />
|
||||
<span><Text id="app.main.channel.misc.failed_load" /></span>
|
||||
</ReplyBase>
|
||||
)
|
||||
}
|
||||
const message = view.messages.find((x) => x._id === id);
|
||||
if (!message) {
|
||||
return (
|
||||
<ReplyBase head={index === 0} fail>
|
||||
<Reply size={16} />
|
||||
<span>
|
||||
<Text id="app.main.channel.misc.failed_load" />
|
||||
</span>
|
||||
</ReplyBase>
|
||||
);
|
||||
}
|
||||
|
||||
const user = useUser(message.author);
|
||||
const user = useUser(message.author);
|
||||
|
||||
return (
|
||||
<ReplyBase head={index === 0}>
|
||||
<Reply size={16} />
|
||||
<UserShort user={user} size={16} />
|
||||
{ message.attachments && message.attachments.length > 0 && <File size={16} /> }
|
||||
<Markdown disallowBigEmoji content={(message.content as string).replace(/\n/g, ' ')} />
|
||||
</ReplyBase>
|
||||
)
|
||||
return (
|
||||
<ReplyBase head={index === 0}>
|
||||
<Reply size={16} />
|
||||
<UserShort user={user} size={16} />
|
||||
{message.attachments && message.attachments.length > 0 && (
|
||||
<File size={16} />
|
||||
)}
|
||||
<Markdown
|
||||
disallowBigEmoji
|
||||
content={(message.content as string).replace(/\n/g, " ")}
|
||||
/>
|
||||
</ReplyBase>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,57 +1,72 @@
|
||||
import axios from 'axios';
|
||||
import Preloader from '../../../ui/Preloader';
|
||||
import styles from './Attachment.module.scss';
|
||||
import { Attachment } from 'revolt.js/dist/api/objects';
|
||||
import { useContext, useEffect, useState } from 'preact/hooks';
|
||||
import RequiresOnline from '../../../../context/revoltjs/RequiresOnline';
|
||||
import { AppContext, StatusContext } from '../../../../context/revoltjs/RevoltClient';
|
||||
import axios from "axios";
|
||||
import { Attachment } from "revolt.js/dist/api/objects";
|
||||
|
||||
import styles from "./Attachment.module.scss";
|
||||
import { useContext, useEffect, useState } from "preact/hooks";
|
||||
|
||||
import RequiresOnline from "../../../../context/revoltjs/RequiresOnline";
|
||||
import {
|
||||
AppContext,
|
||||
StatusContext,
|
||||
} from "../../../../context/revoltjs/RevoltClient";
|
||||
|
||||
import Preloader from "../../../ui/Preloader";
|
||||
|
||||
interface Props {
|
||||
attachment: Attachment;
|
||||
attachment: Attachment;
|
||||
}
|
||||
|
||||
const fileCache: { [key: string]: string } = {};
|
||||
|
||||
export default function TextFile({ attachment }: Props) {
|
||||
const [ content, setContent ] = useState<undefined | string>(undefined);
|
||||
const [ loading, setLoading ] = useState(false);
|
||||
const status = useContext(StatusContext);
|
||||
const client = useContext(AppContext);
|
||||
const [content, setContent] = useState<undefined | string>(undefined);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const status = useContext(StatusContext);
|
||||
const client = useContext(AppContext);
|
||||
|
||||
const url = client.generateFileURL(attachment)!;
|
||||
const url = client.generateFileURL(attachment)!;
|
||||
|
||||
useEffect(() => {
|
||||
if (typeof content !== 'undefined') return;
|
||||
if (loading) return;
|
||||
setLoading(true);
|
||||
useEffect(() => {
|
||||
if (typeof content !== "undefined") return;
|
||||
if (loading) return;
|
||||
setLoading(true);
|
||||
|
||||
let cached = fileCache[attachment._id];
|
||||
if (cached) {
|
||||
setContent(cached);
|
||||
setLoading(false);
|
||||
} else {
|
||||
axios.get(url)
|
||||
.then(res => {
|
||||
setContent(res.data);
|
||||
fileCache[attachment._id] = res.data;
|
||||
setLoading(false);
|
||||
})
|
||||
.catch(() => {
|
||||
console.error("Failed to load text file. [", attachment._id, "]");
|
||||
setLoading(false)
|
||||
})
|
||||
}
|
||||
}, [ content, loading, status ]);
|
||||
let cached = fileCache[attachment._id];
|
||||
if (cached) {
|
||||
setContent(cached);
|
||||
setLoading(false);
|
||||
} else {
|
||||
axios
|
||||
.get(url)
|
||||
.then((res) => {
|
||||
setContent(res.data);
|
||||
fileCache[attachment._id] = res.data;
|
||||
setLoading(false);
|
||||
})
|
||||
.catch(() => {
|
||||
console.error(
|
||||
"Failed to load text file. [",
|
||||
attachment._id,
|
||||
"]",
|
||||
);
|
||||
setLoading(false);
|
||||
});
|
||||
}
|
||||
}, [content, loading, status]);
|
||||
|
||||
return (
|
||||
<div className={styles.textContent} data-loading={typeof content === 'undefined'}>
|
||||
{
|
||||
content ?
|
||||
<pre><code>{ content }</code></pre>
|
||||
: <RequiresOnline>
|
||||
<Preloader type="ring" />
|
||||
</RequiresOnline>
|
||||
}
|
||||
</div>
|
||||
)
|
||||
return (
|
||||
<div
|
||||
className={styles.textContent}
|
||||
data-loading={typeof content === "undefined"}>
|
||||
{content ? (
|
||||
<pre>
|
||||
<code>{content}</code>
|
||||
</pre>
|
||||
) : (
|
||||
<RequiresOnline>
|
||||
<Preloader type="ring" />
|
||||
</RequiresOnline>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user