diff --git a/config/root/root.tsx b/config/root/root.tsx deleted file mode 100644 index a9672387..00000000 --- a/config/root/root.tsx +++ /dev/null @@ -1,95 +0,0 @@ -import React from 'react'; -import { ActivityIndicator, StatusBar, View, ViewStyle } from 'react-native'; -import SplashScreen from 'react-native-splash-screen'; -import AsyncStorage from '@react-native-community/async-storage'; -import changeNavigationBarColor from 'react-native-navigation-bar-color'; -import { ColorSchemeProvider, ColorSchemeContext } from 'react-native-dynamic'; -import { onChanges } from 'store'; -import { i18n } from 'services/i18n'; -import { loadLocalSettings } from 'services/settings-sync'; - -import { syncService, navigation, settings } from 'services'; -import { dark, color } from 'types/colors'; - -class App extends React.Component { - state = { isLoaded: false }; - RootStack: any = null; - loadNavigationState: Function = null; - persistNavigationState: Function = null; - style: ViewStyle = { flex: 1 }; - - sync = async () => { - const lastSync: number = +(await AsyncStorage.getItem('lastSync')) || 0; - const hour = 60 * 60 * 1000; - const now = Date.now(); - - if (now - lastSync > hour) { - await syncService.sync(); - AsyncStorage.setItem('lastSync', now.toString()); - } - }; - - subscription = onChanges.subscribe(() => syncService.sync()); - - constructor(props, context) { - super(props, context); - - Promise.all([loadLocalSettings(), i18n.init()]) - .then(() => this.setState({ isLoaded: true })) - .then(this.sync); - } - - render() { - if (!this.state.isLoaded) { - return ; - } - - if (!this.RootStack) { - const routes = require('../router'); - - this.RootStack = routes.create(settings.userId ? 'App' : 'Login'); - SplashScreen.hide(); - - if (__DEV__) { - this.loadNavigationState = routes.loadNavigationState; - this.persistNavigationState = routes.persistNavigationState; - } - } - - return ( - - {this.renderRoot} - - ); - } - - renderRoot = mode => { - const { RootStack, loadNavigationState, persistNavigationState } = this; - const isDark = mode === 'dark'; - - const barStyle = isDark ? 'light-content' : 'dark-content'; - const backgroundColor = isDark ? dark.Background : color.Background; - - if (this.style.backgroundColor !== backgroundColor) { - this.style = { flex: 1, backgroundColor }; - changeNavigationBarColor(backgroundColor, !isDark, false); - } - - return ( - - - - - ); - }; - - componentWillUnmount() { - this.subscription.unsubscribe(); - } -} - -export default App; diff --git a/config/root/root.web.tsx b/config/root/root.web.tsx deleted file mode 100644 index 00cb6eea..00000000 --- a/config/root/root.web.tsx +++ /dev/null @@ -1,79 +0,0 @@ -import React from 'react'; -import { ActivityIndicator, StatusBar, View, ViewStyle } from 'react-native'; -import AsyncStorage from '@react-native-community/async-storage'; -import { ColorSchemeProvider, ColorSchemeContext } from 'react-native-dynamic'; -import { onChanges } from 'store'; -import { i18n } from 'services/i18n'; -import { loadLocalSettings } from 'services/settings-sync'; - -import { settings, syncService, navigation } from 'services'; -import { dark, color } from 'types/colors'; -import { create } from '../router'; - -class App extends React.Component { - state = { isLoaded: false }; - stack: any = null; - style: ViewStyle = { flex: 1 }; - - sync = async () => { - const lastSync: number = +(await AsyncStorage.getItem('lastSync')) || 0; - const hour = 60 * 60 * 1000; - const now = Date.now(); - - if (now - lastSync > hour) { - await syncService.sync(); - AsyncStorage.setItem('lastSync', now.toString()); - } - }; - - subscription = onChanges.subscribe(() => syncService.sync()); - - constructor(props, context) { - super(props, context); - - Promise.all([loadLocalSettings(), i18n.init()]) - .then(() => this.setState({ isLoaded: true })) - .then(this.sync); - } - - render() { - if (!this.state.isLoaded) { - return ; - } - - if (!this.stack) { - this.stack = create(settings.userId ? 'App' : 'Login'); - } - - return ( - - {this.renderRoot} - - ); - } - - renderRoot = mode => { - const RootStack = this.stack; - const isDark = mode === 'dark'; - - const barStyle = isDark ? 'light-content' : 'dark-content'; - const backgroundColor = isDark ? dark.Background : color.Background; - - if (this.style.backgroundColor !== backgroundColor) { - this.style = { flex: 1, backgroundColor }; - } - - return ( - - - - - ); - }; - - componentWillUnmount() { - this.subscription.unsubscribe(); - } -} - -export default App; diff --git a/config/router/create-app.ts b/config/router/create-app.ts deleted file mode 100644 index e6622985..00000000 --- a/config/router/create-app.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { createAppContainer } from 'react-navigation'; -import { createStackNavigator } from 'react-navigation-stack'; - -export const createApp = createAppContainer; -export const createStackPersistNavigator = createStackNavigator; diff --git a/config/router/create-app.web.ts b/config/router/create-app.web.ts deleted file mode 100644 index c628a44a..00000000 --- a/config/router/create-app.web.ts +++ /dev/null @@ -1,34 +0,0 @@ -import _ from 'lodash'; -import { createBrowserApp } from '@react-navigation/web'; -import { createStackNavigator } from 'react-navigation-stack'; - -export const createApp = nav => { - const { getPathAndParamsForState, getActionForPathAndParams } = nav.router; - - nav.router.getPathAndParamsForState = state => { - const res = getPathAndParamsForState(state); - - if (res?.path.startsWith('/modal')) return null; - - return res; - }; - - nav.router.getActionForPathAndParams = (path, params) => { - const removeParams = action => { - if (action.action) { - action.params = {}; - removeParams(action.action); - } - - return action; - }; - - return removeParams(getActionForPathAndParams(path, params)); - }; - - return createBrowserApp(nav, { history: 'hash' }); -}; - -export function createStackPersistNavigator(stack, options) { - return createStackNavigator(stack, options); -} diff --git a/config/router/index.ts b/config/router/index.ts deleted file mode 100644 index f8903b3a..00000000 --- a/config/router/index.ts +++ /dev/null @@ -1,115 +0,0 @@ -import _ from 'lodash'; -import { createSwitchNavigator } from 'react-navigation'; -import { createStackNavigator, TransitionPresets } from 'react-navigation-stack'; -import { Easing, Platform } from 'react-native'; -import AsyncStorage from '@react-native-community/async-storage'; -import { enableScreens } from 'react-native-screens'; - -import { LoginScreen } from 'screens/login/login.screen'; -import { createApp, createStackPersistNavigator } from './create-app'; -import { MainStack, ModalStack } from './routes'; - -const createNavigator = initialRouteName => - createSwitchNavigator( - { - Login: { - screen: LoginScreen, - path: '/login', - }, - App: { - screen: createStackNavigator( - { - MainStack: { - screen: createStackPersistNavigator(MainStack, { - initialRouteName: 'Home', - headerMode: 'none', - gestureEnabled: true, - defaultNavigationOptions: { - ...TransitionPresets.SlideFromRightIOS, - gestureEnabled: true, - cardStyle: { backgroundColor: null }, - cardOverlayEnabled: false, - cardShadowEnabled: false, - }, - } as any), - path: '', - }, - ...createModalStack(ModalStack), - }, - { - initialRouteName: 'MainStack', - mode: 'modal', - headerMode: 'none', - gestureEnabled: false, - defaultNavigationOptions: { - gestureEnabled: false, - cardStyleInterpolator({ current }) { - return { - cardStyle: { - opacity: current.progress, - }, - }; - }, - transitionSpec: { - open: modalConfig, - close: modalConfig, - }, - cardStyle: { backgroundColor: null }, - cardOverlayEnabled: false, - cardShadowEnabled: false, - }, - } as any, - ), - path: '', - }, - }, - { - initialRouteName, - }, - ); - -const PERSISTENCE_KEY = 'REACT_DEV_NAVIGATION'; - -export const persistNavigationState = async nav => { - if (!hasModals(nav)) { - await AsyncStorage.setItem(PERSISTENCE_KEY, JSON.stringify(nav)); - } -}; - -export const loadNavigationState = async () => { - const jsonString = await AsyncStorage.getItem(PERSISTENCE_KEY); - return JSON.parse(jsonString); -}; - -export const create = route => { - enableScreens(true); - return createApp(createNavigator(route)); -}; - -const modalConfig = { - animation: 'timing', - config: { - duration: 100, - easing: Easing.out(Easing.poly(4)), - }, -}; - -function isRouteModal(scene) { - return scene && scene.routeName.startsWith('/modal'); -} - -function hasModals(nav) { - if (_.get(nav, 'routes[1].routeName') !== 'App') return false; - - return _.some(nav.routes[1].routes, isRouteModal); -} - -function createModalStack(stack) { - const result = {}; - - _.forEach(stack, (screen, key) => { - result[`/modal/${_.kebabCase(key)}`] = screen; - }); - - return result; -} diff --git a/config/router/routes.ts b/config/router/routes.ts deleted file mode 100644 index 361f2c71..00000000 --- a/config/router/routes.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { HomeScreen } from 'screens/home/home.screen'; -import { SearchScreen } from 'screens/search/search.screen'; -import { ReadListScreen } from 'screens/book-list/read-list.screen'; -import { WishListScreen } from 'screens/book-list/wish-list.screen'; -import { ProfileScreen } from 'screens/profile/profile.screen'; -import { DetailsScreen } from 'screens/details/details.screen'; -import { EditionsListScreen } from 'screens/editions/editions.screen'; -import { BookSelectScreen } from 'screens/book-select/book-select.screen'; -import { StatScreen } from 'screens/stat/stat.screen'; -import { WorkListScreen } from 'screens/work-list/work-list.screen'; -import { TopRateScreen } from 'screens/top-rate/top-rate.screen'; -import { AuthorsScreen } from 'screens/authors/authors.screen'; -import { AuthorSearchScreen } from 'screens/authors/author-search.screen'; -import { SettingsScreen } from 'screens/settings/settings.screen'; -import { ListsScreen } from 'screens/lists/lists.screen'; - -import { ChangeStatusModal } from 'modals/change-status/change-status.modal'; -import { BookSelectModal } from 'modals/book-select/book-select.modal'; -import { BookFiltersModal } from 'modals/book-filters/book-filters.modal'; -import { ThumbnailSelectModal } from 'modals/thumbnail-select/thumbnail-select.modal'; -import { ReviewWriteModal } from 'modals/review-write/review-write.modal'; -import { FantlabLoginModal } from 'modals/fantlab-login/fantlab-login.modal'; -import { BookTitleEditModal } from 'modals/book-title-edit/book-title-edit.modal'; -import { ScanIsbnModal } from 'modals/scan-isbn/scan-isbn.modal'; -import { ListAddModal } from 'modals/list-add.modal'; -import { ListEditModal } from 'modals/list-edit.modal'; -import { ListBookSelectModal } from 'modals/list-book-select.modal'; -import { BookActionsModal } from 'modals/book-actions'; -import { BookEditorModal } from 'modals/book-editor/book-editor.modal'; - -export const MainStack = { - Home: { screen: HomeScreen, path: '/' }, - Search: SearchScreen, - ReadList: ReadListScreen, - WishList: WishListScreen, - Profile: ProfileScreen, - Details: DetailsScreen, - Editions: EditionsListScreen, - BookSelect: BookSelectScreen, - Stat: StatScreen, - WorkList: WorkListScreen, - TopRate: TopRateScreen, - Authors: AuthorsScreen, - AuthorSearch: AuthorSearchScreen, - Settings: SettingsScreen, - Lists: ListsScreen, -}; - -export const ModalStack = { - ChangeStatus: ChangeStatusModal, - BookSelect: BookSelectModal, - BookFilters: BookFiltersModal, - ThumbnailSelect: ThumbnailSelectModal, - ReviewWrite: ReviewWriteModal, - FantlabLogin: FantlabLoginModal, - BookTitleEdit: BookTitleEditModal, - ScanIsbn: ScanIsbnModal, - ListAdd: ListAddModal, - ListEdit: ListEditModal, - ListBookSelect: ListBookSelectModal, - BookActions: BookActionsModal, - BookEditor: BookEditorModal, -}; diff --git a/index.js b/index.js index 6c39c155..13b38f89 100755 --- a/index.js +++ b/index.js @@ -1,11 +1,6 @@ import 'react-native-gesture-handler'; -import { AppRegistry } from 'react-native'; +import { AppRegistry, LogBox } from 'react-native'; import { name as appName } from './app.json'; -console.disableYellowBox = true; -AppRegistry.registerComponent(appName, () => require('./config/root/root').default); - -// if (__DEV__) { -// console.disableYellowBox = true; -// require('why-did-you-update').whyDidYouUpdate(require('react'), { exclude: /^YellowBox/ }); -// } +LogBox.ignoreLogs(['Non-serializable values were found']); +AppRegistry.registerComponent(appName, () => require('./src/app').default); diff --git a/package.json b/package.json index d58bb290..12fdb6be 100755 --- a/package.json +++ b/package.json @@ -31,9 +31,10 @@ "@nozbe/watermelondb": "0.20.0", "@nozbe/with-observables": "1.0.8", "@react-native-community/async-storage": "1.12.1", - "@react-native-community/datetimepicker": "3.3.0", + "@react-native-community/datetimepicker": "3.4.0", "@react-native-community/masked-view": "0.1.10", - "@react-navigation/web": "1.0.0-alpha.9", + "@react-navigation/native": "5.9.3", + "@react-navigation/stack": "5.14.3", "bbcode-to-react": "0.2.9", "i18next": "19.9.2", "i18next-react-native-language-detector": "1.0.2", @@ -59,9 +60,6 @@ "react-native-triangle": "0.0.9", "react-native-vector-icons": "8.1.0", "react-native-web": "0.15.0", - "react-navigation": "4.4.4", - "react-navigation-props-mapper": "1.0.4", - "react-navigation-stack": "2.10.4", "recyclerlistview": "3.0.5", "rn-classnames": "1.0.1", "rxjs": "6.5.3", @@ -79,10 +77,10 @@ "@babel/preset-typescript": "7.13.0", "@babel/runtime": "7.13.10", "@react-native-community/eslint-config": "2.0.0", - "@types/jest": "26.0.20", + "@types/jest": "26.0.21", "@types/lodash": "4.14.168", "@types/react": "17.0.3", - "@types/react-native": "0.63.52", + "@types/react-native": "0.64.0", "@types/react-native-calendars": "1.505.1", "@types/react-native-vector-icons": "6.4.6", "@types/react-test-renderer": "17.0.1", @@ -110,7 +108,7 @@ "jest": "26.6.3", "metro-minify-terser": "0.65.2", "metro-react-native-babel-preset": "0.65.2", - "mockdate": "3.0.2", + "mockdate": "3.0.4", "patch-package": "6.4.7", "postinstall-postinstall": "2.1.0", "prettier": "2.2.1", diff --git a/src/app.tsx b/src/app.tsx new file mode 100644 index 00000000..2c1b010c --- /dev/null +++ b/src/app.tsx @@ -0,0 +1,20 @@ +import React from 'react'; +import { ColorSchemeProvider } from 'react-native-dynamic'; + +import { StatusBarColor } from 'components/status-bar-color'; +import { MultiProvider } from 'utils/multi-provider'; +import { Initializator } from 'services/initializator'; +import { Root } from 'navigation'; + +const providers = [ColorSchemeProvider]; + +export default function App() { + return ( + + + + + + + ); +} diff --git a/src/components/action-sheet.tsx b/src/components/action-sheet.tsx index 83031465..1448387b 100644 --- a/src/components/action-sheet.tsx +++ b/src/components/action-sheet.tsx @@ -2,9 +2,9 @@ import React, { useEffect, useMemo } from 'react'; import { Animated, View, Text, TouchableWithoutFeedback, TouchableOpacity, Platform } from 'react-native'; import { DynamicStyleSheet, useDynamicStyleSheet } from 'react-native-dynamic'; import { dynamicColor, light } from 'types/colors'; -import { navigation, t } from 'services'; +import { getNavigation, t } from 'services'; import { confirm } from 'screens/details/components/book-details-lines'; -import { useSafeAreaInsets } from 'react-native-safe-area-context'; +import { useNavigation } from '@react-navigation/core'; export interface Action { id: string; @@ -20,6 +20,7 @@ type Props = { const paddingBottom = Platform.OS === 'web' ? 50 : 0; export function ActionSheet({ actions, onSelect }: Props) { + const navigation = useNavigation(); const s = useDynamicStyleSheet(ds); const value = useMemo(() => new Animated.Value(0), []); const sheetStyle = useMemo( @@ -41,6 +42,8 @@ export function ActionSheet({ actions, onSelect }: Props) { }).start(); }, []); + const onBack = () => navigation.goBack(); + return ( @@ -49,7 +52,7 @@ export function ActionSheet({ actions, onSelect }: Props) { {actions.map(action => ( - select(action, onSelect)}> + select(action, onSelect, onBack)}> {t(action.label)} ))} @@ -58,11 +61,7 @@ export function ActionSheet({ actions, onSelect }: Props) { ); } -function onBack() { - return navigation.pop(); -} - -function select(action: Action, onSelect) { +function select(action: Action, onSelect, onBack) { onBack(); if (action.dangerous) { diff --git a/src/components/book-item.tsx b/src/components/book-item.tsx index d41c59a0..b104c438 100644 --- a/src/components/book-item.tsx +++ b/src/components/book-item.tsx @@ -1,15 +1,16 @@ import React from 'react'; -import { Text, TouchableOpacity, View, ViewStyle, ImageStyle, TextStyle, Platform } from 'react-native'; +import { Text, TouchableOpacity, View, ViewStyle, ImageStyle, TextStyle } from 'react-native'; import withObservables from '@nozbe/with-observables'; import { of } from 'rxjs/internal/observable/of'; import Icon from 'react-native-vector-icons/FontAwesome5'; import { getColor, dynamicColor } from 'types/colors'; -import { navigation } from 'services'; +import { getNavigation, openModal } from 'services'; import { Thumbnail } from 'components/thumbnail'; import { BOOK_STATUSES } from 'types/book-statuses.enum'; import Book, { BookData } from 'store/book'; import { formatDate } from 'utils/date'; import { ColorSchemeContext, DynamicStyleSheet } from 'react-native-dynamic'; +import { MainRoutes, ModalRoutes } from 'navigation/routes'; const NEXT_STATUSES = { [BOOK_STATUSES.WISH]: BOOK_STATUSES.NOW, @@ -101,18 +102,18 @@ export class BookItem extends React.Component { openBook = () => { const { book, fantlabId, extra } = this.props; - navigation.push('Details', { bookId: book.id, fantlabId, extra }); + getNavigation().push(MainRoutes.Details, { bookId: book.id, fantlabId, extra }); }; openBookActions = () => { - navigation.navigate('/modal/book-actions', { bookId: this.props.book.id }); + openModal(ModalRoutes.BookActions, { bookId: this.props.book.id }); }; openChangeStatusModal = () => { const book = this.props.book; const status = this.nextStatus; - navigation.navigate('/modal/change-status', { book, status }); + openModal(ModalRoutes.ChangeStatus, { book, status }); }; } const ds = new DynamicStyleSheet({ diff --git a/src/components/dialog.tsx b/src/components/dialog.tsx index 4c0ba81c..22d529fa 100644 --- a/src/components/dialog.tsx +++ b/src/components/dialog.tsx @@ -2,8 +2,9 @@ import React, { ReactNode, useCallback } from 'react'; import { Text, View, TouchableWithoutFeedback, TextStyle, ViewStyle, Platform } from 'react-native'; import { DynamicStyleSheet } from 'react-native-dynamic'; import { dynamicColor, light, useSColor } from 'types/colors'; -import { navigation, t } from 'services'; +import { t } from 'services'; import { TouchIcon } from 'components/touch-icon'; +import { useNavigation } from '@react-navigation/core'; interface Props { style?: ViewStyle; @@ -17,9 +18,11 @@ interface Props { } export const Dialog = (props: Props) => { + const navigation = useNavigation(); + const { s, color } = useSColor(ds); const back = useCallback(() => { - onBack(); + navigation.goBack(); props.onClose?.(); }, [props.onClose]); @@ -53,10 +56,6 @@ function renderDialogHeader(title: string, back, rightIcon, onApply, s, color) { ); } -function onBack() { - return navigation.pop(); -} - const ds = new DynamicStyleSheet({ container: { flex: 1, @@ -68,9 +67,8 @@ const ds = new DynamicStyleSheet({ left: 0, right: 0, bottom: 0, - opacity: 0.5, + opacity: 0, position: 'absolute', - backgroundColor: light.Black, } as ViewStyle, modal: { marginTop: 50, diff --git a/src/components/screen-header.tsx b/src/components/screen-header.tsx index 6ee240da..1f855a9a 100644 --- a/src/components/screen-header.tsx +++ b/src/components/screen-header.tsx @@ -2,7 +2,7 @@ import React, { memo, useContext, useState, useCallback, useEffect } from 'react import { View, Text, ViewStyle, TextStyle } from 'react-native'; import { DynamicStyleSheet } from 'react-native-dynamic'; import { useSColor, dynamicColor } from 'types/colors'; -import { navigation, t } from 'services'; +import { getNavigation, t } from 'services'; import { ScrollToTopContext } from 'utils/scroll-to-top'; import { TouchIcon } from './touch-icon'; import { SearchBar } from './search-bar'; @@ -15,6 +15,16 @@ interface Props { onSearch?: (value: string) => void; } +export function headerRightButton(name, onPress) { + return ({ tintColor }) => ( + + ); +} + +export const headerBackImage = ({ tintColor }) => ( + +); + export const ScreenHeader = memo((props: Props) => { const { scroll } = useContext(ScrollToTopContext); const [search, setSearch] = useState(false); @@ -49,7 +59,7 @@ export const ScreenHeader = memo((props: Props) => { { }); function goBack() { - navigation.pop(); + getNavigation().pop(); } function goToHome() { - navigation.popToTop(); + getNavigation().popToTop(); } const ds = new DynamicStyleSheet({ diff --git a/src/components/status-bar-color.tsx b/src/components/status-bar-color.tsx new file mode 100644 index 00000000..36d7621f --- /dev/null +++ b/src/components/status-bar-color.tsx @@ -0,0 +1,18 @@ +import React, { FC, useEffect } from 'react'; +import { StatusBar } from 'react-native'; +import { useDarkMode } from 'react-native-dynamic'; +import changeNavigationBarColor from 'react-native-navigation-bar-color'; +import { dark, color } from 'types/colors'; + +export const StatusBarColor: FC = () => { + const isDark = useDarkMode(); + + const barStyle = isDark ? 'light-content' : 'dark-content'; + const backgroundColor = isDark ? dark.Background : color.Background; + + useEffect(() => { + changeNavigationBarColor(backgroundColor, !isDark, false); + }, [backgroundColor, isDark]); + + return ; +}; diff --git a/src/modals/book-actions.tsx b/src/modals/book-actions.tsx index 3aaa11d1..e6b80883 100644 --- a/src/modals/book-actions.tsx +++ b/src/modals/book-actions.tsx @@ -1,7 +1,9 @@ -import React from 'react'; +import React, { FC } from 'react'; import { Action, ActionSheet } from 'components/action-sheet'; import { database } from 'store'; import Book from 'store/book'; +import { openModal } from 'services'; +import { ModalRoutes, ModalScreenProps } from 'navigation/routes'; const ACTIONS: Action[] = [ { id: 'edit' as const, label: 'modal.edit' }, @@ -13,20 +15,19 @@ const HANDLERS = { delete: deleteBook, }; -export function BookActionsModal({ navigation }) { - const onSelect = actionId => HANDLERS[actionId](navigation); +type Props = ModalScreenProps; - return ; -} +export const BookActionsModal: FC = ({ route }) => { + const onSelect = actionId => HANDLERS[actionId](route.params.bookId); -function openBookEditor(navigation) { - const bookId = navigation.getParam('bookId'); + return ; +}; - navigation.navigate('/modal/book-editor', { bookId }); +function openBookEditor(bookId) { + openModal(ModalRoutes.BookEditor, { bookId }); } -async function deleteBook(navigation) { - const bookId = navigation.getParam('bookId'); +async function deleteBook(bookId) { const book = await database.collections.get('books').find(bookId); await database.action(() => book.markAsDeleted()); diff --git a/src/modals/book-editor/book-editor.modal.tsx b/src/modals/book-editor/book-editor.modal.tsx index 05d3f317..7027e160 100644 --- a/src/modals/book-editor/book-editor.modal.tsx +++ b/src/modals/book-editor/book-editor.modal.tsx @@ -1,23 +1,21 @@ -import React, { useState, useCallback, useRef } from 'react'; +import React, { useState, useCallback, useRef, FC } from 'react'; import _ from 'lodash'; import { ViewStyle, StyleSheet, View, ScrollView } from 'react-native'; -import { withNavigationProps } from 'utils/with-navigation-props'; + import { Dialog, Button, Fetcher } from 'components'; import Book from 'store/book'; -import { NavigationStackProp } from 'react-navigation-stack'; import { BookExtended } from 'types/book-extended'; import { api, t } from 'services'; +import { ModalRoutes, ModalScreenProps } from 'navigation/routes'; import { TitleEdit } from './components/title-edit'; import { ThumbnailEdit } from './components/thumbnail-edit'; -interface Props { - bookId: string; - navigation: NavigationStackProp; -} +type Props = ModalScreenProps; const TITLE_SEPARATOR = /\s*;\s*/g; -export const BookEditorModal = withNavigationProps()(({ bookId, navigation }: Props) => { +export const BookEditorModal: FC = ({ route, navigation }: Props) => { + const bookId = route.params.bookId; const book = useRef(null); const [title, setTitle] = useState(''); @@ -48,9 +46,9 @@ export const BookEditorModal = withNavigationProps()(({ bookId, navigation }: Pr