diff --git a/src/queries/ChoreQueries.jsx b/src/queries/ChoreQueries.jsx index 6af620e..68ad1b3 100644 --- a/src/queries/ChoreQueries.jsx +++ b/src/queries/ChoreQueries.jsx @@ -1,6 +1,7 @@ import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query' import { useState } from 'react' import { networkManager } from '../hooks/NetworkManager' +import { FEATURES, isFeatureEnabled } from '../utils/FeatureToggle' import { CreateChore, GetChoreByID, @@ -17,6 +18,11 @@ export const useChores = includeArchive => { queryFn: async () => { const onlineChores = await GetChoresNew(includeArchive) + // Only handle offline tasks if experimental offline mode is enabled + if (!isFeatureEnabled(FEATURES.OFFLINE_MODE)) { + return onlineChores + } + const offlineTasks = (await localStore.getFromCache('offlineTasks')) || [] // go throught each and if there is two chores with same id in offline and online, prefer the offline one: var finalChores = [] @@ -58,7 +64,7 @@ export const useCreateChore = () => { return useMutation({ mutationFn: CreateChore, onMutate: async newTask => { - if (!networkManager.isOnline) { + if (!networkManager.isOnline && isFeatureEnabled(FEATURES.OFFLINE_MODE)) { const tempId = crypto.randomUUID() // Generate temp ID const offlineTasks = (await localStore.getFromCache('offlineTasks')) || [] @@ -95,7 +101,7 @@ export const useUpdateChore = () => { return useMutation({ mutationFn: async updatedChore => { - if (!networkManager.isOnline) { + if (!networkManager.isOnline && isFeatureEnabled(FEATURES.OFFLINE_MODE)) { updatedChore['updatedAt'] = new Date().toISOString() if (!updatedChore['nextDueDate']) { updatedChore['nextDueDate'] = updatedChore['dueDate'] @@ -150,7 +156,7 @@ export const useUpdateChore = () => { queryClient.invalidateQueries(['chores']) }, onMutate: async updatedChore => { - if (!networkManager.isOnline) { + if (!networkManager.isOnline && isFeatureEnabled(FEATURES.OFFLINE_MODE)) { // Handle offline case here if needed return } @@ -192,6 +198,11 @@ export const useChoreDetails = choreId => { console.error('Error fetching chore detail:', error) } + // Only check offline tasks if experimental offline mode is enabled + if (!isFeatureEnabled(FEATURES.OFFLINE_MODE)) { + return onlineChore + } + const offlineTasks = (await localStore.getFromCache('offlineTasks')) || [] const offline = offlineTasks.find(task => { // Match by tempId or id if it was created offline @@ -224,6 +235,11 @@ export const useChore = choreId => { console.error('Error fetching chore detail:', error) } + // Only check offline tasks if experimental offline mode is enabled + if (!isFeatureEnabled(FEATURES.OFFLINE_MODE)) { + return onlineChore + } + const offlineTasks = (await localStore.getFromCache('offlineTasks')) || [] const offline = offlineTasks.find(task => { return ( diff --git a/src/utils/Chores.jsx b/src/utils/Chores.jsx index a2c5551..8beb774 100644 --- a/src/utils/Chores.jsx +++ b/src/utils/Chores.jsx @@ -327,21 +327,21 @@ export const notInCompletionWindow = chore => { moment().add(chore.completionWindow, 'hours') < moment(chore.nextDueDate) ) } -export const ChoreFilters = userProfile => ({ +export const ChoreFilters = userId => ({ anyone: () => true, assigned_to_me: chore => { - return chore.assignedTo && chore.assignedTo === userProfile?.id + return chore.assignedTo && chore.assignedTo === userId }, assigned_to_others: chore => { - return chore.assignedTo && chore.assignedTo !== userProfile?.id + return chore.assignedTo && chore.assignedTo !== userId }, assigned_to_me_tasks: chore => { return ( chore.assignees && - chore.assignees.some(assignee => assignee.userId === userProfile?.id) + chore.assignees.some(assignee => assignee.userId === userId) ) }, created_by_me: chore => { - return chore.createdBy && chore.createdBy === userProfile?.id + return chore.createdBy && chore.createdBy === userId }, }) diff --git a/src/views/Chores/MyChores.jsx b/src/views/Chores/MyChores.jsx index 20a7360..69c51a3 100644 --- a/src/views/Chores/MyChores.jsx +++ b/src/views/Chores/MyChores.jsx @@ -146,7 +146,9 @@ const MyChores = () => { const sections = ChoresGrouper( selectedChoreSection, sortedChores, - ChoreFilters(userProfile)[selectedChoreFilter], + ChoreFilters(impersonatedUser?.userId || userProfile?.id)[ + selectedChoreFilter + ], ) setChoreSections(sections) if (localStorage.getItem('openChoreSections') === null) { @@ -537,7 +539,11 @@ const MyChores = () => { ) } - return choresToFilter.filter(ChoreFilters(userProfile)[selectedChoreFilter]) + return choresToFilter.filter( + ChoreFilters(impersonatedUser?.userId || userProfile?.id)[ + selectedChoreFilter + ], + ) } // Helper function to get chores for a specific date @@ -567,7 +573,9 @@ const MyChores = () => { ChoresGrouper( selectedChoreSection, newChores, - ChoreFilters(userProfile)[selectedChoreFilter], + ChoreFilters(impersonatedUser?.userId || userProfile?.id)[ + selectedChoreFilter + ], ), ) setSearchFilter('All') @@ -641,7 +649,9 @@ const MyChores = () => { ChoresGrouper( selectedChoreSection, newChores, - ChoreFilters(userProfile)[selectedChoreFilter], + ChoreFilters(impersonatedUser?.userId || userProfile?.id)[ + selectedChoreFilter + ], ), ) @@ -715,7 +725,9 @@ const MyChores = () => { ChoresGrouper( selectedChoreSection, newChores, - ChoreFilters(userProfile)[selectedChoreFilter], + ChoreFilters(impersonatedUser?.userId || userProfile?.id)[ + selectedChoreFilter + ], ), ) } @@ -982,7 +994,9 @@ const MyChores = () => { ChoresGrouper( selectedChoreSection, newChores, - ChoreFilters(userProfile)[selectedChoreFilter], + ChoreFilters(impersonatedUser?.userId || userProfile?.id)[ + selectedChoreFilter + ], ), ) } @@ -1155,7 +1169,9 @@ const MyChores = () => { const section = ChoresGrouper( selectedChoreSection, chores, - ChoreFilters(impersonatedUser | userProfile)[filter], + ChoreFilters(impersonatedUser?.userId || userProfile?.id)[ + filter + ], ) setChoreSections(section) setOpenChoreSectionsWithCache( @@ -1170,7 +1186,9 @@ const MyChores = () => { const section = ChoresGrouper( selected.value, chores, - ChoreFilters(userProfile)[selectedChoreFilter], + ChoreFilters(impersonatedUser?.userId || userProfile?.id)[ + selectedChoreFilter + ], ) setChoreSections(section) setSelectedChoreSectionWithCache(selected.value) diff --git a/src/views/Settings/StorageSettings.jsx b/src/views/Settings/StorageSettings.jsx index c5cdf29..66259c8 100644 --- a/src/views/Settings/StorageSettings.jsx +++ b/src/views/Settings/StorageSettings.jsx @@ -1,8 +1,20 @@ import { Capacitor } from '@capacitor/core' -import { Button, Card, Chip, LinearProgress, Typography } from '@mui/joy' +import { + Button, + Card, + Chip, + LinearProgress, + Switch, + Typography, +} from '@mui/joy' import { useEffect, useState } from 'react' import { useNavigate } from 'react-router-dom' import { useUserProfile } from '../../queries/UserQueries' +import { + FEATURES, + isFeatureEnabled, + setFeatureEnabled, +} from '../../utils/FeatureToggle' import { GetStorageUsage } from '../../utils/Fetcher' import { isPlusAccount } from '../../utils/Helpers' import ConfirmationModal from '../Modals/Inputs/ConfirmationModal' @@ -14,6 +26,9 @@ const StorageSettings = () => { const [usage, setUsage] = useState({ used: 0, total: 0 }) const [loading, setLoading] = useState(true) const [confirmModalConfig, setConfirmModalConfig] = useState({}) + const [offlineModeEnabled, setOfflineModeEnabledState] = useState( + isFeatureEnabled(FEATURES.OFFLINE_MODE), + ) const showConfirmation = ( message, @@ -39,6 +54,11 @@ const StorageSettings = () => { }) } + const handleOfflineModeToggle = enabled => { + setOfflineModeEnabledState(enabled) + setFeatureEnabled(FEATURES.OFFLINE_MODE, enabled) + } + useEffect(() => { if (isPlusAccount(userProfile)) { GetStorageUsage().then(resp => { @@ -106,6 +126,40 @@ const StorageSettings = () => { )} + + + + Experimental Features + + Coming Soon + + +
+
+ + Enable Offline Mode + + + Allows the app to work offline by caching data locally. This is + experimental and may cause some slowness. If you experience + performance issues, we recommend turning this off. + +
+ handleOfflineModeToggle(event.target.checked)} + sx={{ ml: 2 }} + /> +
+ {offlineModeEnabled && ( + + ⚠️ Offline mode is enabled. If you experience slowness, disable + this setting. + + )} +
+ {Capacitor.isNativePlatform() ? 'App' : 'Browser'} Local Storage &