aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcrupest <crupest@outlook.com>2021-03-07 16:48:51 +0800
committercrupest <crupest@outlook.com>2021-03-07 16:48:51 +0800
commit28d3fe8bb0a60402ed09ab3c208b577d0607324c (patch)
tree623ef95fbd5fa703d66812dad8fe6998defb7264
parent486663e6b4b2aa4addc4c84d24e1ce5252941858 (diff)
downloadtimeline-28d3fe8bb0a60402ed09ab3c208b577d0607324c.tar.gz
timeline-28d3fe8bb0a60402ed09ab3c208b577d0607324c.tar.bz2
timeline-28d3fe8bb0a60402ed09ab3c208b577d0607324c.zip
...
-rw-r--r--FrontEnd/src/app/views/timeline-common/TimelinePostEdit.tsx135
1 files changed, 98 insertions, 37 deletions
diff --git a/FrontEnd/src/app/views/timeline-common/TimelinePostEdit.tsx b/FrontEnd/src/app/views/timeline-common/TimelinePostEdit.tsx
index 5bc5b166..efe5a6ff 100644
--- a/FrontEnd/src/app/views/timeline-common/TimelinePostEdit.tsx
+++ b/FrontEnd/src/app/views/timeline-common/TimelinePostEdit.tsx
@@ -18,12 +18,38 @@ import { base64 } from "@/http/common";
import BlobImage from "../common/BlobImage";
import LoadingButton from "../common/LoadingButton";
+interface TimelinePostEditTextProps {
+ text: string;
+ disabled: boolean;
+ onChange: (text: string) => void;
+ className?: string;
+ style?: React.CSSProperties;
+}
+
+const TimelinePostEditText: React.FC<TimelinePostEditTextProps> = (props) => {
+ const { text, disabled, onChange, className, style } = props;
+
+ return (
+ <Form.Control
+ as="textarea"
+ value={text}
+ disabled={disabled}
+ onChange={(event) => {
+ onChange(event.target.value);
+ }}
+ className={className}
+ style={style}
+ />
+ );
+};
+
interface TimelinePostEditImageProps {
onSelect: (file: File | null) => void;
+ disabled: boolean;
}
const TimelinePostEditImage: React.FC<TimelinePostEditImageProps> = (props) => {
- const { onSelect } = props;
+ const { onSelect, disabled } = props;
const { t } = useTranslation();
@@ -47,6 +73,7 @@ const TimelinePostEditImage: React.FC<TimelinePostEditImageProps> = (props) => {
label={t("chooseImage")}
onChange={onInputChange}
accept="image/*"
+ disabled={disabled}
className="mx-3 my-1 d-inline-block"
/>
{file != null && !error && (
@@ -78,15 +105,24 @@ const TimelinePostEdit: React.FC<TimelinePostEditProps> = (props) => {
const { t } = useTranslation();
const [process, setProcess] = React.useState<boolean>(false);
- const [kind, setKind] = React.useState<"text" | "image">("text");
+
+ type PostKind = "text" | "markdown" | "image";
+
+ const [kind, setKind] = React.useState<PostKind>("text");
+
const [text, setText] = React.useState<string>("");
+ const [markdown, setMarkdown] = React.useState<string>("");
const [image, setImage] = React.useState<File | null>(null);
- const draftLocalStorageKey = `timeline.${timeline.name}.postDraft`;
+ const draftTextLocalStorageKey = `timeline.${timeline.name}.postDraft.text`;
+ const draftMarkdownLocalStorageKey = `timeline.${timeline.name}.postDraft.markdown`;
React.useEffect(() => {
- setText(window.localStorage.getItem(draftLocalStorageKey) ?? "");
- }, [draftLocalStorageKey]);
+ setText(window.localStorage.getItem(draftTextLocalStorageKey) ?? "");
+ setMarkdown(
+ window.localStorage.getItem(draftMarkdownLocalStorageKey) ?? ""
+ );
+ }, [draftTextLocalStorageKey, draftMarkdownLocalStorageKey]);
const canSend =
(kind === "text" && text.length !== 0) ||
@@ -102,9 +138,7 @@ const TimelinePostEdit: React.FC<TimelinePostEditProps> = (props) => {
};
React.useEffect(() => {
- if (onHeightChange) {
- onHeightChange(containerRef.current.clientHeight);
- }
+ notifyHeightChange();
return () => {
if (onHeightChange) {
onHeightChange(0);
@@ -112,11 +146,6 @@ const TimelinePostEdit: React.FC<TimelinePostEditProps> = (props) => {
};
});
- const toggleKind = React.useCallback(() => {
- setKind((oldKind) => (oldKind === "text" ? "image" : "text"));
- setImage(null);
- }, []);
-
const onSend = async (): Promise<void> => {
setProcess(true);
@@ -128,6 +157,12 @@ const TimelinePostEdit: React.FC<TimelinePostEditProps> = (props) => {
data: await base64(new Blob([text])),
};
break;
+ case "markdown":
+ requestData = {
+ contentType: "text/markdown",
+ data: await base64(new Blob([markdown])),
+ };
+ break;
case "image":
if (image == null) {
throw new UiLogicError(
@@ -151,7 +186,10 @@ const TimelinePostEdit: React.FC<TimelinePostEditProps> = (props) => {
(data) => {
if (kind === "text") {
setText("");
- window.localStorage.removeItem(draftLocalStorageKey);
+ window.localStorage.removeItem(draftTextLocalStorageKey);
+ } else if (kind === "markdown") {
+ setMarkdown("");
+ window.localStorage.removeItem(draftMarkdownLocalStorageKey);
}
setProcess(false);
setKind("text");
@@ -174,32 +212,55 @@ const TimelinePostEdit: React.FC<TimelinePostEditProps> = (props) => {
>
<Row>
<Col className="px-1 py-1">
- {kind === "text" ? (
- <Form.Control
- as="textarea"
- className="w-100 h-100 timeline-post-edit"
- value={text}
- disabled={process}
- onChange={(event: React.ChangeEvent<HTMLTextAreaElement>) => {
- const value = event.currentTarget.value;
- setText(value);
- window.localStorage.setItem(draftLocalStorageKey, value);
- }}
- />
- ) : (
- <TimelinePostEditImage onSelect={setImage} />
- )}
+ {(() => {
+ if (kind === "text") {
+ return (
+ <TimelinePostEditText
+ className="w-100 h-100 timeline-post-edit"
+ text={text}
+ disabled={process}
+ onChange={(t) => {
+ setText(t);
+ window.localStorage.setItem(draftTextLocalStorageKey, t);
+ }}
+ />
+ );
+ } else if (kind === "image") {
+ return (
+ <TimelinePostEditImage onSelect={setImage} disabled={process} />
+ );
+ } else if (kind === "markdown") {
+ return (
+ <TimelinePostEditText
+ className="w-100 h-100 timeline-post-edit"
+ text={markdown}
+ disabled={process}
+ onChange={(t) => {
+ setMarkdown(t);
+ window.localStorage.setItem(
+ draftMarkdownLocalStorageKey,
+ t
+ );
+ }}
+ />
+ );
+ }
+ })()}
</Col>
<Col xs="auto" className="align-self-end m-1">
<div className="d-block text-center mt-1 mb-2">
- <i
- onLoad={notifyHeightChange}
- className={clsx(
- kind === "text" ? "bi-image" : "bi-card-text",
- "icon-button"
- )}
- onClick={process ? undefined : toggleKind}
- />
+ <Form.Control
+ as="select"
+ value={kind}
+ onChange={(event) => {
+ const { value } = event.currentTarget;
+ setKind(value as PostKind);
+ }}
+ >
+ <option value="text">text</option>
+ <option value="image">image</option>
+ <option value="markdown">markdown</option>
+ </Form.Control>
</div>
<LoadingButton
variant="primary"