diff --git a/lib/shared/staff-utils.js b/lib/shared/staff-utils.js index e00609475..827e0cedc 100644 --- a/lib/shared/staff-utils.js +++ b/lib/shared/staff-utils.js @@ -1,19 +1,27 @@ // @flow import bots from '../facts/bots.js'; import staff from '../facts/staff.js'; +import { useSelector } from '../utils/redux-utils.js'; function isStaff(userID: string): boolean { if (staff.includes(userID)) { return true; } for (const key in bots) { const bot = bots[key]; if (userID === bot.userID) { return true; } } return false; } -export { isStaff }; +function useIsCurrentUserStaff(): boolean { + const isCurrentUserStaff = useSelector(state => + state.currentUserInfo?.id ? isStaff(state.currentUserInfo.id) : false, + ); + return isCurrentUserStaff; +} + +export { isStaff, useIsCurrentUserStaff }; diff --git a/native/components/feature-flags-provider.react.js b/native/components/feature-flags-provider.react.js index ba9909cc3..1c0bb90ab 100644 --- a/native/components/feature-flags-provider.react.js +++ b/native/components/feature-flags-provider.react.js @@ -1,119 +1,119 @@ // @flow import AsyncStorage from '@react-native-async-storage/async-storage'; import * as React from 'react'; import { Platform } from 'react-native'; +import { useIsCurrentUserStaff } from 'lib/shared/staff-utils.js'; import { fetchFeatureFlags } from 'lib/utils/feature-flags-utils.js'; import sleep from 'lib/utils/sleep.js'; -import { useIsCurrentUserStaff } from 'native/utils/staff-utils.js'; import { codeVersion } from '../redux/persist.js'; type FeatureFlagsConfiguration = { +[feature: string]: boolean, }; type FeatureFlagsContextType = { +configuration: FeatureFlagsConfiguration, +loadedFromService: boolean, }; const defaultContext = { configuration: {}, loadedFromService: false, }; const FeatureFlagsContext: React.Context = React.createContext(defaultContext); const featureFlagsStorageKey = 'FeatureFlags'; type Props = { +children: React.Node, }; function FeatureFlagsProvider(props: Props): React.Node { const { children } = props; const isStaff = useIsCurrentUserStaff(); const [featuresConfig, setFeaturesConfig] = React.useState(defaultContext); React.useEffect(() => { (async () => { if (featuresConfig.loadedFromService) { return; } const persistedFeaturesConfig = await AsyncStorage.getItem( featureFlagsStorageKey, ); if (!persistedFeaturesConfig) { return; } setFeaturesConfig(config => config.loadedFromService ? config : { configuration: JSON.parse(persistedFeaturesConfig), loadedFromService: false, }, ); })(); }, [featuresConfig.loadedFromService]); React.useEffect(() => { (async () => { try { const config = await tryMultipleTimes( () => fetchFeatureFlags(Platform.OS, isStaff, codeVersion), 3, 5000, ); const configuration = {}; for (const feature of config.enabledFeatures) { configuration[feature] = true; } setFeaturesConfig({ configuration, loadedFromService: true, }); await AsyncStorage.setItem( featureFlagsStorageKey, JSON.stringify(configuration), ); } catch (e) { console.error('Feature flag retrieval failed:', e); } })(); }, [isStaff]); return ( {children} ); } async function tryMultipleTimes( f: () => Promise, numberOfTries: number, delay: number, ): Promise { let lastError; while (numberOfTries > 0) { try { return await f(); } catch (e) { --numberOfTries; lastError = e; if (numberOfTries > 0) { await sleep(delay); } } } throw lastError; } export { FeatureFlagsContext, FeatureFlagsProvider, featureFlagsStorageKey }; diff --git a/native/profile/build-info.react.js b/native/profile/build-info.react.js index b8b6d291d..c7b4f8303 100644 --- a/native/profile/build-info.react.js +++ b/native/profile/build-info.react.js @@ -1,118 +1,116 @@ // @flow import * as React from 'react'; import { View, Text } from 'react-native'; import { ScrollView } from 'react-native-gesture-handler'; +import { useIsCurrentUserStaff } from 'lib/shared/staff-utils.js'; + import { persistConfig, codeVersion } from '../redux/persist.js'; import { StaffContext } from '../staff/staff-context.js'; import { useStyles } from '../themes/colors.js'; -import { - isStaffRelease, - useIsCurrentUserStaff, - useStaffCanSee, -} from '../utils/staff-utils.js'; +import { isStaffRelease, useStaffCanSee } from '../utils/staff-utils.js'; // eslint-disable-next-line no-unused-vars function BuildInfo(props: { ... }): React.Node { const isCurrentUserStaff = useIsCurrentUserStaff(); const { staffUserHasBeenLoggedIn } = React.useContext(StaffContext); const styles = useStyles(unboundStyles); const staffCanSee = useStaffCanSee(); let staffCanSeeRows; if (staffCanSee || staffUserHasBeenLoggedIn) { staffCanSeeRows = ( <> __DEV__ {__DEV__ ? 'TRUE' : 'FALSE'} Staff Release {isStaffRelease ? 'TRUE' : 'FALSE'} isCurrentUserStaff {isCurrentUserStaff ? 'TRUE' : 'FALSE'} hasStaffUserLoggedIn {staffUserHasBeenLoggedIn ? 'TRUE' : 'FALSE'} ); } return ( Code version {codeVersion} State version {persistConfig.version} {staffCanSeeRows} Thank you for using Comm! ); } const unboundStyles = { label: { color: 'panelForegroundTertiaryLabel', fontSize: 16, paddingRight: 12, }, releaseText: { color: 'orange', fontSize: 16, }, row: { flexDirection: 'row', justifyContent: 'space-between', paddingVertical: 6, }, scrollView: { backgroundColor: 'panelBackground', }, scrollViewContentContainer: { paddingTop: 24, }, section: { backgroundColor: 'panelForeground', borderBottomWidth: 1, borderColor: 'panelForegroundBorder', borderTopWidth: 1, marginBottom: 24, paddingHorizontal: 24, paddingVertical: 6, }, text: { color: 'panelForegroundLabel', fontSize: 16, }, thanksText: { color: 'panelForegroundLabel', flex: 1, fontSize: 16, textAlign: 'center', }, }; export default BuildInfo; diff --git a/native/staff/staff-context.provider.react.js b/native/staff/staff-context.provider.react.js index 8379b6b22..329b92342 100644 --- a/native/staff/staff-context.provider.react.js +++ b/native/staff/staff-context.provider.react.js @@ -1,35 +1,36 @@ // @flow import * as React from 'react'; +import { useIsCurrentUserStaff } from 'lib/shared/staff-utils.js'; + import { StaffContext, type StaffContextType } from './staff-context.js'; -import { useIsCurrentUserStaff } from '../utils/staff-utils.js'; type Props = { +children: React.Node, }; function StaffContextProvider(props: Props): React.Node { const [staffUserHasBeenLoggedIn, setStaffUserHasBeenLoggedIn] = React.useState(false); const isCurrentUserStaff = useIsCurrentUserStaff(); React.useEffect(() => { if (isCurrentUserStaff) { setStaffUserHasBeenLoggedIn(true); } }, [isCurrentUserStaff]); const staffContextValue: StaffContextType = React.useMemo( () => ({ staffUserHasBeenLoggedIn }), [staffUserHasBeenLoggedIn], ); return ( {props.children} ); } export { StaffContextProvider }; diff --git a/native/utils/staff-utils.js b/native/utils/staff-utils.js index 7b5580309..c76228090 100644 --- a/native/utils/staff-utils.js +++ b/native/utils/staff-utils.js @@ -1,21 +1,12 @@ // @flow -import { isStaff } from 'lib/shared/staff-utils.js'; - -import { useSelector } from '../redux/redux-utils.js'; +import { useIsCurrentUserStaff } from 'lib/shared/staff-utils.js'; const isStaffRelease = false; -function useIsCurrentUserStaff(): boolean { - const isCurrentUserStaff = useSelector(state => - state.currentUserInfo?.id ? isStaff(state.currentUserInfo.id) : false, - ); - return isCurrentUserStaff; -} - function useStaffCanSee(): boolean { const isCurrentUserStaff = useIsCurrentUserStaff(); return __DEV__ || isStaffRelease || isCurrentUserStaff; } -export { isStaffRelease, useIsCurrentUserStaff, useStaffCanSee }; +export { isStaffRelease, useStaffCanSee };