diff --git a/__snapshots__/features/share/pages/ShareAppModal.native.test.tsx.native-snap b/__snapshots__/features/share/pages/ShareAppModal.native.test.tsx.native-snap
index bef6e4b734c..ee6fee64b45 100644
--- a/__snapshots__/features/share/pages/ShareAppModal.native.test.tsx.native-snap
+++ b/__snapshots__/features/share/pages/ShareAppModal.native.test.tsx.native-snap
@@ -5,7 +5,7 @@ exports[`ShareAppModal should match snapshot 1`] = `
accessibilityLabelledBy="testUuidV4"
animationType="fade"
hardwareAccelerated={false}
- onRequestClose={[Function]}
+ onRequestClose={[MockFunction]}
statusBarTranslucent={true}
transparent={true}
visible={true}
@@ -229,15 +229,12 @@ exports[`ShareAppModal should match snapshot 1`] = `
]
}
/>
-
- 35 % des jeunes en France n’ont pas encore le pass Culture.
-
-
+
+ 35 % des jeunes en France n’ont pas encore le pass Culture.
+
+
- Fais découvrir le pass à tes amis !
-
-
-
+ Fais découvrir le pass à tes amis !
+
-
- undefined-SVG-Mock
-
-
-
undefined-SVG-Mock
-
- Partager l’appli
-
+
+
+ undefined-SVG-Mock
+
+
+
+ Partager l’appli
+
+
-
-
-
-
-
- button-icon-left-SVG-Mock
-
+
+
+ button-icon-left-SVG-Mock
+
+
+
-
+ >
+ Non merci
+
-
- Non merci
-
diff --git a/__snapshots__/features/share/pages/ShareAppModalVersionA.native.test.tsx.native-snap b/__snapshots__/features/share/pages/ShareAppModalVersionA.native.test.tsx.native-snap
new file mode 100644
index 00000000000..b08bc6683ed
--- /dev/null
+++ b/__snapshots__/features/share/pages/ShareAppModalVersionA.native.test.tsx.native-snap
@@ -0,0 +1,599 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`ShareAppModalVersionA should match snapshot 1`] = `
+
+
+
+
+
+
+
+
+ La culture, ça ce partage !
+
+
+
+
+
+
+ rightIcon-SVG-Mock
+
+
+
+
+
+
+
+
+
+
+
+
+
+ undefined-SVG-Mock
+
+
+
+
+
+ 35 % des jeunes en France n’ont pas encore le pass Culture.
+
+
+
+ Fais découvrir le pass à tes amis !
+
+
+
+
+
+
+
+ button-icon-left-SVG-Mock
+
+
+
+
+
+ Partager l’app
+
+
+
+
+
+
+
+
+ button-icon-left-SVG-Mock
+
+
+
+
+
+ Non merci
+
+
+
+
+
+
+
+
+
+
+
+`;
diff --git a/__snapshots__/features/share/pages/ShareAppModalVersionB.native.test.tsx.native-snap b/__snapshots__/features/share/pages/ShareAppModalVersionB.native.test.tsx.native-snap
new file mode 100644
index 00000000000..3d4aea2f25e
--- /dev/null
+++ b/__snapshots__/features/share/pages/ShareAppModalVersionB.native.test.tsx.native-snap
@@ -0,0 +1,599 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`ShareAppModalVersionB should match snapshot 1`] = `
+
+
+
+
+
+
+
+
+ La culture, ça ce partage !
+
+
+
+
+
+
+ rightIcon-SVG-Mock
+
+
+
+
+
+
+
+
+
+
+
+
+
+ undefined-SVG-Mock
+
+
+
+
+
+ 35 % des jeunes en France n’ont pas encore le pass Culture.
+
+
+
+ Fais découvrir le pass à tes amis !
+
+
+
+
+
+
+
+ button-icon-left-SVG-Mock
+
+
+
+
+
+ Partager l’app
+
+
+
+
+
+
+
+
+ button-icon-left-SVG-Mock
+
+
+
+
+
+ Non merci
+
+
+
+
+
+
+
+
+
+
+
+`;
diff --git a/src/features/internal/cheatcodes/pages/AppComponents/illustrationsExports.ts b/src/features/internal/cheatcodes/pages/AppComponents/illustrationsExports.ts
index d76c5aca28d..b462a365e52 100644
--- a/src/features/internal/cheatcodes/pages/AppComponents/illustrationsExports.ts
+++ b/src/features/internal/cheatcodes/pages/AppComponents/illustrationsExports.ts
@@ -16,6 +16,8 @@ import { BicolorIdCardWithMagnifyingGlass } from 'ui/svg/icons/BicolorIdCardWith
import { BicolorPhonePending } from 'ui/svg/icons/BicolorPhonePending'
import { BicolorProfileDeletion } from 'ui/svg/icons/BicolorProfileDeletion'
import { BicolorSadFace } from 'ui/svg/icons/BicolorSadFace'
+import { BicolorShareChat } from 'ui/svg/icons/BicolorShareChat'
+import { BicolorSharePhones } from 'ui/svg/icons/BicolorSharePhones'
import { BicolorTicketBooked } from 'ui/svg/icons/BicolorTicketBooked'
import { BicolorUserFavorite } from 'ui/svg/icons/BicolorUserFavorite'
import { CalendarIllustration } from 'ui/svg/icons/CalendarIllustration'
@@ -52,6 +54,8 @@ export const BicolorIllustrations = {
BicolorUserError,
BicolorUserFavorite,
BicolorUserIdentification,
+ BicolorSharePhones,
+ BicolorShareChat,
}
export const UniqueColorIllustrations = {
diff --git a/src/features/share/api/useShareAppModalViewmodel.native.test.ts b/src/features/share/api/useShareAppModalViewmodel.native.test.ts
new file mode 100644
index 00000000000..47e96cb4f2c
--- /dev/null
+++ b/src/features/share/api/useShareAppModalViewmodel.native.test.ts
@@ -0,0 +1,140 @@
+import * as shareApp from 'features/share/helpers/shareApp'
+import { ShareAppModalType } from 'features/share/types'
+import { analytics } from 'libs/analytics/__mocks__/provider'
+import { DEFAULT_REMOTE_CONFIG } from 'libs/firebase/remoteConfig/remoteConfig.constants'
+import { CustomRemoteConfig } from 'libs/firebase/remoteConfig/remoteConfig.types'
+import * as useRemoteConfigContext from 'libs/firebase/remoteConfig/RemoteConfigProvider'
+import { renderHook } from 'tests/utils'
+
+import {
+ ShareAppModalSelectorViewmodelParams,
+ useShareAppModalViewmodel,
+} from './useShareAppModalViewmodel'
+
+const useRemoteConfigContextSpy = jest.spyOn(useRemoteConfigContext, 'useRemoteConfigContext')
+jest.mock('react-native/Libraries/EventEmitter/NativeEventEmitter')
+
+const mockShareApp = jest.spyOn(shareApp, 'shareApp')
+mockShareApp.mockImplementation(jest.fn())
+
+const useShareAppModalSelectorViewmodelTest = ({
+ hideModal = jest.fn(),
+ type: type = ShareAppModalType.BENEFICIARY,
+ showModal = jest.fn(),
+ setType = jest.fn(),
+}: Partial = {}) => {
+ const hook = renderHook(() =>
+ // eslint-disable-next-line react-hooks/rules-of-hooks
+ useShareAppModalViewmodel({
+ type,
+ hideModal,
+ showModal,
+ setType,
+ })
+ )
+
+ return hook.result.current
+}
+
+const givenRemoteConfigShareAppModalVersion = (
+ version: CustomRemoteConfig['shareAppModalVersion']
+) => {
+ useRemoteConfigContextSpy.mockReturnValue({
+ ...DEFAULT_REMOTE_CONFIG,
+ shareAppModalVersion: version,
+ })
+}
+
+describe('useShareAppModalViewmodel', () => {
+ describe('version', () => {
+ test.each`
+ expectedVersion
+ ${'default'}
+ ${'version_1'}
+ `('get version $expectedVersion from remote config', async ({ expectedVersion }) => {
+ givenRemoteConfigShareAppModalVersion(expectedVersion)
+ const { version } = useShareAppModalSelectorViewmodelTest()
+
+ expect(version).toEqual(expectedVersion)
+ })
+ })
+
+ describe('close', () => {
+ test('close modal on close', async () => {
+ const hideModal = jest.fn()
+
+ const { close } = useShareAppModalSelectorViewmodelTest({ hideModal })
+
+ close()
+
+ expect(hideModal).toHaveBeenCalledWith()
+ })
+
+ test.each`
+ type
+ ${ShareAppModalType.BENEFICIARY}
+ ${ShareAppModalType.NOT_ELIGIBLE}
+ `('log dismiss share app on close with type $type', async ({ type }) => {
+ const { close } = useShareAppModalSelectorViewmodelTest({ type })
+
+ close()
+
+ expect(analytics.logDismissShareApp).toHaveBeenCalledWith(type)
+ })
+ })
+
+ describe('share', () => {
+ test('close modal on share', async () => {
+ const hideModal = jest.fn()
+
+ const { share } = useShareAppModalSelectorViewmodelTest({ hideModal })
+
+ await share()
+
+ expect(hideModal).toHaveBeenCalledWith()
+ })
+
+ test.each`
+ type
+ ${ShareAppModalType.BENEFICIARY}
+ ${ShareAppModalType.NOT_ELIGIBLE}
+ `('log share app on share with type $type', async ({ type }) => {
+ const { share } = useShareAppModalSelectorViewmodelTest({ type })
+
+ await share()
+
+ expect(analytics.logShareApp).toHaveBeenCalledWith({ type })
+ })
+ })
+
+ describe('show', () => {
+ test.each`
+ type
+ ${ShareAppModalType.BENEFICIARY}
+ ${ShareAppModalType.NOT_ELIGIBLE}
+ `('show modal on show with type $type', async ({ type }) => {
+ const showModal = jest.fn()
+ const setType = jest.fn()
+ const { show } = useShareAppModalSelectorViewmodelTest({ showModal, setType })
+
+ show(type)
+
+ expect(setType).toHaveBeenCalledWith(type)
+ expect(showModal).toHaveBeenCalledWith()
+ })
+
+ test.each`
+ type
+ ${ShareAppModalType.BENEFICIARY}
+ ${ShareAppModalType.NOT_ELIGIBLE}
+ `('send analytics on show with $type', ({ type }) => {
+ const { show } = useShareAppModalSelectorViewmodelTest()
+
+ show(type)
+
+ expect(analytics.logShowShareAppModal).toHaveBeenCalledWith({
+ type,
+ })
+ })
+ })
+})
diff --git a/src/features/share/api/useShareAppModalViewmodel.ts b/src/features/share/api/useShareAppModalViewmodel.ts
new file mode 100644
index 00000000000..8dc25606d4e
--- /dev/null
+++ b/src/features/share/api/useShareAppModalViewmodel.ts
@@ -0,0 +1,49 @@
+import { useCallback } from 'react'
+
+import { shareApp } from 'features/share/helpers/shareApp'
+import { ShareAppModalType } from 'features/share/types'
+import { analytics } from 'libs/analytics'
+import { useRemoteConfigContext } from 'libs/firebase/remoteConfig/RemoteConfigProvider'
+
+export type ShareAppModalSelectorViewmodelParams = {
+ type: ShareAppModalType
+ hideModal: () => void
+ setType: (type: ShareAppModalType) => void
+ showModal: () => void
+}
+
+export const useShareAppModalViewmodel = ({
+ hideModal,
+ type,
+ showModal,
+ setType,
+}: ShareAppModalSelectorViewmodelParams) => {
+ const { shareAppModalVersion: version } = useRemoteConfigContext()
+
+ const close = useCallback(() => {
+ analytics.logDismissShareApp(type)
+ hideModal()
+ }, [hideModal, type])
+
+ const share = useCallback(async () => {
+ analytics.logShareApp({ type: type })
+ await shareApp(ShareAppModalType.BENEFICIARY ? 'beneficiary_modal' : 'uneligible_modal')
+ hideModal()
+ }, [hideModal, type])
+
+ const show = useCallback(
+ (_type: ShareAppModalType) => {
+ analytics.logShowShareAppModal({ type: _type })
+ setType(_type)
+ showModal()
+ },
+ [setType, showModal]
+ )
+
+ return {
+ version,
+ share,
+ close,
+ show,
+ }
+}
diff --git a/src/features/share/components/ShareAppModalSelector.tsx b/src/features/share/components/ShareAppModalSelector.tsx
new file mode 100644
index 00000000000..e4cea0d7557
--- /dev/null
+++ b/src/features/share/components/ShareAppModalSelector.tsx
@@ -0,0 +1,25 @@
+import React, { FC } from 'react'
+
+import { ShareAppModal } from 'features/share/pages/ShareAppModal'
+import { ShareAppModalVersionA } from 'features/share/pages/ShareAppModalVersionA'
+import { ShareAppModalVersionB } from 'features/share/pages/ShareAppModalVersionB'
+import { CustomRemoteConfig } from 'libs/firebase/remoteConfig/remoteConfig.types'
+
+type SelectorProps = {
+ visible: boolean
+ close: () => void
+ share: () => void
+ version: CustomRemoteConfig['shareAppModalVersion']
+}
+
+export const ShareAppModalSelector: FC = ({ visible, close, share, version }) => {
+ if (version === 'A') {
+ return
+ }
+
+ if (version === 'B') {
+ return
+ }
+
+ return
+}
diff --git a/src/features/share/context/ShareAppWrapper.native.test.tsx b/src/features/share/context/ShareAppWrapper.native.test.tsx
deleted file mode 100644
index 1f177f6e87b..00000000000
--- a/src/features/share/context/ShareAppWrapper.native.test.tsx
+++ /dev/null
@@ -1,60 +0,0 @@
-import { ShareAppWrapper, useShareAppContext } from 'features/share/context/ShareAppWrapper'
-import { ShareAppModalType } from 'features/share/types'
-import { analytics } from 'libs/analytics'
-import { renderHook, act } from 'tests/utils'
-
-const mockShowModal = jest.fn()
-const mockShareAppModal = jest.fn()
-
-jest.mock('ui/components/modals/useModal', () => ({
- useModal: () => ({
- visible: false,
- showModal: mockShowModal,
- hideModal: jest.fn(),
- toggleModal: jest.fn(),
- }),
-}))
-
-jest.mock('features/share/pages/ShareAppModal', () => ({
- ShareAppModal: ({ modalType }: { modalType: ShareAppModalType }) => {
- mockShareAppModal(modalType)
- return null
- },
-}))
-
-describe('useShareAppContext()', () => {
- it.each([
- ShareAppModalType.BENEFICIARY,
- ShareAppModalType.NOT_ELIGIBLE,
- ShareAppModalType.ON_BOOKING_SUCCESS,
- ])('should show modal with correct modal type', async (modalType) => {
- const { result } = renderShareAppHook()
-
- await act(async () => {
- result.current.showShareAppModal(modalType)
- })
-
- expect(mockShowModal).toHaveBeenCalledTimes(1)
- expect(mockShareAppModal).toHaveBeenCalledWith(modalType)
- })
-
- it.each([
- ShareAppModalType.BENEFICIARY,
- ShareAppModalType.NOT_ELIGIBLE,
- ShareAppModalType.ON_BOOKING_SUCCESS,
- ])('should log analytics when displaying modal', async (modalType) => {
- const { result } = renderShareAppHook()
-
- await act(async () => {
- result.current.showShareAppModal(modalType)
- })
-
- expect(analytics.logShowShareAppModal).toHaveBeenCalledWith({ type: modalType })
- })
-})
-
-function renderShareAppHook() {
- return renderHook(useShareAppContext, {
- wrapper: ShareAppWrapper,
- })
-}
diff --git a/src/features/share/context/ShareAppWrapper.tsx b/src/features/share/context/ShareAppWrapper.tsx
index 56e48fe7259..8148f2602ac 100644
--- a/src/features/share/context/ShareAppWrapper.tsx
+++ b/src/features/share/context/ShareAppWrapper.tsx
@@ -1,10 +1,11 @@
-import React, { memo, useCallback, useContext, useMemo, useState } from 'react'
+import React, { memo, useContext, useMemo, useState } from 'react'
-import { ShareAppModal } from 'features/share/pages/ShareAppModal'
import { ShareAppModalType } from 'features/share/types'
-import { analytics } from 'libs/analytics'
import { useModal } from 'ui/components/modals/useModal'
+import { useShareAppModalViewmodel } from '../api/useShareAppModalViewmodel'
+import { ShareAppModalSelector } from '../components/ShareAppModalSelector'
+
interface ShareAppContextValue {
showShareAppModal: (modalType: ShareAppModalType) => void
}
@@ -18,29 +19,27 @@ export const ShareAppWrapper = memo(function ShareAppWrapper({
}: {
children: React.JSX.Element
}) {
- const { showModal, ...shareAppModalProps } = useModal(false)
+ const { showModal, visible, hideModal } = useModal(false)
const [modalType, setModalType] = useState(ShareAppModalType.NOT_ELIGIBLE)
- const showShareAppModal = useCallback(
- (modalType: ShareAppModalType) => {
- analytics.logShowShareAppModal({ type: modalType })
- setModalType(modalType)
- showModal()
- },
- [showModal]
- )
+ const { close, share, show, version } = useShareAppModalViewmodel({
+ hideModal,
+ showModal,
+ setType: setModalType,
+ type: modalType,
+ })
const value = useMemo(
() => ({
- showShareAppModal,
+ showShareAppModal: show,
}),
- [showShareAppModal]
+ [show]
)
return (
{children}
-
+
)
})
diff --git a/src/features/share/pages/ShareAppModal.native.test.tsx b/src/features/share/pages/ShareAppModal.native.test.tsx
index 39c08d3d21d..d8d93eabdc1 100644
--- a/src/features/share/pages/ShareAppModal.native.test.tsx
+++ b/src/features/share/pages/ShareAppModal.native.test.tsx
@@ -1,16 +1,9 @@
import React from 'react'
-import * as Share from 'features/share/helpers/shareApp'
-import { ShareAppModalType } from 'features/share/types'
-import { analytics } from 'libs/analytics'
-import { fireEvent, render, screen, waitFor } from 'tests/utils'
+import { render, screen } from 'tests/utils'
import { ShareAppModal } from './ShareAppModal'
-const visible = true
-const hideModal = jest.fn()
-const shareApp = jest.spyOn(Share, 'shareApp').mockResolvedValue()
-
jest.mock('react-native/Libraries/Animated/createAnimatedComponent', () => {
return function createAnimatedComponent(Component: unknown) {
return Component
@@ -19,72 +12,8 @@ jest.mock('react-native/Libraries/Animated/createAnimatedComponent', () => {
describe('ShareAppModal', () => {
it('should match snapshot', () => {
- render(
-
- )
+ render()
expect(screen).toMatchSnapshot()
})
-
- it('should open native share modal when clicking on "Partager l’appli" button', async () => {
- render(
-
- )
-
- const shareButton = screen.getByTestId('Partager l’appli')
- fireEvent.press(shareButton)
-
- await waitFor(() => {
- expect(shareApp).toHaveBeenCalledTimes(1)
- })
- })
-
- it('should close modal when clicking on "Partager l’appli" button', () => {
- render(
-
- )
-
- const shareButton = screen.getByText('Partager l’appli')
- fireEvent.press(shareButton)
-
- expect(hideModal).toHaveBeenCalledTimes(1)
- })
-
- it.each([
- ShareAppModalType.NOT_ELIGIBLE,
- ShareAppModalType.BENEFICIARY,
- ShareAppModalType.ON_BOOKING_SUCCESS,
- ])('should log analytics when clicking on "Partager l’appli" button', (modalType) => {
- render()
-
- const shareButton = screen.getByTestId('Partager l’appli')
- fireEvent.press(shareButton)
-
- expect(analytics.logShareApp).toHaveBeenNthCalledWith(1, { type: modalType })
- })
-
- it.each([
- ShareAppModalType.NOT_ELIGIBLE,
- ShareAppModalType.BENEFICIARY,
- ShareAppModalType.ON_BOOKING_SUCCESS,
- ])('should log analytics when clicking on "Fermer la modale"', (modalType) => {
- render()
-
- const closeButton = screen.getByTestId('Fermer la modale')
- fireEvent.press(closeButton)
-
- expect(analytics.logDismissShareApp).toHaveBeenNthCalledWith(1, modalType)
- })
})
diff --git a/src/features/share/pages/ShareAppModal.tsx b/src/features/share/pages/ShareAppModal.tsx
index b2d2a823a6c..7678867467a 100644
--- a/src/features/share/pages/ShareAppModal.tsx
+++ b/src/features/share/pages/ShareAppModal.tsx
@@ -1,71 +1,51 @@
-import React, { FunctionComponent, useCallback } from 'react'
+import React, { FunctionComponent } from 'react'
import styled from 'styled-components/native'
import { SHARE_APP_IMAGE_SOURCE } from 'features/share/components/shareAppImage'
-import { shareApp } from 'features/share/helpers/shareApp'
-import { ShareAppModalType } from 'features/share/types'
-import { analytics } from 'libs/analytics'
import { ButtonQuaternaryBlack } from 'ui/components/buttons/ButtonQuaternaryBlack'
import { ButtonWithLinearGradient } from 'ui/components/buttons/buttonWithLinearGradient/ButtonWithLinearGradient'
import { MarketingModal } from 'ui/components/modals/MarketingModal'
+import { ViewGap } from 'ui/components/ViewGap/ViewGap'
import { Share } from 'ui/svg/icons/BicolorShare'
import { Invalidate } from 'ui/svg/icons/Invalidate'
-import { Spacer, Typo } from 'ui/theme'
+import { Typo } from 'ui/theme'
import { LINE_BREAK } from 'ui/theme/constants'
type Props = {
visible: boolean
- hideModal: () => void
- modalType: ShareAppModalType
+ close: () => void
+ share: () => void
}
-export const ShareAppModal: FunctionComponent = ({ visible, hideModal, modalType }) => {
- const openShareAppModal = useCallback(() => {
- analytics.logShareApp({ type: modalType })
- hideModal()
- const utmMedium =
- modalType === ShareAppModalType.BENEFICIARY ? 'beneficiary_modal' : 'uneligible_modal'
- setTimeout(() => shareApp(utmMedium), 0)
- }, [modalType, hideModal])
-
- const closeModal = useCallback(() => {
- analytics.logDismissShareApp(modalType)
- hideModal()
- }, [modalType, hideModal])
-
+export const ShareAppModal: FunctionComponent = ({ visible, close, share }) => {
return (
-
-
- 35 % des jeunes en France n’ont pas encore le pass Culture.
-
- {LINE_BREAK}
- Fais découvrir le pass à tes amis !
-
-
-
-
-
-
-
+ onBackdropPress={close}>
+
+
+
+ 35 % des jeunes en France n’ont pas encore le pass Culture.
+
+ {LINE_BREAK}
+ Fais découvrir le pass à tes amis !
+
+
+
+
+
+
)
}
-const ButtonContainer = styled.View({ width: '100%' })
const StyledBody = styled(Typo.Body)({
textAlign: 'center',
})
diff --git a/src/features/share/pages/ShareAppModal.web.test.tsx b/src/features/share/pages/ShareAppModal.web.test.tsx
index 5c8939237bd..dd4bfe4236b 100644
--- a/src/features/share/pages/ShareAppModal.web.test.tsx
+++ b/src/features/share/pages/ShareAppModal.web.test.tsx
@@ -1,19 +1,12 @@
import React from 'react'
-import { ShareAppModalType } from 'features/share/types'
import { render } from 'tests/utils/web'
import { ShareAppModal } from './ShareAppModal'
describe('ShareAppModal', () => {
- it.each([
- ShareAppModalType.NOT_ELIGIBLE,
- ShareAppModalType.BENEFICIARY,
- ShareAppModalType.ON_BOOKING_SUCCESS,
- ])('should render null in web', (modalType) => {
- const { container } = render(
-
- )
+ it('should render null in web', () => {
+ const { container } = render()
expect(container).toBeEmptyDOMElement()
})
diff --git a/src/features/share/pages/ShareAppModalVersionA.native.test.tsx b/src/features/share/pages/ShareAppModalVersionA.native.test.tsx
new file mode 100644
index 00000000000..ac7da2bab0e
--- /dev/null
+++ b/src/features/share/pages/ShareAppModalVersionA.native.test.tsx
@@ -0,0 +1,17 @@
+import React from 'react'
+
+import { render, screen } from 'tests/utils'
+
+import { ShareAppModalVersionA } from './ShareAppModalVersionA'
+
+jest.mock('react-native-safe-area-context', () => ({
+ useSafeAreaInsets: jest.fn(() => ({ bottom: 10 })),
+}))
+
+describe('ShareAppModalVersionA', () => {
+ it('should match snapshot', () => {
+ render()
+
+ expect(screen).toMatchSnapshot()
+ })
+})
diff --git a/src/features/share/pages/ShareAppModalVersionA.tsx b/src/features/share/pages/ShareAppModalVersionA.tsx
new file mode 100644
index 00000000000..20de04377c9
--- /dev/null
+++ b/src/features/share/pages/ShareAppModalVersionA.tsx
@@ -0,0 +1,58 @@
+import React, { FC } from 'react'
+import styled from 'styled-components/native'
+
+import { ButtonPrimary } from 'ui/components/buttons/ButtonPrimary'
+import { ButtonTertiaryBlack } from 'ui/components/buttons/ButtonTertiaryBlack'
+import { AppModal } from 'ui/components/modals/AppModal'
+import { ViewGap } from 'ui/components/ViewGap/ViewGap'
+import { Share } from 'ui/svg/icons/BicolorShare'
+import { BicolorShareChat } from 'ui/svg/icons/BicolorShareChat'
+import { Close } from 'ui/svg/icons/Close'
+import { Invalidate } from 'ui/svg/icons/Invalidate'
+import { TypoDS } from 'ui/theme'
+import { LINE_BREAK } from 'ui/theme/constants'
+
+type Props = {
+ visible: boolean
+ close: () => void
+ share: () => void
+}
+
+export const ShareAppModalVersionA: FC = ({ visible, close, share }) => {
+ return (
+
+
+
+
+
+
+ 35 % des jeunes en France n’ont pas encore le pass Culture.
+ {LINE_BREAK}
+ Fais découvrir le pass à tes amis !
+
+
+
+
+
+
+
+ )
+}
+
+const StyledBody = styled(TypoDS.Body)({
+ textAlign: 'center',
+})
+
+const ImageContainer = styled.View({
+ alignItems: 'center',
+})
+
+const Icon = styled(BicolorShareChat).attrs(({ theme }) => ({
+ size: theme.illustrations.sizes.medium,
+}))({})
diff --git a/src/features/share/pages/ShareAppModalVersionA.web.test.tsx b/src/features/share/pages/ShareAppModalVersionA.web.test.tsx
new file mode 100644
index 00000000000..bd0de4ae74f
--- /dev/null
+++ b/src/features/share/pages/ShareAppModalVersionA.web.test.tsx
@@ -0,0 +1,15 @@
+import React from 'react'
+
+import { render } from 'tests/utils/web'
+
+import { ShareAppModalVersionA } from './ShareAppModalVersionA'
+
+describe('ShareAppModalVersionA', () => {
+ it('should render null in web', () => {
+ const { container } = render(
+
+ )
+
+ expect(container).toBeEmptyDOMElement()
+ })
+})
diff --git a/src/features/share/pages/ShareAppModalVersionA.web.tsx b/src/features/share/pages/ShareAppModalVersionA.web.tsx
new file mode 100644
index 00000000000..053a09fa886
--- /dev/null
+++ b/src/features/share/pages/ShareAppModalVersionA.web.tsx
@@ -0,0 +1 @@
+export const ShareAppModalVersionA = () => null
diff --git a/src/features/share/pages/ShareAppModalVersionB.native.test.tsx b/src/features/share/pages/ShareAppModalVersionB.native.test.tsx
new file mode 100644
index 00000000000..821e48c6af2
--- /dev/null
+++ b/src/features/share/pages/ShareAppModalVersionB.native.test.tsx
@@ -0,0 +1,17 @@
+import React from 'react'
+
+import { render, screen } from 'tests/utils'
+
+import { ShareAppModalVersionB } from './ShareAppModalVersionB'
+
+jest.mock('react-native-safe-area-context', () => ({
+ useSafeAreaInsets: jest.fn(() => ({ bottom: 10 })),
+}))
+
+describe('ShareAppModalVersionB', () => {
+ it('should match snapshot', () => {
+ render()
+
+ expect(screen).toMatchSnapshot()
+ })
+})
diff --git a/src/features/share/pages/ShareAppModalVersionB.tsx b/src/features/share/pages/ShareAppModalVersionB.tsx
new file mode 100644
index 00000000000..8aa04b7a9aa
--- /dev/null
+++ b/src/features/share/pages/ShareAppModalVersionB.tsx
@@ -0,0 +1,58 @@
+import React, { FC } from 'react'
+import styled from 'styled-components/native'
+
+import { ButtonPrimary } from 'ui/components/buttons/ButtonPrimary'
+import { ButtonTertiaryBlack } from 'ui/components/buttons/ButtonTertiaryBlack'
+import { AppModal } from 'ui/components/modals/AppModal'
+import { ViewGap } from 'ui/components/ViewGap/ViewGap'
+import { Share } from 'ui/svg/icons/BicolorShare'
+import { BicolorSharePhones } from 'ui/svg/icons/BicolorSharePhones'
+import { Close } from 'ui/svg/icons/Close'
+import { Invalidate } from 'ui/svg/icons/Invalidate'
+import { TypoDS } from 'ui/theme'
+import { LINE_BREAK } from 'ui/theme/constants'
+
+type Props = {
+ visible: boolean
+ close: () => void
+ share: () => void
+}
+
+export const ShareAppModalVersionB: FC = ({ visible, close, share }) => {
+ return (
+
+
+
+
+
+
+ 35 % des jeunes en France n’ont pas encore le pass Culture.
+ {LINE_BREAK}
+ Fais découvrir le pass à tes amis !
+
+
+
+
+
+
+
+ )
+}
+
+const StyledBody = styled(TypoDS.Body)({
+ textAlign: 'center',
+})
+
+const ImageContainer = styled.View({
+ alignItems: 'center',
+})
+
+const Icon = styled(BicolorSharePhones).attrs(({ theme }) => ({
+ size: theme.illustrations.sizes.medium,
+}))({})
diff --git a/src/features/share/pages/ShareAppModalVersionB.web.test.tsx b/src/features/share/pages/ShareAppModalVersionB.web.test.tsx
new file mode 100644
index 00000000000..af828c5f364
--- /dev/null
+++ b/src/features/share/pages/ShareAppModalVersionB.web.test.tsx
@@ -0,0 +1,15 @@
+import React from 'react'
+
+import { render } from 'tests/utils/web'
+
+import { ShareAppModalVersionB } from './ShareAppModalVersionB'
+
+describe('ShareAppModalVersionB', () => {
+ it('should render null in web', () => {
+ const { container } = render(
+
+ )
+
+ expect(container).toBeEmptyDOMElement()
+ })
+})
diff --git a/src/features/share/pages/ShareAppModalVersionB.web.tsx b/src/features/share/pages/ShareAppModalVersionB.web.tsx
new file mode 100644
index 00000000000..74a07b51061
--- /dev/null
+++ b/src/features/share/pages/ShareAppModalVersionB.web.tsx
@@ -0,0 +1 @@
+export const ShareAppModalVersionB = () => null
diff --git a/src/libs/firebase/remoteConfig/helpers/getRemoteConfigFromConfigValues.ts b/src/libs/firebase/remoteConfig/helpers/getRemoteConfigFromConfigValues.ts
index 320cec41ba0..74cbbaf010c 100644
--- a/src/libs/firebase/remoteConfig/helpers/getRemoteConfigFromConfigValues.ts
+++ b/src/libs/firebase/remoteConfig/helpers/getRemoteConfigFromConfigValues.ts
@@ -37,4 +37,7 @@ export const getRemoteConfigFromConfigValues = (
subscriptionHomeEntryIds: JSON.parse(
getConfigValue(parameters.subscriptionHomeEntryIds).asString()
),
+ shareAppModalVersion: getConfigValue(
+ parameters.shareAppModalVersion
+ ).asString() as CustomRemoteConfig['shareAppModalVersion'],
})
diff --git a/src/libs/firebase/remoteConfig/remoteConfig.constants.ts b/src/libs/firebase/remoteConfig/remoteConfig.constants.ts
index a620b0d76e1..4c2debcbbe2 100644
--- a/src/libs/firebase/remoteConfig/remoteConfig.constants.ts
+++ b/src/libs/firebase/remoteConfig/remoteConfig.constants.ts
@@ -33,4 +33,5 @@ export const DEFAULT_REMOTE_CONFIG: CustomRemoteConfig = {
[SubscriptionTheme.VISITES]: '',
[SubscriptionTheme.ACTIVITES]: '',
},
+ shareAppModalVersion: 'default',
}
diff --git a/src/libs/firebase/remoteConfig/remoteConfig.types.ts b/src/libs/firebase/remoteConfig/remoteConfig.types.ts
index 3474d8751bf..2b60f98dadd 100644
--- a/src/libs/firebase/remoteConfig/remoteConfig.types.ts
+++ b/src/libs/firebase/remoteConfig/remoteConfig.types.ts
@@ -21,6 +21,7 @@ export type CustomRemoteConfig = {
shouldLogInfo: boolean
displayInAppFeedback: boolean
subscriptionHomeEntryIds: Record
+ shareAppModalVersion: 'default' | 'A' | 'B'
}
/* The purpose of GenericRemoteConfig is only to resolve type conflicts.
diff --git a/src/ui/svg/icons/BicolorShareChat.tsx b/src/ui/svg/icons/BicolorShareChat.tsx
new file mode 100644
index 00000000000..4bf97ad907b
--- /dev/null
+++ b/src/ui/svg/icons/BicolorShareChat.tsx
@@ -0,0 +1,95 @@
+import * as React from 'react'
+import { Defs, LinearGradient, Path, Stop } from 'react-native-svg'
+import styled from 'styled-components/native'
+
+import { AccessibleIcon } from 'ui/svg/icons/types'
+import { svgIdentifier } from 'ui/svg/utils'
+
+import { AccessibleSvg } from '../AccessibleSvg'
+
+const BicolorShareChatSVG: React.FunctionComponent = ({
+ size,
+ color,
+ color2,
+ accessibilityLabel,
+ testID,
+ style,
+}) => {
+ const height = typeof size === 'string' ? size : ((size as number) * 122) / 170
+
+ const { id: gradientId, fill: gradientFill } = svgIdentifier()
+ const { id: gradientId2, fill: gradientFill2 } = svgIdentifier()
+ const { id: gradientId3, fill: gradientFill3 } = svgIdentifier()
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )
+}
+
+export const BicolorShareChat = styled(BicolorShareChatSVG).attrs(
+ ({ color, color2, size, theme }) => ({
+ color: color ?? theme.colors.primary,
+ color2: color2 ?? color ?? theme.colors.secondary,
+ size: size ?? theme.illustrations.sizes.medium,
+ })
+)``
diff --git a/src/ui/svg/icons/BicolorSharePhones.tsx b/src/ui/svg/icons/BicolorSharePhones.tsx
new file mode 100644
index 00000000000..2bb5238619e
--- /dev/null
+++ b/src/ui/svg/icons/BicolorSharePhones.tsx
@@ -0,0 +1,108 @@
+import * as React from 'react'
+import { Defs, LinearGradient, Path, Stop } from 'react-native-svg'
+import styled from 'styled-components/native'
+
+import { AccessibleIcon } from 'ui/svg/icons/types'
+import { svgIdentifier } from 'ui/svg/utils'
+
+import { AccessibleSvg } from '../AccessibleSvg'
+
+const BicolorSharePhonesSVG: React.FunctionComponent = ({
+ size,
+ color,
+ color2,
+ accessibilityLabel,
+ testID,
+ style,
+}) => {
+ const height = typeof size === 'string' ? size : ((size as number) * 128) / 139
+
+ const { id: gradientId, fill: gradientFill } = svgIdentifier()
+ const { id: gradientId2, fill: gradientFill2 } = svgIdentifier()
+ const { id: gradientId3, fill: gradientFill3 } = svgIdentifier()
+ const { id: gradientId4, fill: gradientFill4 } = svgIdentifier()
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )
+}
+
+export const BicolorSharePhones = styled(BicolorSharePhonesSVG).attrs(
+ ({ color, color2, size, theme }) => ({
+ color: color ?? theme.colors.primary,
+ color2: color2 ?? color ?? theme.colors.secondary,
+ size: size ?? theme.illustrations.sizes.medium,
+ })
+)``