react-notify-sdk 1.0.61 → 1.0.63
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/dist/FadeWrapper.d.ts
CHANGED
package/dist/FeatureMessage.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { FeatureMessages } from './types';
|
|
2
2
|
interface FeatureMessageProps {
|
|
3
|
-
message: FeatureMessages;
|
|
3
|
+
message: FeatureMessages | null;
|
|
4
4
|
onDismiss?: (id: string) => void;
|
|
5
5
|
}
|
|
6
6
|
declare const FeatureMessage: ({ message, onDismiss }: FeatureMessageProps) => import("react/jsx-runtime").JSX.Element;
|
package/dist/FeatureMessage.js
CHANGED
|
@@ -31,16 +31,16 @@ const FeatureMessage = ({ message, onDismiss }) => {
|
|
|
31
31
|
if (e.target.closest('[data-dismiss-button]')) {
|
|
32
32
|
return;
|
|
33
33
|
}
|
|
34
|
-
const action = message
|
|
34
|
+
const action = message?.click_action || 'none';
|
|
35
35
|
// Perform the action
|
|
36
36
|
switch (action) {
|
|
37
37
|
case 'navigate':
|
|
38
|
-
if (message
|
|
39
|
-
spaNavigate(message
|
|
38
|
+
if (message?.click_url) {
|
|
39
|
+
spaNavigate(message?.click_url);
|
|
40
40
|
}
|
|
41
41
|
break;
|
|
42
42
|
case 'external':
|
|
43
|
-
if (message
|
|
43
|
+
if (message?.click_url) {
|
|
44
44
|
window.open(message.click_url, '_blank', 'noopener,noreferrer');
|
|
45
45
|
}
|
|
46
46
|
break;
|
|
@@ -54,7 +54,7 @@ const FeatureMessage = ({ message, onDismiss }) => {
|
|
|
54
54
|
};
|
|
55
55
|
const handleDismiss = () => {
|
|
56
56
|
if (onDismiss) {
|
|
57
|
-
onDismiss(message.id);
|
|
57
|
+
onDismiss(message?.id ? message.id : '');
|
|
58
58
|
}
|
|
59
59
|
};
|
|
60
60
|
const filterButton = (type) => {
|
|
@@ -85,8 +85,8 @@ const FeatureMessage = ({ message, onDismiss }) => {
|
|
|
85
85
|
borderRadius: "0.5rem", // rounded-lg
|
|
86
86
|
backgroundColor: message?.backgroundColor,
|
|
87
87
|
borderWidth: "1px",
|
|
88
|
-
borderColor: hexToRgba(message?.borderColor, 0.3),
|
|
89
|
-
boxShadow: `0 10px 15px -3px ${hexToRgba(message
|
|
88
|
+
borderColor: hexToRgba(message?.borderColor ? message?.borderColor : '', 0.3),
|
|
89
|
+
boxShadow: `0 10px 15px -3px ${hexToRgba(message?.borderColor ? message?.borderColor : '', 0.4)}, 0 4px 6px -4px ${hexToRgba(message?.borderColor ? message?.borderColor : '', 0.4)}`
|
|
90
90
|
}, children: [_jsxs("div", { style: {
|
|
91
91
|
width: message?.click_action === "view only" ? "100%" : "80%", // w-4/5
|
|
92
92
|
height: "100%", // h-full
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { FeatureMessageProviderProps } from './types';
|
|
2
|
-
export declare const FeatureMessageProvider: ({ projectKey, }: FeatureMessageProviderProps) => import("react/jsx-runtime").JSX.Element
|
|
2
|
+
export declare const FeatureMessageProvider: ({ projectKey, }: FeatureMessageProviderProps) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -6,8 +6,8 @@ import { getSupabaseClient } from './supabase/supabaseClient';
|
|
|
6
6
|
import useDeviceDetection from './useDeviceDetection';
|
|
7
7
|
import FadeWrapper from './FadeWrapper';
|
|
8
8
|
// Wildcard route matching utility
|
|
9
|
-
const routeMatches = (pattern, path
|
|
10
|
-
if (pattern === path
|
|
9
|
+
const routeMatches = (pattern, path) => {
|
|
10
|
+
if (pattern === path)
|
|
11
11
|
return true;
|
|
12
12
|
const escapeRegex = (str) => str.replace(/([.+^=!:${}()|[\]/\\])/g, "\\$1");
|
|
13
13
|
const regexPattern = "^" + pattern.split("*").map(escapeRegex).join(".*") + "$";
|
|
@@ -18,8 +18,16 @@ const routeMatches = (pattern, path, baseUrl) => {
|
|
|
18
18
|
return false;
|
|
19
19
|
}
|
|
20
20
|
};
|
|
21
|
+
const baseUrlMatches = (msgBaseUrl) => {
|
|
22
|
+
if (!msgBaseUrl)
|
|
23
|
+
return true; // backward compatibility
|
|
24
|
+
if (typeof window === "undefined")
|
|
25
|
+
return false;
|
|
26
|
+
return msgBaseUrl === window.location.origin;
|
|
27
|
+
};
|
|
21
28
|
export const FeatureMessageProvider = ({ projectKey, }) => {
|
|
22
29
|
const [message, setMessage] = useState(null);
|
|
30
|
+
const [messages, setMessages] = useState([]);
|
|
23
31
|
const [visible, setVisible] = useState(false);
|
|
24
32
|
const [pathname, setPathname] = useState(() => typeof window !== 'undefined' ? window.location.pathname : '');
|
|
25
33
|
const device = useDeviceDetection();
|
|
@@ -48,11 +56,11 @@ export const FeatureMessageProvider = ({ projectKey, }) => {
|
|
|
48
56
|
setVisible(false);
|
|
49
57
|
};
|
|
50
58
|
const isDismissed = (message) => {
|
|
51
|
-
const dismissed = getDismissedMessages()[message
|
|
59
|
+
const dismissed = getDismissedMessages()[message?.id];
|
|
52
60
|
if (!dismissed)
|
|
53
61
|
return false;
|
|
54
62
|
// Re-show if message changed
|
|
55
|
-
return dismissed.messageUpdatedAt === message
|
|
63
|
+
return dismissed.messageUpdatedAt === message?.updated_at;
|
|
56
64
|
};
|
|
57
65
|
// Create supabase client with project key header
|
|
58
66
|
const supabaseClient = getSupabaseClient(projectKey);
|
|
@@ -87,54 +95,67 @@ export const FeatureMessageProvider = ({ projectKey, }) => {
|
|
|
87
95
|
if (typeof window === 'undefined')
|
|
88
96
|
return; // Skip on server
|
|
89
97
|
let fadeOutTimer = null; // Track the timer
|
|
90
|
-
const
|
|
98
|
+
const origin = window.location.origin;
|
|
99
|
+
// 🔹 1. Fetch ALL active messages once per project
|
|
100
|
+
const fetchMessages = async () => {
|
|
91
101
|
const { data } = await supabaseClient
|
|
92
|
-
.from(
|
|
93
|
-
.select(
|
|
94
|
-
.eq(
|
|
95
|
-
.eq(
|
|
96
|
-
.
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
const match = data?.find((msg) => routeMatches(msg.route, pathname, msg.base_url));
|
|
100
|
-
if (match && !isDismissed(match)) {
|
|
101
|
-
if (fadeOutTimer)
|
|
102
|
-
clearTimeout(fadeOutTimer); // Clear any pending timeout
|
|
103
|
-
setMessage(match);
|
|
104
|
-
setVisible(true); // Fade in
|
|
105
|
-
}
|
|
106
|
-
else {
|
|
107
|
-
// Trigger fade out before removing message
|
|
108
|
-
fadeOutTimer = setTimeout(() => setMessage(null), 300);
|
|
109
|
-
setVisible(false);
|
|
102
|
+
.from("feature_messages")
|
|
103
|
+
.select("*")
|
|
104
|
+
.eq("project_key", projectKey)
|
|
105
|
+
.eq("is_active", true)
|
|
106
|
+
.order("created_at", { ascending: false });
|
|
107
|
+
if (data) {
|
|
108
|
+
setMessages(data);
|
|
110
109
|
}
|
|
111
110
|
};
|
|
112
|
-
|
|
111
|
+
fetchMessages();
|
|
112
|
+
// 🔹 2. Subscribe ONCE per project
|
|
113
113
|
const subscription = supabaseClient
|
|
114
|
-
.channel(
|
|
115
|
-
.on(
|
|
116
|
-
event: '*',
|
|
117
|
-
schema: 'public',
|
|
118
|
-
table: 'feature_messages',
|
|
119
|
-
}, (payload) => {
|
|
114
|
+
.channel("feature_messages_channel")
|
|
115
|
+
.on("postgres_changes", { event: "*", schema: "public", table: "feature_messages" }, (payload) => {
|
|
120
116
|
const msg = payload.new;
|
|
121
|
-
if (msg.project_key
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
}
|
|
117
|
+
if (msg.project_key !== projectKey)
|
|
118
|
+
return;
|
|
119
|
+
setMessages((prev) => {
|
|
120
|
+
const filtered = prev.filter((m) => m.id !== msg.id);
|
|
121
|
+
if (msg.is_active) {
|
|
122
|
+
return [msg, ...filtered];
|
|
123
|
+
}
|
|
124
|
+
return filtered;
|
|
125
|
+
});
|
|
131
126
|
})
|
|
132
127
|
.subscribe();
|
|
133
128
|
return () => {
|
|
129
|
+
if (fadeOutTimer)
|
|
130
|
+
clearTimeout(fadeOutTimer);
|
|
134
131
|
supabaseClient.removeChannel(subscription);
|
|
135
132
|
};
|
|
136
|
-
}, [
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
133
|
+
}, [projectKey]);
|
|
134
|
+
useEffect(() => {
|
|
135
|
+
if (!pathname || !messages.length)
|
|
136
|
+
return;
|
|
137
|
+
let fadeOutTimer = null;
|
|
138
|
+
const origin = typeof window !== "undefined" ? window.location.origin : "";
|
|
139
|
+
const match = messages.find((msg) => routeMatches(msg.route, pathname) &&
|
|
140
|
+
baseUrlMatches(msg.base_url) &&
|
|
141
|
+
!isDismissed(msg));
|
|
142
|
+
if (match) {
|
|
143
|
+
if (fadeOutTimer)
|
|
144
|
+
clearTimeout(fadeOutTimer);
|
|
145
|
+
setMessage(match);
|
|
146
|
+
setVisible(true);
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
setVisible(false);
|
|
150
|
+
fadeOutTimer = setTimeout(() => setMessage(null), 300);
|
|
151
|
+
}
|
|
152
|
+
return () => {
|
|
153
|
+
if (fadeOutTimer)
|
|
154
|
+
clearTimeout(fadeOutTimer);
|
|
155
|
+
};
|
|
156
|
+
}, [pathname, messages]);
|
|
157
|
+
return (_jsx(FadeWrapper, { visible: visible, device: device, message: message, children: _jsx(FeatureMessage, { message: message, onDismiss: () => {
|
|
158
|
+
if (message)
|
|
159
|
+
dismissMessage(message);
|
|
160
|
+
} }) }));
|
|
140
161
|
};
|