diff --git a/ts/RootContainer.tsx b/ts/RootContainer.tsx index 1a15684fa77..fb0fda38843 100644 --- a/ts/RootContainer.tsx +++ b/ts/RootContainer.tsx @@ -6,29 +6,27 @@ import { AppState, AppStateStatus, EmitterSubscription, - NativeEventSubscription, - StatusBar + NativeEventSubscription } from "react-native"; import SplashScreen from "react-native-splash-screen"; import { connect } from "react-redux"; -import configurePushNotifications from "./features/pushNotifications/utils/configurePushNotification"; import DebugInfoOverlay from "./components/DebugInfoOverlay"; import PagoPATestIndicatorOverlay from "./components/PagoPATestIndicatorOverlay"; import { LightModalRoot } from "./components/ui/LightModal"; +import configurePushNotifications from "./features/pushNotifications/utils/configurePushNotification"; import { setLocale } from "./i18n"; import { IONavigationContainer } from "./navigation/AppStackNavigator"; import RootModal from "./screens/modal/RootModal"; import { applicationChangeState } from "./store/actions/application"; import { setDebugCurrentRouteName } from "./store/actions/debug"; import { navigateBack } from "./store/actions/navigation"; +import { setScreenReaderEnabled } from "./store/actions/preferences"; import { isDebugModeEnabledSelector } from "./store/reducers/debug"; import { isPagoPATestEnabledSelector, preferredLanguageSelector } from "./store/reducers/persistedPreferences"; import { GlobalState } from "./store/reducers/types"; -import customVariables from "./theme/variables"; -import { setScreenReaderEnabled } from "./store/actions/preferences"; type Props = ReturnType & typeof mapDispatchToProps; @@ -109,11 +107,6 @@ class RootContainer extends PureComponent { return ( <> - - {/* When debug mode is enabled, the following information diff --git a/ts/components/BonusCard/BonusCardScreenComponent.tsx b/ts/components/BonusCard/BonusCardScreenComponent.tsx index c1d587d1f38..500ce5f6361 100644 --- a/ts/components/BonusCard/BonusCardScreenComponent.tsx +++ b/ts/components/BonusCard/BonusCardScreenComponent.tsx @@ -1,9 +1,15 @@ -import { HeaderActionProps } from "@pagopa/io-app-design-system"; +import { + HeaderActionProps, + IOColors, + useIOThemeContext +} from "@pagopa/io-app-design-system"; import { ReactNode } from "react"; import { Dimensions } from "react-native"; import Animated, { useAnimatedRef } from "react-native-reanimated"; import { useHeaderSecondLevel } from "../../hooks/useHeaderSecondLevel"; import { SupportRequestParams } from "../../hooks/useStartSupportRequest"; +import { isAndroid } from "../../utils/platform"; +import FocusAwareStatusBar from "../ui/FocusAwareStatusBar"; import { IOScrollView, IOScrollViewActions } from "../ui/IOScrollView"; import { BonusCard } from "./BonusCard"; @@ -41,10 +47,24 @@ const BonusCardScreenComponent = ({ const screenHeight = Dimensions.get("window").height; const shouldHideLogo = screenHeight < MIN_HEIGHT_TO_SHOW_FULL_RENDER; + const { themeType } = useIOThemeContext(); + + const isDark = themeType === "dark"; + // We need to check if the card is a CGN type to set the background color + const isCGNType = !cardProps.isLoading && cardProps.cardBackground; + // Custom background color for CGN based on the platform + const cgnBackgroundColor = isAndroid ? IOColors.white : IOColors["grey-50"]; + // If the card is not a CGN type, we set the default header background color as card color + const backgroundColor = isCGNType + ? cgnBackgroundColor + : IOColors["blueIO-50"]; + useHeaderSecondLevel({ title: title || "", transparent: true, supportRequest: true, + variant: "neutral", + backgroundColor, faqCategories, contextualHelpMarkdown, contextualHelp, @@ -54,14 +74,19 @@ const BonusCardScreenComponent = ({ }); return ( - - - {children} - + <> + + + + {children} + + ); }; diff --git a/ts/components/ui/AppHeader.tsx b/ts/components/ui/AppHeader.tsx index a50a69799d7..d141b15baaa 100644 --- a/ts/components/ui/AppHeader.tsx +++ b/ts/components/ui/AppHeader.tsx @@ -4,9 +4,8 @@ import { IOStyles, IOVisualCostants } from "@pagopa/io-app-design-system"; import { PropsWithChildren } from "react"; -import { ColorValue, StatusBar, View, ViewProps } from "react-native"; +import { ColorValue, View, ViewProps } from "react-native"; import { useSafeAreaInsets } from "react-native-safe-area-context"; -import variables from "../../theme/variables"; type Props = ViewProps & { backgroundColor?: ColorValue; @@ -23,10 +22,6 @@ const AppHeader = (props: PropsWithChildren) => { backgroundColor: props.backgroundColor }} > - { const isFocused = useIsFocused(); - return <>{isFocused && }; + + return isFocused && ; }; export default FocusAwareStatusBar; diff --git a/ts/features/bonus/cgn/components/merchants/ModuleCgnDiscount.tsx b/ts/features/bonus/cgn/components/merchants/ModuleCgnDiscount.tsx index cd1d921337f..8df3725f91d 100644 --- a/ts/features/bonus/cgn/components/merchants/ModuleCgnDiscount.tsx +++ b/ts/features/bonus/cgn/components/merchants/ModuleCgnDiscount.tsx @@ -49,6 +49,7 @@ export const CategoryTag = ({ category }: CategoryTagProps) => { return O.isSome(categorySpecs) ? ( { )} -
{discount.name}
+
{discount.name}
{discount.productCategories.map(categoryKey => ( diff --git a/ts/features/bonus/cgn/components/merchants/discount/CgnDiscountHeader.tsx b/ts/features/bonus/cgn/components/merchants/discount/CgnDiscountHeader.tsx index 82bab063c2f..7f5b1c0abeb 100644 --- a/ts/features/bonus/cgn/components/merchants/discount/CgnDiscountHeader.tsx +++ b/ts/features/bonus/cgn/components/merchants/discount/CgnDiscountHeader.tsx @@ -6,7 +6,6 @@ import { IOStyles, VSpacer } from "@pagopa/io-app-design-system"; -import { useHeaderHeight } from "@react-navigation/elements"; import { StyleSheet, View } from "react-native"; import { Discount } from "../../../../../../../definitions/cgn/merchants/Discount"; import I18n from "../../../../../../i18n"; @@ -26,8 +25,6 @@ export const CgnDiscountHeader = ({ ? styles.backgroundNewItem : styles.backgroundDefault; - const headerHeight = useHeaderHeight(); - const { isNew, discount, name, productCategories } = discountDetails; return ( @@ -36,7 +33,6 @@ export const CgnDiscountHeader = ({ style={[ IOStyles.horizontalContentPadding, { - paddingTop: headerHeight, backgroundColor: discountColor.backgroundColor, paddingBottom: 24 } @@ -63,7 +59,7 @@ export const CgnDiscountHeader = ({ )} -

{name}

+

{name}

{productCategories.map(categoryKey => ( diff --git a/ts/features/bonus/cgn/screens/CgnDetailScreen.tsx b/ts/features/bonus/cgn/screens/CgnDetailScreen.tsx index c5696e11d74..07c54e42c0e 100644 --- a/ts/features/bonus/cgn/screens/CgnDetailScreen.tsx +++ b/ts/features/bonus/cgn/screens/CgnDetailScreen.tsx @@ -196,6 +196,7 @@ const CgnDetailScreen = (props: Props): ReactElement => { } cardFooter={

{ }, backgroundColor, canGoBack: true, - supportRequest: true + supportRequest: true, + variant: "neutral" }); useEffect(() => { @@ -256,6 +258,10 @@ const CgnDiscountDetailScreen = () => { if (discountDetails && merchantDetails) { return ( <> + { + const theme = useIOTheme(); const insets = useSafeAreaInsets(); const dispatch = useIODispatch(); const [isPullRefresh, setIsPullRefresh] = useState(false); @@ -110,7 +112,7 @@ export const CgnMerchantCategoriesListScreen = () => { } ); }} - iconColor="grey-300" + iconColor={theme["icon-decorative"]} icon={s.icon} /> ) diff --git a/ts/features/bonus/cgn/screens/merchants/CgnMerchantsListByCategory.tsx b/ts/features/bonus/cgn/screens/merchants/CgnMerchantsListByCategory.tsx index 342b1a5a69b..a2d5e80d50d 100644 --- a/ts/features/bonus/cgn/screens/merchants/CgnMerchantsListByCategory.tsx +++ b/ts/features/bonus/cgn/screens/merchants/CgnMerchantsListByCategory.tsx @@ -3,9 +3,7 @@ import { H3, HSpacer, IOColors, - IOVisualCostants, Icon, - VSpacer, hexToRgba } from "@pagopa/io-app-design-system"; import { Route, useNavigation, useRoute } from "@react-navigation/native"; @@ -13,18 +11,8 @@ import { pipe } from "fp-ts/lib/function"; import * as O from "fp-ts/lib/Option"; import { useCallback, useEffect, useMemo, useState } from "react"; -import { - Dimensions, - LayoutChangeEvent, - Platform, - RefreshControl, - View -} from "react-native"; -import Animated, { - useAnimatedScrollHandler, - useSharedValue -} from "react-native-reanimated"; -import { useSafeAreaInsets } from "react-native-safe-area-context"; +import { Platform, RefreshControl, View } from "react-native"; +import Animated, { useAnimatedRef } from "react-native-reanimated"; import { Merchant } from "../../../../../../definitions/cgn/merchants/Merchant"; import { ProductCategoryEnum } from "../../../../../../definitions/cgn/merchants/ProductCategory"; import { @@ -59,23 +47,11 @@ export type CgnMerchantListByCategoryScreenNavigationParams = Readonly<{ }>; const CgnMerchantsListByCategory = () => { - const screenHeight = Dimensions.get("window").height; - const [titleHeight, setTitleHeight] = useState(0); - const translationY = useSharedValue(0); + // const screenHeight = Dimensions.get("window").height; + // const translationY = useSharedValue(0); - const getTitleHeight = (event: LayoutChangeEvent) => { - const { height } = event.nativeEvent.layout; - if (titleHeight === 0) { - setTitleHeight(height - insets.top - IOVisualCostants.headerHeight); - } - }; - - const scrollHandler = useAnimatedScrollHandler(event => { - // eslint-disable-next-line functional/immutable-data - translationY.value = event.contentOffset.y; - }); + const animatedFlatListRef = useAnimatedRef>(); - const insets = useSafeAreaInsets(); const dispatch = useIODispatch(); const route = useRoute< @@ -148,11 +124,10 @@ const CgnMerchantsListByCategory = () => { ) ) ), - scrollValues: { - contentOffsetY: translationY, - triggerOffset: titleHeight - }, + enableDiscreteTransition: true, + animatedRef: animatedFlatListRef, backgroundColor: categorySpecs?.colors, + variant: categorySpecs?.headerVariant, supportRequest: true, secondAction: { icon: "search", @@ -191,7 +166,6 @@ const CgnMerchantsListByCategory = () => { )} {categorySpecs && ( { } ]} > - { const refreshControl = ( { initLoadingLists(); @@ -241,21 +214,12 @@ const CgnMerchantsListByCategory = () => { /> ); - const getPaddingBottom = () => { - const ELEMENT_HEIGHT = 49; - const totalListElementsHeight = ELEMENT_HEIGHT * merchantsAll.length; - const usedVerticalSpace = - titleHeight + totalListElementsHeight + insets.bottom; - const availableVerticalSpace = screenHeight - usedVerticalSpace; - - return availableVerticalSpace < titleHeight ? availableVerticalSpace : 0; - }; - return ( <> {isError(onlineMerchants) && isError(offlineMerchants) ? ( { /> ) : ( = { @@ -22,70 +28,90 @@ export const categories: Record = { icon: "categCulture", nameKey: "bonus.cgn.merchantDetail.categories.cultureAndEntertainment", colors: "#AA338B", - textColor: "white" + textColor: "white", + statusBarStyle: "light-content", + headerVariant: "contrast" }, [ProductCategoryEnum.health]: { type: ProductCategoryEnum.health, icon: "categWellness", nameKey: "bonus.cgn.merchantDetail.categories.health", colors: "#B5D666", - textColor: "black" + textColor: "black", + statusBarStyle: "dark-content", + headerVariant: "neutral" }, [ProductCategoryEnum.learning]: { type: ProductCategoryEnum.learning, icon: "categLearning", nameKey: "bonus.cgn.merchantDetail.categories.learning", colors: "#2A61AE", - textColor: "white" + textColor: "white", + statusBarStyle: "light-content", + headerVariant: "contrast" }, [ProductCategoryEnum.sports]: { type: ProductCategoryEnum.sports, icon: "categSport", nameKey: "bonus.cgn.merchantDetail.categories.sport", colors: "#65BE72", - textColor: "black" + textColor: "black", + statusBarStyle: "dark-content", + headerVariant: "neutral" }, [ProductCategoryEnum.home]: { type: ProductCategoryEnum.home, icon: "categHome", nameKey: "bonus.cgn.merchantDetail.categories.home", colors: "#F8D547", - textColor: "black" + textColor: "black", + statusBarStyle: "dark-content", + headerVariant: "neutral" }, [ProductCategoryEnum.telephonyAndInternet]: { type: ProductCategoryEnum.telephonyAndInternet, icon: "categTelco", nameKey: "bonus.cgn.merchantDetail.categories.telco", colors: "#0089C7", - textColor: "white" + textColor: "white", + statusBarStyle: "light-content", + headerVariant: "contrast" }, [ProductCategoryEnum.bankingServices]: { type: ProductCategoryEnum.bankingServices, icon: "categFinance", nameKey: "bonus.cgn.merchantDetail.categories.finance", colors: "#4F51A3", - textColor: "white" + textColor: "white", + statusBarStyle: "light-content", + headerVariant: "contrast" }, [ProductCategoryEnum.travelling]: { type: ProductCategoryEnum.travelling, icon: "categTravel", nameKey: "bonus.cgn.merchantDetail.categories.travel", colors: "#E02F6E", - textColor: "white" + textColor: "white", + statusBarStyle: "light-content", + headerVariant: "contrast" }, [ProductCategoryEnum.sustainableMobility]: { type: ProductCategoryEnum.sustainableMobility, icon: "categMobility", nameKey: "bonus.cgn.merchantDetail.categories.mobility", colors: "#00AEB1", - textColor: "black" + textColor: "black", + statusBarStyle: "dark-content", + headerVariant: "neutral" }, [ProductCategoryEnum.jobOffers]: { type: ProductCategoryEnum.jobOffers, icon: "categJobOffers", nameKey: "bonus.cgn.merchantDetail.categories.job", colors: "#FAAE56", - textColor: "black" + textColor: "black", + statusBarStyle: "dark-content", + headerVariant: "neutral" } }; diff --git a/ts/features/design-system/DesignSystem.tsx b/ts/features/design-system/DesignSystem.tsx index 8648b1eaa46..d9501d6bab3 100644 --- a/ts/features/design-system/DesignSystem.tsx +++ b/ts/features/design-system/DesignSystem.tsx @@ -8,7 +8,7 @@ import { VStack, useIOTheme } from "@pagopa/io-app-design-system"; -import { SectionList, StatusBar, useColorScheme } from "react-native"; +import { SectionList } from "react-native"; import { IOStyles } from "../../components/core/variables/IOStyles"; import { useScreenEndMargin } from "../../hooks/useScreenEndMargin"; import { useIONavigation } from "../../navigation/params/AppParamsList"; @@ -85,7 +85,6 @@ const DESIGN_SYSTEM_SECTION_DATA: Array = [ export const DesignSystem = () => { const theme = useIOTheme(); - const colorScheme = useColorScheme(); const navigation = useIONavigation(); const { screenEndMargin } = useScreenEndMargin(); @@ -128,28 +127,22 @@ export const DesignSystem = () => { ) : null; return ( - <> - - `${item.route}-${index}`} - stickySectionHeadersEnabled={false} - contentContainerStyle={[ - IOStyles.horizontalContentPadding, - { - paddingTop: IOVisualCostants.appMarginDefault, - paddingBottom: screenEndMargin - } - ]} - renderSectionHeader={renderDSSection} - renderSectionFooter={renderDSSectionFooter} - SectionSeparatorComponent={() => } - renderItem={renderDSNavItem} - ItemSeparatorComponent={() => } - sections={DESIGN_SYSTEM_SECTION_DATA} - /> - + `${item.route}-${index}`} + stickySectionHeadersEnabled={false} + contentContainerStyle={[ + IOStyles.horizontalContentPadding, + { + paddingTop: IOVisualCostants.appMarginDefault, + paddingBottom: screenEndMargin + } + ]} + renderSectionHeader={renderDSSection} + renderSectionFooter={renderDSSectionFooter} + SectionSeparatorComponent={() => } + renderItem={renderDSNavItem} + ItemSeparatorComponent={() => } + sections={DESIGN_SYSTEM_SECTION_DATA} + /> ); }; diff --git a/ts/features/design-system/components/DesignSystemScreen.tsx b/ts/features/design-system/components/DesignSystemScreen.tsx index 9ef596b7b5e..082bda038d9 100644 --- a/ts/features/design-system/components/DesignSystemScreen.tsx +++ b/ts/features/design-system/components/DesignSystemScreen.tsx @@ -1,11 +1,7 @@ -import { - ContentWrapper, - IOVisualCostants, - useIOTheme -} from "@pagopa/io-app-design-system"; +import { ContentWrapper, IOVisualCostants } from "@pagopa/io-app-design-system"; import { ReactNode } from "react"; -import { ScrollView, StatusBar, View, useColorScheme } from "react-native"; +import { ScrollView, View } from "react-native"; import { useScreenEndMargin } from "../../../hooks/useScreenEndMargin"; type Props = { @@ -15,29 +11,20 @@ type Props = { }; export const DesignSystemScreen = ({ children, noMargin = false }: Props) => { - const colorScheme = useColorScheme(); - const theme = useIOTheme(); - const { screenEndMargin } = useScreenEndMargin(); return ( - <> - - - {noMargin ? ( - {children} - ) : ( - {children} - )} - - + + {noMargin ? ( + {children} + ) : ( + {children} + )} + ); }; diff --git a/ts/features/design-system/core/DSDynamicBackground.tsx b/ts/features/design-system/core/DSDynamicBackground.tsx index a4365fd921f..06811b2436d 100644 --- a/ts/features/design-system/core/DSDynamicBackground.tsx +++ b/ts/features/design-system/core/DSDynamicBackground.tsx @@ -1,12 +1,12 @@ import { Avatar, Body, + BodySmall, ContentWrapper, H3, HStack, IOColors, IOVisualCostants, - BodySmall, RadioGroup, VStack, hexToRgba, @@ -17,17 +17,18 @@ import { Canvas, Group, Image, - LinearGradient as SkiaLinearGradient, Mask, Rect, + LinearGradient as SkiaLinearGradient, useImage, vec } from "@shopify/react-native-skia"; import { useCallback, useMemo, useState } from "react"; -import { Dimensions, Platform, View, StatusBar } from "react-native"; +import { Dimensions, Platform, View } from "react-native"; import { ScrollView } from "react-native-gesture-handler"; -import { useSafeAreaInsets } from "react-native-safe-area-context"; import LinearGradient from "react-native-linear-gradient"; +import { useSafeAreaInsets } from "react-native-safe-area-context"; +import FocusAwareStatusBar from "../../../components/ui/FocusAwareStatusBar"; const cdnPath = "https://assets.cdn.io.italia.it/logos/organizations/"; @@ -98,11 +99,7 @@ export const DSDynamicBackground = () => { return ( <> - + { : undefined } > - {/* The following line is used to show the background color gray that overlay the basic one which is white */} diff --git a/ts/navigation/AppStackNavigator.tsx b/ts/navigation/AppStackNavigator.tsx index 5c0dc1e49ab..8918a0c0cb1 100644 --- a/ts/navigation/AppStackNavigator.tsx +++ b/ts/navigation/AppStackNavigator.tsx @@ -1,5 +1,9 @@ /* eslint-disable functional/immutable-data */ -import { useIOThemeContext } from "@pagopa/io-app-design-system"; +import { + IOColors, + useIOTheme, + useIOThemeContext +} from "@pagopa/io-app-design-system"; import { LinkingOptions, NavigationContainer, @@ -8,13 +12,19 @@ import { import { PropsWithChildren, ReactElement, useEffect, useRef } from "react"; import { Linking, View } from "react-native"; +import { ReactNavigationInstrumentation } from "../App"; import { useStoredExperimentalDesign } from "../common/context/DSExperimentalContext"; +import { useStoredFontPreference } from "../common/context/DSTypefaceContext"; import LoadingSpinnerOverlay from "../components/LoadingSpinnerOverlay"; +import FocusAwareStatusBar from "../components/ui/FocusAwareStatusBar"; import { cgnLinkingOptions } from "../features/bonus/cgn/navigation/navigator"; import { fciLinkingOptions } from "../features/fci/navigation/FciStackNavigator"; import { idPayLinkingOptions } from "../features/idpay/common/navigation/linking"; -import { MESSAGES_ROUTES } from "../features/messages/navigation/routes"; import { IngressScreen } from "../features/ingress/screens/IngressScreen"; +import { useItwLinkingOptions } from "../features/itwallet/navigation/useItwLinkingOptions"; +import { MESSAGES_ROUTES } from "../features/messages/navigation/routes"; +import { SERVICES_ROUTES } from "../features/services/common/navigation/routes"; +import { processUtmLink } from "../features/utmLink"; import { startApplicationInitialization } from "../store/actions/application"; import { setDebugCurrentRouteName } from "../store/actions/debug"; import { useIODispatch, useIOSelector, useIOStore } from "../store/hooks"; @@ -26,17 +36,13 @@ import { IONavigationLightTheme } from "../theme/navigations"; import { isTestEnv } from "../utils/environment"; +import { useOnFirstRender } from "../utils/hooks/useOnFirstRender"; import { IO_INTERNAL_LINK_PREFIX, IO_UNIVERSAL_LINK_PREFIX } from "../utils/navigation"; -import { SERVICES_ROUTES } from "../features/services/common/navigation/routes"; -import { useItwLinkingOptions } from "../features/itwallet/navigation/useItwLinkingOptions"; -import { ReactNavigationInstrumentation } from "../App"; -import { useOnFirstRender } from "../utils/hooks/useOnFirstRender"; -import { processUtmLink } from "../features/utmLink"; -import { useStoredFontPreference } from "../common/context/DSTypefaceContext"; import AuthenticatedStackNavigator from "./AuthenticatedStackNavigator"; +import { linkingSubscription } from "./linkingSubscription"; import NavigationService, { navigationRef, setMainNavigatorReady @@ -44,7 +50,6 @@ import NavigationService, { import NotAuthenticatedStackNavigator from "./NotAuthenticatedStackNavigator"; import { AppParamsList } from "./params/AppParamsList"; import ROUTES from "./routes"; -import { linkingSubscription } from "./linkingSubscription"; type OnStateChangeStateType = Parameters< NonNullable @@ -94,6 +99,7 @@ const InnerNavigationContainer = (props: InnerNavigationContainerProps) => { // Dark/Light Mode const { themeType } = useIOThemeContext(); + const theme = useIOTheme(); const linking: LinkingOptions = { enabled: !isTestEnv, // disable linking in test env @@ -184,6 +190,11 @@ const InnerNavigationContainer = (props: InnerNavigationContainerProps) => { routeNameRef.current = currentRouteName; }} > + {props.children} ); diff --git a/ts/theme/variables.ts b/ts/theme/variables.ts index 12e72de5ae4..ab2a3afa3d5 100644 --- a/ts/theme/variables.ts +++ b/ts/theme/variables.ts @@ -93,8 +93,6 @@ const customVariables = { headerBodyFontSize: 14, headerBodyFontWeight: "600" as FontWeight, - androidStatusBarColor: IOColors.white, - // Text textColor: IOColors["grey-700"], textMessageDetailLinkColor: "#0073E6",