react-notify-sdk 1.0.63 → 1.0.65
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/FeatureMessageProvider.js +72 -37
- package/package.json +1 -1
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
// src/FeatureMessageProvider.tsx
|
|
3
|
-
import { useEffect, useState } from 'react';
|
|
3
|
+
import { useEffect, useState, useRef } from 'react';
|
|
4
4
|
import FeatureMessage from './FeatureMessage';
|
|
5
|
-
import { getSupabaseClient } from './supabase/supabaseClient';
|
|
6
5
|
import useDeviceDetection from './useDeviceDetection';
|
|
7
6
|
import FadeWrapper from './FadeWrapper';
|
|
8
7
|
// Wildcard route matching utility
|
|
@@ -26,12 +25,17 @@ const baseUrlMatches = (msgBaseUrl) => {
|
|
|
26
25
|
return msgBaseUrl === window.location.origin;
|
|
27
26
|
};
|
|
28
27
|
export const FeatureMessageProvider = ({ projectKey, }) => {
|
|
28
|
+
const TTL = 30000; // 30 seconds
|
|
29
|
+
// Route-level cache (module scoped, persists across re-renders)
|
|
30
|
+
const routeCache = {};
|
|
29
31
|
const [message, setMessage] = useState(null);
|
|
30
32
|
const [messages, setMessages] = useState([]);
|
|
31
33
|
const [visible, setVisible] = useState(false);
|
|
32
34
|
const [pathname, setPathname] = useState(() => typeof window !== 'undefined' ? window.location.pathname : '');
|
|
33
35
|
const device = useDeviceDetection();
|
|
34
|
-
//
|
|
36
|
+
// 🔹 Persist version across renders
|
|
37
|
+
const versionRef = useRef(0);
|
|
38
|
+
const intervalRef = useRef(null);
|
|
35
39
|
//Dismissed message cached retrieval
|
|
36
40
|
const DISMISSED_KEY = "__feature_messages_dismissed__";
|
|
37
41
|
const getDismissedMessages = () => {
|
|
@@ -62,9 +66,9 @@ export const FeatureMessageProvider = ({ projectKey, }) => {
|
|
|
62
66
|
// Re-show if message changed
|
|
63
67
|
return dismissed.messageUpdatedAt === message?.updated_at;
|
|
64
68
|
};
|
|
65
|
-
//
|
|
66
|
-
|
|
67
|
-
//
|
|
69
|
+
// --------------------------------------------
|
|
70
|
+
// PATHNAME TRACKING
|
|
71
|
+
// --------------------------------------------
|
|
68
72
|
useEffect(() => {
|
|
69
73
|
if (typeof window === 'undefined')
|
|
70
74
|
return;
|
|
@@ -90,47 +94,78 @@ export const FeatureMessageProvider = ({ projectKey, }) => {
|
|
|
90
94
|
window.history.replaceState = originalReplaceState;
|
|
91
95
|
};
|
|
92
96
|
}, []);
|
|
97
|
+
// --------------------------------------------
|
|
98
|
+
// FETCH + VERSION DIFF POLLING
|
|
99
|
+
// --------------------------------------------
|
|
93
100
|
// Your main effect - now uses the reactive pathname state
|
|
94
101
|
useEffect(() => {
|
|
95
102
|
if (typeof window === 'undefined')
|
|
96
103
|
return; // Skip on server
|
|
97
|
-
let fadeOutTimer = null; // Track the timer
|
|
98
104
|
const origin = window.location.origin;
|
|
105
|
+
const cacheKey = `${projectKey}_${pathname}`;
|
|
106
|
+
// Track current version per route
|
|
107
|
+
//const versionRef = { current: 0 };
|
|
99
108
|
// 🔹 1. Fetch ALL active messages once per project
|
|
100
|
-
const fetchMessages = async () => {
|
|
101
|
-
const
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
};
|
|
111
|
-
fetchMessages();
|
|
112
|
-
// 🔹 2. Subscribe ONCE per project
|
|
113
|
-
const subscription = supabaseClient
|
|
114
|
-
.channel("feature_messages_channel")
|
|
115
|
-
.on("postgres_changes", { event: "*", schema: "public", table: "feature_messages" }, (payload) => {
|
|
116
|
-
const msg = payload.new;
|
|
117
|
-
if (msg.project_key !== projectKey)
|
|
109
|
+
const fetchMessages = async (force = false) => {
|
|
110
|
+
const now = Date.now();
|
|
111
|
+
const cacheKey = `${projectKey}_${pathname}`;
|
|
112
|
+
const cached = routeCache[cacheKey];
|
|
113
|
+
// ✅ TTL cache check
|
|
114
|
+
if (!force &&
|
|
115
|
+
cached &&
|
|
116
|
+
now - cached.timestamp < TTL) {
|
|
117
|
+
versionRef.current = cached.version;
|
|
118
|
+
setMessages(cached.data);
|
|
118
119
|
return;
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
120
|
+
}
|
|
121
|
+
try {
|
|
122
|
+
const response = await fetch("https://dhgnstjrkeuqnsapwcec.functions.supabase.co/get-feature-message", {
|
|
123
|
+
method: "POST",
|
|
124
|
+
headers: {
|
|
125
|
+
"Content-Type": "application/json",
|
|
126
|
+
},
|
|
127
|
+
body: JSON.stringify({
|
|
128
|
+
projectKey,
|
|
129
|
+
pathname: pathname,
|
|
130
|
+
origin: origin,
|
|
131
|
+
version: versionRef.current, // 🔥 Send current version
|
|
132
|
+
}),
|
|
133
|
+
});
|
|
134
|
+
if (!response.ok)
|
|
135
|
+
return null;
|
|
136
|
+
const data = await response.json();
|
|
137
|
+
// 🔁 No changes — just bump timestamp
|
|
138
|
+
if (data.unchanged && cached) {
|
|
139
|
+
routeCache[cacheKey].timestamp = Date.now();
|
|
140
|
+
return;
|
|
123
141
|
}
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
142
|
+
versionRef.current = data.version;
|
|
143
|
+
routeCache[cacheKey] = {
|
|
144
|
+
data: data.messages,
|
|
145
|
+
version: data.version,
|
|
146
|
+
timestamp: Date.now(),
|
|
147
|
+
};
|
|
148
|
+
setMessages(data.messages);
|
|
149
|
+
}
|
|
150
|
+
catch (error) {
|
|
151
|
+
console.error("Failed to fetch feature messages:", error);
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
fetchMessages(true);
|
|
155
|
+
// 🔄 Poll every 30 seconds
|
|
156
|
+
intervalRef.current = setInterval(() => {
|
|
157
|
+
fetchMessages(false);
|
|
158
|
+
}, TTL);
|
|
128
159
|
return () => {
|
|
129
|
-
if (
|
|
130
|
-
|
|
131
|
-
|
|
160
|
+
if (intervalRef.current) {
|
|
161
|
+
clearInterval(intervalRef.current);
|
|
162
|
+
}
|
|
132
163
|
};
|
|
133
|
-
}, [projectKey]);
|
|
164
|
+
}, [projectKey, pathname]);
|
|
165
|
+
// --------------------------------------------
|
|
166
|
+
// MATCH ROUTE → SHOW MESSAGE
|
|
167
|
+
// --------------------------------------------
|
|
168
|
+
// Effect to determine which message to show based on current pathname and messages
|
|
134
169
|
useEffect(() => {
|
|
135
170
|
if (!pathname || !messages.length)
|
|
136
171
|
return;
|