diff --git a/.storybook/index.tsx b/.storybook/index.tsx index c4bee8e2..90779825 100644 --- a/.storybook/index.tsx +++ b/.storybook/index.tsx @@ -1,9 +1,11 @@ -import AsyncStorage from '@react-native-async-storage/async-storage' +import { createAsyncStorage } from '@react-native-async-storage/async-storage' import { view } from './storybook.requires' +const storage = createAsyncStorage('storybook') + const StorybookUIRoot = view.getStorybookUI({ - storage: { getItem: AsyncStorage.getItem, setItem: AsyncStorage.setItem }, + storage, theme: { typography: { size: { diff --git a/.storybook/preview.tsx b/.storybook/preview.tsx index 2147252d..a4f29b17 100644 --- a/.storybook/preview.tsx +++ b/.storybook/preview.tsx @@ -1,14 +1,28 @@ import type { Preview } from '@storybook/react' -import { StyleSheet } from 'react-native-unistyles' -import { ThemeContextProvider, ThemeVariant } from '../src' -import { View } from 'react-native' -import React, { type FunctionComponent, type ReactNode } from 'react' +import { useArgs } from '@storybook/preview-api' +import { StyleSheet, UnistylesRuntime } from 'react-native-unistyles' +import { ThemeContextProvider, ThemeVariant } from '../src/theme' +import { View, Appearance } from 'react-native' +import React, { + useEffect, + useLayoutEffect, + useRef, + type FunctionComponent, + type ReactNode, +} from 'react' + +let currentTheme = + Appearance.getColorScheme() === 'dark' + ? ThemeVariant.Dark + : ThemeVariant.Light const preview: Preview = { decorators: [ - (Story, { args }) => { + (Story, context) => { + const [args, updateArgs] = useArgs() + return ( - + @@ -26,17 +40,45 @@ const preview: Preview = { control: { type: 'radio' }, }, }, - args: { theme: ThemeVariant.Light }, + args: { theme: currentTheme }, } export default preview +interface StorybookThemeArgs { + theme: ThemeVariant +} + +const THEME_NAME_MAP: Record = { + [ThemeVariant.Light]: 'light', + [ThemeVariant.Dark]: 'dark', +} + const Container: FunctionComponent<{ children: ReactNode theme: ThemeVariant -}> = ({ children, theme }) => { + updateArgs: (args: StorybookThemeArgs) => void +}> = ({ children, theme, updateArgs }) => { + const themeSynchronized = useRef(false) + + useEffect(() => { + if (!themeSynchronized.current) { + themeSynchronized.current = true + updateArgs({ theme: currentTheme }) + } + }, [updateArgs]) + + useLayoutEffect(() => { + if (themeSynchronized.current) { + const nextTheme = THEME_NAME_MAP[theme] + Appearance.setColorScheme(nextTheme) + UnistylesRuntime.setTheme(nextTheme) + currentTheme = theme + } + }, [theme]) + return ( - + {children} ) diff --git a/.storybook/storybook.requires.ts b/.storybook/storybook.requires.ts index 00985b4f..fa27ce80 100644 --- a/.storybook/storybook.requires.ts +++ b/.storybook/storybook.requires.ts @@ -1,5 +1,6 @@ /* do not change this file, it is auto generated by storybook. */ -import { start, updateView, View } from '@storybook/react-native'; +/// +import { start, updateView, View, type Features } from '@storybook/react-native'; import "@storybook/addon-ondevice-notes/register"; import "@storybook/addon-ondevice-controls/register"; @@ -11,7 +12,6 @@ const normalizedStories = [ directory: "./src", files: "**/*.stories.?(ts|tsx|js|jsx)", importPathMatcher: /^\.(?:(?:^|\/|(?:(?:(?!(?:^|\/)\.).)*?)\/)(?!\.)(?=.)[^/]*?\.stories\.(?:ts|tsx|js|jsx)?)$/, - // @ts-ignore req: require.context( '../src', true, @@ -24,6 +24,10 @@ const normalizedStories = [ declare global { var view: View; var STORIES: typeof normalizedStories; + var STORYBOOK_WEBSOCKET: + | { host?: string; port?: number; secured?: boolean } + | undefined; + var FEATURES: Features; } @@ -32,21 +36,21 @@ const annotations = [ require("@storybook/react-native/preview") ]; -global.STORIES = normalizedStories; +globalThis.STORIES = normalizedStories; + -// @ts-ignore module?.hot?.accept?.(); -if (!global.view) { - global.view = start({ +if (!globalThis.view) { + globalThis.view = start({ annotations, storyEntries: normalizedStories, }); } else { - updateView(global.view, annotations, normalizedStories); + updateView(globalThis.view, annotations, normalizedStories); } -export const view: View = global.view; +export const view: View = globalThis.view; diff --git a/android/app/build.gradle b/android/app/build.gradle index 4064f3df..31b7051e 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -11,7 +11,7 @@ def projectRoot = rootDir.getAbsoluteFile().getParentFile().getAbsolutePath() react { entryFile = file(["node", "-e", "require('expo/scripts/resolveAppEntry')", projectRoot, "android", "absolute"].execute(null, rootDir).text.trim()) reactNativeDir = new File(["node", "--print", "require.resolve('react-native/package.json')"].execute(null, rootDir).text.trim()).getParentFile().getAbsoluteFile() - hermesCommand = new File(["node", "--print", "require.resolve('react-native/package.json')"].execute(null, rootDir).text.trim()).getParentFile().getAbsolutePath() + "/sdks/hermesc/%OS-BIN%/hermesc" + hermesCommand = new File(["node", "--print", "require.resolve('hermes-compiler/package.json', { paths: [require.resolve('react-native/package.json')] })"].execute(null, rootDir).text.trim()).getParentFile().getAbsolutePath() + "/hermesc/%OS-BIN%/hermesc" codegenDir = new File(["node", "--print", "require.resolve('@react-native/codegen/package.json', { paths: [require.resolve('react-native/package.json')] })"].execute(null, rootDir).text.trim()).getParentFile().getAbsoluteFile() enableBundleCompression = (findProperty('android.enableBundleCompression') ?: false).toBoolean() diff --git a/android/app/src/debugOptimized/AndroidManifest.xml b/android/app/src/debugOptimized/AndroidManifest.xml new file mode 100644 index 00000000..3ec2507b --- /dev/null +++ b/android/app/src/debugOptimized/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + + + diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 3f6e5a87..b16270fa 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -1,9 +1,9 @@ - + - + - + @@ -15,7 +15,7 @@ - + diff --git a/android/app/src/main/java/ru/cdek/uikit/prime/MainApplication.kt b/android/app/src/main/java/ru/cdek/uikit/prime/MainApplication.kt index bc96c8a6..af834dbc 100644 --- a/android/app/src/main/java/ru/cdek/uikit/prime/MainApplication.kt +++ b/android/app/src/main/java/ru/cdek/uikit/prime/MainApplication.kt @@ -6,37 +6,26 @@ import android.content.res.Configuration import com.facebook.react.PackageList import com.facebook.react.ReactApplication import com.facebook.react.ReactNativeApplicationEntryPoint.loadReactNative -import com.facebook.react.ReactNativeHost import com.facebook.react.ReactPackage import com.facebook.react.ReactHost import com.facebook.react.common.ReleaseLevel import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint -import com.facebook.react.defaults.DefaultReactNativeHost import expo.modules.ApplicationLifecycleDispatcher -import expo.modules.ReactNativeHostWrapper +import expo.modules.ExpoReactHostFactory class MainApplication : Application(), ReactApplication { - override val reactNativeHost: ReactNativeHost = ReactNativeHostWrapper( - this, - object : DefaultReactNativeHost(this) { - override fun getPackages(): List = - PackageList(this).packages.apply { - // Packages that cannot be autolinked yet can be added manually here, for example: - // add(MyReactNativePackage()) - } - - override fun getJSMainModuleName(): String = ".expo/.virtual-metro-entry" - - override fun getUseDeveloperSupport(): Boolean = BuildConfig.DEBUG - - override val isNewArchEnabled: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED - } - ) - - override val reactHost: ReactHost - get() = ReactNativeHostWrapper.createReactHost(applicationContext, reactNativeHost) + override val reactHost: ReactHost by lazy { + ExpoReactHostFactory.getDefaultReactHost( + context = applicationContext, + packageList = + PackageList(this).packages.apply { + // Packages that cannot be autolinked yet can be added manually here, for example: + // add(MyReactNativePackage()) + } + ) + } override fun onCreate() { super.onCreate() diff --git a/android/app/src/main/res/values/colors.xml b/android/app/src/main/res/values/colors.xml index f2d4a9b5..6b6dc255 100644 --- a/android/app/src/main/res/values/colors.xml +++ b/android/app/src/main/res/values/colors.xml @@ -2,5 +2,4 @@ #FFFFFF #ffffff #023c69 - #FFFFFF \ No newline at end of file diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml index 35c07f1e..7fc351dd 100644 --- a/android/app/src/main/res/values/strings.xml +++ b/android/app/src/main/res/values/strings.xml @@ -1,5 +1,4 @@ CDEK UI cover - false \ No newline at end of file diff --git a/android/app/src/main/res/values/styles.xml b/android/app/src/main/res/values/styles.xml index 3e4a0560..eaf64280 100644 --- a/android/app/src/main/res/values/styles.xml +++ b/android/app/src/main/res/values/styles.xml @@ -1,9 +1,9 @@