From 36145a18463e0ad4fb372df82cd488f1b4dae2f7 Mon Sep 17 00:00:00 2001
From: crupest <crupest@outlook.com>
Date: Thu, 18 Mar 2021 21:17:12 +0800
Subject: feat: Prevent leave.

---
 .../app/views/timeline-common/MarkdownPostEdit.tsx | 149 ++++++++++++---------
 1 file changed, 84 insertions(+), 65 deletions(-)

(limited to 'FrontEnd/src/app/views/timeline-common/MarkdownPostEdit.tsx')

diff --git a/FrontEnd/src/app/views/timeline-common/MarkdownPostEdit.tsx b/FrontEnd/src/app/views/timeline-common/MarkdownPostEdit.tsx
index d43077b4..ab6aafea 100644
--- a/FrontEnd/src/app/views/timeline-common/MarkdownPostEdit.tsx
+++ b/FrontEnd/src/app/views/timeline-common/MarkdownPostEdit.tsx
@@ -1,6 +1,7 @@
 import React from "react";
 import { Form } from "react-bootstrap";
 import { useTranslation } from "react-i18next";
+import { Prompt } from "react-router";
 
 import { getHttpTimelineClient, HttpTimelinePostInfo } from "@/http/timeline";
 
@@ -26,6 +27,8 @@ const MarkdownPostEdit: React.FC<MarkdownPostEditProps> = ({
 }) => {
   const { t } = useTranslation();
 
+  const [canLeave, setCanLeave] = React.useState<boolean>(true);
+
   const [process, setProcess] = React.useState<boolean>(false);
 
   const [text, _setText] = React.useState<string>("");
@@ -39,6 +42,7 @@ const MarkdownPostEdit: React.FC<MarkdownPostEditProps> = ({
   const getBuilder = (): TimelinePostBuilder => {
     if (_builder.current == null) {
       const builder = new TimelinePostBuilder(() => {
+        setCanLeave(builder.isEmpty);
         _setText(builder.text);
         _setImages(builder.images);
         _setPreviewHtml(builder.renderHtml());
@@ -54,6 +58,18 @@ const MarkdownPostEdit: React.FC<MarkdownPostEditProps> = ({
     };
   }, []);
 
+  React.useEffect(() => {
+    window.onbeforeunload = () => {
+      if (!canLeave) {
+        return t("timeline.confirmLeave");
+      }
+    };
+
+    return () => {
+      window.onbeforeunload = null;
+    };
+  }, [canLeave, t]);
+
   const send = async (): Promise<void> => {
     setProcess(true);
     try {
@@ -70,73 +86,76 @@ const MarkdownPostEdit: React.FC<MarkdownPostEditProps> = ({
   };
 
   return (
-    <TabPages
-      className={className}
-      style={style}
-      pageContainerClassName="py-2"
-      actions={
-        <>
-          <div className="flat-button text-danger mr-2" onClick={onClose}>
-            {t("operationDialog.cancel")}
-          </div>
-          <div className="flat-button text-primary" onClick={send}>
-            {t("timeline.send")}
-          </div>
-        </>
-      }
-      pages={[
-        {
-          id: "text",
-          tabText: "edit",
-          page: (
-            <Form.Control
-              as="textarea"
-              value={text}
-              disabled={process}
-              onChange={(event) => {
-                getBuilder().setMarkdownText(event.currentTarget.value);
-              }}
-            />
-          ),
-        },
-        {
-          id: "images",
-          tabText: "image",
-          page: (
-            <div className="timeline-markdown-post-edit-page">
-              {images.map((image) => (
-                <img
-                  key={image.url}
-                  src={image.url}
-                  className="timeline-markdown-post-edit-image"
-                />
-              ))}
-              <Form.File
-                label={t("chooseImage")}
-                accept="image/*"
-                onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
-                  const { files } = event.currentTarget;
-                  if (files != null && files.length !== 0) {
-                    getBuilder().appendImage(files[0]);
-                  }
-                }}
+    <>
+      <Prompt when={!canLeave} message={t("timeline.confirmLeave")} />
+      <TabPages
+        className={className}
+        style={style}
+        pageContainerClassName="py-2"
+        actions={
+          <>
+            <div className="flat-button text-danger mr-2" onClick={onClose}>
+              {t("operationDialog.cancel")}
+            </div>
+            <div className="flat-button text-primary" onClick={send}>
+              {t("timeline.send")}
+            </div>
+          </>
+        }
+        pages={[
+          {
+            id: "text",
+            tabText: "edit",
+            page: (
+              <Form.Control
+                as="textarea"
+                value={text}
                 disabled={process}
+                onChange={(event) => {
+                  getBuilder().setMarkdownText(event.currentTarget.value);
+                }}
               />
-            </div>
-          ),
-        },
-        {
-          id: "preview",
-          tabText: "preview",
-          page: (
-            <div
-              className="markdown-container timeline-markdown-post-edit-page"
-              dangerouslySetInnerHTML={{ __html: previewHtml }}
-            />
-          ),
-        },
-      ]}
-    />
+            ),
+          },
+          {
+            id: "images",
+            tabText: "image",
+            page: (
+              <div className="timeline-markdown-post-edit-page">
+                {images.map((image) => (
+                  <img
+                    key={image.url}
+                    src={image.url}
+                    className="timeline-markdown-post-edit-image"
+                  />
+                ))}
+                <Form.File
+                  label={t("chooseImage")}
+                  accept="image/*"
+                  onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
+                    const { files } = event.currentTarget;
+                    if (files != null && files.length !== 0) {
+                      getBuilder().appendImage(files[0]);
+                    }
+                  }}
+                  disabled={process}
+                />
+              </div>
+            ),
+          },
+          {
+            id: "preview",
+            tabText: "preview",
+            page: (
+              <div
+                className="markdown-container timeline-markdown-post-edit-page"
+                dangerouslySetInnerHTML={{ __html: previewHtml }}
+              />
+            ),
+          },
+        ]}
+      />
+    </>
   );
 };
 
-- 
cgit v1.2.3

