@ethora/chat-component 25.12.2 → 26.1.1
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/README.md +587 -145
- package/dist/components/MainComponents/MessageContainer.d.ts +1 -0
- package/dist/components/MessageBubble/MessageReply.d.ts +2 -2
- package/dist/components/MessageNotification/MessageNotificationToast.d.ts +17 -0
- package/dist/components/MessageNotification/index.d.ts +2 -0
- package/dist/components/Modals/SettingsModals/SharedStyledComponents.d.ts +22 -0
- package/dist/components/Modals/styledModalComponents.d.ts +28 -0
- package/dist/components/styled/Button.d.ts +2 -2
- package/dist/components/styled/DateLabel.d.ts +2 -2
- package/dist/components/styled/StyledComponents.d.ts +10 -10
- package/dist/components/styled/StyledInputComponents/StyledInputComponents.d.ts +6 -6
- package/dist/context/MessageNotificationContext.d.ts +12 -0
- package/dist/firebase-config.d.ts +6 -2
- package/dist/firebase-messaging-sw.js +351 -0
- package/dist/helpers/getDataFromXml.d.ts +1 -0
- package/dist/helpers/initRoomsPresence.d.ts +1 -1
- package/dist/helpers/storeConsole.d.ts +6 -0
- package/dist/hooks/useInAppNotifications.d.ts +18 -0
- package/dist/hooks/usePushNotifications.d.ts +45 -0
- package/dist/hooks/useTabVisibility.d.ts +1 -0
- package/dist/main.css +1 -1
- package/dist/main.d.ts +5 -0
- package/dist/main.js +14686 -11893
- package/dist/main.js.map +1 -1
- package/dist/networking/api-requests/push.api.d.ts +18 -0
- package/dist/networking/stanzaHandlers.d.ts +4 -2
- package/dist/networking/xmpp/allRoomPresences.xmpp.d.ts +11 -1
- package/dist/networking/xmpp/presenceInRoom.xmpp.d.ts +1 -1
- package/dist/networking/xmpp/sendTextMessage.xmpp.d.ts +1 -1
- package/dist/networking/xmpp/sendTextMessageWithTranslateTag.xmpp.d.ts +1 -1
- package/dist/networking/xmpp/subscribeToRoomMessages.xmpp.d.ts +9 -0
- package/dist/networking/xmppClient.d.ts +13 -3
- package/dist/roomStore/chatSettingsSlice.d.ts +1 -0
- package/dist/roomStore/index.d.ts +28 -0
- package/dist/roomStore/roomHeapSlice.d.ts +1 -1
- package/dist/roomStore/roomsSlice.d.ts +11 -1
- package/dist/types/models/config.model.d.ts +35 -1
- package/dist/types/models/room.model.d.ts +4 -1
- package/dist/types/models/xmpp.model.d.ts +3 -1
- package/dist/utils/firebasePushNotifications.d.ts +34 -0
- package/dist/utils/formatError.d.ts +1 -0
- package/dist/utils/messageNotificationManager.d.ts +16 -0
- package/dist/utils/notificationPolicy.d.ts +45 -0
- package/dist/utils/notificationUtils.d.ts +22 -0
- package/dist/utils/pushSubscriptionService.d.ts +12 -0
- package/dist/version.d.ts +1 -1
- package/package.json +7 -4
- package/public/firebase-messaging-sw.js +351 -0
- package/scripts/init-push.js +48 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { FC } from 'react';
|
|
2
2
|
export declare const StyledMessageReply: import('styled-components/dist/types').IStyledComponentBase<"web", import('styled-components/dist/types').Substitute<import('react').DetailedHTMLProps<import('react').HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {
|
|
3
|
-
isUser: boolean;
|
|
4
|
-
configColor: string;
|
|
3
|
+
$isUser: boolean;
|
|
4
|
+
$configColor: string;
|
|
5
5
|
}>> & string;
|
|
6
6
|
interface MessageReplyProps {
|
|
7
7
|
isUser: boolean;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
import { IMessage } from '../../types/models/message.model';
|
|
3
|
+
export interface MessageNotificationData {
|
|
4
|
+
id: string;
|
|
5
|
+
message: IMessage;
|
|
6
|
+
roomName: string;
|
|
7
|
+
senderName: string;
|
|
8
|
+
roomJID: string;
|
|
9
|
+
timestamp: number;
|
|
10
|
+
}
|
|
11
|
+
export interface MessageNotificationToastProps extends MessageNotificationData {
|
|
12
|
+
onClose: () => void;
|
|
13
|
+
onNavigateToMessage: (roomJID: string, messageId: string, message: IMessage, roomName: string, senderName: string) => void;
|
|
14
|
+
duration: number;
|
|
15
|
+
}
|
|
16
|
+
declare const MessageNotificationToast: React.FC<MessageNotificationToastProps>;
|
|
17
|
+
export default MessageNotificationToast;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { ButtonProps } from '../../styled/Button';
|
|
2
|
+
export declare const SharedSettingsCenterContainer: import('styled-components/dist/types').IStyledComponentBase<"web", import('styled-components').FastOmit<import('styled-components').FastOmit<Omit<import('styled-components').FastOmit<import('react').DetailedHTMLProps<import('react').HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>, "ref"> & {
|
|
3
|
+
ref?: import('react').Ref<HTMLDivElement>;
|
|
4
|
+
}, never>, never>> & string;
|
|
5
|
+
export declare const SharedSettingsColumnContainer: import('styled-components/dist/types').IStyledComponentBase<"web", import('styled-components').FastOmit<import('react').DetailedHTMLProps<import('react').HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
|
|
6
|
+
export declare const SharedSettingsSectionContainer: import('styled-components/dist/types').IStyledComponentBase<"web", import('styled-components').FastOmit<import('react').DetailedHTMLProps<import('react').HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
|
|
7
|
+
export declare const SharedSettingsStyledLabel: import('styled-components/dist/types').IStyledComponentBase<"web", import('styled-components').FastOmit<Omit<import('styled-components').FastOmit<import('react').DetailedHTMLProps<import('react').HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, never>, "ref"> & {
|
|
8
|
+
ref?: import('react').Ref<HTMLSpanElement>;
|
|
9
|
+
}, never>> & string;
|
|
10
|
+
export declare const RowWrapper: import('styled-components/dist/types').IStyledComponentBase<"web", import('styled-components').FastOmit<import('react').DetailedHTMLProps<import('react').HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
|
|
11
|
+
export declare const SharedSettingsLabelData: import('styled-components/dist/types').IStyledComponentBase<"web", import('styled-components').FastOmit<Omit<import('styled-components').FastOmit<import('react').DetailedHTMLProps<import('react').HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, never>, "ref"> & {
|
|
12
|
+
ref?: import('react').Ref<HTMLSpanElement>;
|
|
13
|
+
}, never>> & string;
|
|
14
|
+
export declare const SharedSettingsStyledButton: import('styled-components/dist/types').IStyledComponentBase<"web", import('styled-components/dist/types').Substitute<Omit<ButtonProps & import('react').RefAttributes<HTMLButtonElement>, "ref"> & {
|
|
15
|
+
ref?: import('react').Ref<HTMLButtonElement>;
|
|
16
|
+
}, {
|
|
17
|
+
borderColor: string;
|
|
18
|
+
}>> & string & Omit<import('react').ForwardRefExoticComponent<ButtonProps & import('react').RefAttributes<HTMLButtonElement>>, keyof import('react').Component<any, {}, any>>;
|
|
19
|
+
export declare const SharedSettingsInfoPanel: import('styled-components/dist/types').IStyledComponentBase<"web", import('styled-components/dist/types').Substitute<import('react').DetailedHTMLProps<import('react').HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {
|
|
20
|
+
bgColor: string;
|
|
21
|
+
}>> & string;
|
|
22
|
+
export declare const SharedSettingsInfoText: import('styled-components/dist/types').IStyledComponentBase<"web", import('styled-components').FastOmit<import('react').DetailedHTMLProps<import('react').HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { ButtonProps } from '../styled/Button';
|
|
2
|
+
export declare const ModalBackground: import('styled-components/dist/types').IStyledComponentBase<"web", import('styled-components').FastOmit<import('react').DetailedHTMLProps<import('react').HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
|
|
3
|
+
export declare const CloseButton: import('styled-components/dist/types').IStyledComponentBase<"web", import('styled-components').FastOmit<import('react').DetailedHTMLProps<import('react').ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, never>> & string;
|
|
4
|
+
export declare const ModalContainer: import('styled-components/dist/types').IStyledComponentBase<"web", import('styled-components').FastOmit<import('react').DetailedHTMLProps<import('react').HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
|
|
5
|
+
export declare const ModalTitle: import('styled-components/dist/types').IStyledComponentBase<"web", import('styled-components').FastOmit<import('react').DetailedHTMLProps<import('react').HTMLAttributes<HTMLHeadingElement>, HTMLHeadingElement>, never>> & string;
|
|
6
|
+
export declare const ModalDescription: import('styled-components/dist/types').IStyledComponentBase<"web", import('styled-components').FastOmit<import('react').DetailedHTMLProps<import('react').HTMLAttributes<HTMLParagraphElement>, HTMLParagraphElement>, never>> & string;
|
|
7
|
+
export declare const GroupContainer: import('styled-components/dist/types').IStyledComponentBase<"web", import('styled-components').FastOmit<import('react').DetailedHTMLProps<import('react').HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
|
|
8
|
+
export declare const ModalContainerFullScreen: import('styled-components/dist/types').IStyledComponentBase<"web", import('styled-components').FastOmit<import('react').DetailedHTMLProps<import('react').HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
|
|
9
|
+
export declare const HeaderContainer: import('styled-components/dist/types').IStyledComponentBase<"web", import('styled-components').FastOmit<Omit<import('styled-components').FastOmit<import('react').DetailedHTMLProps<import('react').HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>, "ref"> & {
|
|
10
|
+
ref?: import('react').Ref<HTMLDivElement>;
|
|
11
|
+
}, never>> & string;
|
|
12
|
+
export declare const HeaderLeft: import('styled-components/dist/types').IStyledComponentBase<"web", import('styled-components').FastOmit<import('react').DetailedHTMLProps<import('react').HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
|
|
13
|
+
export declare const HeaderRight: import('styled-components/dist/types').IStyledComponentBase<"web", import('styled-components').FastOmit<import('react').DetailedHTMLProps<import('react').HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
|
|
14
|
+
export declare const CenterContainer: import('styled-components/dist/types').IStyledComponentBase<"web", import('styled-components').FastOmit<Omit<import('styled-components').FastOmit<import('react').DetailedHTMLProps<import('react').HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>, "ref"> & {
|
|
15
|
+
ref?: import('react').Ref<HTMLDivElement>;
|
|
16
|
+
}, never>> & string;
|
|
17
|
+
export declare const ProfileImage: import('styled-components/dist/types').IStyledComponentBase<"web", import('styled-components').FastOmit<import('react').DetailedHTMLProps<import('react').HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
|
|
18
|
+
export declare const UserInfo: import('styled-components/dist/types').IStyledComponentBase<"web", import('styled-components').FastOmit<import('react').DetailedHTMLProps<import('react').HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
|
|
19
|
+
export declare const UserName: import('styled-components/dist/types').IStyledComponentBase<"web", import('styled-components').FastOmit<import('react').DetailedHTMLProps<import('react').HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
|
|
20
|
+
export declare const UserStatus: import('styled-components/dist/types').IStyledComponentBase<"web", import('styled-components').FastOmit<import('react').DetailedHTMLProps<import('react').HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
|
|
21
|
+
export declare const BorderedContainer: import('styled-components/dist/types').IStyledComponentBase<"web", import('styled-components').FastOmit<import('react').DetailedHTMLProps<import('react').HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
|
|
22
|
+
export declare const LabelData: import('styled-components/dist/types').IStyledComponentBase<"web", import('styled-components').FastOmit<import('react').DetailedHTMLProps<import('react').HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
|
|
23
|
+
export declare const Label: import('styled-components/dist/types').IStyledComponentBase<"web", import('styled-components').FastOmit<import('react').DetailedHTMLProps<import('react').HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, never>> & string;
|
|
24
|
+
export declare const ActionButton: import('styled-components/dist/types').IStyledComponentBase<"web", import('styled-components').FastOmit<Omit<ButtonProps & import('react').RefAttributes<HTMLButtonElement>, "ref"> & {
|
|
25
|
+
ref?: import('react').Ref<HTMLButtonElement>;
|
|
26
|
+
}, never>> & string & Omit<import('react').ForwardRefExoticComponent<ButtonProps & import('react').RefAttributes<HTMLButtonElement>>, keyof import('react').Component<any, {}, any>>;
|
|
27
|
+
export declare const EmptySection: import('styled-components/dist/types').IStyledComponentBase<"web", import('styled-components').FastOmit<import('react').DetailedHTMLProps<import('react').HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
|
|
28
|
+
export declare const Divider: import('styled-components/dist/types').IStyledComponentBase<"web", import('styled-components').FastOmit<import('react').DetailedHTMLProps<import('react').HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { default as React, ReactElement } from 'react';
|
|
2
|
-
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
2
|
+
export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
3
3
|
text?: string | ReactElement;
|
|
4
4
|
EndIcon?: ReactElement;
|
|
5
5
|
StartIcon?: ReactElement;
|
|
@@ -8,5 +8,5 @@ interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
|
8
8
|
variant?: 'default' | 'filled' | 'outlined';
|
|
9
9
|
children?: React.ReactNode;
|
|
10
10
|
}
|
|
11
|
-
declare const Button: React.
|
|
11
|
+
declare const Button: React.ForwardRefExoticComponent<ButtonProps & React.RefAttributes<HTMLButtonElement>>;
|
|
12
12
|
export default Button;
|
|
@@ -7,8 +7,8 @@ interface DateLabelProps {
|
|
|
7
7
|
};
|
|
8
8
|
}
|
|
9
9
|
export declare const StyledDateLabel: import('styled-components/dist/types').IStyledComponentBase<"web", import('styled-components/dist/types').Substitute<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {
|
|
10
|
-
primary?: string;
|
|
11
|
-
secondary?: string;
|
|
10
|
+
$primary?: string;
|
|
11
|
+
$secondary?: string;
|
|
12
12
|
}>> & string;
|
|
13
13
|
declare const DateLabel: React.FC<DateLabelProps>;
|
|
14
14
|
export default DateLabel;
|
|
@@ -10,7 +10,7 @@ export declare const MessagesScroll: import('styled-components/dist/types').ISty
|
|
|
10
10
|
export declare const MessagesList: import('styled-components/dist/types').IStyledComponentBase<"web", import('styled-components').FastOmit<import('react').DetailedHTMLProps<import('react').HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
|
|
11
11
|
export declare const MessageTimestamp: import('styled-components/dist/types').IStyledComponentBase<"web", import('styled-components').FastOmit<import('react').DetailedHTMLProps<import('react').HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
|
|
12
12
|
export declare const Message: import('styled-components/dist/types').IStyledComponentBase<"web", import('styled-components/dist/types').Substitute<import('react').DetailedHTMLProps<import('react').HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {
|
|
13
|
-
isUser: boolean;
|
|
13
|
+
$isUser: boolean;
|
|
14
14
|
}>> & string;
|
|
15
15
|
export declare const MessageText: import('styled-components/dist/types').IStyledComponentBase<"web", import('styled-components').FastOmit<import('react').DetailedHTMLProps<import('react').HTMLAttributes<HTMLParagraphElement>, HTMLParagraphElement>, never>> & string;
|
|
16
16
|
export declare const UserName: import('styled-components/dist/types').IStyledComponentBase<"web", import('styled-components').FastOmit<import('react').DetailedHTMLProps<import('react').HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, never>> & string;
|
|
@@ -18,18 +18,18 @@ export declare const InputContainer: import('styled-components/dist/types').ISty
|
|
|
18
18
|
export declare const MessageInput: import('styled-components/dist/types').IStyledComponentBase<"web", import('styled-components').FastOmit<import('react').DetailedHTMLProps<import('react').InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>, never>> & string;
|
|
19
19
|
export declare const SendButton: import('styled-components/dist/types').IStyledComponentBase<"web", import('styled-components').FastOmit<import('react').DetailedHTMLProps<import('react').ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, never>> & string;
|
|
20
20
|
export declare const CustomMessageContainer: import('styled-components/dist/types').IStyledComponentBase<"web", import('styled-components/dist/types').Substitute<import('react').DetailedHTMLProps<import('react').HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {
|
|
21
|
-
isUser: boolean;
|
|
22
|
-
reply: boolean;
|
|
23
|
-
reaction: boolean;
|
|
21
|
+
$isUser: boolean;
|
|
22
|
+
$reply: boolean;
|
|
23
|
+
$reaction: boolean;
|
|
24
24
|
}>> & string;
|
|
25
25
|
export declare const CustomMessageBubble: import('styled-components/dist/types').IStyledComponentBase<"web", import('styled-components/dist/types').Substitute<import('react').DetailedHTMLProps<import('react').HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {
|
|
26
|
-
isUser: boolean;
|
|
27
|
-
deleted: boolean;
|
|
26
|
+
$isUser: boolean;
|
|
27
|
+
$deleted: boolean;
|
|
28
28
|
}>> & string;
|
|
29
|
-
export declare const CustomMessageText: import('styled-components/dist/types').IStyledComponentBase<"web", import('styled-components').FastOmit<import('react').DetailedHTMLProps<import('react').HTMLAttributes<
|
|
29
|
+
export declare const CustomMessageText: import('styled-components/dist/types').IStyledComponentBase<"web", import('styled-components').FastOmit<import('react').DetailedHTMLProps<import('react').HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
|
|
30
30
|
export declare const CustomUserName: import('styled-components/dist/types').IStyledComponentBase<"web", import('styled-components/dist/types').Substitute<import('react').DetailedHTMLProps<import('react').HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, {
|
|
31
|
-
isUser: boolean;
|
|
32
|
-
color?: string;
|
|
31
|
+
$isUser: boolean;
|
|
32
|
+
$color?: string;
|
|
33
33
|
}>> & string;
|
|
34
34
|
export declare const CustomMessageTimestamp: import('styled-components/dist/types').IStyledComponentBase<"web", import('styled-components').FastOmit<import('react').DetailedHTMLProps<import('react').HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, never>> & string;
|
|
35
35
|
export declare const CustomMessagePhoto: import('styled-components/dist/types').IStyledComponentBase<"web", import('styled-components').FastOmit<import('react').DetailedHTMLProps<import('react').ImgHTMLAttributes<HTMLImageElement>, HTMLImageElement>, never>> & string;
|
|
@@ -38,7 +38,7 @@ export declare const CustomSystemMessage: import('styled-components/dist/types')
|
|
|
38
38
|
export declare const CustomSystemMessageText: import('styled-components/dist/types').IStyledComponentBase<"web", import('styled-components').FastOmit<import('react').DetailedHTMLProps<import('react').HTMLAttributes<HTMLParagraphElement>, HTMLParagraphElement>, never>> & string;
|
|
39
39
|
export declare const IconButton: import('styled-components/dist/types').IStyledComponentBase<"web", import('styled-components').FastOmit<import('react').DetailedHTMLProps<import('react').ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, never>> & string;
|
|
40
40
|
export declare const MessageFooter: import('styled-components/dist/types').IStyledComponentBase<"web", import('styled-components/dist/types').Substitute<import('react').DetailedHTMLProps<import('react').HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {
|
|
41
|
-
isUser: boolean;
|
|
41
|
+
$isUser: boolean;
|
|
42
42
|
}>> & string;
|
|
43
43
|
export declare const Line: import('styled-components/dist/types').IStyledComponentBase<"web", import('styled-components').FastOmit<import('react').DetailedHTMLProps<import('react').HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
|
|
44
44
|
export declare const StyledLoaderWrapper: import('styled-components/dist/types').IStyledComponentBase<"web", import('styled-components').FastOmit<import('react').DetailedHTMLProps<import('react').HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export declare const InputContainer: import('styled-components/dist/types').IStyledComponentBase<"web", import('styled-components').FastOmit<import('react').DetailedHTMLProps<import('react').HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
|
|
2
2
|
export declare const MessageInputContainer: import('styled-components/dist/types').IStyledComponentBase<"web", import('styled-components').FastOmit<import('react').DetailedHTMLProps<import('react').HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
|
|
3
3
|
export declare const MessageInput: import('styled-components/dist/types').IStyledComponentBase<"web", import('styled-components/dist/types').Substitute<import('react').DetailedHTMLProps<import('react').InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>, {
|
|
4
|
-
color?: string;
|
|
4
|
+
$color?: string;
|
|
5
5
|
}>> & string;
|
|
6
6
|
export declare const HiddenFileInput: import('styled-components/dist/types').IStyledComponentBase<"web", import('styled-components').FastOmit<import('react').DetailedHTMLProps<import('react').InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>, never>> & string;
|
|
7
7
|
export declare const Timer: import('styled-components/dist/types').IStyledComponentBase<"web", import('styled-components').FastOmit<import('react').DetailedHTMLProps<import('react').HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
|
|
@@ -13,11 +13,11 @@ export declare const ImagePreview: import('styled-components/dist/types').IStyle
|
|
|
13
13
|
export declare const VideoPreview: import('styled-components/dist/types').IStyledComponentBase<"web", import('styled-components').FastOmit<import('react').DetailedHTMLProps<import('react').VideoHTMLAttributes<HTMLVideoElement>, HTMLVideoElement>, never>> & string;
|
|
14
14
|
export declare const StyledInput: import('styled-components/dist/types').IStyledComponentBase<"web", import('styled-components').FastOmit<import('react').DetailedHTMLProps<import('react').InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>, never>> & string;
|
|
15
15
|
export declare const TextareaWrapper: import('styled-components/dist/types').IStyledComponentBase<"web", import('styled-components/dist/types').Substitute<import('react').DetailedHTMLProps<import('react').HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {
|
|
16
|
-
dynamicHeight?: number;
|
|
17
|
-
color?: string;
|
|
18
|
-
isFocused?: boolean;
|
|
16
|
+
$dynamicHeight?: number;
|
|
17
|
+
$color?: string;
|
|
18
|
+
$isFocused?: boolean;
|
|
19
19
|
}>> & string;
|
|
20
20
|
export declare const TextareaInput: import('styled-components/dist/types').IStyledComponentBase<"web", import('styled-components/dist/types').Substitute<import('react').DetailedHTMLProps<import('react').TextareaHTMLAttributes<HTMLTextAreaElement>, HTMLTextAreaElement>, {
|
|
21
|
-
dynamicHeight?: number;
|
|
22
|
-
color?: string;
|
|
21
|
+
$dynamicHeight?: number;
|
|
22
|
+
$color?: string;
|
|
23
23
|
}>> & string;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { default as React, ReactNode } from 'react';
|
|
2
|
+
import { IMessage } from '../types/models/message.model';
|
|
3
|
+
import { IConfig } from '../types/types';
|
|
4
|
+
interface MessageNotificationContextType {
|
|
5
|
+
showMessageNotification: (message: IMessage, roomName: string, senderName: string, roomJID: string) => void;
|
|
6
|
+
}
|
|
7
|
+
export declare const MessageNotificationProvider: React.FC<{
|
|
8
|
+
children: ReactNode;
|
|
9
|
+
config?: IConfig;
|
|
10
|
+
}>;
|
|
11
|
+
export declare const useMessageNotification: () => MessageNotificationContextType;
|
|
12
|
+
export {};
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
import { FirebaseApp } from 'firebase/app';
|
|
2
|
+
import { Messaging } from 'firebase/messaging';
|
|
3
|
+
export declare const defaultConfig: {
|
|
2
4
|
apiKey: any;
|
|
3
5
|
authDomain: any;
|
|
4
6
|
projectId: any;
|
|
@@ -6,4 +8,6 @@ export declare const config: {
|
|
|
6
8
|
messagingSenderId: any;
|
|
7
9
|
appId: any;
|
|
8
10
|
};
|
|
9
|
-
export declare const
|
|
11
|
+
export declare const getFirebaseMessaging: (customConfig?: any) => Messaging | null;
|
|
12
|
+
export declare const app: FirebaseApp;
|
|
13
|
+
export declare const messaging: Messaging;
|
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
/* ============================================================
|
|
2
|
+
* Unified Service Worker
|
|
3
|
+
* Handles BOTH Firebase Cloud Messaging (FCM) background pushes
|
|
4
|
+
* AND generic Web Push API events, so all push notifications
|
|
5
|
+
* are captured regardless of origin.
|
|
6
|
+
* ============================================================ */
|
|
7
|
+
|
|
8
|
+
// ── Firebase SDK ──────────────────────────────────────────────
|
|
9
|
+
importScripts('https://www.gstatic.com/firebasejs/10.12.0/firebase-app-compat.js');
|
|
10
|
+
importScripts('https://www.gstatic.com/firebasejs/10.12.0/firebase-messaging-compat.js');
|
|
11
|
+
|
|
12
|
+
// ── Dynamic Configuration ─────────────────────────────────────
|
|
13
|
+
const params = new URL(self.location).searchParams;
|
|
14
|
+
const firebaseConfig = {
|
|
15
|
+
apiKey: params.get('apiKey'),
|
|
16
|
+
authDomain: params.get('authDomain'),
|
|
17
|
+
projectId: params.get('projectId'),
|
|
18
|
+
storageBucket: params.get('storageBucket'),
|
|
19
|
+
messagingSenderId: params.get('messagingSenderId'),
|
|
20
|
+
appId: params.get('appId'),
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
// Only initialize if we have at least apiKey and appId
|
|
24
|
+
if (firebaseConfig.apiKey && firebaseConfig.appId) {
|
|
25
|
+
firebase.initializeApp(firebaseConfig);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const messaging = firebase.messaging();
|
|
29
|
+
const APP_URL = self.location.origin;
|
|
30
|
+
|
|
31
|
+
// ── Deduplication ─────────────────────────────────────────────
|
|
32
|
+
// Track message IDs handled by FCM so the generic `push` listener
|
|
33
|
+
// can skip them and avoid duplicate notifications.
|
|
34
|
+
const _handledByFcm = new Set();
|
|
35
|
+
const DEDUP_TTL_MS = 60_000; // auto-cleanup after 60 s
|
|
36
|
+
|
|
37
|
+
function markHandledByFcm(id) {
|
|
38
|
+
if (!id) return;
|
|
39
|
+
_handledByFcm.add(id);
|
|
40
|
+
console.log('[SW] FCM message marked as handled:', id);
|
|
41
|
+
setTimeout(() => _handledByFcm.delete(id), DEDUP_TTL_MS);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function wasHandledByFcm(id) {
|
|
45
|
+
return id ? _handledByFcm.has(id) : false;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// ── Shared Helpers ────────────────────────────────────────────
|
|
49
|
+
function isSystemPayload(data) {
|
|
50
|
+
return !data?.msgID && !data?.jid && !!data?.userJid;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function buildTargetUrl(data, notification, fallbackUrl) {
|
|
54
|
+
if (fallbackUrl && String(fallbackUrl).startsWith('http')) return fallbackUrl;
|
|
55
|
+
|
|
56
|
+
const title = notification?.title || data?.title || '';
|
|
57
|
+
if (title.startsWith('http')) return title;
|
|
58
|
+
|
|
59
|
+
if (isSystemPayload(data)) return APP_URL;
|
|
60
|
+
if (!data?.jid) return APP_URL;
|
|
61
|
+
const chatId = String(data.jid).split('@')[0];
|
|
62
|
+
return `${APP_URL}/chat?chatId=${encodeURIComponent(chatId)}`;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function postBridgeToClients(windowClients, bridgePayload) {
|
|
66
|
+
windowClients.forEach((client) => {
|
|
67
|
+
client.postMessage({
|
|
68
|
+
type: 'PUSH_FOREGROUND_BRIDGE',
|
|
69
|
+
payload: bridgePayload,
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function isAnyClientVisible(windowClients) {
|
|
75
|
+
return windowClients.some((c) => c.visibilityState === 'visible');
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// ── 1. FCM Background Messages ───────────────────────────────
|
|
79
|
+
// This fires for pushes delivered through Firebase Cloud Messaging
|
|
80
|
+
// when no foreground tab is handling them via onMessage().
|
|
81
|
+
messaging.onBackgroundMessage((payload) => {
|
|
82
|
+
console.log('[SW] FCM onBackgroundMessage received', payload);
|
|
83
|
+
|
|
84
|
+
const data = payload.data || {};
|
|
85
|
+
const notification = payload.notification || {};
|
|
86
|
+
const messageId = payload.messageId || data.msgID || null;
|
|
87
|
+
|
|
88
|
+
// Mark so the generic push handler skips this one
|
|
89
|
+
markHandledByFcm(messageId);
|
|
90
|
+
|
|
91
|
+
const isSystem = isSystemPayload(data);
|
|
92
|
+
const title =
|
|
93
|
+
(isSystem ? 'System' : undefined) ||
|
|
94
|
+
notification.title ||
|
|
95
|
+
data.title ||
|
|
96
|
+
'New Message';
|
|
97
|
+
const body =
|
|
98
|
+
notification.body || data.body || 'You have a new message.';
|
|
99
|
+
const url = buildTargetUrl(data, notification, data.url);
|
|
100
|
+
|
|
101
|
+
const bridgePayload = {
|
|
102
|
+
messageId,
|
|
103
|
+
notification: { title, body, image: notification.image || '/favicon.ico' },
|
|
104
|
+
data: {
|
|
105
|
+
...data,
|
|
106
|
+
jid: data.jid || '',
|
|
107
|
+
userJid: data.userJid || '',
|
|
108
|
+
msgID: data.msgID || '',
|
|
109
|
+
workspaceId: data.workspaceId || data.workspace_id || '',
|
|
110
|
+
},
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
const options = {
|
|
114
|
+
body,
|
|
115
|
+
icon: notification.image || '/favicon.ico',
|
|
116
|
+
badge: '/favicon.ico',
|
|
117
|
+
tag: data.tag || 'ethora-notification',
|
|
118
|
+
data: {
|
|
119
|
+
url,
|
|
120
|
+
roomJid: data.jid || null,
|
|
121
|
+
senderId: data.userJid || null,
|
|
122
|
+
messageId,
|
|
123
|
+
workspaceId: data.workspaceId || data.workspace_id || null,
|
|
124
|
+
},
|
|
125
|
+
requireInteraction: false,
|
|
126
|
+
silent: false,
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
return clients
|
|
130
|
+
.matchAll({ type: 'window', includeUncontrolled: true })
|
|
131
|
+
.then((windowClients) => {
|
|
132
|
+
postBridgeToClients(windowClients, bridgePayload);
|
|
133
|
+
|
|
134
|
+
if (!isAnyClientVisible(windowClients)) {
|
|
135
|
+
console.log(
|
|
136
|
+
`[NotifyPolicy] source=fcm_bg action=show reason=${isSystem ? 'system' : 'background'} msgId=${messageId || ''}`
|
|
137
|
+
);
|
|
138
|
+
return self.registration.showNotification(title, options);
|
|
139
|
+
} else {
|
|
140
|
+
console.log(
|
|
141
|
+
`[NotifyPolicy] source=fcm_bg action=skip reason=tab_visible msgId=${messageId || ''}`
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
// ── 2. Generic Web Push API ───────────────────────────────────
|
|
148
|
+
// This fires for ANY push delivered via the Web Push protocol,
|
|
149
|
+
// including direct backend pushes for XMPP messages that are
|
|
150
|
+
// NOT routed through FCM.
|
|
151
|
+
self.addEventListener('push', (event) => {
|
|
152
|
+
console.log('[SW] Generic push event received');
|
|
153
|
+
|
|
154
|
+
let raw = {};
|
|
155
|
+
try {
|
|
156
|
+
if (event.data) {
|
|
157
|
+
raw = event.data.json();
|
|
158
|
+
}
|
|
159
|
+
} catch (err) {
|
|
160
|
+
console.warn('[SW] Failed to parse push payload as JSON:', err);
|
|
161
|
+
raw = { title: 'New message', body: event.data ? event.data.text() : '' };
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const notification = raw.notification || {};
|
|
165
|
+
const payloadData = raw.data || {};
|
|
166
|
+
const messageId = raw.messageId || payloadData.msgID || null;
|
|
167
|
+
|
|
168
|
+
// Skip if FCM already handled this exact message
|
|
169
|
+
if (wasHandledByFcm(messageId)) {
|
|
170
|
+
console.log(`[SW] push event skipped – already handled by FCM (msgId=${messageId})`);
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
const isSystem = isSystemPayload(payloadData);
|
|
175
|
+
const title =
|
|
176
|
+
(isSystem ? 'System' : undefined) ||
|
|
177
|
+
notification.title ||
|
|
178
|
+
raw.title ||
|
|
179
|
+
'Ethora Chat';
|
|
180
|
+
const body =
|
|
181
|
+
notification.body ||
|
|
182
|
+
raw.body ||
|
|
183
|
+
raw.message ||
|
|
184
|
+
payloadData.body ||
|
|
185
|
+
'You have a new message.';
|
|
186
|
+
const url = buildTargetUrl(
|
|
187
|
+
payloadData,
|
|
188
|
+
notification,
|
|
189
|
+
raw.url || raw.clickAction
|
|
190
|
+
);
|
|
191
|
+
|
|
192
|
+
const bridgePayload = {
|
|
193
|
+
messageId,
|
|
194
|
+
notification: {
|
|
195
|
+
title,
|
|
196
|
+
body,
|
|
197
|
+
image: raw.icon || '/favicon.ico',
|
|
198
|
+
},
|
|
199
|
+
data: {
|
|
200
|
+
...payloadData,
|
|
201
|
+
jid: raw.roomJid || payloadData.jid || '',
|
|
202
|
+
userJid: raw.senderId || payloadData.userJid || '',
|
|
203
|
+
msgID: messageId || '',
|
|
204
|
+
workspaceId: raw.workspaceId || payloadData.workspaceId || payloadData.workspace_id || '',
|
|
205
|
+
},
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
const options = {
|
|
209
|
+
body,
|
|
210
|
+
icon: raw.icon || '/favicon.ico',
|
|
211
|
+
badge: raw.badge || '/favicon.ico',
|
|
212
|
+
tag: raw.tag || 'ethora-notification',
|
|
213
|
+
data: {
|
|
214
|
+
url,
|
|
215
|
+
roomJid: raw.roomJid || payloadData.jid || null,
|
|
216
|
+
senderId: raw.senderId || payloadData.userJid || null,
|
|
217
|
+
messageId,
|
|
218
|
+
workspaceId: raw.workspaceId || payloadData.workspaceId || payloadData.workspace_id || null,
|
|
219
|
+
},
|
|
220
|
+
requireInteraction: false,
|
|
221
|
+
silent: false,
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
event.waitUntil(
|
|
225
|
+
clients
|
|
226
|
+
.matchAll({ type: 'window', includeUncontrolled: true })
|
|
227
|
+
.then((windowClients) => {
|
|
228
|
+
postBridgeToClients(windowClients, bridgePayload);
|
|
229
|
+
|
|
230
|
+
if (!isAnyClientVisible(windowClients)) {
|
|
231
|
+
console.log(
|
|
232
|
+
`[NotifyPolicy] source=push_bg action=show reason=${isSystem ? 'system' : 'background'} msgId=${messageId || ''}`
|
|
233
|
+
);
|
|
234
|
+
return self.registration.showNotification(title, options);
|
|
235
|
+
} else {
|
|
236
|
+
console.log(
|
|
237
|
+
`[NotifyPolicy] source=push_bg action=skip reason=tab_visible msgId=${messageId || ''}`
|
|
238
|
+
);
|
|
239
|
+
}
|
|
240
|
+
})
|
|
241
|
+
);
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
// ── 3. Notification Click ─────────────────────────────────────
|
|
245
|
+
self.addEventListener('notificationclick', (event) => {
|
|
246
|
+
console.log('[NotifyPolicy] source=push_bg action=click_start');
|
|
247
|
+
event.notification.close();
|
|
248
|
+
|
|
249
|
+
const targetUrl =
|
|
250
|
+
(event.notification.data && event.notification.data.url) || APP_URL;
|
|
251
|
+
console.log('[NotifyPolicy] source=push_bg action=click_url', {
|
|
252
|
+
url: targetUrl,
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
async function handleClick() {
|
|
256
|
+
try {
|
|
257
|
+
const windowClients = await clients.matchAll({
|
|
258
|
+
type: 'window',
|
|
259
|
+
includeUncontrolled: true,
|
|
260
|
+
});
|
|
261
|
+
console.log('[NotifyPolicy] source=push_bg action=clients_found', {
|
|
262
|
+
count: windowClients.length,
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
// 1. Try to find an exactly matching URL
|
|
266
|
+
for (const client of windowClients) {
|
|
267
|
+
if (client.url === targetUrl && 'focus' in client) {
|
|
268
|
+
console.log('[NotifyPolicy] source=push_bg action=focus_exact', {
|
|
269
|
+
url: client.url,
|
|
270
|
+
});
|
|
271
|
+
return client.focus();
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// 2. Try to find any client on our origin, focus it, and navigate
|
|
276
|
+
for (const client of windowClients) {
|
|
277
|
+
try {
|
|
278
|
+
const clientOrigin = new URL(client.url).origin;
|
|
279
|
+
const swOrigin = self.location.origin;
|
|
280
|
+
if (clientOrigin === swOrigin && 'focus' in client) {
|
|
281
|
+
console.log(
|
|
282
|
+
'[NotifyPolicy] source=push_bg action=focus_and_navigate',
|
|
283
|
+
{ from: client.url, to: targetUrl }
|
|
284
|
+
);
|
|
285
|
+
const focusedClient = await client.focus();
|
|
286
|
+
if (focusedClient && 'navigate' in focusedClient) {
|
|
287
|
+
return focusedClient.navigate(targetUrl);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
} catch (e) {
|
|
291
|
+
// Ignore invalid URLs
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// 3. Fallback: Open a new window
|
|
296
|
+
if (clients.openWindow) {
|
|
297
|
+
console.log('[NotifyPolicy] source=push_bg action=open_new_window', {
|
|
298
|
+
url: targetUrl,
|
|
299
|
+
});
|
|
300
|
+
return clients.openWindow(targetUrl);
|
|
301
|
+
}
|
|
302
|
+
} catch (err) {
|
|
303
|
+
console.error('[NotifyPolicy] source=push_bg action=click_error', err);
|
|
304
|
+
if (clients.openWindow) {
|
|
305
|
+
return clients.openWindow(targetUrl);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
event.waitUntil(handleClick());
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
// ── 4. Push Subscription Change ───────────────────────────────
|
|
314
|
+
// Fired when the browser automatically re-creates a subscription
|
|
315
|
+
// (e.g. after expiry). Notify clients so they can re-register.
|
|
316
|
+
self.addEventListener('pushsubscriptionchange', (event) => {
|
|
317
|
+
console.log('[SW] Push subscription changed – re-subscribing');
|
|
318
|
+
|
|
319
|
+
event.waitUntil(
|
|
320
|
+
self.registration.pushManager
|
|
321
|
+
.subscribe({ userVisibleOnly: true })
|
|
322
|
+
.then((subscription) => {
|
|
323
|
+
console.log(
|
|
324
|
+
'[SW] New subscription obtained:',
|
|
325
|
+
subscription.endpoint
|
|
326
|
+
);
|
|
327
|
+
return clients.matchAll().then((allClients) => {
|
|
328
|
+
allClients.forEach((client) => {
|
|
329
|
+
client.postMessage({
|
|
330
|
+
type: 'PUSH_SUBSCRIPTION_CHANGED',
|
|
331
|
+
subscription: subscription.toJSON(),
|
|
332
|
+
});
|
|
333
|
+
});
|
|
334
|
+
});
|
|
335
|
+
})
|
|
336
|
+
.catch((err) => {
|
|
337
|
+
console.error('[SW] pushsubscriptionchange – failed to re-subscribe:', err);
|
|
338
|
+
})
|
|
339
|
+
);
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
// ── 5. Lifecycle ──────────────────────────────────────────────
|
|
343
|
+
self.addEventListener('activate', (event) => {
|
|
344
|
+
console.log('[SW] Service worker activated');
|
|
345
|
+
event.waitUntil(clients.claim());
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
self.addEventListener('install', () => {
|
|
349
|
+
console.log('[SW] Service worker installed');
|
|
350
|
+
self.skipWaiting();
|
|
351
|
+
});
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hook to enable in-app notifications globally
|
|
3
|
+
* Call this hook in your app root or XMPP provider to enable notifications
|
|
4
|
+
* even when the chat component isn't mounted
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```tsx
|
|
8
|
+
* import { useInAppNotifications } from '@ethora/chat-component';
|
|
9
|
+
*
|
|
10
|
+
* function App() {
|
|
11
|
+
* useInAppNotifications();
|
|
12
|
+
* return <YourApp />;
|
|
13
|
+
* }
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
export declare const useInAppNotifications: () => {
|
|
17
|
+
navigateToMessage: (roomJID: string, messageId: string) => void;
|
|
18
|
+
};
|