aboutsummaryrefslogtreecommitdiff
path: root/FrontEnd/src/services/timeline.ts
diff options
context:
space:
mode:
Diffstat (limited to 'FrontEnd/src/services/timeline.ts')
-rw-r--r--FrontEnd/src/services/timeline.ts85
1 files changed, 85 insertions, 0 deletions
diff --git a/FrontEnd/src/services/timeline.ts b/FrontEnd/src/services/timeline.ts
new file mode 100644
index 00000000..4ebb705d
--- /dev/null
+++ b/FrontEnd/src/services/timeline.ts
@@ -0,0 +1,85 @@
+import { TimelineVisibility } from "http/timeline";
+import XRegExp from "xregexp";
+import { Observable } from "rxjs";
+import { HubConnectionBuilder, HubConnectionState } from "@microsoft/signalr";
+
+import { getHttpToken } from "http/common";
+
+const timelineNameReg = XRegExp("^[-_\\p{L}]*$", "u");
+
+export function validateTimelineName(name: string): boolean {
+ return timelineNameReg.test(name);
+}
+
+export const timelineVisibilityTooltipTranslationMap: Record<
+ TimelineVisibility,
+ string
+> = {
+ Public: "timeline.visibilityTooltip.public",
+ Register: "timeline.visibilityTooltip.register",
+ Private: "timeline.visibilityTooltip.private",
+};
+
+export function getTimelinePostUpdate$(
+ timelineName: string
+): Observable<{ update: boolean; state: HubConnectionState }> {
+ return new Observable((subscriber) => {
+ subscriber.next({
+ update: false,
+ state: HubConnectionState.Connecting,
+ });
+
+ const token = getHttpToken();
+ const connection = new HubConnectionBuilder()
+ .withUrl("/api/hub/timeline", {
+ accessTokenFactory: token == null ? undefined : () => token,
+ })
+ .withAutomaticReconnect()
+ .build();
+
+ const handler = (tn: string): void => {
+ if (timelineName === tn) {
+ subscriber.next({ update: true, state: connection.state });
+ }
+ };
+
+ connection.onclose(() => {
+ subscriber.next({
+ update: false,
+ state: HubConnectionState.Disconnected,
+ });
+ });
+
+ connection.onreconnecting(() => {
+ subscriber.next({
+ update: false,
+ state: HubConnectionState.Reconnecting,
+ });
+ });
+
+ connection.onreconnected(() => {
+ subscriber.next({
+ update: false,
+ state: HubConnectionState.Connected,
+ });
+ });
+
+ connection.on("OnTimelinePostChanged", handler);
+
+ void connection.start().then(() => {
+ subscriber.next({ update: false, state: HubConnectionState.Connected });
+
+ return connection.invoke("SubscribeTimelinePostChange", timelineName);
+ });
+
+ return () => {
+ connection.off("OnTimelinePostChanged", handler);
+
+ if (connection.state === HubConnectionState.Connected) {
+ void connection
+ .invoke("UnsubscribeTimelinePostChange", timelineName)
+ .then(() => connection.stop());
+ }
+ };
+ });
+}