From 67c3be97a1d5921df738b8915695e7362a9234f7 Mon Sep 17 00:00:00 2001
From: Matiss Janis Aboltins <matiss@mja.lv>
Date: Sat, 18 Mar 2023 18:41:45 +0000
Subject: [PATCH] :recycle:  move all feature flags to use useFeatureFlag hook
 (#786)

Refactored all feature flags to use the new `useFeatureFlag` hook.

Also added a new functionality to this feature flag: ability to define
custom "default" value for a feature flag. This will allow us to enable
the new autocomplete component for everyone using Netlify builds
eventually (need to address some issues before doing so).
---
 .../desktop-client/src/components/Modals.js   |  6 +++++
 .../src/components/SidebarWithData.js         |  8 +++---
 .../desktop-client/src/components/Titlebar.js |  4 ++-
 .../src/components/accounts/Account.js        |  4 ++-
 .../src/components/settings/Experimental.js   |  8 +++---
 .../src/hooks/useFeatureFlag.js               | 27 ++++++++++++++++++-
 .../budget/rollover/BudgetSummary.js          | 15 +++--------
 .../src/components/modals/EditField.js        |  1 -
 upcoming-release-notes/786.md                 |  6 +++++
 9 files changed, 55 insertions(+), 24 deletions(-)
 create mode 100644 upcoming-release-notes/786.md

diff --git a/packages/desktop-client/src/components/Modals.js b/packages/desktop-client/src/components/Modals.js
index f824e30c7..894c34077 100644
--- a/packages/desktop-client/src/components/Modals.js
+++ b/packages/desktop-client/src/components/Modals.js
@@ -19,6 +19,7 @@ import NordigenExternalMsg from 'loot-design/src/components/modals/NordigenExter
 import PlaidExternalMsg from 'loot-design/src/components/modals/PlaidExternalMsg';
 import SelectLinkedAccounts from 'loot-design/src/components/modals/SelectLinkedAccounts';
 
+import useFeatureFlag from '../hooks/useFeatureFlag';
 import useSyncServerStatus from '../hooks/useSyncServerStatus';
 
 import ConfirmCategoryDelete from './modals/ConfirmCategoryDelete';
@@ -40,6 +41,9 @@ function Modals({
   budgetId,
   actions,
 }) {
+  const isNewAutocompleteEnabled = useFeatureFlag('newAutocomplete');
+  const isGoalTemplatesEnabled = useFeatureFlag('goalTemplatesEnabled');
+
   const syncServerStatus = useSyncServerStatus();
 
   return modalStack.map(({ name, options = {} }, idx) => {
@@ -272,6 +276,7 @@ function Modals({
                 actions={actions}
                 name={options.name}
                 onSubmit={options.onSubmit}
+                isNewAutocompleteEnabled={isNewAutocompleteEnabled}
               />
             );
           }}
@@ -283,6 +288,7 @@ function Modals({
             modalProps={modalProps}
             month={options.month}
             actions={actions}
+            isGoalTemplatesEnabled={isGoalTemplatesEnabled}
           />
         </Route>
       </Switch>
diff --git a/packages/desktop-client/src/components/SidebarWithData.js b/packages/desktop-client/src/components/SidebarWithData.js
index b63092b18..0dffcfade 100644
--- a/packages/desktop-client/src/components/SidebarWithData.js
+++ b/packages/desktop-client/src/components/SidebarWithData.js
@@ -22,6 +22,8 @@ import { Sidebar } from 'loot-design/src/components/sidebar';
 import { styles, colors } from 'loot-design/src/style';
 import ExpandArrow from 'loot-design/src/svg/v0/ExpandArrow';
 
+import useFeatureFlag from '../hooks/useFeatureFlag';
+
 function EditableBudgetName({ prefs, savePrefs }) {
   let dispatch = useDispatch();
   let history = useHistory();
@@ -123,6 +125,8 @@ function SidebarWithData({
   saveGlobalPrefs,
   getAccounts,
 }) {
+  const syncAccount = useFeatureFlag('syncAccount');
+
   useEffect(() => void getAccounts(), [getAccounts]);
 
   async function onReorder(id, dropPos, targetId) {
@@ -149,9 +153,7 @@ function SidebarWithData({
       onFloat={() => saveGlobalPrefs({ floatingSidebar: !floatingSidebar })}
       onReorder={onReorder}
       onAddAccount={() =>
-        replaceModal(
-          prefs['flags.syncAccount'] ? 'add-account' : 'add-local-account',
-        )
+        replaceModal(syncAccount ? 'add-account' : 'add-local-account')
       }
       showClosedAccounts={prefs['ui.showClosedAccounts']}
       onToggleClosedAccounts={() =>
diff --git a/packages/desktop-client/src/components/Titlebar.js b/packages/desktop-client/src/components/Titlebar.js
index 5233286ea..e6fb8c910 100644
--- a/packages/desktop-client/src/components/Titlebar.js
+++ b/packages/desktop-client/src/components/Titlebar.js
@@ -25,6 +25,8 @@ import ArrowButtonRight1 from 'loot-design/src/svg/v2/ArrowButtonRight1';
 import NavigationMenu from 'loot-design/src/svg/v2/NavigationMenu';
 import tokens from 'loot-design/src/tokens';
 
+import useFeatureFlag from '../hooks/useFeatureFlag';
+
 import AccountSyncCheck from './accounts/AccountSyncCheck';
 import AnimatedRefresh from './AnimatedRefresh';
 import { MonthCountSelector } from './budget/MonthCountSelector';
@@ -163,7 +165,7 @@ function BudgetTitlebar({ globalPrefs, saveGlobalPrefs, localPrefs }) {
   let [loading, setLoading] = useState(false);
   let [showTooltip, setShowTooltip] = useState(false);
 
-  let reportBudgetEnabled = localPrefs['flags.reportBudget'];
+  const reportBudgetEnabled = useFeatureFlag('reportBudget');
 
   function onSwitchType() {
     setLoading(true);
diff --git a/packages/desktop-client/src/components/accounts/Account.js b/packages/desktop-client/src/components/accounts/Account.js
index 32bccd20c..54de03461 100644
--- a/packages/desktop-client/src/components/accounts/Account.js
+++ b/packages/desktop-client/src/components/accounts/Account.js
@@ -60,6 +60,7 @@ import Pencil1 from 'loot-design/src/svg/v2/Pencil1';
 import SvgRemove from 'loot-design/src/svg/v2/Remove';
 import SearchAlternate from 'loot-design/src/svg/v2/SearchAlternate';
 
+import useFeatureFlag from '../../hooks/useFeatureFlag';
 import useSyncServerStatus from '../../hooks/useSyncServerStatus';
 import { authorizeBank } from '../../nordigen';
 import { useActiveLocation } from '../ActiveLocation';
@@ -1914,13 +1915,13 @@ function AccountHack(props) {
 }
 
 export default function Account(props) {
+  const syncEnabled = useFeatureFlag('syncAccount');
   let state = useSelector(state => ({
     newTransactions: state.queries.newTransactions,
     matchedTransactions: state.queries.matchedTransactions,
     accounts: state.queries.accounts,
     failedAccounts: state.account.failedAccounts,
     categoryGroups: state.queries.categories.grouped,
-    syncEnabled: state.prefs.local['flags.syncAccount'],
     dateFormat: state.prefs.local.dateFormat || 'MM/dd/yyyy',
     hideFraction: state.prefs.local.hideFraction || false,
     expandSplits: props.match && state.prefs.local['expand-splits'],
@@ -1975,6 +1976,7 @@ export default function Account(props) {
         <AccountHack
           {...state}
           {...actionCreators}
+          syncEnabled={syncEnabled}
           modalShowing={
             state.modalShowing ||
             !!(activeLocation.state && activeLocation.state.locationPtr)
diff --git a/packages/desktop-client/src/components/settings/Experimental.js b/packages/desktop-client/src/components/settings/Experimental.js
index e51a325d0..2dcf251e3 100644
--- a/packages/desktop-client/src/components/settings/Experimental.js
+++ b/packages/desktop-client/src/components/settings/Experimental.js
@@ -4,15 +4,13 @@ import { Link, Text, View } from 'loot-design/src/components/common';
 import { Checkbox } from 'loot-design/src/components/forms';
 import { colors } from 'loot-design/src/style';
 
+import { useAllFeatureFlags } from '../../hooks/useFeatureFlag';
+
 import { Setting } from './UI';
 
 export default function ExperimentalFeatures({ prefs, savePrefs }) {
   let [expanded, setExpanded] = React.useState(false);
-  let flags = Object.fromEntries(
-    Object.entries(prefs)
-      .filter(([key]) => key.startsWith('flags.'))
-      .map(([key, value]) => [key.replace('flags.', ''), value]),
-  );
+  const flags = useAllFeatureFlags();
   let disabled = prefs.budgetType === 'report' && flags.reportBudget;
 
   return (
diff --git a/packages/desktop-client/src/hooks/useFeatureFlag.js b/packages/desktop-client/src/hooks/useFeatureFlag.js
index 4ea6dc4fd..6cda94e42 100644
--- a/packages/desktop-client/src/hooks/useFeatureFlag.js
+++ b/packages/desktop-client/src/hooks/useFeatureFlag.js
@@ -1,5 +1,30 @@
 import { useSelector } from 'react-redux';
 
+const DEFAULT_FEATURE_FLAG_STATE = {
+  newAutocomplete: false,
+  syncAccount: false,
+  goalTemplatesEnabled: false,
+};
+
 export default function useFeatureFlag(name) {
-  return useSelector(state => state.prefs.local[`flags.${name}`]);
+  return useSelector(state => {
+    const value = state.prefs.local[`flags.${name}`];
+
+    return value === undefined
+      ? DEFAULT_FEATURE_FLAG_STATE[name] || false
+      : value;
+  });
+}
+
+export function useAllFeatureFlags() {
+  return useSelector(state => {
+    return {
+      ...DEFAULT_FEATURE_FLAG_STATE,
+      ...Object.fromEntries(
+        Object.entries(state.prefs.local)
+          .filter(([key]) => key.startsWith('flags.'))
+          .map(([key, value]) => [key.replace('flags.', ''), value]),
+      ),
+    };
+  });
 }
diff --git a/packages/loot-design/src/components/budget/rollover/BudgetSummary.js b/packages/loot-design/src/components/budget/rollover/BudgetSummary.js
index 1d23c300f..2aa757e67 100644
--- a/packages/loot-design/src/components/budget/rollover/BudgetSummary.js
+++ b/packages/loot-design/src/components/budget/rollover/BudgetSummary.js
@@ -1,5 +1,4 @@
 import React, { useState } from 'react';
-import { connect } from 'react-redux';
 
 import Component from '@reactions/component';
 import { css } from 'glamor';
@@ -7,7 +6,6 @@ import { css } from 'glamor';
 import { rolloverBudget } from 'loot-core/src/client/queries';
 import * as monthUtils from 'loot-core/src/shared/months';
 
-import * as actions from '../../../../../loot-core/src/client/actions';
 import { colors, styles } from '../../../style';
 import DotsHorizontalTriple from '../../../svg/v1/DotsHorizontalTriple';
 import ArrowButtonDown1 from '../../../svg/v2/ArrowButtonDown1';
@@ -245,7 +243,7 @@ function ToBudget({ month, prevMonthName, collapsed, onBudgetAction }) {
   );
 }
 
-function BudgetSummaryComponent({ month, localPrefs }) {
+export function BudgetSummary({ month, isGoalTemplatesEnabled }) {
   let {
     currentMonth,
     summaryCollapsed: collapsed,
@@ -266,8 +264,6 @@ function BudgetSummaryComponent({ month, localPrefs }) {
 
   let ExpandOrCollapseIcon = collapsed ? ArrowButtonDown1 : ArrowButtonUp1;
 
-  let goalTemplatesEnabled = localPrefs['flags.goalTemplatesEnabled'];
-
   return (
     <View
       style={{
@@ -378,11 +374,11 @@ function BudgetSummaryComponent({ month, localPrefs }) {
                         name: 'set-3-avg',
                         text: 'Set budgets to 3 month avg',
                       },
-                      goalTemplatesEnabled && {
+                      isGoalTemplatesEnabled && {
                         name: 'apply-goal-template',
                         text: 'Apply budget template',
                       },
-                      goalTemplatesEnabled && {
+                      isGoalTemplatesEnabled && {
                         name: 'overwrite-goal-template',
                         text: 'Overwrite with budget template',
                       },
@@ -423,8 +419,3 @@ function BudgetSummaryComponent({ month, localPrefs }) {
     </View>
   );
 }
-
-export const BudgetSummary = connect(
-  state => ({ localPrefs: state.prefs.local }),
-  actions,
-)(BudgetSummaryComponent);
diff --git a/packages/loot-design/src/components/modals/EditField.js b/packages/loot-design/src/components/modals/EditField.js
index ce88888a9..44d1ff40b 100644
--- a/packages/loot-design/src/components/modals/EditField.js
+++ b/packages/loot-design/src/components/modals/EditField.js
@@ -200,7 +200,6 @@ export default connect(
     categoryGroups: state.queries.categories.grouped,
     accounts: state.queries.accounts,
     payees: state.queries.payees,
-    isNewAutocompleteEnabled: state.prefs.local['flags.newAutocomplete'],
   }),
   actions,
 )(EditField);
diff --git a/upcoming-release-notes/786.md b/upcoming-release-notes/786.md
new file mode 100644
index 000000000..049342f8d
--- /dev/null
+++ b/upcoming-release-notes/786.md
@@ -0,0 +1,6 @@
+---
+category: Maintenance
+authors: [MatissJanis]
+---
+
+Refactored all feature flgas to use the new `useFeatureFlag` hook
-- 
GitLab