From 85c0cfaabc3066e7e58e356d87f5a766a2c1d8e1 Mon Sep 17 00:00:00 2001 From: Ilya Pakhomov Date: Mon, 1 Dec 2025 17:09:08 +0600 Subject: [PATCH 1/6] chore: remove lib readme and leave only root one --- src/lib/README.md | 430 ------------------------------------------- src/lib/project.json | 2 +- 2 files changed, 1 insertion(+), 431 deletions(-) delete mode 100644 src/lib/README.md diff --git a/src/lib/README.md b/src/lib/README.md deleted file mode 100644 index 727c2fe..0000000 --- a/src/lib/README.md +++ /dev/null @@ -1,430 +0,0 @@ -# React Native Common Modules - -Common components for Ronas IT projects. - -## Usage - -1. Install the package: `npm i @ronas-it/react-native-common-modules` -2. Import modules to your app and use as described below - -### UI-components - -At the moment this library contains the following components: - -#### 1. `AppSafeAreaView` - -> **_NOTE:_** Required dependencies: `react-native-safe-area-context` - -A component for granular control of safe area edges on each screen. The difference from `SafeAreaView` in [react-native-safe-area-context](https://www.npmjs.com/package/react-native-safe-area-context) is that the container adds padding to the elements inside it, rather than to the entire screen, making it more flexible for use. - -**Props:** - -- `edges`: An array indicating which edges of the screen to respect. Possible values are 'top', 'right', 'bottom', 'left'. Defaults to all edges. -- `style`: Custom styles to apply to the view. Note that padding values will be adjusted to respect safe area insets. - -**Example:** - -```jsx -import { AppSafeAreaView } from '@ronas-it/react-native-common-modules/safe-area-view'; - - - Content goes here -; -``` - -### Services - -#### 1. Push notifications - -> **_NOTE:_** Required dependencies: `@pusher/pusher-websocket-react-native`, `pusher-js`, `expo-notifications`, `expo-router`, `expo-constants`, `expo-device`, `expo-modules-core` - -##### `PushNotificationsService` - -Service for integrating [Expo push notifications](https://docs.expo.dev/push-notifications/overview/) into apps. -Requires [setup](https://docs.expo.dev/push-notifications/push-notifications-setup/) and [backend implementation](https://docs.expo.dev/push-notifications/sending-notifications/) for sending notifications. - -`PushNotificationsService` public methods: - -- `obtainPushNotificationsToken` - get an Expo token that can be used to send a push notification to the device using Expo's push notifications service. - -- `pushToken` - getter for retrieving the token if it was already obtained. - -##### `usePushNotifications` - -Hook, that automatically subscribes the device to receive push notifications when a user becomes authenticated, and unsubscribes when a user becomes non-authenticated. It supports custom subscription and unsubscription logic through provided functions or API configuration. Listens for [responses](https://docs.expo.dev/push-notifications/receiving-notifications/) to notifications and executes a callback, if provided, when a notification is interacted with. -Used in the root `App` component. - -`usePushNotifications` hook arguments: - -- `isAuthenticated` (required) - flag, that indicates whether the user is authenticated or not. -- `onNotificationResponse` (optional) - callback when a notification is interacted with. -- `subscribeDevice` (optional) - function for subscribing the device. -- `unsubscribeDevice` (optional) - function for unsubscribing the device. -- `apiConfig` (optional) - API configuration for subscribing and unsubscribing the device (when `subscribeDevice` and `unsubscribeDevice` are not provided). -- `apiErrorHandler` (optional) - API error handler for subscribe/unsubscribe functions. -- `getTokenErrorHandler` (optional) - handler for error that occur when attempting to obtain a push notifications token. - -**Example:** - -```ts -// Somewhere in a root component of your app: -import { usePushNotifications } from '@ronas-it/react-native-common-modules/push-notifications'; - -... -const authToken = useSelector(authSelectors.token); -... -usePushNotifications({ - apiConfig: { - subscribeDeviceUrl: 'https://your-api.com/api/v1/push-notifications/subscribe', - unsubscribeDeviceUrl: 'https://your-api.com/api/v1/push-notifications/unsubscribe', - accessToken: authToken, - }, - isAuthenticated: !!authToken, -}) -``` - -> **_NOTE:_** By default, when using the `apiConfig` option, the hook sends the Expo push token to your server in the following format: `JSON.stringify({ expo_token })` - -#### 2. Image Picker - -> **_NOTE:_** Required dependencies: `expo-image-picker` - -`ImagePickerService` gives the application access to the camera and image gallery. - -Public methods: - -- `getImage` - initializes the application (camera or gallery) and returns a result containing an image. -- `launchGallery` - launches the gallery application and returns a result containing the selected images. -- `launchCamera` - launches the camera application and returns the taken photo. -- `requestGalleryAccess` - requests the application access to the gallery. -- `requestCameraAccess` - requests the application access to the camera. -- `getFormData` - creates a [FormData](https://developer.mozilla.org/en-US/docs/Web/API/FormData) object with image. - -**Example** - -Pick image and send request: - -```ts -import { imagePickerService, ImagePickerSource } from '@ronas-it/react-native-common-modules/image-picker'; - -const handlePickImage = async (source: ImagePickerSource) => { - const image = await imagePickerService.getImage(source); - const asset = image?.assets?.[0]; - - if (!asset) { - return; - } - - const data = imagePickerService.getFormData(asset.uri); - - // API call - createMedia(data); -}; -``` - -#### 3. WebSocket - -> **_NOTE:_** Required dependencies: `@pusher/pusher-websocket-react-native`, `pusher-js` - -`WebSocketService` manages WebSocket connections using [Pusher](https://pusher.com/) and can work in both web and mobile applications. -Doesn't support Expo Go. - -It's necessary to install [@pusher/pusher-websocket-react-native](https://github.com/pusher/pusher-websocket-react-native) -for a mobile app and [pusher-js](https://github.com/pusher/pusher-js) for a web app. - -Options for `WebSocketService` constructor: - -- `apiKey` (required) - `APP_KEY` from [Pusher Channels Dashboard](https://dashboard.pusher.com/). -- `cluster` (required) - `APP_CLUSTER` from [Pusher Channels Dashboard](https://dashboard.pusher.com/). -- `authURL` (optional) - a URL that returns the authentication signature needed for private channels. -- `useTLS` (optional) - a flag that indicates whether TLS encrypted transport should be used. Default value is `true`. -- `activityTimeout` (optional) - time in milliseconds to ping a server after last message. -- `pongTimeout` (optional) - time in milliseconds to wait a response after a pinging request. - -`WebSocketService` public methods: - -- `connect` initializes and connects the Pusher client. Optional authorization token is used for secure connections. -- `subscribeToChannel` subscribes to a specified channel and registers an event listener for incoming messages on that channel. -- `unsubscribeFromChannel` removes an event listener and, if there are no listeners for a specified channel, unsubscribes from it. - -**Example:** - -```ts -import { WebSocketService } from '@ronas-it/react-native-common-modules/websocket'; - -// Create a service instance -type ChannelName = `private-conversations.${number}` | `private-users.${number}`; -const webSocketService = new WebSocketService({ - apiKey: '1234567890qwertyuiop', - cluster: 'eu', - authURL: 'https://your-api.com/api/v1/broadcasting/auth', -}); - -// Initialize Pusher, e.g. after an app initialization or successful authorization -await webSocketService.connect('your-auth-token'); - -// Subscribe to a channel when it's necessary -webSocketService.subscribeToChannel('private-conversations.123', (event) => { - console.log('Received event:', event); -}); - -// Unsubscribe from a channel, e.g. before an app closing or logging out -webSocketService.unsubscribeFromChannel('private-conversations.123', (event) => { - console.log('Received event:', event); -}); -``` - -### Utils - -#### 1. `setupReactotron(projectName: string, plugins: Array)` - -> **_NOTE:_** Required dependencies: `@reduxjs/toolkit`, `reactotron-react-native`, `reactotron-react-js`, `reactotron-redux` - -Configures and initializes [Reactotron debugger](https://github.com/infinitered/reactotron) with [redux plugin](https://docs.infinite.red/reactotron/plugins/redux/) for development purposes. -Install the [Reactotron app](https://github.com/infinitered/reactotron/releases?q=reactotron-app&expanded=true) on your computer for use. - -**Example:** - -```ts -import { setupReactotron } from '@ronas-it/react-native-common-modules/reactotron'; -import { createStoreInitializer } from '@ronas-it/rtkq-entity-api'; -import Reactotron from 'reactotron-react-native'; -import mmkvPlugin from 'reactotron-react-native-mmkv'; -import type { ReactotronReactNative } from 'reactotron-react-native'; -import { storage } from './mmkv/storage/instance/location'; // <--- update this to your mmkv instance. - -const reactotron = setupReactotron('your-app', [ - // You can add an array of Reactotron plugins here - (reactotron) => mmkvPlugin({ storage }), -]); -const enhancers = reactotron ? [reactotron.createEnhancer()] : []; - -const initStore = createStoreInitializer({ - rootReducer: rootReducer as unknown as Reducer, - middlewares, - enhancers, -}); -``` - -#### 2. `i18n` - -> **_NOTE:_** Required dependencies: `i18n-js`, `expo-localization` - -Provides functions to set language and use translations using [i18n-js](https://github.com/fnando/i18n-js) - -**Example:** - -root layout: - -```ts -import { setLanguage } from '@ronas-it/react-native-common-modules/i18n'; - -const translations = { - en: { - ...require('i18n/example/en.json') - }, - fr: { - ...require('i18n/example/fr.json') - } -}; - -const useLanguage = setLanguage(translations, 'en'); - -interface LanguageContextProps { - language: string; - onLanguageChange?: (language: keyof typeof translations) => void; -} - -export const LanguageContext = createContext({ language: 'en' }); - -function App(): ReactElement { - return ( - - - - ); -} - -export default function RootLayout(): ReactElement | null { - const [language, setLanguage] = useState('en'); - - useLanguage(language); - - return ( - - - - ); -} -``` - -screen: - -```ts -import { AppSafeAreaView } from '@ronas-it/react-native-common-modules/safe-area-view'; -import { useTranslation } from '@ronas-it/react-native-common-modules/i18n'; -import { ReactElement, useContext } from 'react'; -import { View, Text, Alert, Pressable } from 'react-native'; -import { LanguageContext } from './_layout'; - -export default function RootScreen(): ReactElement { - const translate = useTranslation('EXAMPLE'); - const { language, onLanguageChange } = useContext(LanguageContext); - - const onPress = () => Alert.alert(translate('TEXT_PRESSED')); - - const handleLanguageChange = (): void => { - onLanguageChange?.(language === 'en' ? 'fr' : 'en'); - }; - - return ( - - - - {translate('BUTTON_PRESS_ME')} - - - {translate('BUTTON_LANGUAGE')} - - - - ); -} -``` - -### Features - -#### 1. Clerk - -> **_NOTE:_** Required dependencies: `@clerk/clerk-expo`, `expo-web-browser`, `expo-auth-session` - -Hooks and helpers to create user authentication with [Clerk Expo SDK](https://clerk.com/docs/references/expo/overview). - -#### `useClerkResources` - -Hook, that provides access to essential Clerk methods and objects. - -Returned Object: - -- `signUp` - provides access to [SignUp](https://clerk.com/docs/references/javascript/sign-up) object. -- `signIn` - provides access to [SignIn](https://clerk.com/docs/references/javascript/sign-in) object. -- `setActive` - A function that sets the active session. -- `signOut` - A function that signs out the current user. - -#### `useAuthWithIdentifier` - -Hook, that provides functionality to handle user sign-up and sign-in processes using an identifier such as an email, phone number, or username. It supports both OTP (One Time Password) and password-based authentication methods. - -Parameters: - -- `method`: Specifies the type of identifier used for authentication (e.g., 'emailAddress', 'phoneNumber', 'username'). -- `verifyBy`: Specifies the verification method ('otp' for one-time passwords or 'password'). - -Returned Object: - -- `startSignUp`: Initiates a new user registration using the specified identifier and verification method. -- `startSignIn`: Initiates authentication of an existing user using the specified identifier and verification method. -- `startAuthorization`: Determines whether to initiate a sign-up or sign-in based on whether the user has been registered previously. -- `verifyCode`: Verifies an OTP code if the verification method is 'otp'. -- `isLoading`: Indicates whether an authentication request is in progress. -- `isVerifying`: Indicates whether an OTP verification is in progress. - -**Example:** - -```ts -import React, { useState } from 'react'; -import { View, TextInput, Button } from 'react-native'; -import { useAuthWithIdentifier } from '@ronas-it/react-native-common-modules/clerk'; - -export const AuthWithIdentifierComponent = () => { - const [identifier, setIdentifier] = useState(''); - const [verificationCode, setVerificationCode] = useState(''); - const { startSignUp, verifyCode, isLoading, isVerifying } = useAuthWithIdentifier('emailAddress', 'otp'); - - const handleSignUp = async () => { - await startSignUp({ identifier }); - }; - - const handleVerifyCode = async () => { - const result = await verifyCode({ code: verificationCode }); - console.log(result.sessionToken) - }; - - return ( - - - -