aboutsummaryrefslogtreecommitdiff
path: root/FrontEnd/src
diff options
context:
space:
mode:
authorcrupest <crupest@outlook.com>2023-09-21 21:05:04 +0800
committercrupest <crupest@outlook.com>2023-09-21 21:05:04 +0800
commita8a8385cd959e4d9d57b8a35381d2851049c07ff (patch)
treea933e8a6c1e8b577149dba624514148507a61a50 /FrontEnd/src
parent04863bd8ebb543a436bde0d49250010038ab9f90 (diff)
downloadtimeline-a8a8385cd959e4d9d57b8a35381d2851049c07ff.tar.gz
timeline-a8a8385cd959e4d9d57b8a35381d2851049c07ff.tar.bz2
timeline-a8a8385cd959e4d9d57b8a35381d2851049c07ff.zip
...
Diffstat (limited to 'FrontEnd/src')
-rw-r--r--FrontEnd/src/components/hooks/index.ts2
-rw-r--r--FrontEnd/src/components/hooks/useAutoUnsubscribePromise.ts24
-rw-r--r--FrontEnd/src/components/hooks/useReloadKey.ts9
-rw-r--r--FrontEnd/src/components/utilities/index.ts2
-rw-r--r--FrontEnd/src/locales/en/translation.json10
-rw-r--r--FrontEnd/src/locales/zh/translation.json10
-rw-r--r--FrontEnd/src/pages/timeline/Timeline.tsx21
-rw-r--r--FrontEnd/src/pages/timeline/view/MarkdownPostView.tsx23
-rw-r--r--FrontEnd/src/pages/timeline/view/PlainTextPostView.tsx23
-rw-r--r--FrontEnd/src/utilities/index.ts1
-rw-r--r--FrontEnd/src/utilities/promise.ts35
11 files changed, 81 insertions, 79 deletions
diff --git a/FrontEnd/src/components/hooks/index.ts b/FrontEnd/src/components/hooks/index.ts
index 98ce729e..972bf5ce 100644
--- a/FrontEnd/src/components/hooks/index.ts
+++ b/FrontEnd/src/components/hooks/index.ts
@@ -2,4 +2,4 @@ export { useMobile } from "./responsive";
export { default as useClickOutside } from "./useClickOutside";
export { default as useScrollToBottom } from "./useScrollToBottom";
export { default as useWindowLeave } from "./useWindowLeave";
-export { default as useAutoUnsubscribePromise } from "./useAutoUnsubscribePromise";
+export { default as useReloadKey } from "./useReloadKey";
diff --git a/FrontEnd/src/components/hooks/useAutoUnsubscribePromise.ts b/FrontEnd/src/components/hooks/useAutoUnsubscribePromise.ts
deleted file mode 100644
index 01c5a1db..00000000
--- a/FrontEnd/src/components/hooks/useAutoUnsubscribePromise.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-import { useEffect, DependencyList } from "react";
-
-export default function useAutoUnsubscribePromise<T>(
- promiseGenerator: () => Promise<T> | null | undefined,
- resultHandler: (data: T) => void,
- dependencies?: DependencyList | undefined,
-) {
- useEffect(() => {
- let subscribe = true;
- const promise = promiseGenerator();
- if (promise) {
- void promise.then((data) => {
- if (subscribe) {
- resultHandler(data);
- }
- });
-
- return () => {
- subscribe = false;
- };
- }
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [promiseGenerator, resultHandler, ...(dependencies ?? [])]);
-}
diff --git a/FrontEnd/src/components/hooks/useReloadKey.ts b/FrontEnd/src/components/hooks/useReloadKey.ts
new file mode 100644
index 00000000..4f63f914
--- /dev/null
+++ b/FrontEnd/src/components/hooks/useReloadKey.ts
@@ -0,0 +1,9 @@
+import { useState } from "react";
+
+export default function useReloadKey(): [
+ key: number | string,
+ reload: () => void,
+] {
+ const [key, setKey] = useState(0);
+ return [key, () => setKey((k) => k + 1)];
+}
diff --git a/FrontEnd/src/components/utilities/index.ts b/FrontEnd/src/components/utilities/index.ts
new file mode 100644
index 00000000..000c2640
--- /dev/null
+++ b/FrontEnd/src/components/utilities/index.ts
@@ -0,0 +1,2 @@
+export * from "~src/utilities";
+
diff --git a/FrontEnd/src/locales/en/translation.json b/FrontEnd/src/locales/en/translation.json
index a7e4efe5..1b43357c 100644
--- a/FrontEnd/src/locales/en/translation.json
+++ b/FrontEnd/src/locales/en/translation.json
@@ -38,14 +38,6 @@
"registerCodeInvalid": "Register code is invalid."
}
},
- "serviceWorker": {
- "availableOffline": "Timeline is now cached in your computer and you can use it offline. 🎉🎉🎉",
- "upgradePrompt": "App is getting a new version!",
- "upgradeNow": "Update Now",
- "upgradeSuccess": "Congratulations! App update succeeded! Still you can use it offline. 🎉🎉🎉",
- "externalActivatedPrompt": "A new version of app is activated. Please refresh the page. Or it may be broken.",
- "reloadNow": "Refresh Now"
- },
"nav": {
"settings": "Settings",
"login": "Login",
@@ -233,4 +225,4 @@
"admin": {
"title": "admin"
}
-} \ No newline at end of file
+}
diff --git a/FrontEnd/src/locales/zh/translation.json b/FrontEnd/src/locales/zh/translation.json
index 8a2f628f..dc0d6672 100644
--- a/FrontEnd/src/locales/zh/translation.json
+++ b/FrontEnd/src/locales/zh/translation.json
@@ -38,14 +38,6 @@
"Disconnecting": "正在断开连接",
"Reconnecting": "正在重新连接"
},
- "serviceWorker": {
- "availableOffline": "Timeline 已经缓存在本地,你可以离线使用它。🎉🎉🎉",
- "upgradePrompt": "App 有新版本!",
- "upgradeNow": "现在升级",
- "upgradeSuccess": "App 升级成功,当然,你仍可以离线使用它。 🎉🎉🎉",
- "externalActivatedPrompt": "一个新的 App 版本已经激活,请刷新页面使用,否则页面可能会出现故障。",
- "reloadNow": "立刻刷新"
- },
"nav": {
"settings": "设置",
"login": "登陆",
@@ -246,4 +238,4 @@
"admin": {
"title": "管理"
}
-} \ No newline at end of file
+}
diff --git a/FrontEnd/src/pages/timeline/Timeline.tsx b/FrontEnd/src/pages/timeline/Timeline.tsx
index 32cbf8c8..e2ab5c71 100644
--- a/FrontEnd/src/pages/timeline/Timeline.tsx
+++ b/FrontEnd/src/pages/timeline/Timeline.tsx
@@ -15,7 +15,7 @@ import {
import { getTimelinePostUpdate$ } from "~src/services/timeline";
-import { useScrollToBottom } from "~src/components/hooks";
+import { useReloadKey, useScrollToBottom } from "~src/components/hooks";
import TimelinePostList from "./TimelinePostList";
import TimelineInfoCard from "./TimelineInfoCard";
@@ -44,11 +44,8 @@ export function Timeline(props: TimelineProps) {
const [currentPage, setCurrentPage] = useState(1);
const [totalPage, setTotalPage] = useState(0);
- const [timelineReloadKey, setTimelineReloadKey] = useState(0);
- const [postsReloadKey, setPostsReloadKey] = useState(0);
-
- const updateTimeline = (): void => setTimelineReloadKey((o) => o + 1);
- const updatePosts = (): void => setPostsReloadKey((o) => o + 1);
+ const [timelineKey, reloadTimeline] = useReloadKey();
+ const [postsKey, reloadPosts] = useReloadKey();
useEffect(() => {
setTimeline(null);
@@ -77,7 +74,7 @@ export function Timeline(props: TimelineProps) {
}
},
);
- }, [timelineOwner, timelineName, timelineReloadKey]);
+ }, [timelineOwner, timelineName, timelineKey]);
useEffect(() => {
getHttpTimelineClient()
@@ -102,7 +99,7 @@ export function Timeline(props: TimelineProps) {
}
},
);
- }, [timelineOwner, timelineName, postsReloadKey]);
+ }, [timelineOwner, timelineName, postsKey]);
useEffect(() => {
const timelinePostUpdate$ = getTimelinePostUpdate$(
@@ -111,7 +108,7 @@ export function Timeline(props: TimelineProps) {
);
const subscription = timelinePostUpdate$.subscribe(({ update, state }) => {
if (update) {
- setPostsReloadKey((o) => o + 1);
+ reloadPosts();
}
setSignalrState(state);
});
@@ -162,15 +159,15 @@ export function Timeline(props: TimelineProps) {
<TimelineInfoCard
timeline={timeline}
connectionStatus={signalrState}
- onReload={updateTimeline}
+ onReload={reloadTimeline}
/>
)}
{posts && (
<div className={classNames("timeline", className)}>
{timeline?.postable && (
- <TimelinePostEdit timeline={timeline} onPosted={updatePosts} />
+ <TimelinePostEdit timeline={timeline} onPosted={reloadPosts} />
)}
- <TimelinePostList posts={posts} onReload={updatePosts} />
+ <TimelinePostList posts={posts} onReload={reloadPosts} />
</div>
)}
</div>
diff --git a/FrontEnd/src/pages/timeline/view/MarkdownPostView.tsx b/FrontEnd/src/pages/timeline/view/MarkdownPostView.tsx
index 9bb9f980..d0a43f7d 100644
--- a/FrontEnd/src/pages/timeline/view/MarkdownPostView.tsx
+++ b/FrontEnd/src/pages/timeline/view/MarkdownPostView.tsx
@@ -1,4 +1,4 @@
-import { useMemo, useState } from "react";
+import { useEffect, useMemo, useState } from "react";
import { marked } from "marked";
import classNames from "classnames";
@@ -7,7 +7,7 @@ import {
getHttpTimelineClient,
} from "~src/http/timeline";
-import { useAutoUnsubscribePromise } from "~src/components/hooks";
+import { subscribePromise } from "~src/components/utilities";
import Skeleton from "~src/components/Skeleton";
import "./MarkdownPostView.css";
@@ -23,19 +23,18 @@ export default function MarkdownPostView({
}: MarkdownPostViewProps) {
const [markdown, setMarkdown] = useState<string | null>(null);
- useAutoUnsubscribePromise(
- () => {
- if (post) {
- return getHttpTimelineClient().getPostDataAsString(
+ useEffect(() => {
+ if (post) {
+ return subscribePromise(
+ getHttpTimelineClient().getPostDataAsString(
post.timelineOwnerV2,
post.timelineNameV2,
post.id,
- );
- }
- },
- setMarkdown,
- [post],
- );
+ ),
+ setMarkdown,
+ );
+ }
+ }, [post]);
const markdownHtml = useMemo<string | null>(() => {
if (markdown == null) return null;
diff --git a/FrontEnd/src/pages/timeline/view/PlainTextPostView.tsx b/FrontEnd/src/pages/timeline/view/PlainTextPostView.tsx
index b964187d..d66bf05b 100644
--- a/FrontEnd/src/pages/timeline/view/PlainTextPostView.tsx
+++ b/FrontEnd/src/pages/timeline/view/PlainTextPostView.tsx
@@ -1,4 +1,4 @@
-import { useState } from "react";
+import { useEffect, useState } from "react";
import classNames from "classnames";
import {
@@ -6,8 +6,8 @@ import {
getHttpTimelineClient,
} from "~src/http/timeline";
+import { subscribePromise } from "~src/components/utilities";
import Skeleton from "~src/components/Skeleton";
-import { useAutoUnsubscribePromise } from "~src/components/hooks";
import "./PlainTextPostView.css";
@@ -22,19 +22,18 @@ export default function PlainTextPostView({
}: PlainTextPostViewProps) {
const [text, setText] = useState<string | null>(null);
- useAutoUnsubscribePromise(
- () => {
- if (post) {
- return getHttpTimelineClient().getPostDataAsString(
+ useEffect(() => {
+ if (post) {
+ return subscribePromise(
+ getHttpTimelineClient().getPostDataAsString(
post.timelineOwnerV2,
post.timelineNameV2,
post.id,
- );
- }
- },
- setText,
- [post],
- );
+ ),
+ setText,
+ );
+ }
+ }, [post]);
return (
<div
diff --git a/FrontEnd/src/utilities/index.ts b/FrontEnd/src/utilities/index.ts
index 7659a8aa..e280274e 100644
--- a/FrontEnd/src/utilities/index.ts
+++ b/FrontEnd/src/utilities/index.ts
@@ -1,5 +1,6 @@
export { default as base64 } from "./base64";
export { withQuery } from "./url";
+export { subscribePromise } from "./promise";
export function delay(milliseconds: number): Promise<void> {
return new Promise<void>((resolve) => {
diff --git a/FrontEnd/src/utilities/promise.ts b/FrontEnd/src/utilities/promise.ts
new file mode 100644
index 00000000..96bcceac
--- /dev/null
+++ b/FrontEnd/src/utilities/promise.ts
@@ -0,0 +1,35 @@
+export function subscribePromise<T>(
+ promise: Promise<T>,
+ resolve: Parameters<Promise<T>["then"]>[0],
+ reject?: Parameters<Promise<T>["then"]>[1],
+): {
+ promise: ReturnType<Promise<T>["then"]>;
+ (): void;
+} {
+ let subscribe = true;
+
+ const p = promise.then(
+ resolve != null
+ ? (value) => {
+ if (subscribe) {
+ resolve(value);
+ }
+ }
+ : undefined,
+ reject != null
+ ? (error) => {
+ if (subscribe) {
+ reject(error);
+ }
+ }
+ : undefined,
+ );
+
+ const result = function () {
+ subscribe = false;
+ };
+ result.promise = p;
+
+ return result;
+}
+