about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/App.native.tsx33
-rw-r--r--src/App.web.tsx33
-rw-r--r--src/lib/statsig/statsig.tsx11
-rw-r--r--src/lib/statsig/statsig.web.tsx51
4 files changed, 98 insertions, 30 deletions
diff --git a/src/App.native.tsx b/src/App.native.tsx
index 4da3f85f0..eff8ab099 100644
--- a/src/App.native.tsx
+++ b/src/App.native.tsx
@@ -43,6 +43,7 @@ import {Provider as UnreadNotifsProvider} from 'state/queries/notifications/unre
 import * as persisted from '#/state/persisted'
 import {Splash} from '#/Splash'
 import {Provider as PortalProvider} from '#/components/Portal'
+import {Provider as StatsigProvider} from '#/lib/statsig/statsig'
 import {msg} from '@lingui/macro'
 import {useLingui} from '@lingui/react'
 import {useIntentHandler} from 'lib/hooks/useIntentHandler'
@@ -77,21 +78,23 @@ function InnerApp() {
           <React.Fragment
             // Resets the entire tree below when it changes:
             key={currentAccount?.did}>
-            <LoggedOutViewProvider>
-              <SelectedFeedProvider>
-                <UnreadNotifsProvider>
-                  <ThemeProvider theme={theme}>
-                    {/* All components should be within this provider */}
-                    <RootSiblingParent>
-                      <GestureHandlerRootView style={s.h100pct}>
-                        <TestCtrls />
-                        <Shell />
-                      </GestureHandlerRootView>
-                    </RootSiblingParent>
-                  </ThemeProvider>
-                </UnreadNotifsProvider>
-              </SelectedFeedProvider>
-            </LoggedOutViewProvider>
+            <StatsigProvider>
+              <LoggedOutViewProvider>
+                <SelectedFeedProvider>
+                  <UnreadNotifsProvider>
+                    <ThemeProvider theme={theme}>
+                      {/* All components should be within this provider */}
+                      <RootSiblingParent>
+                        <GestureHandlerRootView style={s.h100pct}>
+                          <TestCtrls />
+                          <Shell />
+                        </GestureHandlerRootView>
+                      </RootSiblingParent>
+                    </ThemeProvider>
+                  </UnreadNotifsProvider>
+                </SelectedFeedProvider>
+              </LoggedOutViewProvider>
+            </StatsigProvider>
           </React.Fragment>
         </Splash>
       </Alf>
diff --git a/src/App.web.tsx b/src/App.web.tsx
index 6ac32a011..eb2e42593 100644
--- a/src/App.web.tsx
+++ b/src/App.web.tsx
@@ -32,6 +32,7 @@ import {
 import {Provider as UnreadNotifsProvider} from 'state/queries/notifications/unread'
 import * as persisted from '#/state/persisted'
 import {Provider as PortalProvider} from '#/components/Portal'
+import {Provider as StatsigProvider} from '#/lib/statsig/statsig'
 import {useIntentHandler} from 'lib/hooks/useIntentHandler'
 
 function InnerApp() {
@@ -54,21 +55,23 @@ function InnerApp() {
       <React.Fragment
         // Resets the entire tree below when it changes:
         key={currentAccount?.did}>
-        <LoggedOutViewProvider>
-          <SelectedFeedProvider>
-            <UnreadNotifsProvider>
-              <ThemeProvider theme={theme}>
-                {/* All components should be within this provider */}
-                <RootSiblingParent>
-                  <SafeAreaProvider>
-                    <Shell />
-                  </SafeAreaProvider>
-                </RootSiblingParent>
-                <ToastContainer />
-              </ThemeProvider>
-            </UnreadNotifsProvider>
-          </SelectedFeedProvider>
-        </LoggedOutViewProvider>
+        <StatsigProvider>
+          <LoggedOutViewProvider>
+            <SelectedFeedProvider>
+              <UnreadNotifsProvider>
+                <ThemeProvider theme={theme}>
+                  {/* All components should be within this provider */}
+                  <RootSiblingParent>
+                    <SafeAreaProvider>
+                      <Shell />
+                    </SafeAreaProvider>
+                  </RootSiblingParent>
+                  <ToastContainer />
+                </ThemeProvider>
+              </UnreadNotifsProvider>
+            </SelectedFeedProvider>
+          </LoggedOutViewProvider>
+        </StatsigProvider>
       </React.Fragment>
     </Alf>
   )
diff --git a/src/lib/statsig/statsig.tsx b/src/lib/statsig/statsig.tsx
new file mode 100644
index 000000000..88a57c3fc
--- /dev/null
+++ b/src/lib/statsig/statsig.tsx
@@ -0,0 +1,11 @@
+import React from 'react'
+
+export function useGate(_gateName: string) {
+  // Not enabled for native yet.
+  return false
+}
+
+export function Provider({children}: {children: React.ReactNode}) {
+  // Not enabled for native yet.
+  return children
+}
diff --git a/src/lib/statsig/statsig.web.tsx b/src/lib/statsig/statsig.web.tsx
new file mode 100644
index 000000000..6508131c4
--- /dev/null
+++ b/src/lib/statsig/statsig.web.tsx
@@ -0,0 +1,51 @@
+import React from 'react'
+import {StatsigProvider, useGate as useStatsigGate} from 'statsig-react'
+import {useSession} from '../../state/session'
+import {sha256} from 'js-sha256'
+
+const statsigOptions = {
+  environment: {
+    tier: process.env.NODE_ENV === 'development' ? 'development' : 'production',
+  },
+  // Don't block on waiting for network. The fetched config will kick in on next load.
+  // This ensures the UI is always consistent and doesn't update mid-session.
+  // Note this makes cold load (no local storage) and private mode return `false` for all gates.
+  initTimeoutMs: 1,
+}
+
+export function useGate(gateName: string) {
+  const {isLoading, value} = useStatsigGate(gateName)
+  if (isLoading) {
+    // This should not happen because of waitForInitialization={true}.
+    console.error('Did not expected isLoading to ever be true.')
+  }
+  return value
+}
+
+function toStatsigUser(did: string | undefined) {
+  let userID: string | undefined
+  if (did) {
+    userID = sha256(did)
+  }
+  return {userID}
+}
+
+export function Provider({children}: {children: React.ReactNode}) {
+  const {currentAccount} = useSession()
+  const currentStatsigUser = React.useMemo(
+    () => toStatsigUser(currentAccount?.did),
+    [currentAccount?.did],
+  )
+  return (
+    <StatsigProvider
+      sdkKey="client-SXJakO39w9vIhl3D44u8UupyzFl4oZ2qPIkjwcvuPsV"
+      mountKey={currentStatsigUser.userID}
+      user={currentStatsigUser}
+      // This isn't really blocking due to short initTimeoutMs above.
+      // However, it ensures `isLoading` is always `false`.
+      waitForInitialization={true}
+      options={statsigOptions}>
+      {children}
+    </StatsigProvider>
+  )
+}