about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.eslintrc.js1
-rw-r--r--eslint/index.js1
-rw-r--r--eslint/use-typed-gates.js31
-rw-r--r--src/lib/statsig/gates.ts11
-rw-r--r--src/lib/statsig/statsig.tsx3
-rw-r--r--src/view/screens/Search/Search.tsx4
6 files changed, 45 insertions, 6 deletions
diff --git a/.eslintrc.js b/.eslintrc.js
index a999fd24b..29136d5dd 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -31,6 +31,7 @@ module.exports = {
         },
       },
     ],
+    'bsky-internal/use-typed-gates': 'error',
     'simple-import-sort/imports': [
       'warn',
       {
diff --git a/eslint/index.js b/eslint/index.js
index daf5bd81d..bb31a942d 100644
--- a/eslint/index.js
+++ b/eslint/index.js
@@ -3,5 +3,6 @@
 module.exports = {
   rules: {
     'avoid-unwrapped-text': require('./avoid-unwrapped-text'),
+    'use-typed-gates': require('./use-typed-gates'),
   },
 }
diff --git a/eslint/use-typed-gates.js b/eslint/use-typed-gates.js
new file mode 100644
index 000000000..3625a7da3
--- /dev/null
+++ b/eslint/use-typed-gates.js
@@ -0,0 +1,31 @@
+'use strict'
+
+exports.create = function create(context) {
+  return {
+    ImportSpecifier(node) {
+      if (
+        !node.local ||
+        node.local.type !== 'Identifier' ||
+        node.local.name !== 'useGate'
+      ) {
+        return
+      }
+      if (
+        node.parent.type !== 'ImportDeclaration' ||
+        !node.parent.source ||
+        node.parent.source.type !== 'Literal'
+      ) {
+        return
+      }
+      const source = node.parent.source.value
+      if (source.startsWith('.') || source.startsWith('#')) {
+        return
+      }
+      context.report({
+        node,
+        message:
+          "Use useGate() from '#/lib/statsig/statsig' instead of the one on npm.",
+      })
+    },
+  }
+}
diff --git a/src/lib/statsig/gates.ts b/src/lib/statsig/gates.ts
index fce25cb88..c755ad437 100644
--- a/src/lib/statsig/gates.ts
+++ b/src/lib/statsig/gates.ts
@@ -1,3 +1,8 @@
-import {useGate} from './statsig'
-
-export const useNewSearchGate = () => useGate('new_search')
+export type Gate =
+  // Keep this alphabetic please.
+  | 'autoexpand_suggestions_on_profile_follow'
+  | 'disable_min_shell_on_foregrounding'
+  | 'disable_poll_on_discover'
+  | 'new_search'
+  | 'show_follow_back_label'
+  | 'start_session_with_following'
diff --git a/src/lib/statsig/statsig.tsx b/src/lib/statsig/statsig.tsx
index c16461621..18b58d16d 100644
--- a/src/lib/statsig/statsig.tsx
+++ b/src/lib/statsig/statsig.tsx
@@ -11,6 +11,7 @@ import {
 import {logger} from '#/logger'
 import {useSession} from '../../state/session'
 import {LogEvents} from './events'
+import {Gate} from './gates'
 
 export type {LogEvents}
 
@@ -69,7 +70,7 @@ export function logEvent<E extends keyof LogEvents>(
   }
 }
 
-export function useGate(gateName: string) {
+export function useGate(gateName: Gate): boolean {
   const {isLoading, value} = useStatsigGate(gateName)
   if (isLoading) {
     // This should not happen because of waitForInitialization={true}.
diff --git a/src/view/screens/Search/Search.tsx b/src/view/screens/Search/Search.tsx
index fe7a52234..0f24252ce 100644
--- a/src/view/screens/Search/Search.tsx
+++ b/src/view/screens/Search/Search.tsx
@@ -22,7 +22,7 @@ import {HITSLOP_10} from '#/lib/constants'
 import {usePalette} from '#/lib/hooks/usePalette'
 import {MagnifyingGlassIcon} from '#/lib/icons'
 import {NavigationProp} from '#/lib/routes/types'
-import {useNewSearchGate} from '#/lib/statsig/gates'
+import {useGate} from '#/lib/statsig/statsig'
 import {augmentSearchQuery} from '#/lib/strings/helpers'
 import {s} from '#/lib/styles'
 import {logger} from '#/logger'
@@ -337,7 +337,7 @@ export function SearchScreenInner({
   const {isDesktop} = useWebMediaQueries()
   const {_} = useLingui()
 
-  const isNewSearch = useNewSearchGate()
+  const isNewSearch = useGate('new_search')
 
   const onPageSelected = React.useCallback(
     (index: number) => {