@weavy/uikit-react 12.1.0 → 13.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/changelog.md +36 -0
- package/dist/cjs/index.js +28 -6
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/types/client/WeavyClient.d.ts +8 -1
- package/dist/cjs/types/components/Attachment.d.ts +2 -1
- package/dist/cjs/types/components/Chat.d.ts +1 -1
- package/dist/cjs/types/components/PdfViewer.d.ts +3 -1
- package/dist/cjs/types/components/Preview.d.ts +8 -10
- package/dist/cjs/types/contexts/PreviewContext.d.ts +2 -1
- package/dist/cjs/types/contexts/WeavyContext.d.ts +2 -3
- package/dist/cjs/types/types/Chat.d.ts +1 -1
- package/dist/cjs/types/types/types.d.ts +16 -5
- package/dist/cjs/types/ui/Spinner.d.ts +9 -0
- package/dist/cjs/types/utils/fileUtilities.d.ts +1 -4
- package/dist/css/weavy-chat.css +270 -94
- package/dist/css/weavy-messenger.css +274 -96
- package/dist/css/weavy.css +274 -96
- package/dist/esm/index.js +28 -6
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/types/client/WeavyClient.d.ts +8 -1
- package/dist/esm/types/components/Attachment.d.ts +2 -1
- package/dist/esm/types/components/Chat.d.ts +1 -1
- package/dist/esm/types/components/PdfViewer.d.ts +3 -1
- package/dist/esm/types/components/Preview.d.ts +8 -10
- package/dist/esm/types/contexts/PreviewContext.d.ts +2 -1
- package/dist/esm/types/contexts/WeavyContext.d.ts +2 -3
- package/dist/esm/types/types/Chat.d.ts +1 -1
- package/dist/esm/types/types/types.d.ts +16 -5
- package/dist/esm/types/ui/Spinner.d.ts +9 -0
- package/dist/esm/types/utils/fileUtilities.d.ts +1 -4
- package/dist/index.d.ts +14 -7
- package/package.json +2 -2
- package/rollup.config.js +3 -1
- package/src/client/WeavyClient.ts +105 -24
- package/src/components/Attachment.tsx +8 -7
- package/src/components/Chat.tsx +3 -3
- package/src/components/Conversation.tsx +3 -3
- package/src/components/Message.tsx +1 -1
- package/src/components/Messages.tsx +1 -1
- package/src/components/PdfViewer.tsx +88 -83
- package/src/components/Preview.tsx +115 -54
- package/src/components/SearchUsers.tsx +2 -2
- package/src/contexts/PreviewContext.tsx +90 -16
- package/src/contexts/WeavyContext.tsx +7 -4
- package/src/hooks/useBadge.ts +2 -6
- package/src/hooks/useChat.ts +3 -14
- package/src/hooks/useConversation.ts +1 -7
- package/src/hooks/useConversations.ts +1 -7
- package/src/hooks/useFileUploader.ts +6 -8
- package/src/hooks/useMembers.ts +1 -7
- package/src/hooks/useMessages.ts +1 -7
- package/src/hooks/useMutateChat.ts +6 -11
- package/src/hooks/useMutateConversation.ts +7 -10
- package/src/hooks/useMutateConversationName.ts +10 -12
- package/src/hooks/useMutateDeleteReaction.ts +3 -8
- package/src/hooks/useMutateExternalBlobs.ts +6 -11
- package/src/hooks/useMutateMeeting.ts +6 -11
- package/src/hooks/useMutateMembers.ts +8 -13
- package/src/hooks/useMutateMessage.ts +10 -15
- package/src/hooks/useMutatePinned.ts +3 -8
- package/src/hooks/useMutateReaction.ts +6 -12
- package/src/hooks/useMutateRead.ts +1 -10
- package/src/hooks/useMutateRemoveMembers.ts +7 -12
- package/src/hooks/useMutateTyping.ts +6 -11
- package/src/hooks/useSearchUsers.ts +1 -6
- package/src/hooks/useUser.ts +3 -14
- package/src/scss/theme/_appbar.scss +4 -2
- package/src/scss/theme/_cm-editor.scss +1 -1
- package/src/scss/theme/_code-vscode-dark.scss +184 -0
- package/src/scss/theme/_code-vscode-light.scss +179 -0
- package/src/scss/theme/_code.scss +9 -112
- package/src/scss/theme/_files.scss +1 -1
- package/src/scss/theme/_message-editor.scss +1 -1
- package/src/scss/theme/_overlays.scss +2 -2
- package/src/scss/theme/_panels.scss +11 -7
- package/src/scss/theme/_preview-code.scss +5 -0
- package/src/scss/theme/_preview-embed.scss +3 -3
- package/src/scss/theme/_preview-image.scss +1 -1
- package/src/scss/theme/_preview-text.scss +1 -1
- package/src/scss/theme/_preview.scss +7 -2
- package/src/scss/weavy-chat.scss +1 -0
- package/src/scss/weavy-messenger.scss +1 -0
- package/src/types/Chat.ts +1 -1
- package/src/types/types.ts +16 -5
- package/src/ui/Spinner.tsx +18 -0
- package/src/utils/fileUtilities.ts +11 -125
|
@@ -1,16 +1,23 @@
|
|
|
1
1
|
export default class WeavyClient {
|
|
2
2
|
url: string;
|
|
3
|
-
tokenFactory: () => string | Promise<string>;
|
|
4
3
|
connection: import("@microsoft/signalr").HubConnection;
|
|
4
|
+
tokenFactory: (refresh: boolean) => Promise<string>;
|
|
5
5
|
groups: string[];
|
|
6
6
|
connectionEvents: any[];
|
|
7
7
|
isConnectionStarted: any;
|
|
8
|
+
token: string;
|
|
9
|
+
tokenPromise: Promise<string> | null;
|
|
8
10
|
EVENT_NAMESPACE: string;
|
|
9
11
|
EVENT_CLOSE: string;
|
|
10
12
|
EVENT_RECONNECTING: string;
|
|
11
13
|
EVENT_RECONNECTED: string;
|
|
12
14
|
constructor(options: WeavyClientOptions);
|
|
15
|
+
get(url: string, retry?: boolean): Promise<Response>;
|
|
16
|
+
post(url: string, method: "GET" | "POST" | "PUT" | "DELETE" | "PATCH", body: string | FormData, contentType?: string, retry?: boolean): Promise<Response>;
|
|
17
|
+
getToken(refresh: boolean): Promise<string>;
|
|
18
|
+
tokenFactoryInternal(refresh?: boolean, fromSR?: boolean): Promise<string>;
|
|
13
19
|
subscribe(group: string, event: string, callback: any): Promise<void>;
|
|
14
20
|
unsubscribe(group: string, event: string, callback: any): Promise<void>;
|
|
21
|
+
destroy(): void;
|
|
15
22
|
triggerHandler(name: string, ...data: any): void;
|
|
16
23
|
}
|
|
@@ -8,6 +8,7 @@ declare type Props = {
|
|
|
8
8
|
kind: string;
|
|
9
9
|
size: number;
|
|
10
10
|
provider: string;
|
|
11
|
+
onClick?: (e: any) => void;
|
|
11
12
|
};
|
|
12
|
-
declare const Attachment: ({ previewFormat, url, previewUrl, mediaType, name, kind, size, provider }: Props) => JSX.Element;
|
|
13
|
+
declare const Attachment: ({ previewFormat, url, previewUrl, mediaType, name, kind, size, provider, onClick }: Props) => JSX.Element;
|
|
13
14
|
export default Attachment;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
2
|
declare type Props = {
|
|
3
3
|
src: string;
|
|
4
|
+
pdfCMapsUrl: string;
|
|
5
|
+
pdfWorkerUrl: string;
|
|
4
6
|
};
|
|
5
|
-
declare const PdfViewer: ({ src }: Props) => JSX.Element;
|
|
7
|
+
declare const PdfViewer: ({ src, pdfCMapsUrl, pdfWorkerUrl }: Props) => JSX.Element;
|
|
6
8
|
export default PdfViewer;
|
|
@@ -7,20 +7,16 @@ declare type ImageProps = {
|
|
|
7
7
|
export declare const PreviewImage: ({ src, width, height }: ImageProps) => JSX.Element;
|
|
8
8
|
declare type DocumentProps = {
|
|
9
9
|
src: string;
|
|
10
|
+
client: any;
|
|
10
11
|
};
|
|
11
|
-
export declare const PreviewDocument: ({ src }: DocumentProps) => JSX.Element;
|
|
12
|
-
declare type
|
|
12
|
+
export declare const PreviewDocument: ({ src, client }: DocumentProps) => JSX.Element;
|
|
13
|
+
declare type MediaProps = {
|
|
14
|
+
format: string;
|
|
13
15
|
src: string;
|
|
14
16
|
name: string;
|
|
15
17
|
mediaType?: string;
|
|
16
18
|
};
|
|
17
|
-
export declare const
|
|
18
|
-
declare type AudioProps = {
|
|
19
|
-
src: string;
|
|
20
|
-
name: string;
|
|
21
|
-
mediaType?: string;
|
|
22
|
-
};
|
|
23
|
-
export declare const PreviewAudio: ({ src, name, mediaType }: AudioProps) => JSX.Element;
|
|
19
|
+
export declare const PreviewMedia: ({ format, src, name, mediaType }: MediaProps) => JSX.Element;
|
|
24
20
|
declare type TextProps = {
|
|
25
21
|
src: string;
|
|
26
22
|
html?: boolean;
|
|
@@ -45,7 +41,9 @@ declare type IconProps = {
|
|
|
45
41
|
};
|
|
46
42
|
export declare const PreviewIcon: ({ children, src, icon, name, provider, download, className }: IconProps) => JSX.Element;
|
|
47
43
|
declare type PreviewProps = {
|
|
44
|
+
client: any;
|
|
48
45
|
src: string;
|
|
46
|
+
link?: string;
|
|
49
47
|
format: PreviewFormatType;
|
|
50
48
|
name: string;
|
|
51
49
|
icon: string;
|
|
@@ -54,5 +52,5 @@ declare type PreviewProps = {
|
|
|
54
52
|
mediaType?: string;
|
|
55
53
|
provider?: string;
|
|
56
54
|
};
|
|
57
|
-
export declare const Preview: ({ src, format, name, icon, width, height, mediaType, provider }: PreviewProps) => JSX.Element;
|
|
55
|
+
export declare const Preview: ({ client, src, link, format, name, icon, width, height, mediaType, provider }: PreviewProps) => JSX.Element;
|
|
58
56
|
export default Preview;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
export declare const PreviewContext: React.Context<PreviewContextProps>;
|
|
3
3
|
declare type Props = {
|
|
4
|
+
client: any;
|
|
4
5
|
children: React.ReactNode;
|
|
5
6
|
};
|
|
6
|
-
declare const PreviewProvider: ({ children }: Props) => JSX.Element;
|
|
7
|
+
declare const PreviewProvider: ({ client, children }: Props) => JSX.Element;
|
|
7
8
|
export default PreviewProvider;
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import WeavyClient from "../client/WeavyClient";
|
|
3
2
|
export declare const WeavyContext: React.Context<WeavyContextProps>;
|
|
4
|
-
declare type
|
|
3
|
+
declare type WeavyProviderProperties = {
|
|
5
4
|
children: React.ReactNode;
|
|
6
5
|
client: WeavyClient;
|
|
7
6
|
options?: WeavyContextOptions;
|
|
8
7
|
};
|
|
9
|
-
declare const WeavyProvider: ({ children, client, options }:
|
|
8
|
+
declare const WeavyProvider: ({ children, client, options }: WeavyProviderProperties) => JSX.Element;
|
|
10
9
|
export default WeavyProvider;
|
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
2
|
interface WeavyClient {
|
|
3
3
|
url: string;
|
|
4
|
-
|
|
4
|
+
tokenFactoryInternal: () => Promise<string>;
|
|
5
5
|
subscribe: Function;
|
|
6
6
|
unsubscribe: Function;
|
|
7
|
+
destroy: Function;
|
|
8
|
+
get: (url: string, retry?: boolean) => Promise<Response>;
|
|
9
|
+
post: (url: string, method: "GET" | "POST" | "PUT" | "DELETE" | "PATCH", body: string | FormData, contentType?: string, retry?: boolean) => Promise<Response>;
|
|
7
10
|
}
|
|
8
11
|
declare type WeavyClientOptions = {
|
|
9
12
|
url: string;
|
|
10
|
-
tokenFactory: (
|
|
13
|
+
tokenFactory: (refresh: boolean) => Promise<string>;
|
|
11
14
|
};
|
|
12
15
|
declare type WeavyContextProps = {
|
|
13
16
|
client: WeavyClient | null;
|
|
@@ -19,6 +22,8 @@ declare type WeavyContextOptions = {
|
|
|
19
22
|
enableCloudFiles?: boolean;
|
|
20
23
|
enableScrollbarDetection?: boolean;
|
|
21
24
|
filebrowserUrl?: string;
|
|
25
|
+
pdfWorkerUrl?: string;
|
|
26
|
+
pdfCMapsUrl?: string;
|
|
22
27
|
reactions?: string[];
|
|
23
28
|
};
|
|
24
29
|
declare type MessengerContextProps = {
|
|
@@ -114,11 +119,17 @@ declare type AttachmentType = {
|
|
|
114
119
|
size: number;
|
|
115
120
|
provider: string;
|
|
116
121
|
download_url: string;
|
|
117
|
-
|
|
118
|
-
thumbnail_url: string;
|
|
122
|
+
embed_url: string;
|
|
119
123
|
external_url: string;
|
|
124
|
+
thumbnail_url: string;
|
|
125
|
+
preview_format: PreviewFormatType;
|
|
126
|
+
application_url: string;
|
|
127
|
+
preview_url: string;
|
|
128
|
+
created_at: string;
|
|
129
|
+
created_by?: UserType;
|
|
130
|
+
createdById?: number;
|
|
120
131
|
};
|
|
121
|
-
declare type PreviewFormatType = "
|
|
132
|
+
declare type PreviewFormatType = "audio" | "code" | "embed" | "html" | "image" | "pdf" | "text" | "video" | "none";
|
|
122
133
|
declare type ReactionType = {
|
|
123
134
|
id: number;
|
|
124
135
|
parent: MessageType;
|
|
@@ -6,15 +6,12 @@ export declare function isWebImage(path: string): boolean;
|
|
|
6
6
|
export declare function isBitmap(path: string): boolean;
|
|
7
7
|
export declare function isMetaFile(path: string): boolean;
|
|
8
8
|
export declare function isVideo(ext: string): boolean;
|
|
9
|
+
export declare function isMarkdown(ext: string): boolean;
|
|
9
10
|
export declare function isMarkup(ext: string): boolean;
|
|
10
11
|
export declare function isCode(ext: string): boolean;
|
|
11
12
|
export declare function isText(ext: string): boolean;
|
|
12
13
|
export declare function isOfficeDocument(path: string): boolean;
|
|
13
|
-
export declare function canResize(path: string): boolean;
|
|
14
|
-
export declare function canConvertToImage(filename: string): boolean;
|
|
15
|
-
export declare function canConvertToPdf(filename: string): boolean;
|
|
16
14
|
export declare function getIcon(name: string, mediaType?: string): {
|
|
17
15
|
icon: string;
|
|
18
16
|
color?: string;
|
|
19
17
|
};
|
|
20
|
-
export declare function getPreviewFormat(filename: string): PreviewFormatType;
|
package/dist/index.d.ts
CHANGED
|
@@ -3,30 +3,37 @@ import * as _microsoft_signalr from '@microsoft/signalr';
|
|
|
3
3
|
import React, { FC } from 'react';
|
|
4
4
|
import { Styles } from 'react-modal';
|
|
5
5
|
|
|
6
|
-
declare class WeavyClient {
|
|
6
|
+
declare class WeavyClient$1 {
|
|
7
7
|
url: string;
|
|
8
|
-
tokenFactory: () => string | Promise<string>;
|
|
9
8
|
connection: _microsoft_signalr.HubConnection;
|
|
9
|
+
tokenFactory: (refresh: boolean) => Promise<string>;
|
|
10
10
|
groups: string[];
|
|
11
11
|
connectionEvents: any[];
|
|
12
12
|
isConnectionStarted: any;
|
|
13
|
+
token: string;
|
|
14
|
+
tokenPromise: Promise<string> | null;
|
|
13
15
|
EVENT_NAMESPACE: string;
|
|
14
16
|
EVENT_CLOSE: string;
|
|
15
17
|
EVENT_RECONNECTING: string;
|
|
16
18
|
EVENT_RECONNECTED: string;
|
|
17
19
|
constructor(options: WeavyClientOptions);
|
|
20
|
+
get(url: string, retry?: boolean): Promise<Response>;
|
|
21
|
+
post(url: string, method: "GET" | "POST" | "PUT" | "DELETE" | "PATCH", body: string | FormData, contentType?: string, retry?: boolean): Promise<Response>;
|
|
22
|
+
getToken(refresh: boolean): Promise<string>;
|
|
23
|
+
tokenFactoryInternal(refresh?: boolean, fromSR?: boolean): Promise<string>;
|
|
18
24
|
subscribe(group: string, event: string, callback: any): Promise<void>;
|
|
19
25
|
unsubscribe(group: string, event: string, callback: any): Promise<void>;
|
|
26
|
+
destroy(): void;
|
|
20
27
|
triggerHandler(name: string, ...data: any): void;
|
|
21
28
|
}
|
|
22
29
|
|
|
23
30
|
declare const WeavyContext: React.Context<WeavyContextProps>;
|
|
24
|
-
declare type
|
|
31
|
+
declare type WeavyProviderProperties = {
|
|
25
32
|
children: React.ReactNode;
|
|
26
33
|
client: WeavyClient;
|
|
27
34
|
options?: WeavyContextOptions;
|
|
28
35
|
};
|
|
29
|
-
declare const WeavyProvider: ({ children, client, options }:
|
|
36
|
+
declare const WeavyProvider: ({ children, client, options }: WeavyProviderProperties) => JSX.Element;
|
|
30
37
|
|
|
31
38
|
declare const MessengerContext: React.Context<MessengerContextProps>;
|
|
32
39
|
declare type Props$1 = {
|
|
@@ -48,10 +55,10 @@ interface ConversationProps {
|
|
|
48
55
|
declare const _default: React.MemoExoticComponent<({ id, showBackButton }: ConversationProps) => JSX.Element>;
|
|
49
56
|
|
|
50
57
|
interface ChatProps {
|
|
51
|
-
|
|
58
|
+
uid: string;
|
|
52
59
|
}
|
|
53
60
|
|
|
54
|
-
declare const Chat: ({
|
|
61
|
+
declare const Chat: ({ uid }: ChatProps) => JSX.Element;
|
|
55
62
|
|
|
56
63
|
declare const UIButton: {
|
|
57
64
|
UI: any;
|
|
@@ -94,4 +101,4 @@ declare const UIOverlay: {
|
|
|
94
101
|
UI: ({ children, className, isOpen, style }: OverlayProps) => JSX.Element;
|
|
95
102
|
};
|
|
96
103
|
|
|
97
|
-
export { UIButton as Button, Chat, _default as Conversation, ConversationBadge, ConversationList, UIDropdown as Dropdown, UIIcon as Icon, Messenger, MessengerContext, MessengerProvider, UIOverlay as Overlay, WeavyClient, WeavyContext, WeavyProvider };
|
|
104
|
+
export { UIButton as Button, Chat, _default as Conversation, ConversationBadge, ConversationList, UIDropdown as Dropdown, UIIcon as Icon, Messenger, MessengerContext, MessengerProvider, UIOverlay as Overlay, WeavyClient$1 as WeavyClient, WeavyContext, WeavyProvider };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@weavy/uikit-react",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "13.0.0",
|
|
4
4
|
"author": "Weavy",
|
|
5
5
|
"description": "React UI-kit for Weavy",
|
|
6
6
|
"homepage": "https://github.com/weavy/weavy-uikit-react",
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"emoji-toolkit": "^6.6.0",
|
|
51
51
|
"lodash.debounce": "^4.0.8",
|
|
52
52
|
"lodash.throttle": "^4.1.1",
|
|
53
|
-
"pdfjs-dist": "^2.
|
|
53
|
+
"pdfjs-dist": "^2.15.349",
|
|
54
54
|
"react-modal": "^3.14.4",
|
|
55
55
|
"react-query": "^3.34.16"
|
|
56
56
|
}
|
package/rollup.config.js
CHANGED
|
@@ -2,77 +2,158 @@ import { HubConnectionBuilder, LogLevel } from '@microsoft/signalr';
|
|
|
2
2
|
|
|
3
3
|
export default class WeavyClient {
|
|
4
4
|
url;
|
|
5
|
-
tokenFactory;
|
|
6
5
|
connection;
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
tokenFactory;
|
|
7
|
+
groups: string[] = [];
|
|
8
|
+
connectionEvents: any[] = [];
|
|
9
9
|
isConnectionStarted: any;
|
|
10
|
-
|
|
10
|
+
token: string = "";
|
|
11
|
+
tokenPromise: Promise<string> | null;
|
|
11
12
|
EVENT_NAMESPACE = ".connection";
|
|
12
13
|
EVENT_CLOSE = "close";
|
|
13
14
|
EVENT_RECONNECTING = "reconnecting";
|
|
14
15
|
EVENT_RECONNECTED = "reconnected";
|
|
15
16
|
|
|
17
|
+
|
|
16
18
|
constructor(options: WeavyClientOptions) {
|
|
17
19
|
this.url = options.url;
|
|
18
|
-
this.tokenFactory = options.tokenFactory
|
|
19
|
-
this.
|
|
20
|
-
this.connectionEvents = [];
|
|
21
|
-
|
|
20
|
+
this.tokenFactory = options.tokenFactory;
|
|
21
|
+
this.tokenPromise = null;
|
|
22
22
|
this.connection = new HubConnectionBuilder()
|
|
23
23
|
.configureLogging(LogLevel.None)
|
|
24
24
|
.withUrl(this.url + "/hubs/rtm", {
|
|
25
|
-
accessTokenFactory: this.
|
|
25
|
+
accessTokenFactory: () => { return this.tokenFactoryInternal.call(this, true, true) }
|
|
26
26
|
})
|
|
27
27
|
.withAutomaticReconnect()
|
|
28
28
|
.build();
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
|
|
30
|
+
this.isConnectionStarted = this.connection.start();
|
|
31
31
|
|
|
32
32
|
this.connection.onclose(error => this.triggerHandler(this.EVENT_CLOSE, error));
|
|
33
33
|
this.connection.onreconnecting(error => this.triggerHandler(this.EVENT_RECONNECTING, error));
|
|
34
34
|
this.connection.onreconnected(connectionId => this.triggerHandler(this.EVENT_RECONNECTED, connectionId));
|
|
35
|
-
|
|
35
|
+
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
async get(url: string, retry: boolean = true): Promise<Response> {
|
|
39
|
+
//const token = await this.tokenFactoryInternal();
|
|
40
|
+
//console.log("GET:", url, " - t:", token);
|
|
41
|
+
const response = await fetch(this.url + url, {
|
|
42
|
+
headers: {
|
|
43
|
+
"content-type": "application/json",
|
|
44
|
+
"Authorization": "Bearer " + await this.tokenFactoryInternal()
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
if (!response.ok) {
|
|
49
|
+
if ((response.status === 401 || response.status === 403) && retry) {
|
|
50
|
+
await this.tokenFactoryInternal(true);
|
|
51
|
+
return await this.get(url, false);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
console.error(`Error calling endpoint ${url}`, response)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return response;
|
|
36
58
|
}
|
|
37
59
|
|
|
60
|
+
async post(url: string, method: "GET" | "POST" | "PUT" | "DELETE" | "PATCH", body: string | FormData, contentType: string = "application/json", retry: boolean = true): Promise<Response> {
|
|
61
|
+
let headers: HeadersInit = {
|
|
62
|
+
"Authorization": "Bearer " + await this.tokenFactoryInternal()
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
if(contentType !== ""){
|
|
66
|
+
headers["content-type"] = contentType
|
|
67
|
+
}
|
|
68
|
+
const response = await fetch(this.url + url, {
|
|
69
|
+
method: method,
|
|
70
|
+
body: body,
|
|
71
|
+
headers: headers
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
if (!response.ok) {
|
|
75
|
+
if ((response.status === 401 || response.status === 403) && retry) {
|
|
76
|
+
await this.tokenFactoryInternal(true);
|
|
77
|
+
return await this.post(url, method, body, contentType, false);
|
|
78
|
+
}
|
|
38
79
|
|
|
39
|
-
|
|
80
|
+
console.error(`Error calling endpoint ${url}`, response)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return response;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
async getToken(refresh: boolean) {
|
|
87
|
+
console.log("Refresh, ", refresh)
|
|
88
|
+
if (!this.token || refresh) {
|
|
89
|
+
console.log("Getting new token...")
|
|
90
|
+
this.token = await this.tokenFactory(true);
|
|
91
|
+
//return await this.tokenFactory(refresh);
|
|
92
|
+
}
|
|
93
|
+
//this.tokenPromise = null;
|
|
94
|
+
console.log("Resolve new token...")
|
|
95
|
+
return this.token;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
async tokenFactoryInternal(refresh: boolean = false, fromSR: boolean = false): Promise<string> {
|
|
99
|
+
//console.log("Get token with refresh: ", refresh, fromSR)
|
|
100
|
+
if(this.token && !refresh) return this.token;
|
|
101
|
+
|
|
102
|
+
if(!this.tokenPromise){
|
|
103
|
+
//console.log("No ongoing promise, create new one. Refresh: ", refresh)
|
|
104
|
+
this.tokenPromise = this.tokenFactory(refresh);
|
|
105
|
+
let token = await this.tokenPromise;
|
|
106
|
+
//console.log("Got token: ", token)
|
|
107
|
+
this.tokenPromise = null;
|
|
108
|
+
this.token = token;
|
|
109
|
+
return this.token;
|
|
110
|
+
} else{
|
|
111
|
+
//console.log("Already a promise in action, wait for it to resolve...")
|
|
112
|
+
return this.tokenPromise;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
async subscribe(group: string, event: string, callback: any) {
|
|
40
117
|
await this.isConnectionStarted;
|
|
41
|
-
|
|
118
|
+
|
|
42
119
|
try {
|
|
43
120
|
var name = group ? group + ":" + event : event;
|
|
44
121
|
await this.connection.invoke("AddToGroup", name);
|
|
45
122
|
this.groups.push(name);
|
|
46
123
|
this.connection.on(name, callback);
|
|
47
|
-
} catch(err: any){
|
|
124
|
+
} catch (err: any) {
|
|
48
125
|
console.warn("Error in AddToGroup:", err)
|
|
49
126
|
}
|
|
50
|
-
|
|
127
|
+
|
|
51
128
|
}
|
|
52
129
|
|
|
53
130
|
async unsubscribe(group: string, event: string, callback: any) {
|
|
54
131
|
await this.isConnectionStarted;
|
|
55
132
|
var name = group ? group + ":" + event : event;
|
|
56
|
-
|
|
133
|
+
|
|
57
134
|
// get first occurence of group name and remove it
|
|
58
135
|
const index = this.groups.findIndex(e => e === name);
|
|
59
|
-
if(index !== -1){
|
|
136
|
+
if (index !== -1) {
|
|
60
137
|
this.groups = this.groups.splice(index, 1);
|
|
61
138
|
|
|
62
|
-
try {
|
|
139
|
+
try {
|
|
63
140
|
// if no more groups, remove from server
|
|
64
|
-
if(!this.groups.find(e => e === name)){
|
|
141
|
+
if (!this.groups.find(e => e === name)) {
|
|
65
142
|
await this.connection.invoke("RemoveFromGroup", name);
|
|
66
143
|
}
|
|
67
|
-
|
|
68
|
-
} catch(err: any){
|
|
144
|
+
|
|
145
|
+
} catch (err: any) {
|
|
69
146
|
console.warn("Error in RemoveFromGroup:", err)
|
|
70
147
|
}
|
|
71
148
|
}
|
|
72
|
-
|
|
149
|
+
|
|
73
150
|
this.connection.off(name, callback);
|
|
74
151
|
}
|
|
75
|
-
|
|
152
|
+
|
|
153
|
+
destroy(){
|
|
154
|
+
this.connection.stop();
|
|
155
|
+
}
|
|
156
|
+
|
|
76
157
|
triggerHandler(name: string, ...data: any) {
|
|
77
158
|
name = name.endsWith(this.EVENT_NAMESPACE) ? name : name + this.EVENT_NAMESPACE;
|
|
78
159
|
let event = new CustomEvent(name, { cancelable: false });
|
|
@@ -10,19 +10,20 @@ type Props = {
|
|
|
10
10
|
name: string,
|
|
11
11
|
kind: string,
|
|
12
12
|
size: number,
|
|
13
|
-
provider: string
|
|
13
|
+
provider: string,
|
|
14
|
+
onClick?: (e: any) => void
|
|
14
15
|
}
|
|
15
16
|
|
|
16
|
-
const Attachment = ({ previewFormat, url, previewUrl, mediaType, name, kind, size, provider }: Props) => {
|
|
17
|
+
const Attachment = ({ previewFormat, url, previewUrl, mediaType, name, kind, size, provider, onClick }: Props) => {
|
|
17
18
|
let fileSize = size > 0 ? fileSizeAsString(size) : null;
|
|
18
19
|
let { icon, color } = getIcon(name, mediaType)
|
|
19
20
|
return (
|
|
20
|
-
<a href={previewUrl || url} className=
|
|
21
|
-
<div className=
|
|
22
|
-
<div className=
|
|
23
|
-
<div className=
|
|
21
|
+
<a href={previewUrl || url} className="wy-attachment" target={"_blank"} title={name} onClick={onClick ? (e) => onClick(e) : undefined}>
|
|
22
|
+
<div className="wy-attachment-icon" title={kind}><Icon.UI name={icon} color={color} size={2} /></div>
|
|
23
|
+
<div className="wy-attachment-content">
|
|
24
|
+
<div className="wy-attachment-title">{name}</div>
|
|
24
25
|
{fileSize &&
|
|
25
|
-
<div className=
|
|
26
|
+
<div className="wy-attachment-meta" title={fileSize}>{fileSize}</div>
|
|
26
27
|
}
|
|
27
28
|
</div>
|
|
28
29
|
</a>
|
package/src/components/Chat.tsx
CHANGED
|
@@ -7,7 +7,7 @@ import useMembers from '../hooks/useMembers';
|
|
|
7
7
|
import Typing from './Typing';
|
|
8
8
|
import useConversation from '../hooks/useConversation';
|
|
9
9
|
|
|
10
|
-
const Chat = ({
|
|
10
|
+
const Chat = ({ uid }: ChatProps) => {
|
|
11
11
|
const { client } = useContext(WeavyContext);
|
|
12
12
|
const [selectedId, setSelectedId] = useState<number | null>(null)
|
|
13
13
|
|
|
@@ -15,7 +15,7 @@ const Chat = ({ id }: ChatProps) => {
|
|
|
15
15
|
throw new Error('Weavy Chat component must be used within an WeavyProvider');
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
const { isLoading: isLoadingChat, data: dataChat } = useChat(
|
|
18
|
+
const { isLoading: isLoadingChat, data: dataChat } = useChat(uid, {});
|
|
19
19
|
|
|
20
20
|
const { isLoading: isLoadingMembers, data: dataMembers } = useMembers(selectedId, {
|
|
21
21
|
// The query will not execute until the activeConversation exists
|
|
@@ -51,7 +51,7 @@ const Chat = ({ id }: ChatProps) => {
|
|
|
51
51
|
</header>
|
|
52
52
|
|
|
53
53
|
{!isLoadingChat && !dataChat &&
|
|
54
|
-
<div>No chat with the contextual id <strong>{
|
|
54
|
+
<div>No chat with the contextual id <strong>{uid}</strong></div>
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
{selectedId && dataMembers &&
|
|
@@ -25,7 +25,7 @@ const Conversation = ({ id, showBackButton }: ConversationProps) => {
|
|
|
25
25
|
const { selectedConversationId, setSelectedConversationId } = useContext(MessengerContext);
|
|
26
26
|
const { user } = useContext(UserContext);
|
|
27
27
|
const [modalAddOpen, setModalAddOpen] = useState(false);
|
|
28
|
-
const [modalDetailsOpen, setModalDetailsOpen] = useState(false);
|
|
28
|
+
const [modalDetailsOpen, setModalDetailsOpen] = useState(false);
|
|
29
29
|
const [title, setTitle] = useState<string>("");
|
|
30
30
|
|
|
31
31
|
const ChatRoom = "edb400ac-839b-45a7-b2a8-6a01820d1c44";
|
|
@@ -186,7 +186,7 @@ const Conversation = ({ id, showBackButton }: ConversationProps) => {
|
|
|
186
186
|
<div className="wy-pane-group">
|
|
187
187
|
<table className="wy-search-result-table">
|
|
188
188
|
<tbody>
|
|
189
|
-
{dataMembers
|
|
189
|
+
{dataMembers && dataMembers.data && dataMembers.data.map((m: MemberType) => {
|
|
190
190
|
return (
|
|
191
191
|
<tr key={m.id} className="wy-search-result-table-checkbox">
|
|
192
192
|
<td className="wy-search-result-table-icon"><Avatar src={m.avatar_url} name={m.display_name} id={m.id} size={24} presence={m.presence} /></td>
|
|
@@ -203,7 +203,7 @@ const Conversation = ({ id, showBackButton }: ConversationProps) => {
|
|
|
203
203
|
</div>
|
|
204
204
|
</Overlay.UI>
|
|
205
205
|
|
|
206
|
-
|
|
206
|
+
|
|
207
207
|
</>
|
|
208
208
|
)
|
|
209
209
|
}
|
|
@@ -58,7 +58,7 @@ const Message: FC<MessageProps> = ({ id, html, temp, me, avatar, name, created_a
|
|
|
58
58
|
|
|
59
59
|
{files && !!files.length && <div className="wy-attachments">
|
|
60
60
|
{files.map((a: AttachmentType) =>
|
|
61
|
-
<Attachment key={a.id} name={a.name} previewFormat={a.kind} provider={a.provider} url={a.download_url} previewUrl={a.provider ? a.external_url : a.preview_url} mediaType={a.media_type} kind={a.kind} size={a.size} />
|
|
61
|
+
<Attachment key={a.id} onClick={(e) => handlePreviewClick(e, a.id)} name={a.name} previewFormat={a.kind} provider={a.provider} url={a.download_url} previewUrl={a.provider ? a.external_url : a.preview_url} mediaType={a.media_type} kind={a.kind} size={a.size} />
|
|
62
62
|
)}
|
|
63
63
|
</div>}
|
|
64
64
|
</>
|
|
@@ -234,7 +234,7 @@ const Messages = ({ id, members, displayName, avatarUrl }: Props) => {
|
|
|
234
234
|
parentId={id}
|
|
235
235
|
reactions={item.reactions}
|
|
236
236
|
//reactions_count={item.reactions_count}
|
|
237
|
-
seenBy={members.data.length > 0 ? members.data.filter((member) => {
|
|
237
|
+
seenBy={(members.data && members.data.length > 0) ? members.data.filter((member) => {
|
|
238
238
|
const hasRead = member.read_at >= item.created_at;
|
|
239
239
|
const nothingLaterRead = !data.pages.map((p) => p.data).flat().find((message: MessageType) => { return message.id > item.id && member.read_at >= message.created_at });
|
|
240
240
|
return hasRead && nothingLaterRead && member.id !== user.id;
|