From a90fd5d26f1a8aa5149627a68a8dd6b13b26fec5 Mon Sep 17 00:00:00 2001
From: Paul Frazee <pfrazee@gmail.com>
Date: Fri, 30 Dec 2022 15:48:34 -0600
Subject: Add dark mode toggle

---
 src/view/shell/mobile/Menu.tsx | 342 +++++++++++++++++++++--------------------
 1 file changed, 177 insertions(+), 165 deletions(-)

(limited to 'src/view/shell/mobile/Menu.tsx')

diff --git a/src/view/shell/mobile/Menu.tsx b/src/view/shell/mobile/Menu.tsx
index 84c3f494e..81f2164da 100644
--- a/src/view/shell/mobile/Menu.tsx
+++ b/src/view/shell/mobile/Menu.tsx
@@ -6,6 +6,7 @@ import {
   View,
   ViewStyle,
 } from 'react-native'
+import {observer} from 'mobx-react-lite'
 import VersionNumber from 'react-native-version-number'
 import {s, colors} from '../../lib/styles'
 import {useStores} from '../../../state'
@@ -18,187 +19,198 @@ import {
 } from '../../lib/icons'
 import {UserAvatar} from '../../com/util/UserAvatar'
 import {Text} from '../../com/util/text/Text'
+import {ToggleButton} from '../../com/util/forms/ToggleButton'
 import {CreateSceneModal} from '../../../state/models/shell-ui'
 import {usePalette} from '../../lib/hooks/usePalette'
 
-export const Menu = ({
-  visible,
-  onClose,
-}: {
-  visible: boolean
-  onClose: () => void
-}) => {
-  const pal = usePalette('default')
-  const store = useStores()
+export const Menu = observer(
+  ({visible, onClose}: {visible: boolean; onClose: () => void}) => {
+    const pal = usePalette('default')
+    const store = useStores()
 
-  useEffect(() => {
-    if (visible) {
-      // trigger a refresh in case memberships have changed recently
-      // TODO this impacts performance, need to find the right time to do this
-      // store.me.refreshMemberships()
-    }
-  }, [store, visible])
+    useEffect(() => {
+      if (visible) {
+        // trigger a refresh in case memberships have changed recently
+        // TODO this impacts performance, need to find the right time to do this
+        // store.me.refreshMemberships()
+      }
+    }, [store, visible])
 
-  // events
-  // =
+    // events
+    // =
 
-  const onNavigate = (url: string) => {
-    onClose()
-    if (url === '/notifications') {
-      store.nav.switchTo(1, true)
-    } else {
-      store.nav.switchTo(0, true)
-      if (url !== '/') {
-        store.nav.navigate(url)
+    const onNavigate = (url: string) => {
+      onClose()
+      if (url === '/notifications') {
+        store.nav.switchTo(1, true)
+      } else {
+        store.nav.switchTo(0, true)
+        if (url !== '/') {
+          store.nav.navigate(url)
+        }
       }
     }
-  }
-  const onPressCreateScene = () => {
-    onClose()
-    store.shell.openModal(new CreateSceneModal())
-  }
+    const onPressCreateScene = () => {
+      onClose()
+      store.shell.openModal(new CreateSceneModal())
+    }
 
-  // rendering
-  // =
+    // rendering
+    // =
 
-  const MenuItem = ({
-    icon,
-    label,
-    count,
-    url,
-    bold,
-    onPress,
-  }: {
-    icon: JSX.Element
-    label: string
-    count?: number
-    url?: string
-    bold?: boolean
-    onPress?: () => void
-  }) => (
-    <TouchableOpacity
-      style={styles.menuItem}
-      onPress={onPress ? onPress : () => onNavigate(url || '/')}>
-      <View style={[styles.menuItemIconWrapper]}>
-        {icon}
-        {count ? (
-          <View style={styles.menuItemCount}>
-            <Text style={styles.menuItemCountLabel}>{count}</Text>
-          </View>
-        ) : undefined}
-      </View>
-      <Text
-        type="h4"
-        style={[
-          pal.text,
-          bold ? styles.menuItemLabelBold : styles.menuItemLabel,
-        ]}
-        numberOfLines={1}>
-        {label}
-      </Text>
-    </TouchableOpacity>
-  )
-
-  return (
-    <View style={[styles.view, pal.view]}>
+    const MenuItem = ({
+      icon,
+      label,
+      count,
+      url,
+      bold,
+      onPress,
+    }: {
+      icon: JSX.Element
+      label: string
+      count?: number
+      url?: string
+      bold?: boolean
+      onPress?: () => void
+    }) => (
       <TouchableOpacity
-        onPress={() => onNavigate(`/profile/${store.me.handle}`)}
-        style={styles.profileCard}>
-        <UserAvatar
-          size={60}
-          displayName={store.me.displayName}
-          handle={store.me.handle}
-          avatar={store.me.avatar}
-        />
-        <View style={s.flex1}>
-          <Text
-            type="h3"
-            style={[pal.text, styles.profileCardDisplayName]}
-            numberOfLines={1}>
-            {store.me.displayName || store.me.handle}
-          </Text>
-          <Text
-            style={[pal.textLight, styles.profileCardHandle]}
-            numberOfLines={1}>
-            @{store.me.handle}
-          </Text>
+        style={styles.menuItem}
+        onPress={onPress ? onPress : () => onNavigate(url || '/')}>
+        <View style={[styles.menuItemIconWrapper]}>
+          {icon}
+          {count ? (
+            <View style={styles.menuItemCount}>
+              <Text style={styles.menuItemCountLabel}>{count}</Text>
+            </View>
+          ) : undefined}
         </View>
-      </TouchableOpacity>
-      <TouchableOpacity
-        style={[styles.searchBtn, pal.btn]}
-        onPress={() => onNavigate('/search')}>
-        <MagnifyingGlassIcon
-          style={pal.text as StyleProp<ViewStyle>}
-          size={25}
-        />
-        <Text type="h4" style={[pal.text, styles.searchBtnLabel]}>
-          Search
+        <Text
+          type="h4"
+          style={[
+            pal.text,
+            bold ? styles.menuItemLabelBold : styles.menuItemLabel,
+          ]}
+          numberOfLines={1}>
+          {label}
         </Text>
       </TouchableOpacity>
-      <View style={[styles.section, pal.border]}>
-        <MenuItem
-          icon={<HomeIcon style={pal.text as StyleProp<ViewStyle>} size="26" />}
-          label="Home"
-          url="/"
-        />
-        <MenuItem
-          icon={<BellIcon style={pal.text as StyleProp<ViewStyle>} size="28" />}
-          label="Notifications"
-          url="/notifications"
-          count={store.me.notificationCount}
-        />
-      </View>
-      <View style={[styles.section, pal.border]}>
-        <Text type="h5" style={[pal.text, styles.heading]}>
-          Scenes
-        </Text>
-        {store.me.memberships
-          ? store.me.memberships.memberships.map((membership, i) => (
-              <MenuItem
-                key={i}
-                icon={
-                  <UserAvatar
-                    size={34}
-                    displayName={membership.displayName}
-                    handle={membership.handle}
-                    avatar={membership.avatar}
-                  />
-                }
-                label={membership.displayName || membership.handle}
-                url={`/profile/${membership.handle}`}
+    )
+
+    return (
+      <View style={[styles.view, pal.view]}>
+        <TouchableOpacity
+          onPress={() => onNavigate(`/profile/${store.me.handle}`)}
+          style={styles.profileCard}>
+          <UserAvatar
+            size={60}
+            displayName={store.me.displayName}
+            handle={store.me.handle}
+            avatar={store.me.avatar}
+          />
+          <View style={s.flex1}>
+            <Text
+              type="h3"
+              style={[pal.text, styles.profileCardDisplayName]}
+              numberOfLines={1}>
+              {store.me.displayName || store.me.handle}
+            </Text>
+            <Text
+              style={[pal.textLight, styles.profileCardHandle]}
+              numberOfLines={1}>
+              @{store.me.handle}
+            </Text>
+          </View>
+        </TouchableOpacity>
+        <TouchableOpacity
+          style={[styles.searchBtn, pal.btn]}
+          onPress={() => onNavigate('/search')}>
+          <MagnifyingGlassIcon
+            style={pal.text as StyleProp<ViewStyle>}
+            size={25}
+          />
+          <Text type="h4" style={[pal.text, styles.searchBtnLabel]}>
+            Search
+          </Text>
+        </TouchableOpacity>
+        <View style={[styles.section, pal.border]}>
+          <MenuItem
+            icon={
+              <HomeIcon style={pal.text as StyleProp<ViewStyle>} size="26" />
+            }
+            label="Home"
+            url="/"
+          />
+          <MenuItem
+            icon={
+              <BellIcon style={pal.text as StyleProp<ViewStyle>} size="28" />
+            }
+            label="Notifications"
+            url="/notifications"
+            count={store.me.notificationCount}
+          />
+        </View>
+        <View style={[styles.section, pal.border]}>
+          <Text type="h5" style={[pal.text, styles.heading]}>
+            Scenes
+          </Text>
+          {store.me.memberships
+            ? store.me.memberships.memberships.map((membership, i) => (
+                <MenuItem
+                  key={i}
+                  icon={
+                    <UserAvatar
+                      size={34}
+                      displayName={membership.displayName}
+                      handle={membership.handle}
+                      avatar={membership.avatar}
+                    />
+                  }
+                  label={membership.displayName || membership.handle}
+                  url={`/profile/${membership.handle}`}
+                />
+              ))
+            : undefined}
+        </View>
+        <View style={[styles.section, pal.border]}>
+          <MenuItem
+            icon={
+              <UserGroupIcon
+                style={pal.text as StyleProp<ViewStyle>}
+                size="30"
               />
-            ))
-          : undefined}
-      </View>
-      <View style={[styles.section, pal.border]}>
-        <MenuItem
-          icon={
-            <UserGroupIcon style={pal.text as StyleProp<ViewStyle>} size="30" />
-          }
-          label="Create a scene"
-          onPress={onPressCreateScene}
-        />
-        <MenuItem
-          icon={
-            <CogIcon
-              style={pal.text as StyleProp<ViewStyle>}
-              size="30"
-              strokeWidth={2}
-            />
-          }
-          label="Settings"
-          url="/settings"
-        />
-      </View>
-      <View style={styles.footer}>
-        <Text style={[pal.textLight]}>
-          Build version {VersionNumber.appVersion} ({VersionNumber.buildVersion}
-          )
-        </Text>
+            }
+            label="Create a scene"
+            onPress={onPressCreateScene}
+          />
+          <MenuItem
+            icon={
+              <CogIcon
+                style={pal.text as StyleProp<ViewStyle>}
+                size="30"
+                strokeWidth={2}
+              />
+            }
+            label="Settings"
+            url="/settings"
+          />
+        </View>
+        <View style={[styles.section, pal.border]}>
+          <ToggleButton
+            label="Dark mode"
+            isSelected={store.shell.darkMode}
+            onPress={() => store.shell.setDarkMode(!store.shell.darkMode)}
+          />
+        </View>
+        <View style={styles.footer}>
+          <Text style={[pal.textLight]}>
+            Build version {VersionNumber.appVersion} (
+            {VersionNumber.buildVersion})
+          </Text>
+        </View>
       </View>
-    </View>
-  )
-}
+    )
+  },
+)
 
 const styles = StyleSheet.create({
   view: {
-- 
cgit 1.4.1

