diff --git a/src/components/webviews/CozyWebView.js b/src/components/webviews/CozyWebView.js index ca4048ea8..73990e3f7 100644 --- a/src/components/webviews/CozyWebView.js +++ b/src/components/webviews/CozyWebView.js @@ -6,7 +6,6 @@ import {useSession} from '../../hooks/useSession.js' import {jsCozyGlobal} from './jsInteractions/jsCozyInjection' import {jsLogInterception, tryConsole} from './jsInteractions/jsLogInterception' -import {interceptHashAndNavigate} from './jsInteractions/jsNavigation' const log = Minilog('CozyWebView') @@ -18,6 +17,7 @@ const CozyWebView = ({ onMessage: parentOnMessage, logId = '', source, + trackWebviewInnerUri, ...rest }) => { const [ref, setRef] = useState('') @@ -60,8 +60,6 @@ const CozyWebView = ({ })(); ` - interceptHashAndNavigate(source.uri, ref, log, logId) - return uri ? ( { + if (trackWebviewInnerUri) { + trackWebviewInnerUri(nativeEvent.url) + } + }} onMessage={async m => { tryConsole(m, log, logId) diff --git a/src/components/webviews/jsInteractions/jsNavigation.js b/src/components/webviews/jsInteractions/jsNavigation.js deleted file mode 100644 index cc05201c0..000000000 --- a/src/components/webviews/jsInteractions/jsNavigation.js +++ /dev/null @@ -1,13 +0,0 @@ -export const interceptHashAndNavigate = (uri, webviewRef, logger, logId) => { - const url = new URL(uri) - - if (url.hash && webviewRef) { - logger.info(`[Native ${logId}] Redirect webview to ${url.hash}`) - webviewRef.injectJavaScript(` - (function() { - window.location.hash = '${url.hash}'; - true; - })(); - `) - } -} diff --git a/src/libs/functions/routeHelpers.js b/src/libs/functions/routeHelpers.js new file mode 100644 index 000000000..97fa63c18 --- /dev/null +++ b/src/libs/functions/routeHelpers.js @@ -0,0 +1,18 @@ +import {get} from 'lodash' + +/** + * Retrieve the specified route parameter and remove it from the navigation state + * @param {string} paramName - Name of the parameter to retrieve + * @param {*} route - Application's route + * @param {*} navigation - Application's navigation + * @returns the route parameter's value + */ +export const consumeRouteParameter = (paramName, route, navigation) => { + const param = get(route, `params.${paramName}`) + + if (param !== undefined) { + navigation.setParams({[paramName]: undefined}) + } + + return param +} diff --git a/src/libs/functions/routeHelpers.spec.js b/src/libs/functions/routeHelpers.spec.js new file mode 100644 index 000000000..7d02799a9 --- /dev/null +++ b/src/libs/functions/routeHelpers.spec.js @@ -0,0 +1,64 @@ +import {consumeRouteParameter} from './routeHelpers' + +describe('consumeRouteParameter', () => { + beforeEach(() => { + jest.clearAllMocks() + }) + + it('should return parameter and clear it from navigation when parameter exist', async () => { + const route = { + params: { + foo: 'bar', + }, + } + + const navigation = { + setParams: jest.fn(), + } + + const param = consumeRouteParameter('foo', route, navigation) + + expect(param).toBe('bar') + expect(navigation.setParams).toHaveBeenCalled() + expect(navigation.setParams.mock.calls[0][0]).toStrictEqual({ + foo: undefined, + }) + }) + + it('should return undefined and should not try to clear it from navigation when parameter does not exist', async () => { + const route = { + params: { + foo: 'bar', + }, + } + + const navigation = { + setParams: jest.fn(), + } + + const param = consumeRouteParameter('unexistingParam', route, navigation) + + expect(param).toBe(undefined) + expect(navigation.setParams).not.toHaveBeenCalled() + }) + + it('should return parameter and clear it from navigation when parameter exist but has falsy value', async () => { + const route = { + params: { + foo: 0, + }, + } + + const navigation = { + setParams: jest.fn(), + } + + const param = consumeRouteParameter('foo', route, navigation) + + expect(param).toBe(0) + expect(navigation.setParams).toHaveBeenCalled() + expect(navigation.setParams.mock.calls[0][0]).toStrictEqual({ + foo: undefined, + }) + }) +}) diff --git a/src/screens/home/components/HomeView.js b/src/screens/home/components/HomeView.js index ea8cb6fb4..29a37ac5c 100644 --- a/src/screens/home/components/HomeView.js +++ b/src/screens/home/components/HomeView.js @@ -5,13 +5,45 @@ import {useNativeIntent} from 'cozy-intent' import {useSession} from '../../../hooks/useSession' import CozyWebView from '../../../components/webviews/CozyWebView' +import {consumeRouteParameter} from '../../../libs/functions/routeHelpers' const HomeView = ({route, navigation, setLauncherContext}) => { const client = useClient() const [uri, setUri] = useState('') + const [trackedWebviewInnerUri, setTrackedWebviewInnerUri] = useState('') const nativeIntent = useNativeIntent() const session = useSession() + React.useEffect(() => { + const unsubscribe = navigation.addListener('blur', () => { + setUri(trackedWebviewInnerUri) + }) + + return unsubscribe + }, [navigation, uri, trackedWebviewInnerUri]) + + React.useEffect(() => { + const unsubscribe = navigation.addListener('focus', () => { + if (uri) { + const konnectorParam = consumeRouteParameter( + 'konnector', + route, + navigation, + ) + + if (konnectorParam) { + const url = new URL(uri) + url.hash = `/connected/${konnectorParam}` + + const targetUri = url.toString() + setUri(targetUri) + } + } + }) + + return unsubscribe + }, [navigation, route, uri]) + useEffect(() => { const {shouldCreateSession, handleCreateSession, consumeSessionToken} = session @@ -39,13 +71,16 @@ const HomeView = ({route, navigation, setLauncherContext}) => { } }, [uri, client, route, nativeIntent, navigation, session]) - const konnectorParam = get(route, 'params.konnector') - const targetUri = - uri && konnectorParam ? `${uri}connected/${konnectorParam}` : uri + const handleTrackWebviewInnerUri = webviewInneruri => { + if (webviewInneruri !== trackedWebviewInnerUri) { + setTrackedWebviewInnerUri(webviewInneruri) + } + } - return targetUri ? ( + return uri ? ( {