import UriInputField from '@/mdx-components/UriInputField';
import NpmLikeInstallation from '@/mdx-components/NpmLikeInstallation';
import InlineNotification from '@/ds-components/InlineNotification';
import Steps from '@/mdx-components/Steps';
import Step from '@/mdx-components/Step';
import CustomDomainEndpointNotice from '@/mdx-components/CustomDomainEndpointNotice';
import Checkpoint from '../../fragments/_checkpoint.md';
import RedirectUrisNative, { defaultRedirectUri } from '../../fragments/_redirect-uris-native.mdx';

<Steps>

<Step
  title="Install SDK"
  subtitle="Install Logto SDK and peer dependencies"
>

<NpmLikeInstallation packageName="@logto/rn expo-crypto expo-secure-store expo-web-browser @react-native-async-storage/async-storage" />

The `@logto/rn` package is the SDK for Logto. The remaining packages are its peer dependencies. They couldn't be listed as direct dependencies because the Expo CLI requires that all dependencies for native modules be installed directly within the root project's `package.json`.

<InlineNotification>

If you're installing this in a [bare React Native app](https://docs.expo.dev/bare/overview), you should also follow these [additional installation instructions](https://docs.expo.dev/bare/installing-expo-modules/).

</InlineNotification>

</Step>

<Step title="Init Logto provider">

Import and use `LogtoProvider` to provide a Logto context:

<Code className="language-tsx" title="App.tsx">
    {`import { LogtoProvider, LogtoConfig } from '@logto/rn';

const config: LogtoConfig = {
  endpoint: '${props.endpoint}',
  appId: '${props.app.id}',
};

const App = () => (
  <LogtoProvider config={config}>
    <YourAppContent />
  </LogtoProvider>
);`}
</Code>

<br/>

<CustomDomainEndpointNotice />

</Step>

<Step title="Configure redirect URIs">

<RedirectUrisNative />

- For iOS, the redirect URI scheme does not really matter since the `ASWebAuthenticationSession` class will listen to the redirect URI regardless of if it's registered.
- For Android, the redirect URI scheme must be filled in Expo's `app.json` file, for example:

  ```json title="app.json"
  {
    "expo": {
      "scheme": "io.logto"
    }
  }
  ```

The redirect URI is used to redirect the user back to your app after they sign in.

</Step>

<Step title="Implement sign-in and sign-out">

You can use `useLogto` hook to sign in and sign out:

<Code className="language-tsx" title="App.tsx">
    {`import { useLogto } from '@logto/rn';
import { Button } from 'react-native';

const Content = () => {
  const { signIn, signOut, isAuthenticated } = useLogto();

  return (
    <div>
      {isAuthenticated ? (
        <Button title="Sign out" onPress={async () => signOut()} />
      ) : (
        <Button title="Sign in" onPress={async () => signIn('${
          props.redirectUris[0] || defaultRedirectUri
        }')} />
      )}
    </div>
  );
};`}
</Code>

</Step>

<Step title="Checkpoint: Test your app">

<Checkpoint />

</Step>

<Step title="Display user information">

To display the user's information, you can use the `getIdTokenClaims()` method:

<Code className="language-tsx" title="App.tsx">
    {`import { useLogto } from '@logto/rn';
import { Button, Text } from 'react-native';

const Content = () => {
  const { getIdTokenClaims, isAuthenticated } = useLogto();
  const [user, setUser] = useState(null);

  useEffect(() => {
    if (isAuthenticated) {
      getIdTokenClaims().then((claims) => {
        setUser(claims); // { sub: '...', ... }
      });
    }
  }, [isAuthenticated, getIdTokenClaims]);

 // ...
};`}
</Code>

</Step>

<Step title="Troubleshooting">

For Expo projects, if you encounter the error `Unable to resolve "@logto/client/shim" from "node_modules/@logto/rn/lib/index.js"`, you can resolve it by adding the following to your `metro.config.js` file:

```js title="metro.config.js"
const config = {
  // ...
  resolver: {
    unstable_enablePackageExports: true,
  },
};

module.exports = config;
```

This error indicates that `@logto/rn` package is not able to resolve the `@logto/client/shim` module.

As the node exports were used in the`@logto/client` package, and package exports are not enabled by default in Metro bundler, you need to enable them manually.

See the [React Native package exports support](https://reactnative.dev/blog/2023/06/21/package-exports-support#enabling-package-exports-beta) for more details.

</Step>

</Steps>
