aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcrupest <crupest@outlook.com>2021-05-17 21:41:19 +0800
committercrupest <crupest@outlook.com>2021-05-17 21:41:19 +0800
commit5ead84a292481b43f44ae3d044193901045ce092 (patch)
treec5bc4b046f74500721356d0dc83c39a2d76aae52
parent0fc36c865ba46cab42b67e52153cd6115d8087ab (diff)
downloadtimeline-5ead84a292481b43f44ae3d044193901045ce092.tar.gz
timeline-5ead84a292481b43f44ae3d044193901045ce092.tar.bz2
timeline-5ead84a292481b43f44ae3d044193901045ce092.zip
feat: Connection badge.
-rw-r--r--FrontEnd/src/app/locales/en/translation.json7
-rw-r--r--FrontEnd/src/app/locales/zh/translation.json7
-rw-r--r--FrontEnd/src/app/views/timeline-common/ConnectionStatusBadge.tsx39
-rw-r--r--FrontEnd/src/app/views/timeline-common/Timeline.tsx17
-rw-r--r--FrontEnd/src/app/views/timeline-common/TimelinePageCardTemplate.tsx3
-rw-r--r--FrontEnd/src/app/views/timeline-common/TimelinePageTemplate.tsx7
-rw-r--r--FrontEnd/src/app/views/timeline-common/timeline-common.sass29
7 files changed, 105 insertions, 4 deletions
diff --git a/FrontEnd/src/app/locales/en/translation.json b/FrontEnd/src/app/locales/en/translation.json
index 1261b086..49268961 100644
--- a/FrontEnd/src/app/locales/en/translation.json
+++ b/FrontEnd/src/app/locales/en/translation.json
@@ -10,6 +10,13 @@
"network": "Network error.",
"unknown": "Unknown error."
},
+ "connectionState": {
+ "Connected": "Connected",
+ "Connecting": "Connecting",
+ "Disconnected": "Disconnected",
+ "Disconnecting": "Disconnecting",
+ "Reconnecting": "Reconnecting"
+ },
"serviceWorker": {
"availableOffline": "Timeline is now cached in your computer and you can use it offline. 🎉🎉🎉",
"upgradePrompt": "App is getting a new version!",
diff --git a/FrontEnd/src/app/locales/zh/translation.json b/FrontEnd/src/app/locales/zh/translation.json
index b2c651f6..728c3b81 100644
--- a/FrontEnd/src/app/locales/zh/translation.json
+++ b/FrontEnd/src/app/locales/zh/translation.json
@@ -10,6 +10,13 @@
"network": "网络错误。",
"unknown": "未知错误。"
},
+ "connectionState": {
+ "Connected": "已连接",
+ "Connecting": "正在连接",
+ "Disconnected": "已断开连接",
+ "Disconnecting": "正在断开连接",
+ "Reconnecting": "正在重新连接"
+ },
"serviceWorker": {
"availableOffline": "Timeline 已经缓存在本地,你可以离线使用它。🎉🎉🎉",
"upgradePrompt": "App 有新版本!",
diff --git a/FrontEnd/src/app/views/timeline-common/ConnectionStatusBadge.tsx b/FrontEnd/src/app/views/timeline-common/ConnectionStatusBadge.tsx
new file mode 100644
index 00000000..df43d8d2
--- /dev/null
+++ b/FrontEnd/src/app/views/timeline-common/ConnectionStatusBadge.tsx
@@ -0,0 +1,39 @@
+import React from "react";
+import classnames from "classnames";
+import { HubConnectionState } from "@microsoft/signalr";
+import { useTranslation } from "react-i18next";
+
+export interface ConnectionStatusBadgeProps {
+ status: HubConnectionState;
+ className?: string;
+ style?: React.CSSProperties;
+}
+
+const classNameMap: Record<HubConnectionState, string> = {
+ Connected: "success",
+ Connecting: "warning",
+ Disconnected: "danger",
+ Disconnecting: "warning",
+ Reconnecting: "warning",
+};
+
+const ConnectionStatusBadge: React.FC<ConnectionStatusBadgeProps> = (props) => {
+ const { status, className, style } = props;
+
+ const { t } = useTranslation();
+
+ return (
+ <div
+ className={classnames(
+ "connection-status-badge",
+ classNameMap[status],
+ className
+ )}
+ style={style}
+ >
+ {t(`connectionState.${status}`)}
+ </div>
+ );
+};
+
+export default ConnectionStatusBadge;
diff --git a/FrontEnd/src/app/views/timeline-common/Timeline.tsx b/FrontEnd/src/app/views/timeline-common/Timeline.tsx
index 65378563..7b56d129 100644
--- a/FrontEnd/src/app/views/timeline-common/Timeline.tsx
+++ b/FrontEnd/src/app/views/timeline-common/Timeline.tsx
@@ -24,7 +24,7 @@ export interface TimelineProps {
}
const Timeline: React.FC<TimelineProps> = (props) => {
- const { timelineName, className, style, reloadKey, onReload } = props;
+ const { timelineName, className, style, reloadKey } = props;
const [state, setState] =
React.useState<
@@ -37,6 +37,12 @@ const Timeline: React.FC<TimelineProps> = (props) => {
setPosts([]);
}, [timelineName]);
+ const onReload = React.useRef<() => void>(props.onReload);
+
+ React.useEffect(() => {
+ onReload.current = props.onReload;
+ }, [props.onReload]);
+
const onConnectionStateChanged =
React.useRef<((state: HubConnectionState) => void) | null>(null);
@@ -50,7 +56,7 @@ const Timeline: React.FC<TimelineProps> = (props) => {
const subscription = timelinePostUpdate$.subscribe(
({ update, state }) => {
if (update) {
- onReload();
+ onReload.current();
}
onConnectionStateChanged.current?.(state);
}
@@ -59,7 +65,7 @@ const Timeline: React.FC<TimelineProps> = (props) => {
subscription.unsubscribe();
};
}
- }, [timelineName, state, onReload, onConnectionStateChanged]);
+ }, [timelineName, state]);
React.useEffect(() => {
if (timelineName != null) {
@@ -125,7 +131,10 @@ const Timeline: React.FC<TimelineProps> = (props) => {
return (
<>
<TimelineTop height={40} />
- <TimelinePagedPostListView posts={posts} onReload={onReload} />
+ <TimelinePagedPostListView
+ posts={posts}
+ onReload={onReload.current}
+ />
</>
);
}
diff --git a/FrontEnd/src/app/views/timeline-common/TimelinePageCardTemplate.tsx b/FrontEnd/src/app/views/timeline-common/TimelinePageCardTemplate.tsx
index 6adde8d4..623d643f 100644
--- a/FrontEnd/src/app/views/timeline-common/TimelinePageCardTemplate.tsx
+++ b/FrontEnd/src/app/views/timeline-common/TimelinePageCardTemplate.tsx
@@ -16,6 +16,7 @@ import { TimelinePageCardProps } from "./TimelinePageTemplate";
import CollapseButton from "./CollapseButton";
import { TimelineMemberDialog } from "./TimelineMember";
import TimelinePropertyChangeDialog from "./TimelinePropertyChangeDialog";
+import ConnectionStatusBadge from "./ConnectionStatusBadge";
import { MenuItems, PopupMenu } from "../common/Menu";
import FullPage from "../common/FullPage";
@@ -32,6 +33,7 @@ const TimelinePageCardTemplate: React.FC<TimelineCardTemplateProps> = ({
toggleCollapse,
infoArea,
manageItems,
+ connectionStatus,
onReload,
className,
dialog,
@@ -113,6 +115,7 @@ const TimelinePageCardTemplate: React.FC<TimelineCardTemplateProps> = ({
style={{ zIndex: collapse ? 1029 : 1031 }}
>
<div className="float-end d-flex align-items-center">
+ <ConnectionStatusBadge status={connectionStatus} className="me-2" />
<CollapseButton collapse={collapse} onClick={toggleCollapse} />
</div>
{isSmallScreen ? (
diff --git a/FrontEnd/src/app/views/timeline-common/TimelinePageTemplate.tsx b/FrontEnd/src/app/views/timeline-common/TimelinePageTemplate.tsx
index 6e9eba25..d3bbc0bb 100644
--- a/FrontEnd/src/app/views/timeline-common/TimelinePageTemplate.tsx
+++ b/FrontEnd/src/app/views/timeline-common/TimelinePageTemplate.tsx
@@ -1,6 +1,7 @@
import React from "react";
import { useTranslation } from "react-i18next";
import { Container } from "react-bootstrap";
+import { HubConnectionState } from "@microsoft/signalr";
import { HttpNetworkError, HttpNotFoundError } from "@/http/common";
import { getHttpTimelineClient, HttpTimelineInfo } from "@/http/timeline";
@@ -17,6 +18,7 @@ export interface TimelinePageCardProps {
timeline: HttpTimelineInfo;
collapse: boolean;
toggleCollapse: () => void;
+ connectionStatus: HubConnectionState;
className?: string;
onReload: () => void;
}
@@ -40,6 +42,9 @@ const TimelinePageTemplate: React.FC<TimelinePageTemplateProps> = (props) => {
);
const [timeline, setTimeline] = React.useState<HttpTimelineInfo | null>(null);
+ const [connectionStatus, setConnectionStatus] =
+ React.useState<HubConnectionState>(HubConnectionState.Connecting);
+
useReverseScrollPositionRemember();
React.useEffect(() => {
@@ -135,6 +140,7 @@ const TimelinePageTemplate: React.FC<TimelinePageTemplateProps> = (props) => {
collapse={cardCollapse}
toggleCollapse={toggleCardCollapse}
onReload={onReload}
+ connectionStatus={connectionStatus}
/>
) : null}
<Container
@@ -158,6 +164,7 @@ const TimelinePageTemplate: React.FC<TimelinePageTemplateProps> = (props) => {
timelineName={timeline?.name}
reloadKey={timelineReloadKey}
onReload={reloadTimeline}
+ onConnectionStateChanged={setConnectionStatus}
/>
);
}
diff --git a/FrontEnd/src/app/views/timeline-common/timeline-common.sass b/FrontEnd/src/app/views/timeline-common/timeline-common.sass
index 0b0bd24d..4400fead 100644
--- a/FrontEnd/src/app/views/timeline-common/timeline-common.sass
+++ b/FrontEnd/src/app/views/timeline-common/timeline-common.sass
@@ -228,3 +228,32 @@ $timeline-line-color-current: var(--tl-primary-enhance-color)
position: absolute
right: 10px
top: 2px
+
+.connection-status-badge
+ font-size: 0.8em
+ border-radius: 5px
+ padding: 0.1em 1em
+ background-color: rgb(234 242 255)
+
+ &::before
+ width: 10px
+ height: 10px
+ border-radius: 50%
+ display: inline-block
+ content: ''
+ margin-right: 0.6em
+
+ &.success
+ color: #006100
+ &::before
+ background-color: #006100
+
+ &.warning
+ color: #e4a700
+ &::before
+ background-color: #e4a700
+
+ &.danger
+ color: #fd1616
+ &::before
+ background-color: #fd1616