diff --git a/code/aspen_app/src/components/Action/CheckOut/CheckOut.js b/code/aspen_app/src/components/Action/CheckOut/CheckOut.js index cc0184334b..2ca7c810c8 100644 --- a/code/aspen_app/src/components/Action/CheckOut/CheckOut.js +++ b/code/aspen_app/src/components/Action/CheckOut/CheckOut.js @@ -1,4 +1,4 @@ -import { Button, ButtonSpinner, ButtonGroup, ButtonIcon, ButtonText } from '@gluestack-ui/themed'; +import { Box, Button, ButtonSpinner, ButtonGroup, ButtonIcon, ButtonText, Text } from '@gluestack-ui/themed'; import React from 'react'; import _ from 'lodash'; import { useQueryClient } from '@tanstack/react-query'; @@ -56,10 +56,6 @@ export const CheckOut = (props) => { size="md" bgColor={theme['colors']['primary']['500']} variant="solid" - style={{ - flex: 1, - flexWrap: 'wrap', - }} onPress={async () => { setLoading(true); await completeAction(record, type, user.id, null, null, null, library.baseUrl).then(async (eContentResponse) => { diff --git a/code/aspen_app/src/components/Action/Holds/HoldPrompt.js b/code/aspen_app/src/components/Action/Holds/HoldPrompt.js index c52a50ea29..cc7aebfd7d 100644 --- a/code/aspen_app/src/components/Action/Holds/HoldPrompt.js +++ b/code/aspen_app/src/components/Action/Holds/HoldPrompt.js @@ -316,7 +316,7 @@ export const HoldPrompt = (props) => { } }); }}> - {loading ? : {title}} + {loading ? : {title}} diff --git a/code/aspen_app/src/components/Action/Holds/PlaceHold.js b/code/aspen_app/src/components/Action/Holds/PlaceHold.js index 5151e6f227..be3a09f395 100644 --- a/code/aspen_app/src/components/Action/Holds/PlaceHold.js +++ b/code/aspen_app/src/components/Action/Holds/PlaceHold.js @@ -159,7 +159,7 @@ export const PlaceHold = (props) => { }); }}> {loading ? ( - + ) : ( {title} diff --git a/code/aspen_app/src/components/Action/LoadOverDriveSample.js b/code/aspen_app/src/components/Action/LoadOverDriveSample.js index 762a751200..1388ca8109 100644 --- a/code/aspen_app/src/components/Action/LoadOverDriveSample.js +++ b/code/aspen_app/src/components/Action/LoadOverDriveSample.js @@ -1,38 +1,29 @@ import React from 'react'; -import { Button } from 'native-base'; +import { ButtonSpinner, Button, ButtonText } from '@gluestack-ui/themed'; // custom components and helper files -import {LibrarySystemContext, UserContext} from '../../context/initialContext'; +import { LibrarySystemContext, ThemeContext, UserContext } from '../../context/initialContext'; import { completeAction } from '../../util/recordActions'; export const LoadOverDriveSample = (props) => { - const { user } = React.useContext(UserContext); - const { library } = React.useContext(LibrarySystemContext); - const [loading, setLoading] = React.useState(false); + const { user } = React.useContext(UserContext); + const { library } = React.useContext(LibrarySystemContext); + const [loading, setLoading] = React.useState(false); + const { theme } = React.useContext(ThemeContext); - return ( - - ); + return ( + + ); }; \ No newline at end of file diff --git a/code/aspen_app/src/components/Action/OpenSideLoad.js b/code/aspen_app/src/components/Action/OpenSideLoad.js index 70be60b436..ff48ed1576 100644 --- a/code/aspen_app/src/components/Action/OpenSideLoad.js +++ b/code/aspen_app/src/components/Action/OpenSideLoad.js @@ -1,32 +1,31 @@ +import { Button, ButtonText, ButtonSpinner } from '@gluestack-ui/themed'; import React from 'react'; -import { Button } from 'native-base'; +import { ThemeContext } from '../../context/initialContext'; // custom components and helper files -import {openSideLoad} from '../../util/recordActions'; +import { openSideLoad } from '../../util/recordActions'; export const OpenSideLoad = (props) => { - const [loading, setLoading] = React.useState(false); + const [loading, setLoading] = React.useState(false); + const { theme } = React.useContext(ThemeContext); - return ( - - ); + return ( + + ); }; \ No newline at end of file diff --git a/code/aspen_app/src/components/LibraryCardScanner.js b/code/aspen_app/src/components/LibraryCardScanner.js index bef797db92..12142a3936 100644 --- a/code/aspen_app/src/components/LibraryCardScanner.js +++ b/code/aspen_app/src/components/LibraryCardScanner.js @@ -6,7 +6,7 @@ import { StyleSheet } from 'react-native'; import BarcodeMask from 'react-native-barcode-mask'; import { navigate } from '../helpers/RootNavigator'; import { loadError } from './loadError'; -import { loadingSpinner } from './loadingSpinner'; +import { LoadingSpinner, loadingSpinner } from './loadingSpinner'; export default function LibraryCardScanner() { const navigation = useNavigation(); @@ -35,7 +35,7 @@ export default function LibraryCardScanner() { }; if (hasPermission === null) { - return loadingSpinner('Requesting for camera permissions'); + return LoadingSpinner('Requesting for camera permissions'); } if (hasPermission === false) { diff --git a/code/aspen_app/src/components/NotificationsOnboard.js b/code/aspen_app/src/components/NotificationsOnboard.js index 28975983cf..61a9998de4 100644 --- a/code/aspen_app/src/components/NotificationsOnboard.js +++ b/code/aspen_app/src/components/NotificationsOnboard.js @@ -1,15 +1,15 @@ import { useFocusEffect } from '@react-navigation/native'; import { useQueryClient } from '@tanstack/react-query'; -import { AlertDialog, Button } from 'native-base'; +import { Text, CheckIcon, Heading, HStack, VStack, Badge, BadgeText, FlatList, Button, ButtonGroup, ButtonText, ButtonIcon, Box, Icon, Center, AlertDialog, AlertDialogContent, AlertDialogHeader, AlertDialogBody, AlertDialogFooter, AlertDialogBackdrop, Select, SelectTrigger, SelectInput, SelectIcon, SelectPortal, SelectBackdrop, SelectContent, SelectDragIndicatorWrapper, SelectDragIndicator, SelectItem, SelectScrollView, ButtonSpinner } from '@gluestack-ui/themed'; import React from 'react'; -import { LanguageContext, LibrarySystemContext, UserContext } from '../context/initialContext'; +import { LanguageContext, LibrarySystemContext, ThemeContext, UserContext } from '../context/initialContext'; import { navigateStack } from '../helpers/RootNavigator'; import { getTermFromDictionary } from '../translations/TranslationService'; import { refreshProfile, updateNotificationOnboardingStatus } from '../util/api/user'; export const NotificationsOnboard = (props) => { const queryClient = useQueryClient(); - const { setAlreadyCheckedNotifications, setShowNotificationsOnboarding } = props; + const { setPromptOpen } = props; const { language } = React.useContext(LanguageContext); const { library } = React.useContext(LibrarySystemContext); const { user, notificationSettings, expoToken, notificationOnboard, updateNotificationOnboard, updateNotificationSettings } = React.useContext(UserContext); @@ -18,6 +18,7 @@ export const NotificationsOnboard = (props) => { const [onboardingButton, setOnboardingButton] = React.useState(''); const [isLoading, setIsLoading] = React.useState(false); const [isCanceling, setIsCanceling] = React.useState(false); + const { colorMode, theme, textColor } = React.useContext(ThemeContext); const onClose = async () => { await updateNotificationOnboardingStatus(false, expoToken, library.baseUrl, language); await refreshProfile(library.baseUrl).then((profile) => { @@ -28,6 +29,7 @@ export const NotificationsOnboard = (props) => { updateNotificationOnboard(0); setIsLoading(false); setIsCanceling(false); + setPromptOpen(''); //setAlreadyCheckedNotifications(true); //setShowNotificationsOnboarding(false); }; @@ -65,36 +67,41 @@ export const NotificationsOnboard = (props) => { return ( onClose()}> - - {getTermFromDictionary(language, 'onboard_notifications_title')} - {onboardingBody} - - + + + + {getTermFromDictionary(language, 'onboard_notifications_title')} + + + {onboardingBody} + + + - - - + + + ); }; \ No newline at end of file diff --git a/code/aspen_app/src/context/initialContext.js b/code/aspen_app/src/context/initialContext.js index 11f32f8291..9ba0a11fcf 100644 --- a/code/aspen_app/src/context/initialContext.js +++ b/code/aspen_app/src/context/initialContext.js @@ -249,6 +249,8 @@ export const LibrarySystemProvider = ({ children }) => { }; const updateCatalogStatus = (data) => { + console.log(data); + if (data.status) { setCatalogStatus(data.status); console.log('updated catalog status'); @@ -364,26 +366,31 @@ export const UserProvider = ({ children }) => { const [notificationOnboard, setNotificationOnboard] = useState(0); const [expoToken, setExpoToken] = useState(false); const [aspenToken, setAspenToken] = useState(false); + const [seenNotificationOnboardPrompt, setSeenNotificationOnboardPrompt] = useState(true); const updateUser = (data) => { - if (_.isObject(data) && !_.isUndefined(data.lastListUsed)) { - PATRON.listLastUsed = data.lastListUsed; - } + if (user !== data) { + if (_.isObject(data) && !_.isUndefined(data.lastListUsed)) { + PATRON.listLastUsed = data.lastListUsed; + } - if (_.isObject(data) && !_.isUndefined(data.numHolds)) { - PATRON.num.holds = data.numHolds; - } + if (_.isObject(data) && !_.isUndefined(data.numHolds)) { + PATRON.num.holds = data.numHolds; + } - if (_.isObject(data) && !_.isUndefined(data.notification_preferences)) { - updateNotificationSettings(data.notification_preferences, data.interfaceLanguage ?? 'en', data.onboardAppNotifications); - } + if (_.isObject(data) && !_.isUndefined(data.notification_preferences)) { + updateNotificationSettings(data.notification_preferences, data.interfaceLanguage ?? 'en', data.onboardAppNotifications); + } - if (_.isObject(data) && !_.isUndefined(data.onboardAppNotifications)) { - updateNotificationOnboard(data.onboardAppNotifications); - } + if (_.isObject(data) && !_.isUndefined(data.onboardAppNotifications)) { + updateNotificationOnboard(data.onboardAppNotifications); + } - setUser(data); - console.log('updated UserContext'); + setUser(data); + console.log('updated UserContext'); + } else { + console.log("User data hasn't changed"); + } }; const resetUser = () => { @@ -487,13 +494,11 @@ export const UserProvider = ({ children }) => { setExpoToken(false); setAspenToken(false); - // let's not intentionally bombard the user with prompts at every boot without knowing their preferences - setNotificationOnboard(0); - const deviceSettings = _.filter(data, { device: 'Unknown' }); if (deviceSettings && _.isObject(deviceSettings)) { if (_.isObject(deviceSettings[0])) { const settings = deviceSettings[0]; + console.log(settings); if (!_.isUndefined(settings.onboardStatus)) { setNotificationOnboard(settings.onboardStatus); } @@ -547,6 +552,11 @@ export const UserProvider = ({ children }) => { console.log('updated notification settings in UserContext'); }; + const updateSeenNotificationOnboardPrompt = (data) => { + setSeenNotificationOnboardPrompt(data); + console.log('updated seenNotificationOnboardPrompt UserContext'); + }; + const updateExpoToken = (data) => { setExpoToken(data); console.log('updated expo token UserContext'); @@ -592,6 +602,8 @@ export const UserProvider = ({ children }) => { updateAspenToken, notificationOnboard, updateNotificationOnboard, + seenNotificationOnboardPrompt, + updateSeenNotificationOnboardPrompt, }}> {children} diff --git a/code/aspen_app/src/navigations/drawer/DrawerContent.js b/code/aspen_app/src/navigations/drawer/DrawerContent.js index 547fdfc437..6a11c0939b 100644 --- a/code/aspen_app/src/navigations/drawer/DrawerContent.js +++ b/code/aspen_app/src/navigations/drawer/DrawerContent.js @@ -2,9 +2,11 @@ import { MaterialIcons } from '@expo/vector-icons'; import AsyncStorage from '@react-native-async-storage/async-storage'; import { DrawerContentScrollView } from '@react-navigation/drawer'; import { useFocusEffect, useLinkTo } from '@react-navigation/native'; +import { useQuery, useQueryClient } from '@tanstack/react-query'; import Constants from 'expo-constants'; import * as Linking from 'expo-linking'; import * as Notifications from 'expo-notifications'; +import * as SecureStore from 'expo-secure-store'; import _ from 'lodash'; import { Badge, Box, Button, Container, Divider, HStack, Icon, Image, Pressable, Text, useColorModeValue, useToken, VStack } from 'native-base'; import React from 'react'; @@ -12,14 +14,21 @@ import { AuthContext } from '../../components/navigation'; // custom components and helper files import { showILSMessage } from '../../components/Notifications'; -import { LanguageContext, LibrarySystemContext, UserContext } from '../../context/initialContext'; +import { BrowseCategoryContext, CheckoutsContext, HoldsContext, LanguageContext, LibraryBranchContext, LibrarySystemContext, SystemMessagesContext, UserContext } from '../../context/initialContext'; import { navigateStack } from '../../helpers/RootNavigator'; +import { CatalogOffline } from '../../screens/Auth/CatalogOffline'; +import { InvalidCredentials } from '../../screens/Auth/InvalidCredentials'; import { UseColorMode } from '../../themes/theme'; import { getTermFromDictionary, getTranslationsWithValues, LanguageSwitcher } from '../../translations/TranslationService'; -import { reloadProfile } from '../../util/api/user'; +import { fetchSavedEvents } from '../../util/api/event'; +import { getCatalogStatus } from '../../util/api/library'; +import { getLists } from '../../util/api/list'; +import { getLocations } from '../../util/api/location'; +import { fetchReadingHistory, fetchSavedSearches, getLinkedAccounts, getPatronCheckedOutItems, getPatronHolds, getViewerAccounts, reloadProfile, revalidateUser, validateSession } from '../../util/api/user'; import { passUserToDiscovery } from '../../util/apiAuth'; -import { formatDiscoveryVersion } from '../../util/loadLibrary'; -import { getILSMessages } from '../../util/loadPatron'; +import { GLOBALS } from '../../util/globals'; +import { formatDiscoveryVersion, getPickupLocations, reloadBrowseCategories } from '../../util/loadLibrary'; +import { getBrowseCategoryListForUser, getILSMessages, PATRON } from '../../util/loadPatron'; Notifications.setNotificationHandler({ handleNotification: async () => ({ @@ -32,13 +41,26 @@ Notifications.setNotificationHandler({ const prefix = Linking.createURL('/'); export const DrawerContent = () => { + const [userLatitude, setUserLatitude] = React.useState(0); + const [userLongitude, setUserLongitude] = React.useState(0); const linkTo = useLinkTo(); - const { user, updateUser } = React.useContext(UserContext); - const { library } = React.useContext(LibrarySystemContext); + const queryClient = useQueryClient(); + const { user, accounts, viewers, cards, lists, updateUser, updateLanguage, updatePickupLocations, updateLinkedAccounts, updateLists, updateSavedEvents, updateLibraryCards, updateLinkedViewerAccounts, updateReadingHistory, notificationSettings, expoToken, updateNotificationOnboard, notificationOnboard } = React.useContext(UserContext); + const { library, catalogStatus, updateCatalogStatus } = React.useContext(LibrarySystemContext); const [notifications, setNotifications] = React.useState([]); const [messages, setILSMessages] = React.useState([]); + const { category, list, maxNum, updateBrowseCategories, updateBrowseCategoryList, updateMaxCategories } = React.useContext(BrowseCategoryContext); + const { checkouts, updateCheckouts } = React.useContext(CheckoutsContext); + const { holds, updateHolds, pendingSortMethod, readySortMethod } = React.useContext(HoldsContext); const { language } = React.useContext(LanguageContext); + const [invalidSession, setInvalidSession] = React.useState(false); const discoveryVersion = formatDiscoveryVersion(library.discoveryVersion) ?? '23.03.00'; + const { location, locations, updateLocations } = React.useContext(LibraryBranchContext); + const { systemMessages, updateSystemMessages } = React.useContext(SystemMessagesContext); + const [numFailedSessions, setNumFailedSessions] = React.useState(0); + const [unlimited, setUnlimitedCategories] = React.useState(false); + const [savedSearchesStorage, updateSavedSearchesStorage] = React.useState([]); + const [maxCategories, setMaxCategories] = React.useState(5); React.useEffect(() => { const subscription = Notifications.addNotificationReceivedListener((notification) => { @@ -54,9 +76,226 @@ export const DrawerContent = () => { return () => subscription.remove(); }, []); + useQuery(['catalog_status', library.baseUrl], () => getCatalogStatus(library.baseUrl), { + enabled: !!library.baseUrl, + refetchInterval: 60 * 1000 * 5, + refetchIntervalInBackground: true, + onSuccess: (data) => { + updateCatalogStatus(data); + }, + }); + + useQuery(['user', library.baseUrl, language], () => reloadProfile(library.baseUrl), { + initialData: user, + refetchInterval: 60 * 1000 * 15, + refetchIntervalInBackground: true, + notifyOnChangeProps: ['data'], + onSuccess: (data) => { + if (user) { + if (data !== user) { + updateUser(data); + updateLanguage(data.interfaceLanguage ?? 'en'); + PATRON.language = data.interfaceLanguage ?? 'en'; + } + } else { + updateUser(data); + updateLanguage(data.interfaceLanguage ?? 'en'); + PATRON.language = data.interfaceLanguage ?? 'en'; + } + }, + }); + + useQuery(['browse_categories', library.baseUrl, language, maxNum], () => reloadBrowseCategories(maxNum, library.baseUrl), { + refetchInterval: 60 * 1000 * 15, + refetchIntervalInBackground: true, + onSuccess: (data) => { + updateBrowseCategories(data); + }, + placeholderData: category, + }); + + useQuery(['holds', user.id, library.baseUrl, language], () => getPatronHolds(readySortMethod, pendingSortMethod, 'all', library.baseUrl, false, language), { + refetchInterval: 60 * 1000 * 15, + refetchIntervalInBackground: true, + notifyOnChangeProps: ['data'], + onSuccess: (data) => updateHolds(data), + placeholderData: [], + }); + + useQuery(['checkouts', user.id, library.baseUrl, language], () => getPatronCheckedOutItems('all', library.baseUrl, false, language), { + refetchInterval: 60 * 1000 * 15, + refetchIntervalInBackground: true, + notifyOnChangeProps: ['data'], + onSuccess: (data) => updateCheckouts(data), + placeholderData: [], + }); + + useQuery(['lists', user.id, library.baseUrl, language], () => getLists(library.baseUrl), { + refetchInterval: 60 * 1000 * 15, + refetchIntervalInBackground: true, + notifyOnChangeProps: ['data'], + onSuccess: (data) => updateLists(data), + placeholderData: [], + }); + + useQuery(['linked_accounts', user, cards ?? [], library.baseUrl, language], () => getLinkedAccounts(user, cards, library.barcodeStyle, library.baseUrl, language), { + initialData: accounts, + refetchInterval: 60 * 1000 * 15, + refetchIntervalInBackground: true, + notifyOnChangeProps: ['data'], + onSuccess: (data) => { + if (accounts !== data.accounts) { + updateLinkedAccounts(data.accounts); + } + }, + placeholderData: [], + }); + + useQuery(['library_cards', user, cards ?? [], library.baseUrl, language], () => getLinkedAccounts(user, cards, library.barcodeStyle, library.baseUrl, language), { + initialData: cards, + refetchInterval: 60 * 1000 * 15, + refetchIntervalInBackground: true, + onSuccess: (data) => { + if (cards !== data.cards) { + updateLibraryCards(data.cards); + } + }, + placeholderData: [], + }); + + useQuery(['viewer_accounts', user.id, library.baseUrl, language], () => getViewerAccounts(library.baseUrl, language), { + initialData: viewers, + refetchInterval: 60 * 1000 * 15, + refetchIntervalInBackground: true, + notifyOnChangeProps: ['data'], + onSuccess: (data) => { + updateLinkedViewerAccounts(data); + }, + placeholderData: [], + }); + + useQuery(['ils_messages', user.id, library.baseUrl, language], () => getILSMessages(library.baseUrl), { + refetchInterval: 60 * 1000 * 5, + refetchIntervalInBackground: true, + placeholderData: [], + }); + + useQuery(['pickup_locations', library.baseUrl, language], () => getPickupLocations(library.baseUrl), { + refetchInterval: 60 * 1000 * 30, + refetchIntervalInBackground: true, + placeholderData: [], + onSuccess: (data) => { + updatePickupLocations(data); + }, + }); + + useQuery(['locations', library.baseUrl, language, userLatitude, userLongitude], () => getLocations(library.baseUrl, language, userLatitude, userLongitude), { + refetchInterval: 60 * 1000 * 30, + refetchIntervalInBackground: true, + placeholderData: [], + onSuccess: (data) => { + updateLocations(data); + }, + }); + + useQuery(['saved_searches', user?.id ?? 'unknown', library.baseUrl, language], () => fetchSavedSearches(library.baseUrl, language), { + refetchInterval: 60 * 1000 * 5, + refetchIntervalInBackground: true, + placeholderData: [], + onSuccess: (data) => { + updateSavedSearchesStorage(data); + }, + }); + + useQuery(['reading_history', user.id, library.baseUrl, 1, 'checkedOut'], () => fetchReadingHistory(1, 25, 'checkedOut', library.baseUrl, language), { + refetchInterval: 60 * 1000 * 30, + refetchIntervalInBackground: true, + placeholderData: [], + onSuccess: (data) => { + updateReadingHistory(data); + }, + }); + + useQuery(['saved_events', user.id, library.baseUrl, 1, 'upcoming'], () => fetchSavedEvents(1, 25, 'upcoming', library.baseUrl), { + refetchInterval: 60 * 1000 * 15, + refetchIntervalInBackground: true, + placeholderData: [], + onSuccess: (data) => { + updateSavedEvents(data.events); + }, + }); + + useQuery(['saved_events', user?.id ?? 'unknown', library.baseUrl, 1, 'all'], () => fetchSavedEvents(1, 25, 'all', library.baseUrl), { + refetchInterval: 60 * 1000 * 15, + refetchIntervalInBackground: true, + placeholderData: [], + onSuccess: (data) => { + updateSavedEvents(data.events); + }, + }); + + useQuery(['saved_events', user.id, library.baseUrl, 1, 'past'], () => fetchSavedEvents(1, 25, 'past', library.baseUrl), { + refetchInterval: 60 * 1000 * 15, + refetchIntervalInBackground: true, + placeholderData: [], + onSuccess: (data) => { + updateSavedEvents(data.events); + }, + }); + + useQuery(['browse_categories_list', library.baseUrl, language], () => getBrowseCategoryListForUser(library.baseUrl), { + refetchInterval: 60 * 1000 * 15, + refetchIntervalInBackground: true, + placeholderData: [], + onSuccess: (data) => { + updateBrowseCategoryList(data); + }, + }); + + useQuery(['session', library.baseUrl, user.id], () => validateSession(library.baseUrl), { + initialData: GLOBALS.appSessionId, + refetchInterval: 86400000, + refetchIntervalInBackground: true, + retry: 5, + onSuccess: (data) => { + if (typeof data.result?.session !== 'undefined') { + GLOBALS.appSessionId = data.result.session; + } + }, + }); + + useQuery(['valid_user', library.baseUrl, user.id], () => revalidateUser(library.baseUrl), { + initialData: true, + refetchInterval: 60 * 1000 * 5, + refetchIntervalInBackground: true, + retry: 5, + onSuccess: (data) => { + if (data === false || data === 'false') { + let tmp = numFailedSessions; + tmp = tmp + 1; + setNumFailedSessions(tmp); + console.log('Added +1 to numFailedSessions'); + if (tmp >= 2) { + console.log('More than two failed sessions, logging user out'); + setInvalidSession(true); + } + setInvalidSession(false); + } else { + console.log('Resetting numFailedSessions to 0'); + setNumFailedSessions(0); + setInvalidSession(false); + } + }, + }); + useFocusEffect( React.useCallback(() => { const update = async () => { + let latitude = await SecureStore.getItemAsync('latitude'); + let longitude = await SecureStore.getItemAsync('longitude'); + setUserLatitude(latitude); + setUserLongitude(longitude); + await reloadProfile(library.baseUrl).then((result) => { if (user !== result) { updateUser(result); @@ -141,6 +380,14 @@ export const DrawerContent = () => { return null; }; + if (catalogStatus > 0) { + return ; + } + + if (invalidSession === true || invalidSession === 'true') { + return ; + } + return ( diff --git a/code/aspen_app/src/navigations/stack/BrowseStackNavigator.js b/code/aspen_app/src/navigations/stack/BrowseStackNavigator.js index 20d612fdc5..d97850a839 100644 --- a/code/aspen_app/src/navigations/stack/BrowseStackNavigator.js +++ b/code/aspen_app/src/navigations/stack/BrowseStackNavigator.js @@ -17,7 +17,7 @@ import { SearchSourceScreen } from '../../screens/Search/Facets/SearchSource'; import { FiltersScreen } from '../../screens/Search/Filters'; import { SearchResultsForBrowseCategory } from '../../screens/Search/SearchByCategory'; import { SearchResultsForList } from '../../screens/Search/SearchByList'; -import SearchBySavedSearch from '../../screens/Search/SearchBySavedSearch'; +import { SearchResultsForSavedSearch } from '../../screens/Search/SearchBySavedSearch'; import { SearchResults } from '../../screens/Search/SearchResults'; import { getTermFromDictionary } from '../../translations/TranslationService'; @@ -135,7 +135,7 @@ const BrowseStackNavigator = () => { ({ title: getTermFromDictionary(language, 'results_for') + ' ' + route.params.title, libraryContext: React.useContext(LibrarySystemContext), diff --git a/code/aspen_app/src/screens/Auth/Loading.js b/code/aspen_app/src/screens/Auth/Loading.js index 452119a02c..ab68a7a8c2 100644 --- a/code/aspen_app/src/screens/Auth/Loading.js +++ b/code/aspen_app/src/screens/Auth/Loading.js @@ -82,7 +82,6 @@ export const LoadingScreen = () => { }); }); - // Return the function to unsubscribe from the event so it gets removed on unmount return unsubscribe; }, [navigation]); @@ -172,7 +171,7 @@ export const LoadingScreen = () => { }, }); - const { status: browseCategoryQueryStatus, data: browseCategoryQuery } = useQuery(['browse_categories', LIBRARY.url], () => reloadBrowseCategories(5, LIBRARY.url), { + const { status: browseCategoryQueryStatus, data: browseCategoryQuery } = useQuery(['browse_categories', LIBRARY.url, 'en', false], () => reloadBrowseCategories(5, LIBRARY.url), { enabled: hasError === false && !!libraryLinksQuery && !!userQueryStatus, onSuccess: (data) => { setProgress(60); @@ -212,15 +211,22 @@ export const LoadingScreen = () => { const { status: linkedAccountQueryStatus, data: linkedAccountQuery } = useQuery(['linked_accounts', user ?? [], cards ?? [], LIBRARY.url, 'en'], () => getLinkedAccounts(user ?? [], cards ?? [], library.barcodeStyle, LIBRARY.url, 'en'), { enabled: hasError === false && !!selfCheckQuery, onSuccess: (data) => { - setProgress(90); updateLinkedAccounts(data.accounts); + setIsReloading(false); + }, + }); + + const { status: libraryCardsQueryStatus, data: libraryCardsQuery } = useQuery(['library_cards', user ?? [], cards ?? [], LIBRARY.url, 'en'], () => getLinkedAccounts(user ?? [], cards ?? [], library.barcodeStyle, LIBRARY.url, 'en'), { + enabled: hasError === false && !!linkedAccountQuery, + onSuccess: (data) => { + setProgress(90); updateLibraryCards(data.cards); setIsReloading(false); }, }); const { status: systemMessagesQueryStatus, data: systemMessagesQuery } = useQuery(['system_messages', LIBRARY.url], () => getSystemMessages(library.libraryId, location.locationId, LIBRARY.url), { - enabled: hasError === false && !!linkedAccountQuery, + enabled: hasError === false && !!libraryCardsQuery, onSuccess: (data) => { setProgress(100); updateSystemMessages(data); @@ -237,7 +243,7 @@ export const LoadingScreen = () => { return ; } - if ((isReloading && librarySystemQueryStatus === 'loading') || catalogStatusQueryStatus === 'loading' || userQueryStatus === 'loading' || browseCategoryQueryStatus === 'loading' || browseCategoryListQueryStatus === 'loading' || languagesQueryStatus === 'loading' || libraryBranchQueryStatus === 'loading' || linkedAccountQueryStatus === 'loading' || systemMessagesQueryStatus === 'loading') { + if ((isReloading && librarySystemQueryStatus === 'loading') || catalogStatusQueryStatus === 'loading' || userQueryStatus === 'loading' || browseCategoryQueryStatus === 'loading' || browseCategoryListQueryStatus === 'loading' || languagesQueryStatus === 'loading' || libraryBranchQueryStatus === 'loading' || linkedAccountQueryStatus === 'loading' || libraryCardsQueryStatus === 'loading' || systemMessagesQueryStatus === 'loading') { return (
@@ -252,7 +258,7 @@ export const LoadingScreen = () => { ); } - if ((!isReloading && librarySystemQueryStatus === 'success') || catalogStatusQueryStatus === 'success' || userQueryStatus === 'success' || browseCategoryQueryStatus === 'success' || browseCategoryListQueryStatus === 'success' || languagesQueryStatus === 'success' || libraryBranchQueryStatus === 'success' || linkedAccountQueryStatus === 'success' || systemMessagesQueryStatus === 'success') { + if ((!isReloading && librarySystemQueryStatus === 'success') || catalogStatusQueryStatus === 'success' || userQueryStatus === 'success' || browseCategoryQueryStatus === 'success' || browseCategoryListQueryStatus === 'success' || languagesQueryStatus === 'success' || libraryBranchQueryStatus === 'success' || linkedAccountQueryStatus === 'success' || libraryCardsQueryStatus === 'success' || systemMessagesQueryStatus === 'success') { if (hasIncomingUrlChanged) { let url = decodeURIComponent(incomingUrl).replace(/\+/g, ' '); url = url.replace('aspen-lida://', prefix); @@ -328,6 +334,4 @@ async function checkStoreVersion() { url: null, latest: GLOBALS.appVersion, }; -} - -export default LoadingScreen; \ No newline at end of file +} \ No newline at end of file diff --git a/code/aspen_app/src/screens/BrowseCategory/Category.js b/code/aspen_app/src/screens/BrowseCategory/Category.js index c42c6bb2d9..5b212ca648 100644 --- a/code/aspen_app/src/screens/BrowseCategory/Category.js +++ b/code/aspen_app/src/screens/BrowseCategory/Category.js @@ -7,7 +7,7 @@ import { LibrarySystemContext } from '../../context/initialContext'; import { getTermFromDictionary } from '../../translations/TranslationService'; const DisplayBrowseCategory = (props) => { - const { language, id, user, renderRecords, libraryUrl, records, categoryLabel, categoryKey, loadMore, categorySource, discoveryVersion, onPressCategory, categoryList, hideCategory, isHidden, textColor } = props; + const { language, id, renderRecords, libraryUrl, records, categoryLabel, categoryKey, loadMore, categorySource, discoveryVersion, onPressCategory, categoryList, hideCategory, isHidden, textColor } = props; const hide = getTermFromDictionary(language, 'hide'); let key = categoryKey; @@ -16,6 +16,10 @@ const DisplayBrowseCategory = (props) => { } //console.log(categoryLabel + ': ' + isHidden); + if (isHidden) { + return null; + } + //console.log(records); if (typeof records !== 'undefined' || typeof records !== 'subCategories') { @@ -33,7 +37,7 @@ const DisplayBrowseCategory = (props) => { pb="$5" sx={{ '@base': { - height: 225, + height: categorySource === 'SavedSearch' ? 240 : 225, }, '@lg': { height: 325, diff --git a/code/aspen_app/src/screens/BrowseCategory/Home.js b/code/aspen_app/src/screens/BrowseCategory/Home.js index 0ee35af936..619031c563 100644 --- a/code/aspen_app/src/screens/BrowseCategory/Home.js +++ b/code/aspen_app/src/screens/BrowseCategory/Home.js @@ -1,8 +1,7 @@ import { ScanBarcode, SearchIcon, XIcon, Settings, RotateCwIcon, ClockIcon } from 'lucide-react-native'; -import { Center, Box, Button, ButtonGroup, ButtonIcon, ButtonText, ButtonSpinner, HStack, Icon, Badge, BadgeText, FormControl, Input, InputField, InputSlot, InputIcon, Pressable, ScrollView, Text } from '@gluestack-ui/themed'; +import { Center, Box, Button, ButtonGroup, ButtonIcon, ButtonText, ButtonSpinner, HStack, Badge, BadgeText, FormControl, Input, InputField, InputSlot, InputIcon, Pressable, ScrollView, Text } from '@gluestack-ui/themed'; import { useFocusEffect, useIsFocused, useNavigation } from '@react-navigation/native'; -import { useIsFetching, useQuery, useQueryClient } from '@tanstack/react-query'; -import * as SecureStore from 'expo-secure-store'; +import { useIsFetching, useQueryClient } from '@tanstack/react-query'; import _ from 'lodash'; import React from 'react'; import { Image } from 'expo-image'; @@ -11,44 +10,28 @@ import { Image } from 'expo-image'; import { loadingSpinner } from '../../components/loadingSpinner'; import { DisplaySystemMessage } from '../../components/Notifications'; import { NotificationsOnboard } from '../../components/NotificationsOnboard'; -import { BrowseCategoryContext, CheckoutsContext, HoldsContext, LanguageContext, LibraryBranchContext, LibrarySystemContext, SearchContext, SystemMessagesContext, ThemeContext, UserContext } from '../../context/initialContext'; +import { BrowseCategoryContext, LanguageContext, LibrarySystemContext, SearchContext, SystemMessagesContext, ThemeContext, UserContext } from '../../context/initialContext'; import { navigateStack } from '../../helpers/RootNavigator'; import { getTermFromDictionary } from '../../translations/TranslationService'; -import { fetchSavedEvents } from '../../util/api/event'; -import { getCatalogStatus } from '../../util/api/library'; -import { getLists } from '../../util/api/list'; -import { getLocations } from '../../util/api/location'; -import { fetchReadingHistory, fetchSavedSearches, getLinkedAccounts, getPatronCheckedOutItems, getPatronHolds, getViewerAccounts, reloadProfile, revalidateUser, validateSession } from '../../util/api/user'; -import { GLOBALS } from '../../util/globals'; -import { formatDiscoveryVersion, getPickupLocations, reloadBrowseCategories } from '../../util/loadLibrary'; -import { getBrowseCategoryListForUser, getILSMessages, PATRON, updateBrowseCategoryStatus } from '../../util/loadPatron'; +import { formatDiscoveryVersion } from '../../util/loadLibrary'; +import { updateBrowseCategoryStatus } from '../../util/loadPatron'; import { getDefaultFacets, getSearchIndexes, getSearchSources } from '../../util/search'; -import { CatalogOffline } from '../Auth/CatalogOffline'; -import { InvalidCredentials } from '../Auth/InvalidCredentials'; import DisplayBrowseCategory from './Category'; const blurhash = 'MHPZ}tt7*0WC5S-;ayWBofj[K5RjM{ofM_'; -let maxCategories = 5; - export const DiscoverHomeScreen = () => { + const isFetchingBrowseCategories = useIsFetching({ queryKey: ['browse_categories'] }); const isFocused = useIsFocused(); const isQueryFetching = useIsFetching(); const queryClient = useQueryClient(); const navigation = useNavigation(); - const [invalidSession, setInvalidSession] = React.useState(false); const [loading, setLoading] = React.useState(false); - const [userLatitude, setUserLatitude] = React.useState(0); - const [userLongitude, setUserLongitude] = React.useState(0); const [showNotificationsOnboarding, setShowNotificationsOnboarding] = React.useState(false); - const [alreadyCheckedNotifications, setAlreadyCheckedNotifications] = React.useState(true); - const { user, accounts, cards, lists, updateUser, updateLanguage, updatePickupLocations, updateLinkedAccounts, updateLists, updateSavedEvents, updateLibraryCards, updateLinkedViewerAccounts, updateReadingHistory, notificationSettings, expoToken, updateNotificationOnboard, notificationOnboard } = React.useContext(UserContext); - const { library, updateCatalogStatus, catalogStatus } = React.useContext(LibrarySystemContext); + const { notificationOnboard, updateNotificationOnboard } = React.useContext(UserContext); + const { library } = React.useContext(LibrarySystemContext); const [preliminaryLoadingCheck, setPreliminaryCheck] = React.useState(false); - const { location, locations, updateLocations } = React.useContext(LibraryBranchContext); - const { category, list, updateBrowseCategories, updateBrowseCategoryList, updateMaxCategories } = React.useContext(BrowseCategoryContext); - const { checkouts, updateCheckouts } = React.useContext(CheckoutsContext); - const { holds, updateHolds, pendingSortMethod, readySortMethod } = React.useContext(HoldsContext); + const { category, updateMaxCategories, maxNum } = React.useContext(BrowseCategoryContext); const { language } = React.useContext(LanguageContext); const version = formatDiscoveryVersion(library.discoveryVersion); const [searchTerm, setSearchTerm] = React.useState(''); @@ -56,7 +39,7 @@ export const DiscoverHomeScreen = () => { const { updateIndexes, updateSources, updateCurrentIndex, updateCurrentSource } = React.useContext(SearchContext); const { theme, mode, textColor } = React.useContext(ThemeContext); const [unlimited, setUnlimitedCategories] = React.useState(false); - const [numFailedSessions, setNumFailedSessions] = React.useState(0); + const [promptOpen, setPromptOpen] = React.useState(''); navigation.setOptions({ headerLeft: () => { @@ -64,215 +47,9 @@ export const DiscoverHomeScreen = () => { }, }); - useQuery(['catalog_status', library.baseUrl], () => getCatalogStatus(library.baseUrl), { - enabled: !!library.baseUrl, - refetchInterval: 60 * 1000 * 5, - refetchIntervalInBackground: true, - onSuccess: (data) => { - updateCatalogStatus(data); - }, - }); - - useQuery(['user', library.baseUrl, language], () => reloadProfile(library.baseUrl), { - initialData: user, - refetchInterval: 60 * 1000 * 15, - refetchIntervalInBackground: true, - notifyOnChangeProps: ['data'], - onSuccess: (data) => { - if (user) { - if (data !== user) { - updateUser(data); - updateLanguage(data.interfaceLanguage ?? 'en'); - PATRON.language = data.interfaceLanguage ?? 'en'; - } - } else { - updateUser(data); - updateLanguage(data.interfaceLanguage ?? 'en'); - PATRON.language = data.interfaceLanguage ?? 'en'; - } - }, - }); - - const { status, data, error, isFetching, isPreviousData } = useQuery(['browse_categories', library.baseUrl, language], () => reloadBrowseCategories(maxCategories, library.baseUrl), { - initialData: category, - refetchInterval: 60 * 1000 * 15, - refetchIntervalInBackground: true, - onSuccess: (data) => { - if (maxCategories === 9999) { - setUnlimitedCategories(true); - } - updateBrowseCategories(data); - setLoading(false); - }, - onSettle: (data) => { - setLoading(false); - }, - placeholderData: [], - }); - - useQuery(['holds', user.id, library.baseUrl, language], () => getPatronHolds(readySortMethod, pendingSortMethod, 'all', library.baseUrl, false, language), { - refetchInterval: 60 * 1000 * 15, - refetchIntervalInBackground: true, - notifyOnChangeProps: ['data'], - onSuccess: (data) => updateHolds(data), - placeholderData: [], - }); - - useQuery(['checkouts', user.id, library.baseUrl, language], () => getPatronCheckedOutItems('all', library.baseUrl, false, language), { - refetchInterval: 60 * 1000 * 15, - refetchIntervalInBackground: true, - notifyOnChangeProps: ['data'], - onSuccess: (data) => updateCheckouts(data), - placeholderData: [], - }); - - useQuery(['lists', user.id, library.baseUrl, language], () => getLists(library.baseUrl), { - refetchInterval: 60 * 1000 * 15, - refetchIntervalInBackground: true, - notifyOnChangeProps: ['data'], - onSuccess: (data) => updateLists(data), - placeholderData: [], - }); - - useQuery(['linked_accounts', user, cards ?? [], library.baseUrl, language], () => getLinkedAccounts(user, cards, library.barcodeStyle, library.baseUrl, language), { - refetchInterval: 60 * 1000 * 15, - refetchIntervalInBackground: true, - notifyOnChangeProps: ['data'], - onSuccess: (data) => { - updateLinkedAccounts(data.accounts); - updateLibraryCards(data.cards); - }, - placeholderData: [], - }); - - useQuery(['viewer_accounts', user.id, library.baseUrl, language], () => getViewerAccounts(library.baseUrl, language), { - refetchInterval: 60 * 1000 * 15, - refetchIntervalInBackground: true, - notifyOnChangeProps: ['data'], - onSuccess: (data) => { - updateLinkedViewerAccounts(data); - }, - placeholderData: [], - }); - - useQuery(['ils_messages', user.id, library.baseUrl, language], () => getILSMessages(library.baseUrl), { - refetchInterval: 60 * 1000 * 5, - refetchIntervalInBackground: true, - placeholderData: [], - }); - - useQuery(['pickup_locations', library.baseUrl, language], () => getPickupLocations(library.baseUrl), { - refetchInterval: 60 * 1000 * 30, - refetchIntervalInBackground: true, - placeholderData: [], - onSuccess: (data) => { - updatePickupLocations(data); - }, - }); - - useQuery(['locations', library.baseUrl, language, userLatitude, userLongitude], () => getLocations(library.baseUrl, language, userLatitude, userLongitude), { - refetchInterval: 60 * 1000 * 30, - refetchIntervalInBackground: true, - placeholderData: [], - onSuccess: (data) => { - updateLocations(data); - }, - }); - - useQuery(['saved_searches', user?.id ?? 'unknown', library.baseUrl, language], () => fetchSavedSearches(library.baseUrl, language), { - refetchInterval: 60 * 1000 * 5, - refetchIntervalInBackground: true, - placeholderData: [], - onSuccess: (data) => { - console.log(data); - }, - }); - - useQuery(['reading_history', user.id, library.baseUrl, 1, 'checkedOut'], () => fetchReadingHistory(1, 25, 'checkedOut', library.baseUrl, language), { - refetchInterval: 60 * 1000 * 30, - refetchIntervalInBackground: true, - placeholderData: [], - onSuccess: (data) => { - updateReadingHistory(data); - }, - }); - - useQuery(['saved_events', user.id, library.baseUrl, 1, 'upcoming'], () => fetchSavedEvents(1, 25, 'upcoming', library.baseUrl), { - refetchInterval: 60 * 1000 * 15, - refetchIntervalInBackground: true, - placeholderData: [], - onSuccess: (data) => { - updateSavedEvents(data.events); - }, - }); - - useQuery(['saved_events', user?.id ?? 'unknown', library.baseUrl, 1, 'all'], () => fetchSavedEvents(1, 25, 'all', library.baseUrl), { - refetchInterval: 60 * 1000 * 15, - refetchIntervalInBackground: true, - placeholderData: [], - onSuccess: (data) => { - updateSavedEvents(data.events); - }, - }); - - useQuery(['saved_events', user.id, library.baseUrl, 1, 'past'], () => fetchSavedEvents(1, 25, 'past', library.baseUrl), { - refetchInterval: 60 * 1000 * 15, - refetchIntervalInBackground: true, - placeholderData: [], - onSuccess: (data) => { - updateSavedEvents(data.events); - }, - }); - - useQuery(['browse_categories_list', library.baseUrl, language], () => getBrowseCategoryListForUser(library.baseUrl), { - refetchInterval: 60 * 1000 * 15, - refetchIntervalInBackground: true, - placeholderData: [], - onSuccess: (data) => { - updateBrowseCategoryList(data); - }, - }); - - useQuery(['session', library.baseUrl, user.id], () => validateSession(library.baseUrl), { - refetchInterval: 86400000, - refetchIntervalInBackground: true, - onSuccess: (data) => { - if (typeof data.result?.session !== 'undefined') { - GLOBALS.appSessionId = data.result.session; - } - }, - }); - - useQuery(['valid_user', library.baseUrl, user.id], () => revalidateUser(library.baseUrl), { - refetchInterval: 60 * 1000 * 5, - refetchIntervalInBackground: true, - onSuccess: (data) => { - if (data === false || data === 'false') { - let tmp = numFailedSessions; - tmp = tmp + 1; - setNumFailedSessions(tmp); - console.log('Added +1 to numFailedSessions'); - if (tmp >= 2) { - console.log('More than two failed sessions, logging user out'); - setInvalidSession(true); - } - setInvalidSession(false); - } else { - console.log('Resetting numFailedSessions to 0'); - setNumFailedSessions(0); - setInvalidSession(false); - } - }, - }); - useFocusEffect( React.useCallback(() => { const checkSettings = async () => { - let latitude = await SecureStore.getItemAsync('latitude'); - let longitude = await SecureStore.getItemAsync('longitude'); - setUserLatitude(latitude); - setUserLongitude(longitude); - if (version >= '24.02.00') { updateCurrentIndex('Keyword'); updateCurrentSource('local'); @@ -293,15 +70,18 @@ export const DiscoverHomeScreen = () => { console.log('notificationOnboard: ' + notificationOnboard); if (!_.isUndefined(notificationOnboard)) { if (notificationOnboard === 1 || notificationOnboard === 2 || notificationOnboard === '1' || notificationOnboard === '2') { + console.log('Notification onboarding preferences found. Set to 1 or 2. Show onboard prompt.'); setShowNotificationsOnboarding(true); - //setAlreadyCheckedNotifications(false); + setPromptOpen('yes'); } else { + console.log('Notification onboarding preferences found. Set to 0. Do not show onboard prompt.'); setShowNotificationsOnboarding(false); - //setAlreadyCheckedNotifications(true); + setPromptOpen(''); } } else { + console.log('No notification onboarding preferences found. Show onboard prompt.'); + setPromptOpen('yes'); setShowNotificationsOnboarding(true); - //setAlreadyCheckedNotifications(false); } }; checkSettings().then(() => { @@ -331,16 +111,13 @@ export const DiscoverHomeScreen = () => { // load notification onboarding prompt if (isQueryFetching === 0 && preliminaryLoadingCheck) { if (notificationOnboard !== '0' && notificationOnboard !== 0) { - if (isFocused) { - return ; + if (isFocused && promptOpen === 'yes') { + console.log('promptOpen: ' + promptOpen); + return ; } } } - if (catalogStatus > 0) { - return ; - } - const renderHeader = (title, key, user, url) => { return ( @@ -389,7 +166,6 @@ export const DiscoverHomeScreen = () => { } if (type === 'Event') { - console.log(id); if (_.includes(id, 'lc_')) { type = 'library_calendar_event'; } @@ -428,13 +204,6 @@ export const DiscoverHomeScreen = () => { height: 250, }, }}> - {version >= '22.08.00' && isNew ? ( - - - {getTermFromDictionary(language, 'flag_new')} - - - ) : null} {item.title_display} { transition={1000} contentFit="cover" /> + {isNew ? ( + + + + {getTermFromDictionary(language, 'flag_new')} + + + + ) : null} ); }; const onPressItem = (key, type, title, version) => { - if (version >= '22.07.00') { - console.log('type: ' + type); - console.log('key: ' + key); - if (type === 'List' || type === 'list') { - navigateStack('BrowseTab', 'SearchByList', { - id: key, - url: library.baseUrl, - title: title, - userContext: user, - libraryContext: library, - prevRoute: 'HomeScreen', - }); - } else if (type === 'SavedSearch') { - navigateStack('BrowseTab', 'SearchBySavedSearch', { - id: key, - url: library.baseUrl, - title: title, - userContext: user, - libraryContext: library, - prevRoute: 'HomeScreen', - }); - } else if (type === 'Event' || _.includes(type, '_event')) { - let eventSource = 'unknown'; - if (type === 'communico_event') { - eventSource = 'communico'; - } else if (type === 'library_calendar_event') { - eventSource = 'library_calendar'; - } else if (type === 'springshare_libcal_event') { - eventSource = 'springshare'; - } else if (type === 'assabet_event') { - eventSource = 'assabet'; - } - - navigateStack('BrowseTab', 'EventScreen', { - id: key, - title: title, - source: eventSource, - prevRoute: 'HomeScreen', - }); - } else { - navigateStack('BrowseTab', 'GroupedWorkScreen', { - id: key, - title: title, - prevRoute: 'HomeScreen', - }); + if (type === 'List' || type === 'list') { + navigateStack('BrowseTab', 'SearchByList', { + id: key, + title: title, + prevRoute: 'HomeScreen', + }); + } else if (type === 'SavedSearch') { + navigateStack('BrowseTab', 'SearchBySavedSearch', { + id: key, + title: title, + prevRoute: 'HomeScreen', + }); + } else if (type === 'Event' || _.includes(type, '_event')) { + let eventSource = 'unknown'; + if (type === 'communico_event') { + eventSource = 'communico'; + } else if (type === 'library_calendar_event') { + eventSource = 'library_calendar'; + } else if (type === 'springshare_libcal_event') { + eventSource = 'springshare'; + } else if (type === 'assabet_event') { + eventSource = 'assabet'; } + + navigateStack('BrowseTab', 'EventScreen', { + id: key, + title: title, + source: eventSource, + prevRoute: 'HomeScreen', + }); } else { navigateStack('BrowseTab', 'GroupedWorkScreen', { id: key, - url: library.baseUrl, title: title, - userContext: user, - libraryContext: library, prevRoute: 'HomeScreen', }); } @@ -515,23 +274,24 @@ export const DiscoverHomeScreen = () => { const onHideCategory = async (url, category) => { setLoading(true); await updateBrowseCategoryStatus(category); - queryClient.invalidateQueries({ queryKey: ['browse_categories', library.baseUrl, language] }); - queryClient.invalidateQueries({ queryKey: ['browse_categories_list', library.baseUrl, language] }); + await queryClient.invalidateQueries({ queryKey: ['browse_categories', library.baseUrl, language, maxNum] }); + await queryClient.invalidateQueries({ queryKey: ['browse_categories_list', library.baseUrl, language] }); + setLoading(false); }; - const onRefreshCategories = () => { + const onRefreshCategories = async () => { setLoading(true); - queryClient.invalidateQueries({ queryKey: ['browse_categories', library.baseUrl, language] }); - queryClient.invalidateQueries({ queryKey: ['browse_categories_list', library.baseUrl, language] }); + await queryClient.invalidateQueries({ queryKey: ['browse_categories', library.baseUrl, language, maxNum] }); + await queryClient.invalidateQueries({ queryKey: ['browse_categories_list', library.baseUrl, language] }); + setLoading(false); }; const onLoadAllCategories = () => { - setLoading(true); - maxCategories = 9999; updateMaxCategories(9999); setUnlimitedCategories(true); - queryClient.invalidateQueries({ queryKey: ['browse_categories', library.baseUrl, language] }); - queryClient.invalidateQueries({ queryKey: ['browse_categories_list', library.baseUrl, language] }); + setLoading(true); + queryClient.invalidateQueries({ queryKey: ['browse_categories', library.baseUrl, language, maxNum] }); + setLoading(false); }; const onPressSettings = () => { @@ -549,17 +309,12 @@ export const DiscoverHomeScreen = () => { navigateStack('BrowseTab', screen, { title: label, id: key, - url: library.baseUrl, - libraryContext: library, - userContext: user, - language: language, }); }; const showSystemMessage = () => { if (_.isArray(systemMessages)) { return systemMessages.map((obj, index, collection) => { - console.log(obj); if (obj.showOn === '0') { return ; } @@ -568,14 +323,10 @@ export const DiscoverHomeScreen = () => { return null; }; - if (loading === true || isFetching) { + if (loading === true || isFetchingBrowseCategories) { return loadingSpinner(); } - if (invalidSession === true || invalidSession === 'true') { - return ; - } - const clearSearch = () => { setSearchTerm(''); }; @@ -601,9 +352,9 @@ export const DiscoverHomeScreen = () => { {category.map((item, index) => { - return ; + return ; })} - + ); @@ -613,7 +364,7 @@ const ButtonOptions = (props) => { const { theme } = React.useContext(ThemeContext); const [loading, setLoading] = React.useState(false); const [refreshing, setRefreshing] = React.useState(false); - const { language, onPressSettings, onRefreshCategories, libraryUrl, patronId, discoveryVersion, loadAll, onLoadAllCategories } = props; + const { language, onPressSettings, onRefreshCategories, discoveryVersion, maxNum, onLoadAllCategories } = props; const version = formatDiscoveryVersion(discoveryVersion); @@ -629,31 +380,29 @@ const ButtonOptions = (props) => { flexDirection: 'row', }, }}> - {!loadAll ? ( - - ) : null} + size="sm" + fontWeight="$medium"> + {getTermFromDictionary(language, 'browse_categories_load_all')} + + - + { } */ useQuery(['linked_accounts', user, cards, library.baseUrl, language], () => getLinkedAccounts(user, cards, library.barcodeStyle, library.baseUrl, language), { + initialData: accounts, onSuccess: (data) => { updateLinkedAccounts(data.accounts); + }, + placeholderData: [], + }); + + useQuery(['library_cards', user, cards, library.baseUrl, language], () => getLinkedAccounts(user, cards, library.barcodeStyle, library.baseUrl, language), { + initialData: cards, + onSuccess: (data) => { updateLibraryCards(data.cards); }, placeholderData: [], diff --git a/code/aspen_app/src/screens/MyAccount/ReadingHistory/ReadingHistory.js b/code/aspen_app/src/screens/MyAccount/ReadingHistory/ReadingHistory.js index 7f094ffb23..3656703bcf 100644 --- a/code/aspen_app/src/screens/MyAccount/ReadingHistory/ReadingHistory.js +++ b/code/aspen_app/src/screens/MyAccount/ReadingHistory/ReadingHistory.js @@ -12,7 +12,7 @@ import { loadError } from '../../../components/loadError'; import { loadingSpinner } from '../../../components/loadingSpinner'; import { DisplaySystemMessage } from '../../../components/Notifications'; -import { LanguageContext, LibrarySystemContext, SystemMessagesContext, UserContext } from '../../../context/initialContext'; +import { LanguageContext, LibrarySystemContext, SystemMessagesContext, ThemeContext, UserContext } from '../../../context/initialContext'; import { getAuthor, getCleanTitle, getFormat, getTitle } from '../../../helpers/item'; import { navigateStack } from '../../../helpers/RootNavigator'; import { getTermFromDictionary, getTranslationsWithValues } from '../../../translations/TranslationService'; @@ -35,6 +35,7 @@ export const MyReadingHistory = () => { const pageSize = 25; const systemMessagesForScreen = []; const [paginationLabel, setPaginationLabel] = React.useState('Page 1 of 1'); + const { textColor } = React.useContext(ThemeContext); const [sortBy, setSortBy] = React.useState({ title: 'Sort by Title', @@ -223,6 +224,10 @@ export const MyReadingHistory = () => { { {