Skip to content

Commit

Permalink
feat: Add context to store Intent data
Browse files Browse the repository at this point in the history
Like that, Harvest knows if it was called from an intent or not. And can
use the data to do what it wants.

I don't think this is a good idea to have this knowledge or having to
check if Harvest is called inside an intent or not, we should not have
to check that at this level.

But ATM, I don't know yet how to handle the opening of Drive when called
from an intent. If we just use a link then this is the intent that
changes the URL, not the caller. And just changing this intent url, then
we just close the intent and thats it.

One solution can have to call intent.redirect() for instance, but we need
to check if we are in an intent or not. So I don't like it neither.

For now, I just target blank because it fixes my issue.

BREAKING CHANGE: If you import Harvest's component without using the
HarvestWrapper or the Route Component, you have to wrap manually the
component in the IntentProvider.
  • Loading branch information
Crash-- committed Jan 4, 2024
1 parent eb4970f commit 1efe0c4
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 10 deletions.
2 changes: 2 additions & 0 deletions packages/cozy-harvest-lib/package.json
Expand Up @@ -68,6 +68,7 @@
"cozy-device-helper": "^3.0.0",
"cozy-flags": "^3.2.0",
"cozy-intent": "^2.18.1",
"cozy-interapp": ">=0.8.1",
"cozy-keys-lib": "^6.0.0",
"cozy-realtime": "^5.0.0",
"cozy-tsconfig": "^1.0.0",
Expand Down Expand Up @@ -96,6 +97,7 @@
"cozy-device-helper": ">=2.6.0",
"cozy-flags": ">=2.3.5",
"cozy-intent": ">=1.14.1",
"cozy-interapp": ">=0.8.1",
"cozy-keys-lib": ">=6.0.0",
"cozy-realtime": ">=4.2.8",
"cozy-ui": ">=95.9.0",
Expand Down
28 changes: 20 additions & 8 deletions packages/cozy-harvest-lib/src/components/HarvestWrapper.jsx
Expand Up @@ -4,23 +4,35 @@ import React from 'react'
import HarvestVaultProvider from './HarvestVaultProvider'
import { MountPointProvider } from './MountPointContext'
import ComponentsPropsProvider from './Providers/ComponentsPropsProvider'
import { IntentProvider } from './Providers/IntentProvider'
import VaultUnlockProvider from './VaultUnlockProvider'

/**
* @param {{ mountPointProviderProps?: { baseRoute: string; }; componentsPropsProviderProps?: { ComponentsProps: import("./Providers/ComponentsPropsProvider").ComponentsProps; }; children: JSX.Element; }} props
* @param {{
* mountPointProviderProps?: { baseRoute: string; };
* componentsPropsProviderProps?: {
* ComponentsProps: import("./Providers/ComponentsPropsProvider").ComponentsProps;
* };
* intentData?: object;
* intentId?: string;
* children: JSX.Element; }} props
*/
export default function HarvestWrapper(props) {
return (
<MountPointProvider baseRoute={props?.mountPointProviderProps?.baseRoute}>
<HarvestVaultProvider>
<VaultUnlockProvider>
<ComponentsPropsProvider
ComponentsProps={
props?.componentsPropsProviderProps?.ComponentsProps
}
<IntentProvider
intentData={props.intentData}
intentId={props.intentId}
>
{props.children}
</ComponentsPropsProvider>
<ComponentsPropsProvider
ComponentsProps={
props?.componentsPropsProviderProps?.ComponentsProps
}
>
{props.children}
</ComponentsPropsProvider>
</IntentProvider>
</VaultUnlockProvider>
</HarvestVaultProvider>
</MountPointProvider>
Expand Down
@@ -0,0 +1,29 @@
import React, { createContext } from 'react'

const IntentProviderContext = createContext()

/**
* @param {object} param
* @param {JSX.Element} param.children
* @param {object=} param.intentData
* @param {string=} param.intentId
* @returns
*/
export const IntentProvider = ({ children, intentData, intentId }) => {
return (
<IntentProviderContext.Provider value={{ intentData, intentId }}>
{children}
</IntentProviderContext.Provider>
)
}

export const useIntentProviderData = () => {
const intentProviderData = React.useContext(IntentProviderContext)
if (!intentProviderData) {
throw new Error(
'useIntentProviderData must be used within a IntentProvider'
)
}

return intentProviderData
}
12 changes: 10 additions & 2 deletions packages/cozy-harvest-lib/src/components/Routes.jsx
Expand Up @@ -67,7 +67,9 @@ const Routes = ({
onDismiss,
datacardOptions,
ComponentsProps,
closable
closable,
intentData,
intentId
}) => {
const RoutesV4orV6 = isRouterV6 ? RoutesV6 : RoutesV4

Expand All @@ -94,6 +96,8 @@ const Routes = ({
<HarvestWrapper
mountPointProviderProps={{ baseRoute: konnectorRoot }}
componentsPropsProviderProps={{ ComponentsProps: ComponentsProps }}
intentData={intentData}
intentId={intentId}
>
<DialogContext.Provider value={dialogContext}>
<HarvestDialog
Expand Down Expand Up @@ -142,7 +146,11 @@ Routes.propTypes = {
/** The props for the components */
ComponentsProps: PropTypes.object,
/** Whether the dialog is closable or not */
closable: PropTypes.bool
closable: PropTypes.bool,
/** Data received from the Intent if called from an intent */
intentData: PropTypes.object,
/** Id of the intent if called from an intent */
intentId: PropTypes.string
}

export default Routes
Expand Up @@ -14,6 +14,7 @@ import palette from 'cozy-ui/transpiled/react/palette'
import useBreakpoints from 'cozy-ui/transpiled/react/providers/Breakpoints'
import { useI18n } from 'cozy-ui/transpiled/react/providers/I18n'

import { useIntentProviderData } from '../Providers/IntentProvider'
import useAppLinkWithStoreFallback from '../hooks/useAppLinkWithStoreFallback'

export const AppLinkButton = ({ slug, path }) => {
Expand All @@ -26,13 +27,16 @@ export const AppLinkButton = ({ slug, path }) => {
client,
path
)

const { intentId } = useIntentProviderData()
return (
<AppLinker app={{ slug }} nativePath={path} href={url || '#'}>
{({ onClick, href }) => (
<ButtonLink
disabled={fetchStatus !== 'loaded'}
onClick={fetchStatus === 'loaded' ? onClick : null}
href={href}
{...(intentId ? { target: '_blank' } : {})}
icon={
isInstalled ? (
<AppIcon
Expand Down

0 comments on commit 1efe0c4

Please sign in to comment.