@mediacubeco/expo-template-fsd 2.0.2 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.local.json +1 -7
- package/.claude/skills/generate-api-model/references/entities/common.ts +1 -1
- package/README.md +1 -1
- package/app.json +9 -7
- package/package.json +16 -16
- package/skills-lock.json +3 -3
- package/src/app/(root)/_layout.tsx +17 -11
- package/src/app/_app.tsx +1 -1
- package/src/app/_layout.tsx +19 -11
- package/src/shared/assets/images/index.ts +2 -1
- package/src/shared/assets/images/splash-dark.png +0 -0
- package/src/shared/assets/images/splash-light.png +0 -0
- package/src/shared/hooks/use-safe-area.ts +31 -12
- package/src/shared/lib/api/api.provider.tsx +2 -2
- package/src/shared/lib/api/entities/common.ts +1 -1
- package/src/shared/lib/index.ts +1 -0
- package/src/shared/lib/localization/utils/storage.ts +2 -6
- package/src/shared/lib/navigation/hooks/index.ts +1 -0
- package/src/shared/lib/navigation/hooks/use-navigation-native-tabs.ts +10 -0
- package/src/shared/lib/navigation/hooks/use-navigation-options.ts +2 -2
- package/src/shared/lib/navigation/index.ts +2 -0
- package/src/shared/lib/navigation/navigation-native-tabs.context.tsx +5 -0
- package/src/shared/lib/navigation/navigation-native-tabs.provider.tsx +12 -0
- package/src/shared/lib/storage/index.ts +2 -0
- package/src/shared/lib/storage/storage.provider.tsx +7 -0
- package/src/shared/lib/storage/storage.ts +27 -0
- package/src/shared/lib/storage/storage.types.ts +5 -0
- package/src/shared/lib/theme/theme.provider.tsx +10 -11
- package/src/shared/lib/theme/utils/index.ts +1 -1
- package/src/shared/lib/theme/utils/storage.ts +2 -6
- package/src/shared/ui/atoms/blur/blur.tsx +27 -0
- package/src/shared/ui/atoms/blur/blur.types.ts +9 -0
- package/src/shared/ui/atoms/blur/index.ts +2 -0
- package/src/shared/ui/atoms/glass/glass.tsx +26 -0
- package/src/shared/ui/atoms/glass/glass.types.ts +9 -0
- package/src/shared/ui/atoms/glass/index.ts +2 -0
- package/src/shared/ui/atoms/index.ts +2 -1
- package/src/shared/ui/molecules/keyboard-area/keyboard-area.styles.ts +5 -5
- package/src/shared/ui/molecules/keyboard-area/keyboard-area.tsx +1 -21
- package/src/shared/assets/images/splash.png +0 -0
- package/src/shared/lib/api/utils/index.ts +0 -1
- package/src/shared/lib/api/utils/storage.ts +0 -9
package/README.md
CHANGED
package/app.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"expo": {
|
|
3
3
|
"name": "expo-template-fsd",
|
|
4
4
|
"slug": "expo-template-fsd",
|
|
5
|
-
"scheme": "
|
|
5
|
+
"scheme": "expo-template-fsd",
|
|
6
6
|
"version": "1.0.0",
|
|
7
7
|
"orientation": "portrait",
|
|
8
8
|
"userInterfaceStyle": "automatic",
|
|
@@ -12,14 +12,14 @@
|
|
|
12
12
|
},
|
|
13
13
|
"ios": {
|
|
14
14
|
"supportsTablet": true,
|
|
15
|
-
"bundleIdentifier": "com.mediacube.
|
|
15
|
+
"bundleIdentifier": "com.mediacube.expo-template-fsd",
|
|
16
16
|
"icon": "./src/shared/assets/images/logo-ios.png"
|
|
17
17
|
},
|
|
18
18
|
"android": {
|
|
19
19
|
"predictiveBackGestureEnabled": false,
|
|
20
|
-
"package": "com.mediacube.
|
|
20
|
+
"package": "com.mediacube.expo-template-fsd",
|
|
21
21
|
"adaptiveIcon": {
|
|
22
|
-
"backgroundColor": "#
|
|
22
|
+
"backgroundColor": "#ffffff00",
|
|
23
23
|
"foregroundImage": "./src/shared/assets/images/logo-android-foreground.png",
|
|
24
24
|
"backgroundImage": "./src/shared/assets/images/logo-android-background.png",
|
|
25
25
|
"monochromeImage": "./src/shared/assets/images/logo-android-monochrome.png"
|
|
@@ -36,10 +36,12 @@
|
|
|
36
36
|
[
|
|
37
37
|
"expo-splash-screen",
|
|
38
38
|
{
|
|
39
|
-
"backgroundColor": "#
|
|
39
|
+
"backgroundColor": "#ffffff00",
|
|
40
40
|
"android": {
|
|
41
|
-
"image": "./assets/images/splash-
|
|
42
|
-
"
|
|
41
|
+
"image": "./src/shared/assets/images/splash-light.png",
|
|
42
|
+
"dark": {
|
|
43
|
+
"image": "./src/shared/assets/images/splash-dark.png"
|
|
44
|
+
}
|
|
43
45
|
}
|
|
44
46
|
}
|
|
45
47
|
]
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"private": false,
|
|
3
|
-
"version": "2.0
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"name": "@mediacubeco/expo-template-fsd",
|
|
5
5
|
"description": "Application by Mediacube developers",
|
|
6
6
|
"license": "MIT",
|
|
@@ -41,9 +41,9 @@
|
|
|
41
41
|
"react-native-svg": "15.15.4",
|
|
42
42
|
"react-native-web": "^0.21.0",
|
|
43
43
|
"react-native-worklets": "0.8.3",
|
|
44
|
-
"@mediacubeco/base
|
|
45
|
-
"@mediacubeco/base-react": "2.0
|
|
46
|
-
"@mediacubeco/base": "2.0
|
|
44
|
+
"@mediacubeco/base": "2.1.0",
|
|
45
|
+
"@mediacubeco/base-react": "2.1.0",
|
|
46
|
+
"@mediacubeco/base-react-native": "2.1.0"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
49
|
"@types/react": "^19.2.0",
|
|
@@ -52,24 +52,24 @@
|
|
|
52
52
|
"husky": "^9.1.7",
|
|
53
53
|
"prettier": "^3.8.1",
|
|
54
54
|
"typescript": "^6.0.3",
|
|
55
|
-
"@mediacubeco/eslint-config
|
|
56
|
-
"@mediacubeco/eslint-config": "2.0
|
|
57
|
-
"@mediacubeco/
|
|
58
|
-
"@mediacubeco/
|
|
59
|
-
"@mediacubeco/prettier-config-fsd": "2.0
|
|
60
|
-
"@mediacubeco/
|
|
61
|
-
"@mediacubeco/typescript-config": "2.0
|
|
62
|
-
"@mediacubeco/typescript-config-react": "2.0
|
|
63
|
-
"@mediacubeco/typescript-config-
|
|
64
|
-
"@mediacubeco/
|
|
55
|
+
"@mediacubeco/eslint-config": "2.1.0",
|
|
56
|
+
"@mediacubeco/eslint-config-fsd": "2.1.0",
|
|
57
|
+
"@mediacubeco/eslint-config-react": "2.1.0",
|
|
58
|
+
"@mediacubeco/prettier-config": "2.1.0",
|
|
59
|
+
"@mediacubeco/prettier-config-fsd": "2.1.0",
|
|
60
|
+
"@mediacubeco/typescript-config": "2.1.0",
|
|
61
|
+
"@mediacubeco/typescript-config-react": "2.1.0",
|
|
62
|
+
"@mediacubeco/typescript-config-react-native": "2.1.0",
|
|
63
|
+
"@mediacubeco/typescript-config-fsd": "2.1.0",
|
|
64
|
+
"@mediacubeco/eslint-config-react-native": "2.1.0"
|
|
65
65
|
},
|
|
66
66
|
"scripts": {
|
|
67
67
|
"postinstall": "npx husky && npx skills update",
|
|
68
68
|
"prebuild": "expo prebuild",
|
|
69
69
|
"start": "expo start",
|
|
70
|
-
"android": "expo
|
|
70
|
+
"android": "expo run:android",
|
|
71
71
|
"android:device": "expo run:android -d",
|
|
72
|
-
"ios": "expo
|
|
72
|
+
"ios": "expo run:ios",
|
|
73
73
|
"ios:device": "expo run:ios -d",
|
|
74
74
|
"web": "expo start --web",
|
|
75
75
|
"format": "prettier --write ./src",
|
package/skills-lock.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"source": "pbakaus/impeccable",
|
|
6
6
|
"sourceType": "github",
|
|
7
7
|
"skillPath": ".agents/skills/impeccable/SKILL.md",
|
|
8
|
-
"computedHash": "
|
|
8
|
+
"computedHash": "5e8c66eeffba8dc0c5e0941afbf4aecd6359184f8b0ea08cfc60a33f2e328e49"
|
|
9
9
|
},
|
|
10
10
|
"react-native-best-practices": {
|
|
11
11
|
"source": "callstackincubator/agent-skills",
|
|
@@ -17,13 +17,13 @@
|
|
|
17
17
|
"source": "vercel-labs/agent-skills",
|
|
18
18
|
"sourceType": "github",
|
|
19
19
|
"skillPath": "skills/react-best-practices/SKILL.md",
|
|
20
|
-
"computedHash": "
|
|
20
|
+
"computedHash": "3219a1944e404ffc14d1d9d6aef6dd2e3855b81387ee0a044ccbfe14d34c2357"
|
|
21
21
|
},
|
|
22
22
|
"vercel-react-native-skills": {
|
|
23
23
|
"source": "vercel-labs/agent-skills",
|
|
24
24
|
"sourceType": "github",
|
|
25
25
|
"skillPath": "skills/react-native-skills/SKILL.md",
|
|
26
|
-
"computedHash": "
|
|
26
|
+
"computedHash": "2e9088a7333666d8c2833b8ff58bd51b955501c42b4c7244f72b4cbf22dafcc4"
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
29
|
}
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { NativeTabs } from 'expo-router/build/native-tabs'
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
NavigationNativeTabsProvider,
|
|
4
|
+
useLocalizationText,
|
|
5
|
+
useNavigationTabBarOptions,
|
|
6
|
+
} from '~shared/lib'
|
|
3
7
|
|
|
4
8
|
const Layout = () => {
|
|
5
9
|
const { createTabBarOptions, createTabOptions } = useNavigationTabBarOptions()
|
|
@@ -22,16 +26,18 @@ const Layout = () => {
|
|
|
22
26
|
})
|
|
23
27
|
|
|
24
28
|
return (
|
|
25
|
-
<
|
|
26
|
-
<NativeTabs
|
|
27
|
-
<NativeTabs.Trigger
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
<NativeTabs.Trigger
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
29
|
+
<NavigationNativeTabsProvider>
|
|
30
|
+
<NativeTabs {...tabBarOptions}>
|
|
31
|
+
<NativeTabs.Trigger {...homeTabOptions.triggerProps}>
|
|
32
|
+
<NativeTabs.Trigger.Label {...homeTabOptions.triggerLabelProps} />
|
|
33
|
+
<NativeTabs.Trigger.Icon {...homeTabOptions.triggerIconProps} />
|
|
34
|
+
</NativeTabs.Trigger>
|
|
35
|
+
<NativeTabs.Trigger {...settingsTabOptions.triggerProps}>
|
|
36
|
+
<NativeTabs.Trigger.Label {...settingsTabOptions.triggerLabelProps} />
|
|
37
|
+
<NativeTabs.Trigger.Icon {...settingsTabOptions.triggerIconProps} />
|
|
38
|
+
</NativeTabs.Trigger>
|
|
39
|
+
</NativeTabs>
|
|
40
|
+
</NavigationNativeTabsProvider>
|
|
35
41
|
)
|
|
36
42
|
}
|
|
37
43
|
|
package/src/app/_app.tsx
CHANGED
|
@@ -10,7 +10,7 @@ const App = () => {
|
|
|
10
10
|
<>
|
|
11
11
|
<StatusBar style={'auto'} />
|
|
12
12
|
<NavigationBar style={'auto'} />
|
|
13
|
-
<Stack screenOptions={createStackOptions()}>
|
|
13
|
+
<Stack initialRouteName={'(root)'} screenOptions={createStackOptions()}>
|
|
14
14
|
<Stack.Screen name={'(root)'} />
|
|
15
15
|
</Stack>
|
|
16
16
|
</>
|
package/src/app/_layout.tsx
CHANGED
|
@@ -1,19 +1,27 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
ApiProvider,
|
|
3
|
+
LocalizationProvider,
|
|
4
|
+
NavigationProvider,
|
|
5
|
+
StorageProvider,
|
|
6
|
+
ThemeProvider,
|
|
7
|
+
} from '~shared/lib'
|
|
2
8
|
import App from './_app'
|
|
3
9
|
import Splash from './_splash'
|
|
4
10
|
|
|
5
11
|
const Layout = () => {
|
|
6
12
|
return (
|
|
7
|
-
<
|
|
8
|
-
<
|
|
9
|
-
<
|
|
10
|
-
<
|
|
11
|
-
<
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
<StorageProvider>
|
|
14
|
+
<ApiProvider>
|
|
15
|
+
<ThemeProvider>
|
|
16
|
+
<LocalizationProvider>
|
|
17
|
+
<NavigationProvider>
|
|
18
|
+
<App />
|
|
19
|
+
<Splash />
|
|
20
|
+
</NavigationProvider>
|
|
21
|
+
</LocalizationProvider>
|
|
22
|
+
</ThemeProvider>
|
|
23
|
+
</ApiProvider>
|
|
24
|
+
</StorageProvider>
|
|
17
25
|
)
|
|
18
26
|
}
|
|
19
27
|
|
|
@@ -4,7 +4,8 @@ const IMAGES = {
|
|
|
4
4
|
LOGO_ANDROID_BACKGROUND: require('./logo-android-background.png'),
|
|
5
5
|
LOGO_ANDROID_FOREGROUND: require('./logo-android-foreground.png'),
|
|
6
6
|
LOGO_ANDROID_MONOCHROME: require('./logo-android-monochrome.png'),
|
|
7
|
-
|
|
7
|
+
SPLASH_LIGHT: require('./splash-light.png'),
|
|
8
|
+
SPLASH_DARK: require('./splash-dark.png'),
|
|
8
9
|
DEFAULT: require('./default.png'),
|
|
9
10
|
}
|
|
10
11
|
|
|
Binary file
|
|
Binary file
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { Platform } from 'react-native'
|
|
1
|
+
import { Platform } from '@mediacubeco/base-react-native'
|
|
2
2
|
import { useSafeAreaInsets } from 'react-native-safe-area-context'
|
|
3
3
|
import { useBottomTabBarHeight } from 'expo-router/js-tabs'
|
|
4
4
|
import { useHeaderHeight } from 'expo-router/react-navigation'
|
|
5
|
+
import { useNavigationNativeTabs } from '../lib'
|
|
5
6
|
|
|
6
7
|
const ANDROID_TAB_BAR_DEFAULT_HEIGHT = 56
|
|
7
8
|
const IOS_TAB_BAR_DEFAULT_HEIGHT = 50
|
|
@@ -10,7 +11,7 @@ const useNavigationHeaderHeight = (safeArea: number = 0) => {
|
|
|
10
11
|
try {
|
|
11
12
|
const height = useHeaderHeight()
|
|
12
13
|
|
|
13
|
-
return Platform.
|
|
14
|
+
return Platform.by({
|
|
14
15
|
android: height ? 0 : safeArea,
|
|
15
16
|
ios: height || safeArea,
|
|
16
17
|
default: safeArea,
|
|
@@ -21,19 +22,36 @@ const useNavigationHeaderHeight = (safeArea: number = 0) => {
|
|
|
21
22
|
}
|
|
22
23
|
|
|
23
24
|
const useNavigationFooterHeight = (safeArea: number = 0) => {
|
|
25
|
+
const isNativeTabs = useNavigationNativeTabs()
|
|
26
|
+
|
|
24
27
|
try {
|
|
25
28
|
const height = useBottomTabBarHeight()
|
|
26
29
|
|
|
27
|
-
return
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
return {
|
|
31
|
+
bottom: Platform.by({
|
|
32
|
+
android: height ? 0 : safeArea,
|
|
33
|
+
ios: height ? 0 : safeArea,
|
|
34
|
+
default: safeArea,
|
|
35
|
+
}),
|
|
36
|
+
value: Platform.by({
|
|
37
|
+
android: height,
|
|
38
|
+
ios: height,
|
|
39
|
+
default: safeArea,
|
|
40
|
+
}),
|
|
41
|
+
}
|
|
32
42
|
} catch (_) {
|
|
33
|
-
return
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
43
|
+
return {
|
|
44
|
+
bottom: Platform.by({
|
|
45
|
+
android: isNativeTabs ? 0 : safeArea,
|
|
46
|
+
ios: safeArea,
|
|
47
|
+
default: safeArea,
|
|
48
|
+
}),
|
|
49
|
+
value: Platform.by({
|
|
50
|
+
android: isNativeTabs ? safeArea * 2 + ANDROID_TAB_BAR_DEFAULT_HEIGHT : safeArea,
|
|
51
|
+
ios: isNativeTabs ? safeArea + IOS_TAB_BAR_DEFAULT_HEIGHT : safeArea,
|
|
52
|
+
default: safeArea,
|
|
53
|
+
}),
|
|
54
|
+
}
|
|
37
55
|
}
|
|
38
56
|
}
|
|
39
57
|
|
|
@@ -44,7 +62,8 @@ const useSafeArea = () => {
|
|
|
44
62
|
|
|
45
63
|
return {
|
|
46
64
|
TOP: header,
|
|
47
|
-
BOTTOM: footer,
|
|
65
|
+
BOTTOM: footer.bottom,
|
|
66
|
+
FOOTER: footer.value,
|
|
48
67
|
LEFT: left,
|
|
49
68
|
RIGHT: right,
|
|
50
69
|
}
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
PersistQueryClientProvider,
|
|
6
6
|
type PersistQueryClientProviderProps,
|
|
7
7
|
} from '@tanstack/react-query-persist-client'
|
|
8
|
-
import {
|
|
8
|
+
import { storageAsync } from '../storage'
|
|
9
9
|
import { type ApiProviderProps } from './api.types'
|
|
10
10
|
|
|
11
11
|
const client = new QueryClient({
|
|
@@ -25,7 +25,7 @@ const persistOptions = {
|
|
|
25
25
|
},
|
|
26
26
|
},
|
|
27
27
|
persister: createAsyncStoragePersister({
|
|
28
|
-
storage:
|
|
28
|
+
storage: storageAsync,
|
|
29
29
|
throttleTime: 1000,
|
|
30
30
|
}),
|
|
31
31
|
} satisfies PersistQueryClientProviderProps['persistOptions']
|
package/src/shared/lib/index.ts
CHANGED
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
import { Storage } from '@mediacubeco/base/services'
|
|
2
|
-
import
|
|
2
|
+
import { storageModel } from '../../storage'
|
|
3
3
|
import { type LocalizationCode } from '../constants'
|
|
4
4
|
|
|
5
|
-
const localizationStorage = new Storage(
|
|
6
|
-
get: SecureStore.getItemAsync,
|
|
7
|
-
set: SecureStore.setItemAsync,
|
|
8
|
-
delete: SecureStore.deleteItemAsync,
|
|
9
|
-
}).create<'code', LocalizationCode>('code')
|
|
5
|
+
const localizationStorage = new Storage(storageModel).create<'code', LocalizationCode>('code')
|
|
10
6
|
|
|
11
7
|
export { localizationStorage }
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { useContext } from 'react'
|
|
2
|
+
import { NavigationNativeTabsContext } from '../navigation-native-tabs.context'
|
|
3
|
+
|
|
4
|
+
const useNavigationNativeTabs = () => {
|
|
5
|
+
const isNativeTabs = useContext(NavigationNativeTabsContext)
|
|
6
|
+
|
|
7
|
+
return isNativeTabs
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export { useNavigationNativeTabs }
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { Platform } from '@mediacubeco/base-react-native'
|
|
1
2
|
import { useCallback } from 'react'
|
|
2
|
-
import { Platform } from 'react-native'
|
|
3
3
|
import { isGlassEffectAPIAvailable } from 'expo-glass-effect'
|
|
4
4
|
import { type StackScreenProps } from 'expo-router'
|
|
5
5
|
import {
|
|
@@ -43,7 +43,7 @@ const useNavigationStackOptions = () => {
|
|
|
43
43
|
headerBlurEffect: isGlassEffectAPIAvailable() ? 'none' : themeModeSystem,
|
|
44
44
|
headerTintColor: COLORS.TYPOGRAPHY.BASE,
|
|
45
45
|
headerStyle: {
|
|
46
|
-
backgroundColor: Platform.
|
|
46
|
+
backgroundColor: Platform.by({
|
|
47
47
|
ios: COLORS.FILL.TRANSPARENT,
|
|
48
48
|
default: COLORS.FILL.CONTRAST,
|
|
49
49
|
}),
|
|
@@ -3,5 +3,7 @@ export {
|
|
|
3
3
|
useNavigationParams,
|
|
4
4
|
useNavigationStackOptions,
|
|
5
5
|
useNavigationTabBarOptions,
|
|
6
|
+
useNavigationNativeTabs,
|
|
6
7
|
} from './hooks'
|
|
7
8
|
export { default as NavigationProvider } from './navigation.provider'
|
|
9
|
+
export { default as NavigationNativeTabsProvider } from './navigation-native-tabs.provider'
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { NavigationNativeTabsContext } from './navigation-native-tabs.context'
|
|
2
|
+
import { type NavigationProviderProps } from './navigation.types'
|
|
3
|
+
|
|
4
|
+
const NavigationNativeTabsProvider = ({ children }: NavigationProviderProps) => {
|
|
5
|
+
return (
|
|
6
|
+
<NavigationNativeTabsContext.Provider value={true}>
|
|
7
|
+
{children}
|
|
8
|
+
</NavigationNativeTabsContext.Provider>
|
|
9
|
+
)
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export default NavigationNativeTabsProvider
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Platform } from '@mediacubeco/base-react-native'
|
|
2
|
+
import * as SecureStore from 'expo-secure-store'
|
|
3
|
+
|
|
4
|
+
const storageModelNative = {
|
|
5
|
+
getItem: SecureStore.getItemAsync,
|
|
6
|
+
setItem: SecureStore.setItemAsync,
|
|
7
|
+
removeItem: SecureStore.deleteItemAsync,
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const storageModelWeb = {
|
|
11
|
+
getItem: (key: string) => Promise.resolve(localStorage.getItem(key)),
|
|
12
|
+
setItem: (key: string, value: string) => Promise.resolve(localStorage.setItem(key, value)),
|
|
13
|
+
removeItem: (key: string) => Promise.resolve(localStorage.removeItem(key)),
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const storageAsync = Platform.by({
|
|
17
|
+
web: storageModelWeb,
|
|
18
|
+
default: storageModelNative,
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
const storageModel = {
|
|
22
|
+
get: storageAsync.getItem,
|
|
23
|
+
set: storageAsync.setItem,
|
|
24
|
+
delete: storageAsync.removeItem,
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export { storageAsync, storageModel }
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { Platform } from '@mediacubeco/base-react-native'
|
|
2
1
|
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
|
3
2
|
import { Appearance, StatusBar, useColorScheme } from 'react-native'
|
|
4
3
|
import { themeStorage } from './utils'
|
|
@@ -22,15 +21,15 @@ const ThemeProvider = ({ children }: ThemeProviderProps) => {
|
|
|
22
21
|
}, [currentThemeMode])
|
|
23
22
|
|
|
24
23
|
const updateThemeModeSystem = useCallback((themeMode: ThemeMode) => {
|
|
25
|
-
if (Platform.isIos) {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
}
|
|
24
|
+
// if (Platform.isIos) {
|
|
25
|
+
if (!hasDarkMode) {
|
|
26
|
+
Appearance.setColorScheme('light')
|
|
27
|
+
} else if (themeMode === ThemeMode.System) {
|
|
28
|
+
Appearance.setColorScheme('unspecified')
|
|
29
|
+
} else {
|
|
30
|
+
Appearance.setColorScheme(themeMode)
|
|
33
31
|
}
|
|
32
|
+
// }
|
|
34
33
|
}, [])
|
|
35
34
|
|
|
36
35
|
useEffect(() => {
|
|
@@ -53,9 +52,9 @@ const ThemeProvider = ({ children }: ThemeProviderProps) => {
|
|
|
53
52
|
const updateThemeMode = async () => {
|
|
54
53
|
if (didDefine.current) {
|
|
55
54
|
await themeStorage.mode.set(themeMode)
|
|
56
|
-
|
|
57
|
-
updateThemeModeSystem(themeMode)
|
|
58
55
|
}
|
|
56
|
+
|
|
57
|
+
updateThemeModeSystem(themeMode)
|
|
59
58
|
}
|
|
60
59
|
|
|
61
60
|
updateThemeMode()
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export
|
|
1
|
+
export { themeStorage } from './storage'
|
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
import { Storage } from '@mediacubeco/base/services'
|
|
2
|
-
import
|
|
2
|
+
import { storageModel } from '../../storage'
|
|
3
3
|
import { type ThemeMode } from '../constants'
|
|
4
4
|
|
|
5
|
-
const themeStorage = new Storage(
|
|
6
|
-
get: SecureStore.getItemAsync,
|
|
7
|
-
set: SecureStore.setItemAsync,
|
|
8
|
-
delete: SecureStore.deleteItemAsync,
|
|
9
|
-
}).create<'mode', ThemeMode>('mode')
|
|
5
|
+
const themeStorage = new Storage(storageModel).create<'mode', ThemeMode>('mode')
|
|
10
6
|
|
|
11
7
|
export { themeStorage }
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { type Ref } from 'react'
|
|
2
|
+
import { BlurView } from 'expo-blur'
|
|
3
|
+
import { type BlurProps } from './blur.types'
|
|
4
|
+
|
|
5
|
+
const Blur = ({
|
|
6
|
+
reference,
|
|
7
|
+
blurTarget,
|
|
8
|
+
tint,
|
|
9
|
+
intensity,
|
|
10
|
+
blurReductionFactor,
|
|
11
|
+
blurMethod,
|
|
12
|
+
...props
|
|
13
|
+
}: BlurProps) => {
|
|
14
|
+
return (
|
|
15
|
+
<BlurView
|
|
16
|
+
ref={reference as Ref<BlurView>}
|
|
17
|
+
blurTarget={blurTarget}
|
|
18
|
+
tint={tint}
|
|
19
|
+
intensity={intensity}
|
|
20
|
+
blurReductionFactor={blurReductionFactor}
|
|
21
|
+
blurMethod={blurMethod}
|
|
22
|
+
{...props}
|
|
23
|
+
/>
|
|
24
|
+
)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export default Blur
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { GlassView, isGlassEffectAPIAvailable } from 'expo-glass-effect'
|
|
2
|
+
import { Blur } from '../blur'
|
|
3
|
+
import { type GlassProps } from './glass.types'
|
|
4
|
+
|
|
5
|
+
const Glass = ({
|
|
6
|
+
reference,
|
|
7
|
+
glassEffectStyle = 'clear',
|
|
8
|
+
tintColor,
|
|
9
|
+
colorScheme,
|
|
10
|
+
isInteractive = true,
|
|
11
|
+
...props
|
|
12
|
+
}: GlassProps) => {
|
|
13
|
+
return isGlassEffectAPIAvailable() ? (
|
|
14
|
+
<GlassView
|
|
15
|
+
ref={reference}
|
|
16
|
+
glassEffectStyle={glassEffectStyle}
|
|
17
|
+
tintColor={tintColor}
|
|
18
|
+
colorScheme={colorScheme}
|
|
19
|
+
isInteractive={isInteractive}
|
|
20
|
+
{...props}
|
|
21
|
+
/>
|
|
22
|
+
) : (
|
|
23
|
+
<Blur reference={reference} {...props} />
|
|
24
|
+
)
|
|
25
|
+
}
|
|
26
|
+
export default Glass
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
export
|
|
1
|
+
export * from './blur'
|
|
2
|
+
export * from './glass'
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
+
import { useAnimatedKeyboard } from 'react-native-keyboard-controller'
|
|
1
2
|
import { useAnimated, useAnimatedStyle, useSafeArea } from '../../../hooks'
|
|
2
3
|
|
|
3
4
|
const useKeyboardAreaStyles = () => {
|
|
4
|
-
const {
|
|
5
|
-
const
|
|
6
|
-
const [
|
|
5
|
+
const { FOOTER } = useSafeArea()
|
|
6
|
+
const { height } = useAnimatedKeyboard()
|
|
7
|
+
const [safeAreaHeight] = useAnimated(FOOTER)
|
|
7
8
|
|
|
8
9
|
const keyboardAnimatedStyle = useAnimatedStyle(() => {
|
|
9
10
|
return {
|
|
10
|
-
height:
|
|
11
|
+
height: height.value - safeAreaHeight.value,
|
|
11
12
|
}
|
|
12
13
|
})
|
|
13
14
|
|
|
14
15
|
return {
|
|
15
|
-
keyboardHeight,
|
|
16
16
|
keyboardAnimatedStyle,
|
|
17
17
|
}
|
|
18
18
|
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { View } from 'react-native'
|
|
2
|
-
import { useKeyboardHandler } from 'react-native-keyboard-controller'
|
|
3
2
|
import { animate } from '../../../hooks'
|
|
4
3
|
import { useKeyboardAreaStyles } from './keyboard-area.styles'
|
|
5
4
|
import { type KeyboardAreaProps } from './keyboard-area.types'
|
|
@@ -7,26 +6,7 @@ import { type KeyboardAreaProps } from './keyboard-area.types'
|
|
|
7
6
|
const KeyboardAnimatedArea = animate(View)
|
|
8
7
|
|
|
9
8
|
const KeyboardArea = ({}: KeyboardAreaProps) => {
|
|
10
|
-
const {
|
|
11
|
-
|
|
12
|
-
useKeyboardHandler(
|
|
13
|
-
{
|
|
14
|
-
onStart: () => {
|
|
15
|
-
'worklet'
|
|
16
|
-
},
|
|
17
|
-
onMove: (event) => {
|
|
18
|
-
'worklet'
|
|
19
|
-
|
|
20
|
-
keyboardHeight.set(event.height)
|
|
21
|
-
},
|
|
22
|
-
onEnd: (event) => {
|
|
23
|
-
'worklet'
|
|
24
|
-
|
|
25
|
-
keyboardHeight.set(event.height)
|
|
26
|
-
},
|
|
27
|
-
},
|
|
28
|
-
[]
|
|
29
|
-
)
|
|
9
|
+
const { keyboardAnimatedStyle } = useKeyboardAreaStyles()
|
|
30
10
|
|
|
31
11
|
return <KeyboardAnimatedArea style={keyboardAnimatedStyle} />
|
|
32
12
|
}
|
|
Binary file
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './storage'
|