diff --git a/README.md b/README.md index 9809643..4d618de 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,9 @@ https://user-images.githubusercontent.com/4402166/134559538-a2801d52-7b8a-44a6-b12a-0cc1eafbb82b.MP4 + +https://user-images.githubusercontent.com/4402166/134838456-69181346-93bc-4e25-8dfa-f629ed58c813.MOV + + This starter is a collection of libraries and approaches from my personal experience. No hard judgements ✌️ For more information, check out [Why](#why) section. @@ -55,7 +59,8 @@ If you need to rename the app, do the following (based on [react-native-rename]( ## What's inside -- [React Navigation (v6)](https://github.com/react-navigation/react-navigation) - routing and navigation for React Native apps. If you'd like to use [React Native Navigation](https://github.com/wix/react-native-navigation) by Wix, check out [rnn-starter](https://github.com/kanzitelli/rnn-starter). +- [React Navigation (v6)](https://github.com/react-navigation/react-navigation) - routing and navigation for React Native apps (with [Native Stack](https://reactnavigation.org/docs/native-stack-navigator/)). If you'd like to use [React Native Navigation](https://github.com/wix/react-native-navigation) by Wix, check out [rnn-starter](https://github.com/kanzitelli/rnn-starter). +- [React Native Screens](https://github.com/software-mansion/react-native-screens) - Native navigation primitives for React Native app - [RN UI lib](https://github.com/wix/react-native-ui-lib) - amazing Design System, UI toolset & components library for React Native. Dark Mode is implemented using this library. - [Reanimated 2](https://github.com/software-mansion/react-native-reanimated) - React Native's Animated library reimplemented. - [MobX](https://github.com/mobxjs/mobx) - simple, scalable state management, with [mobx-persist-store](https://github.com/quarrant/mobx-persist-store) for persisting your stores. @@ -145,6 +150,18 @@ const Screen = ({componentId}) => { #### Samples for new screens, services, stores and components. So you have one structure within the project. You can find them in corresponding folders. Just copy&paste it and make the necessary changes. +Future Feature: I think, it would be good to have it automatically generated by [cli-rn](https://github.com/kanzitelli/cli-rn), so won't be need even for copy&paste. + +```bash +# Future feature +> cli-rn generate (screen|service|store|component) --name SName # maybe something else +> cli-rn g (sc|se|st|co) -n SName # short version +``` + +#### [WIP] Shared Element Transition (repo - [IjzerenHein/react-navigation-shared-element](https://github.com/IjzerenHein/react-navigation-shared-element)) + +It doesn’t use native api, it just [createSharedElementStackNavigator()](https://github.com/kanzitelli/rn-starter/blob/feature/shared-transition/src/services/navigation/help.tsx#L34) with [two screens](https://github.com/kanzitelli/rn-starter/blob/feature/shared-transition/src/screens/index.ts#L67) and [sets this Navigator](https://github.com/kanzitelli/rn-starter/blob/feature/shared-transition/src/screens/index.ts#L67) as a React Navigation’s native stack’s screen. +It was created as an experiment to combine great performance of [native screens](https://github.com/software-mansion/react-native-screens) and some fancy shared transitions by [IjzerenHein/react-navigation-shared-element](https://github.com/IjzerenHein/react-navigation-shared-element). ## Enhancements @@ -155,13 +172,13 @@ There are still some things I would like to add to the starter: - [x] Passing props to a screen example - [x] Constants: add Dimensions - [x] MMKV (AsyncStorage) stores persisting example -- [ ] Shared transitions — [IjzerenHein/react-navigation-shared-element](https://github.com/IjzerenHein/react-navigation-shared-element) +- [ WIP ] Shared transitions — [IjzerenHein/react-navigation-shared-element](https://github.com/IjzerenHein/react-navigation-shared-element) #### Production - [ ] Auth flow - [ ] Fast Image — [DylanVann/react-native-fast-image](https://github.com/DylanVann/react-native-fast-image) -- [ ] Notifications — [wix/react-native-notifications](https://github.com/wix/react-native-notifications) +- [ ] Notifications — [wix/react-native-notifications](https://github.com/wix/react-native-notifications) or/and [invertase/notifee](https://github.com/invertase/notifee) - [ ] E2E tests — [wix/Detox](https://github.com/wix/Detox) - [ ] Permissions — [zoontek/react-native-permissions](https://github.com/zoontek/react-native-permissions) - [ ] FB SDK — [thebergamo/react-native-fbsdk-next](https://github.com/thebergamo/react-native-fbsdk-next) @@ -182,7 +199,7 @@ Feel free to open an issue for suggestions. - Expo + React Native Navigation? Yes! - [Medium](https://kanzitelli.medium.com/expo-react-native-navigation-yes-ebda0cbfa4b1), [Dev.to](https://dev.to/kanzitelli/expo-react-native-navigation-1pll) - cli-rn — making RN app developing experience as smooth as possible - [Medium](https://kanzitelli.medium.com/cli-rn-making-rn-app-developing-experience-as-smooth-as-possible-1022aae3a0d3), [Dev.to](https://dev.to/kanzitelli/cli-rn-making-rn-app-developing-experience-as-smooth-as-possible-4e98) -### Apps in production +### Apps in production (from [rnn-starter](https://github.com/kanzitelli/rnn-starter)) - Wallpapers App - [Twitter](https://twitter.com/kanzitelli/status/1408192827155177472?s=20), App Store soon - Rabbit App. Lite Reddit client - [Github](https://github.com/kanzitelli/rabbit-app), [App Store](https://apps.apple.com/ru/app/rabbit-app-lite-reddit-client/id1535084154), [Google Play](https://play.google.com/store/apps/details?id=io.batyr.rabbitapp) diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 7320c88..1d2b0ff 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -411,6 +411,8 @@ PODS: - RNScreens (3.7.2): - React-Core - React-RCTImage + - RNSharedElement (0.8.2): + - React - RNVectorIcons (8.1.0): - React-Core - Yoga (1.14.0) @@ -485,6 +487,7 @@ DEPENDENCIES: - RNLocalize (from `../node_modules/react-native-localize`) - RNReanimated (from `../node_modules/react-native-reanimated`) - RNScreens (from `../node_modules/react-native-screens`) + - RNSharedElement (from `../node_modules/react-native-shared-element`) - RNVectorIcons (from `../node_modules/react-native-vector-icons`) - Yoga (from `../node_modules/react-native/ReactCommon/yoga`) @@ -594,6 +597,8 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native-reanimated" RNScreens: :path: "../node_modules/react-native-screens" + RNSharedElement: + :path: "../node_modules/react-native-shared-element" RNVectorIcons: :path: "../node_modules/react-native-vector-icons" Yoga: @@ -659,6 +664,7 @@ SPEC CHECKSUMS: RNLocalize: 7f1e5792b65a839af55a9552d05b3558b66d017e RNReanimated: ad24db8af24e3fe1b5c462785bc3db8d5baae2ee RNScreens: 0591543e343c7444ea1756b6265d81a4295922c9 + RNSharedElement: 87baf6d04da5b068f000dd8c953d28a1196999c0 RNVectorIcons: 31cebfcf94e8cf8686eb5303ae0357da64d7a5a4 Yoga: aa0cb45287ebe1004c02a13f279c55a95f1572f4 YogaKit: f782866e155069a2cca2517aafea43200b01fd5a diff --git a/package.json b/package.json index d78754c..191c3d1 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "@react-navigation/bottom-tabs": "^6.0.5", "@react-navigation/native": "^6.0.2", "@react-navigation/native-stack": "^6.1.0", + "@react-navigation/stack": "^6.0.7", "date-fns": "^2.24.0", "formik": "^2.2.9", "i18n-js": "^3.8.0", @@ -48,8 +49,10 @@ "react-native-restart": "^0.0.22", "react-native-safe-area-context": "^3.3.2", "react-native-screens": "^3.7.2", + "react-native-shared-element": "^0.8.2", "react-native-ui-lib": "^6.0.0", - "react-native-vector-icons": "^8.1.0" + "react-native-vector-icons": "^8.1.0", + "react-navigation-shared-element": "^3.1.3" }, "devDependencies": { "@babel/core": "^7.12.9", diff --git a/src/components/reanimated2.tsx b/src/components/reanimated2.tsx index bf6a565..4966e69 100644 --- a/src/components/reanimated2.tsx +++ b/src/components/reanimated2.tsx @@ -1,6 +1,7 @@ import React from 'react'; import {View, Text} from 'react-native-ui-lib'; import Animated, {withSpring, useAnimatedStyle, useSharedValue} from 'react-native-reanimated'; +import {SharedElement} from 'react-navigation-shared-element'; import {Bounceable} from './bounceable'; @@ -20,16 +21,18 @@ export const Reanimated2: React.FC = ({stID}: Reanimated2Props }; return ( - - - - - - Bounceable - - - - - + + + + + + + Bounceable + + + + + + ); }; diff --git a/src/screens/index.ts b/src/screens/index.ts index 71d7cb1..7b6875b 100644 --- a/src/screens/index.ts +++ b/src/screens/index.ts @@ -1,23 +1,44 @@ -import {ModalScreenLayouts, ScreenLayouts, TabScreenLayouts} from '../services/navigation/types'; +import { + ModalScreenLayouts, + ScreenLayouts, + SharedScreenLayouts, + SharedTransitionScreenLayouts, + TabScreenLayouts, +} from '../services/navigation/types'; import {Main} from './main'; import {Settings} from './settings'; import {Example} from './screen-sample'; -import {genRootNavigator, genStackNavigator, genTabNavigator} from '../services/navigation/help'; +import { + genRootNavigator, + genSharedStackNavigator, + genStackNavigator, + genTabNavigator, +} from '../services/navigation/help'; +import {Shared} from './shared'; +import {SharedTo} from './sharedTo'; // Describe your screens here export type Tabs = 'Main' | 'WIP' | 'Settings'; export type Modal = 'ExampleModal'; +export type SharedTransitionScreen = 'Shared' | 'SharedTo'; +export type SharedScreen = 'ExampleShared'; export type Screen = 'Main' | 'Example' | 'Settings'; export type ModalProps = { ExampleModal: undefined; }; +export type SharedScreenProps = { + ExampleShared: undefined; +}; export type ScreenProps = { Main: undefined; Example: ExampleScreenProps; Settings: undefined; -} & ModalProps; + Shared: undefined; + SharedTo: undefined; +} & ModalProps & + SharedScreenProps; // Screens const screens: ScreenLayouts = { @@ -43,8 +64,45 @@ const screens: ScreenLayouts = { }), }, }; -const HomeStack = () => genStackNavigator([screens.Main, screens.Example]); -const ExampleStack = () => genStackNavigator([screens.Example]); +const sharedTransitionScreens: SharedTransitionScreenLayouts = { + Shared: { + name: 'Shared', + component: Shared, + options: () => ({ + title: 'Shared Transition', + }), + }, + SharedTo: { + name: 'SharedTo', + component: SharedTo, + options: () => ({ + title: 'SharedTo Transition', + }), + sharedElements: (route, otherRoute, showing) => { + // const {item} = route.params; + // return [`item.${item.id}.photo`]; + console.log('showing', showing); + return ['image', 'reanimated2']; + }, + }, +}; +const ExampleSharedStack = () => + genSharedStackNavigator([sharedTransitionScreens.Shared, sharedTransitionScreens.SharedTo]); +const sharedScreens: SharedScreenLayouts = { + ExampleShared: { + name: 'ExampleShared', + component: ExampleSharedStack, + options: () => ({ + title: 'Shared Transition', + headerLargeTitle: false, + headerTransparent: false, + headerBlurEffect: undefined, + }), + }, +}; +const HomeStack = () => + genStackNavigator([screens.Main, screens.Example, sharedScreens.ExampleShared]); +const ExampleStack = () => genStackNavigator([screens.Example, sharedScreens.ExampleShared]); const SettingsStack = () => genStackNavigator([screens.Settings]); const ExampleModalStack = () => genStackNavigator([screens.Main, screens.Example]); diff --git a/src/screens/main.tsx b/src/screens/main.tsx index f77a7a0..659c5ec 100644 --- a/src/screens/main.tsx +++ b/src/screens/main.tsx @@ -51,12 +51,12 @@ export const Main: React.FC = observer(({}) => {