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.
@@ -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
- //Dismiss message caching
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
- // Create supabase client with project key header
66
- const supabaseClient = getSupabaseClient(projectKey);
67
- // Effect to track pathname changes
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 { data } = await supabaseClient
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);
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
- setMessages((prev) => {
120
- const filtered = prev.filter((m) => m.id !== msg.id);
121
- if (msg.is_active) {
122
- return [msg, ...filtered];
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
- return filtered;
125
- });
126
- })
127
- .subscribe();
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 (fadeOutTimer)
130
- clearTimeout(fadeOutTimer);
131
- supabaseClient.removeChannel(subscription);
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;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-notify-sdk",
3
- "version": "1.0.63",
3
+ "version": "1.0.65",
4
4
  "description": "SDK for displaying real-time route-specific messages in React apps",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",