Skip to content

Commit

Permalink
fix(store): add reset functionality to preferences store and streamli…
Browse files Browse the repository at this point in the history
…ne initial state setup
  • Loading branch information
Robert27 committed Dec 9, 2024
1 parent a9a720f commit fdcc4ee
Show file tree
Hide file tree
Showing 14 changed files with 102 additions and 59 deletions.
2 changes: 1 addition & 1 deletion android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ android {
applicationId 'app.neuland'
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 244
versionCode 245
versionName "0.11.0"
}
signingConfigs {
Expand Down
2 changes: 1 addition & 1 deletion app.config.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
"android": {
"package": "app.neuland",
"userInterfaceStyle": "automatic",
"versionCode": 244
"versionCode": 245
},
"sdkVersion": "52.0.0",
"experiments": {
Expand Down
Binary file modified bun.lockb
Binary file not shown.
13 changes: 2 additions & 11 deletions src/api/thi-session-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -224,18 +224,9 @@ export async function forgetSession(): Promise<void> {
SecureStore.deleteItemAsync('password'),
])

// clear all AsyncStorage data except analytics
// clear the general storage (cache)
try {
const keys = storage.getAllKeys()
for (const key of keys) {
if (
key !== 'analytics' &&
key !== 'isOnboardedv1' &&
!key.startsWith('isUpdated-')
) {
storage.delete(key)
}
}
storage.clearAll()
} catch (e) {
console.error(e)
}
Expand Down
2 changes: 1 addition & 1 deletion src/app/(flow)/onboarding.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export default function OnboardingScreen(): JSX.Element {
if (Platform.OS === 'ios') {
void Haptics.selectionAsync()
}
setOnboarded(true)
setOnboarded()
toggleUpdated()
setAnalyticsAllowed(true)
router.navigate({
Expand Down
7 changes: 6 additions & 1 deletion src/app/(screens)/profile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import { DashboardContext, UserKindContext } from '@/components/contexts'
import { queryClient } from '@/components/provider'
import { USER_STUDENT } from '@/data/constants'
import { useRefreshByUser } from '@/hooks'
import { useFoodFilterStore } from '@/hooks/useFoodFilterStore'
import { usePreferencesStore } from '@/hooks/usePreferencesStore'
import { type FormListSections } from '@/types/components'
import { getPersonalData, networkError, performLogout } from '@/utils/api-utils'
import { useQuery } from '@tanstack/react-query'
Expand Down Expand Up @@ -36,7 +38,8 @@ export default function Profile(): JSX.Element {
const { resetOrder } = useContext(DashboardContext)
const { t } = useTranslation('settings')
const [isLoggingOut, setIsLoggingOut] = React.useState(false)

const resetPreferences = usePreferencesStore((state) => state.reset)
const resetFood = useFoodFilterStore((state) => state.reset)
const { data, error, isLoading, isPaused, isSuccess, refetch, isError } =
useQuery({
queryKey: ['personalData'],
Expand Down Expand Up @@ -109,6 +112,8 @@ export default function Profile(): JSX.Element {
style: 'destructive',
onPress: () => {
setIsLoggingOut(true)
resetFood()
resetPreferences()
performLogout(toggleUserKind, resetOrder, queryClient)
.catch((e) => {
console.log(e)
Expand Down
6 changes: 6 additions & 0 deletions src/app/(screens)/settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import { queryClient } from '@/components/provider'
import { type UserKindContextType } from '@/contexts/userKind'
import { USER_EMPLOYEE, USER_GUEST, USER_STUDENT } from '@/data/constants'
import { useRefreshByUser } from '@/hooks'
import { useFoodFilterStore } from '@/hooks/useFoodFilterStore'
import { usePreferencesStore } from '@/hooks/usePreferencesStore'
import { type FormListSections } from '@/types/components'
import { type MaterialIcon } from '@/types/material-icons'
import {
Expand Down Expand Up @@ -76,6 +78,8 @@ export default function Settings(): JSX.Element {
const username =
userKind === USER_EMPLOYEE && SecureStore.getItem('username')
const { color, randomizeColor } = useRandomColor()
const resetPreferences = usePreferencesStore((state) => state.reset)
const resetFood = useFoodFilterStore((state) => state.reset)

useEffect(() => {
const { bottomBoundY, topBoundY } = getBounds()
Expand Down Expand Up @@ -157,6 +161,8 @@ export default function Settings(): JSX.Element {
text: t('profile.logout.alert.confirm'),
style: 'destructive',
onPress: () => {
resetPreferences()
resetFood()
performLogout(
toggleUserKind,
resetOrder,
Expand Down
2 changes: 1 addition & 1 deletion src/app/(tabs)/_layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ export default function HomeLayout(): JSX.Element {
const [oldAccentColor] = useMMKVString('accentColor')
// migration of old settings
if (isOnboardedV1 === true) {
setOnboarded(true)
setOnboarded()
storage.delete('isOnboardedv1')
}
if (analyticsV1 === true) {
Expand Down
6 changes: 6 additions & 0 deletions src/components/Dashboard/HeaderRight.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import { DashboardContext, UserKindContext } from '@/components/contexts'
import { queryClient } from '@/components/provider'
import { type UserKindContextType } from '@/contexts/userKind'
import { USER_EMPLOYEE, USER_GUEST, USER_STUDENT } from '@/data/constants'
import { useFoodFilterStore } from '@/hooks/useFoodFilterStore'
import { usePreferencesStore } from '@/hooks/usePreferencesStore'
import { getPersonalData, getUsername, performLogout } from '@/utils/api-utils'
import { getContrastColor, getInitials } from '@/utils/ui-utils'
import { useQuery } from '@tanstack/react-query'
Expand All @@ -22,6 +24,8 @@ export const IndexHeaderRight = (): JSX.Element => {
const { t } = useTranslation(['navigation', 'settings'])
const router = useRouter()
const { styles, theme } = useStyles(stylesheet)
const resetPreferences = usePreferencesStore((state) => state.reset)
const resetFood = useFoodFilterStore((state) => state.reset)

const { userKind = USER_GUEST } =
useContext<UserKindContextType>(UserKindContext)
Expand Down Expand Up @@ -90,6 +94,8 @@ export const IndexHeaderRight = (): JSX.Element => {
text: t('profile.logout.alert.confirm', { ns: 'settings' }),
style: 'destructive',
onPress: () => {
resetPreferences()
resetFood()
performLogout(
toggleUserKind,
resetOrder,
Expand Down
19 changes: 0 additions & 19 deletions src/hooks/mmkv.ts

This file was deleted.

11 changes: 5 additions & 6 deletions src/hooks/useFlowStore.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import { convertToMajorMinorPatch } from '@/utils/app-utils'
import { zustandStorage } from '@/utils/storage'
import * as Application from 'expo-application'
import { create } from 'zustand'
import { createJSONStorage, persist } from 'zustand/middleware'

import { zustandStorage } from './mmkv'

interface FlowStore {
isOnboarded: boolean | undefined
setOnboarded: (value: boolean) => void
setOnboarded: () => void

updatedVersion: string | undefined
toggleUpdated: () => void
Expand All @@ -22,8 +21,8 @@ export const useFlowStore = create<FlowStore>()(
persist(
(set) => ({
isOnboarded: undefined,
setOnboarded: (value: boolean) => {
set({ isOnboarded: value })
setOnboarded: () => {
set({ isOnboarded: true })
},

updatedVersion: undefined,
Expand All @@ -39,7 +38,7 @@ export const useFlowStore = create<FlowStore>()(
},
}),
{
name: `flow-store`,
name: 'flow-store',
storage: createJSONStorage(() => zustandStorage),
}
)
Expand Down
31 changes: 24 additions & 7 deletions src/hooks/useFoodFilterStore.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { type LanguageKey } from '@/localization/i18n'
import { zustandStorage } from '@/utils/storage'
import { create } from 'zustand'
import { createJSONStorage, persist } from 'zustand/middleware'

import { zustandStorage } from './mmkv'

export type FoodLanguage = LanguageKey | 'default'

interface FoodFilterStore {
Expand All @@ -18,16 +17,30 @@ interface FoodFilterStore {
toggleSelectedPreferences: (name: string) => void
setShowStatic: (value: boolean) => void
toggleFoodLanguage: (language: string) => void
reset: () => void
}

const initialState: Omit<
FoodFilterStore,
| 'toggleSelectedRestaurant'
| 'toggleSelectedAllergens'
| 'initAllergenSelection'
| 'toggleSelectedPreferences'
| 'setShowStatic'
| 'toggleFoodLanguage'
| 'reset'
> = {
selectedRestaurants: ['IngolstadtMensa', 'Reimanns'],
preferencesSelection: ['veg', 'V'],
allergenSelection: ['not-configured'],
showStatic: undefined,
foodLanguage: 'default',
}

export const useFoodFilterStore = create<FoodFilterStore>()(
persist(
(set) => ({
selectedRestaurants: ['IngolstadtMensa', 'Reimanns'],
preferencesSelection: ['veg', 'V'],
allergenSelection: ['not-configured'],
showStatic: undefined,
foodLanguage: 'default',
...initialState,
toggleSelectedRestaurant: (name: string) => {
set((state) => {
const checked = state.selectedRestaurants.includes(name)
Expand Down Expand Up @@ -80,6 +93,10 @@ export const useFoodFilterStore = create<FoodFilterStore>()(
toggleFoodLanguage: (language: string) => {
set({ foodLanguage: language as FoodLanguage })
},
reset: () => {
set({ ...initialState })
zustandStorage.removeItem('food-filter-store')
},
}),
{
name: 'food-filter-storage',
Expand Down
36 changes: 27 additions & 9 deletions src/hooks/usePreferencesStore.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { defaultQuicklinks } from '@/data/constants'
import { zustandStorage } from '@/utils/storage'
import { create } from 'zustand'
import { createJSONStorage, persist } from 'zustand/middleware'

import { zustandStorage } from './mmkv'

const DEFAULT_ACCENT_COLOR = 'blue'

interface PreferencesStore {
Expand All @@ -21,18 +20,33 @@ interface PreferencesStore {
setTimetableMode: (mode: string) => void
setSelectedDate: (date: Date) => void
addRecentQuicklink: (quicklink: string) => void
reset: () => void
}

const initialState: Omit<
PreferencesStore,
| 'setAccentColor'
| 'setTheme'
| 'setAppIcon'
| 'addUnlockedAppIcon'
| 'setTimetableMode'
| 'setSelectedDate'
| 'addRecentQuicklink'
| 'reset'
> = {
accentColor: DEFAULT_ACCENT_COLOR,
appIcon: undefined,
theme: 'auto',
unlockedAppIcons: [],
timetableMode: undefined,
selectedDate: new Date(),
recentQuicklinks: defaultQuicklinks,
}

export const usePreferencesStore = create<PreferencesStore>()(
persist(
(set) => ({
accentColor: DEFAULT_ACCENT_COLOR,
theme: 'auto',
appIcon: undefined,
unlockedAppIcons: [],
timetableMode: undefined,
selectedDate: new Date(),
recentQuicklinks: defaultQuicklinks,
...initialState,
setAccentColor: (accentColor: string) => {
set({ accentColor })
},
Expand Down Expand Up @@ -81,6 +95,10 @@ export const usePreferencesStore = create<PreferencesStore>()(
return { recentQuicklinks: finalQuicklinks }
})
},
reset: () => {
set(initialState)
zustandStorage.removeItem('app-storage')
},
}),
{
name: 'app-storage',
Expand Down
24 changes: 22 additions & 2 deletions src/utils/storage.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import { createSyncStoragePersister } from '@tanstack/query-sync-storage-persister'
import { MMKV } from 'react-native-mmkv'
import { type StateStorage } from 'zustand/middleware'

export const storage = new MMKV()
export const storage = new MMKV({
id: 'query-client-storage',
})

const clientStorage = {
setItem: (key: string, value: string | number | boolean | Uint8Array) => {
setItem: (key: string, value: string | number | boolean | ArrayBuffer) => {
storage.set(key, value)
},
getItem: (key: string) => {
Expand All @@ -19,3 +22,20 @@ const clientStorage = {
export const syncStoragePersister = createSyncStoragePersister({
storage: clientStorage,
})

export const appStorage = new MMKV({
id: 'user-settings-storage',
})

export const zustandStorage: StateStorage = {
setItem(name, value) {
appStorage.set(name, value)
},
getItem(name) {
const value = appStorage.getString(name)
return value ?? null
},
removeItem(name) {
appStorage.delete(name)
},
}

0 comments on commit fdcc4ee

Please sign in to comment.