Merge branch 'main' into inherit_system_theme
commit
7f76c2d67e
|
@ -21,7 +21,7 @@
|
||||||
- If you are cloning or forking this repo as an open source developer, please check the tips below as well
|
- If you are cloning or forking this repo as an open source developer, please check the tips below as well
|
||||||
- Run e2e tests
|
- Run e2e tests
|
||||||
- Start in various console tabs:
|
- Start in various console tabs:
|
||||||
- `yarn e2e:server`
|
- `yarn e2e:mock-server`
|
||||||
- `yarn e2e:metro`
|
- `yarn e2e:metro`
|
||||||
- Run once: `yarn e2e:build`
|
- Run once: `yarn e2e:build`
|
||||||
- Each test run: `yarn e2e:run`
|
- Each test run: `yarn e2e:run`
|
||||||
|
@ -31,7 +31,7 @@
|
||||||
- `npx react-native info` Checks what has been installed.
|
- `npx react-native info` Checks what has been installed.
|
||||||
- The android simulator won't be able to access localhost services unless you run `adb reverse tcp:{PORT} tcp:{PORT}`
|
- The android simulator won't be able to access localhost services unless you run `adb reverse tcp:{PORT} tcp:{PORT}`
|
||||||
- For instance, the localhosted dev-wallet will need `adb reverse tcp:3001 tcp:3001`
|
- For instance, the localhosted dev-wallet will need `adb reverse tcp:3001 tcp:3001`
|
||||||
- For some reason, the typescript compiler chokes on platform-specific files (e.g. `foo.native.ts`) but only when compiling for Web thus far. Therefore we always have one version of the file which doesn't use a platform specifier, and that should bee the Web version. ([More info](https://stackoverflow.com/questions/44001050/platform-specific-import-component-in-react-native-with-typescript).)
|
- For some reason, the typescript compiler chokes on platform-specific files (e.g. `foo.native.ts`) but only when compiling for Web thus far. Therefore we always have one version of the file which doesn't use a platform specifier, and that should be the Web version. ([More info](https://stackoverflow.com/questions/44001050/platform-specific-import-component-in-react-native-with-typescript).)
|
||||||
|
|
||||||
## Go-Server Build
|
## Go-Server Build
|
||||||
|
|
||||||
|
|
|
@ -73,7 +73,7 @@
|
||||||
"expo-constants": "~14.2.1",
|
"expo-constants": "~14.2.1",
|
||||||
"expo-dev-client": "~2.1.1",
|
"expo-dev-client": "~2.1.1",
|
||||||
"expo-device": "~5.2.1",
|
"expo-device": "~5.2.1",
|
||||||
"expo-image": "^1.2.1",
|
"expo-image": "^1.2.3",
|
||||||
"expo-image-manipulator": "^11.1.1",
|
"expo-image-manipulator": "^11.1.1",
|
||||||
"expo-image-picker": "^14.1.1",
|
"expo-image-picker": "^14.1.1",
|
||||||
"expo-localization": "~14.1.1",
|
"expo-localization": "~14.1.1",
|
||||||
|
|
|
@ -28,7 +28,6 @@ import {isNative} from 'platform/detection'
|
||||||
import {useColorSchemeStyle} from 'lib/hooks/useColorSchemeStyle'
|
import {useColorSchemeStyle} from 'lib/hooks/useColorSchemeStyle'
|
||||||
import {router} from './routes'
|
import {router} from './routes'
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
import {useUnreadCountLabel} from 'lib/hooks/useUnreadCountLabel'
|
|
||||||
import {useStores} from './state'
|
import {useStores} from './state'
|
||||||
|
|
||||||
import {HomeScreen} from './view/screens/Home'
|
import {HomeScreen} from './view/screens/Home'
|
||||||
|
@ -296,9 +295,9 @@ const MyProfileTabNavigator = observer(() => {
|
||||||
* The FlatNavigator is used by Web to represent the routes
|
* The FlatNavigator is used by Web to represent the routes
|
||||||
* in a single ("flat") stack.
|
* in a single ("flat") stack.
|
||||||
*/
|
*/
|
||||||
function FlatNavigator() {
|
const FlatNavigator = observer(() => {
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
const unreadCountLabel = useUnreadCountLabel()
|
const unreadCountLabel = useStores().me.notifications.unreadCountLabel
|
||||||
const title = (page: string) => bskyTitle(page, unreadCountLabel)
|
const title = (page: string) => bskyTitle(page, unreadCountLabel)
|
||||||
return (
|
return (
|
||||||
<Flat.Navigator
|
<Flat.Navigator
|
||||||
|
@ -327,7 +326,7 @@ function FlatNavigator() {
|
||||||
{commonScreens(Flat as typeof HomeTab, unreadCountLabel)}
|
{commonScreens(Flat as typeof HomeTab, unreadCountLabel)}
|
||||||
</Flat.Navigator>
|
</Flat.Navigator>
|
||||||
)
|
)
|
||||||
}
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The RoutesContainer should wrap all components which need access
|
* The RoutesContainer should wrap all components which need access
|
||||||
|
|
|
@ -3,11 +3,15 @@ import {useNavigation} from '@react-navigation/native'
|
||||||
|
|
||||||
import {NavigationProp} from 'lib/routes/types'
|
import {NavigationProp} from 'lib/routes/types'
|
||||||
import {bskyTitle} from 'lib/strings/headings'
|
import {bskyTitle} from 'lib/strings/headings'
|
||||||
import {useUnreadCountLabel} from './useUnreadCountLabel'
|
import {useStores} from 'state/index'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Requires consuming component to be wrapped in `observer`:
|
||||||
|
* https://stackoverflow.com/a/71488009
|
||||||
|
*/
|
||||||
export function useSetTitle(title?: string) {
|
export function useSetTitle(title?: string) {
|
||||||
const navigation = useNavigation<NavigationProp>()
|
const navigation = useNavigation<NavigationProp>()
|
||||||
const unreadCountLabel = useUnreadCountLabel()
|
const {unreadCountLabel} = useStores().me.notifications
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (title) {
|
if (title) {
|
||||||
navigation.setOptions({title: bskyTitle(title, unreadCountLabel)})
|
navigation.setOptions({title: bskyTitle(title, unreadCountLabel)})
|
||||||
|
|
|
@ -1,19 +0,0 @@
|
||||||
import {useEffect, useReducer} from 'react'
|
|
||||||
import {DeviceEventEmitter} from 'react-native'
|
|
||||||
import {useStores} from 'state/index'
|
|
||||||
|
|
||||||
export function useUnreadCountLabel() {
|
|
||||||
// HACK: We don't have anything like Redux selectors,
|
|
||||||
// and we don't want to use <RootStoreContext.Consumer />
|
|
||||||
// to react to the whole store
|
|
||||||
const [, forceUpdate] = useReducer(x => x + 1, 0)
|
|
||||||
useEffect(() => {
|
|
||||||
const subscription = DeviceEventEmitter.addListener(
|
|
||||||
'unread-notifications',
|
|
||||||
forceUpdate,
|
|
||||||
)
|
|
||||||
return () => subscription?.remove()
|
|
||||||
}, [forceUpdate])
|
|
||||||
|
|
||||||
return useStores().me.notifications.unreadCountLabel
|
|
||||||
}
|
|
|
@ -320,6 +320,35 @@ export function MoonIcon({
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Copyright (c) 2020 Refactoring UI Inc.
|
||||||
|
// https://github.com/tailwindlabs/heroicons/blob/master/LICENSE
|
||||||
|
export function SunIcon({
|
||||||
|
style,
|
||||||
|
size,
|
||||||
|
strokeWidth = 1.5,
|
||||||
|
}: {
|
||||||
|
style?: StyleProp<ViewStyle>
|
||||||
|
size?: string | number
|
||||||
|
strokeWidth?: number
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<Svg
|
||||||
|
fill="none"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
width={size || 32}
|
||||||
|
height={size || 32}
|
||||||
|
strokeWidth={strokeWidth}
|
||||||
|
stroke="currentColor"
|
||||||
|
style={style}>
|
||||||
|
<Path
|
||||||
|
d="M12 3V5.25M18.364 5.63604L16.773 7.22703M21 12H18.75M18.364 18.364L16.773 16.773M12 18.75V21M7.22703 16.773L5.63604 18.364M5.25 12H3M7.22703 7.22703L5.63604 5.63604M15.75 12C15.75 14.0711 14.0711 15.75 12 15.75C9.92893 15.75 8.25 14.0711 8.25 12C8.25 9.92893 9.92893 8.25 12 8.25C14.0711 8.25 15.75 9.92893 15.75 12Z"
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
/>
|
||||||
|
</Svg>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
// Copyright (c) 2020 Refactoring UI Inc.
|
// Copyright (c) 2020 Refactoring UI Inc.
|
||||||
// https://github.com/tailwindlabs/heroicons/blob/master/LICENSE
|
// https://github.com/tailwindlabs/heroicons/blob/master/LICENSE
|
||||||
export function UserIcon({
|
export function UserIcon({
|
||||||
|
|
|
@ -21,6 +21,9 @@ interface Img {
|
||||||
|
|
||||||
export const Lightbox = observer(function Lightbox() {
|
export const Lightbox = observer(function Lightbox() {
|
||||||
const store = useStores()
|
const store = useStores()
|
||||||
|
|
||||||
|
const onClose = useCallback(() => store.shell.closeLightbox(), [store.shell])
|
||||||
|
|
||||||
if (!store.shell.isLightboxActive) {
|
if (!store.shell.isLightboxActive) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
@ -29,8 +32,6 @@ export const Lightbox = observer(function Lightbox() {
|
||||||
const initialIndex =
|
const initialIndex =
|
||||||
activeLightbox instanceof models.ImagesLightbox ? activeLightbox.index : 0
|
activeLightbox instanceof models.ImagesLightbox ? activeLightbox.index : 0
|
||||||
|
|
||||||
const onClose = () => store.shell.closeLightbox()
|
|
||||||
|
|
||||||
let imgs: Img[] | undefined
|
let imgs: Img[] | undefined
|
||||||
if (activeLightbox instanceof models.ProfileImageLightbox) {
|
if (activeLightbox instanceof models.ProfileImageLightbox) {
|
||||||
const opts = activeLightbox
|
const opts = activeLightbox
|
||||||
|
|
|
@ -128,6 +128,7 @@ export function Button({
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
const onPressWrapped = React.useCallback(
|
const onPressWrapped = React.useCallback(
|
||||||
(event: Event) => {
|
(event: Event) => {
|
||||||
event.stopPropagation()
|
event.stopPropagation()
|
||||||
|
@ -136,9 +137,23 @@ export function Button({
|
||||||
},
|
},
|
||||||
[onPress],
|
[onPress],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const getStyle = React.useCallback(
|
||||||
|
state => {
|
||||||
|
const arr = [typeOuterStyle, styles.outer, style]
|
||||||
|
if (state.pressed) {
|
||||||
|
arr.push({opacity: 0.6})
|
||||||
|
} else if (state.hovered) {
|
||||||
|
arr.push({opacity: 0.8})
|
||||||
|
}
|
||||||
|
return arr
|
||||||
|
},
|
||||||
|
[typeOuterStyle, style],
|
||||||
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Pressable
|
<Pressable
|
||||||
style={[typeOuterStyle, styles.outer, style]}
|
style={getStyle}
|
||||||
onPress={onPressWrapped}
|
onPress={onPressWrapped}
|
||||||
testID={testID}
|
testID={testID}
|
||||||
accessibilityRole="button"
|
accessibilityRole="button"
|
||||||
|
|
|
@ -209,7 +209,7 @@ export function PostDropdownBtn({
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{sep: true},
|
{sep: true},
|
||||||
{
|
!isAuthor && {
|
||||||
testID: 'postDropdownReportBtn',
|
testID: 'postDropdownReportBtn',
|
||||||
icon: 'circle-exclamation',
|
icon: 'circle-exclamation',
|
||||||
label: 'Report post',
|
label: 'Report post',
|
||||||
|
|
|
@ -121,7 +121,7 @@ export const SearchScreen = withAuthRequired(
|
||||||
<TouchableWithoutFeedback onPress={onPress} accessible={false}>
|
<TouchableWithoutFeedback onPress={onPress} accessible={false}>
|
||||||
<View style={[pal.view, styles.container]}>
|
<View style={[pal.view, styles.container]}>
|
||||||
<HeaderWithInput
|
<HeaderWithInput
|
||||||
isInputFocused={true}
|
isInputFocused={isInputFocused}
|
||||||
query={query}
|
query={query}
|
||||||
setIsInputFocused={setIsInputFocused}
|
setIsInputFocused={setIsInputFocused}
|
||||||
onChangeQuery={onChangeQuery}
|
onChangeQuery={onChangeQuery}
|
||||||
|
|
|
@ -215,7 +215,11 @@ export const DrawerContent = observer(() => {
|
||||||
}
|
}
|
||||||
label="Notifications"
|
label="Notifications"
|
||||||
accessibilityLabel="Notifications"
|
accessibilityLabel="Notifications"
|
||||||
accessibilityHint={`${store.me.notifications.unreadCountLabel} unread`}
|
accessibilityHint={
|
||||||
|
notifications.unreadCountLabel === ''
|
||||||
|
? ''
|
||||||
|
: `${notifications.unreadCountLabel} unread`
|
||||||
|
}
|
||||||
count={notifications.unreadCountLabel}
|
count={notifications.unreadCountLabel}
|
||||||
bold={isAtNotifications}
|
bold={isAtNotifications}
|
||||||
onPress={onPressNotifications}
|
onPress={onPressNotifications}
|
||||||
|
|
|
@ -38,6 +38,7 @@ export const BottomBar = observer(({navigation}: BottomTabBarProps) => {
|
||||||
useNavigationTabState()
|
useNavigationTabState()
|
||||||
|
|
||||||
const {footerMinimalShellTransform} = useMinimalShellMode()
|
const {footerMinimalShellTransform} = useMinimalShellMode()
|
||||||
|
const {notifications} = store.me
|
||||||
|
|
||||||
const onPressTab = React.useCallback(
|
const onPressTab = React.useCallback(
|
||||||
(tab: string) => {
|
(tab: string) => {
|
||||||
|
@ -138,11 +139,15 @@ export const BottomBar = observer(({navigation}: BottomTabBarProps) => {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
onPress={onPressNotifications}
|
onPress={onPressNotifications}
|
||||||
notificationCount={store.me.notifications.unreadCountLabel}
|
notificationCount={notifications.unreadCountLabel}
|
||||||
accessible={true}
|
accessible={true}
|
||||||
accessibilityRole="tab"
|
accessibilityRole="tab"
|
||||||
accessibilityLabel="Notifications"
|
accessibilityLabel="Notifications"
|
||||||
accessibilityHint={`${store.me.notifications.unreadCountLabel} unread`}
|
accessibilityHint={
|
||||||
|
notifications.unreadCountLabel === ''
|
||||||
|
? ''
|
||||||
|
: `${notifications.unreadCountLabel} unread`
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
<Btn
|
<Btn
|
||||||
testID="bottomBarProfileBtn"
|
testID="bottomBarProfileBtn"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import React from 'react'
|
import React, {useEffect} from 'react'
|
||||||
import {observer} from 'mobx-react-lite'
|
import {observer} from 'mobx-react-lite'
|
||||||
import {View, StyleSheet, TouchableOpacity} from 'react-native'
|
import {View, StyleSheet, TouchableOpacity} from 'react-native'
|
||||||
import {useStores} from 'state/index'
|
import {useStores} from 'state/index'
|
||||||
|
@ -14,11 +14,21 @@ import {RoutesContainer, FlatNavigator} from '../../Navigation'
|
||||||
import {DrawerContent} from './Drawer'
|
import {DrawerContent} from './Drawer'
|
||||||
import {useWebMediaQueries} from '../../lib/hooks/useWebMediaQueries'
|
import {useWebMediaQueries} from '../../lib/hooks/useWebMediaQueries'
|
||||||
import {BottomBarWeb} from './bottom-bar/BottomBarWeb'
|
import {BottomBarWeb} from './bottom-bar/BottomBarWeb'
|
||||||
|
import {useNavigation} from '@react-navigation/native'
|
||||||
|
import {NavigationProp} from 'lib/routes/types'
|
||||||
|
|
||||||
const ShellInner = observer(() => {
|
const ShellInner = observer(() => {
|
||||||
const store = useStores()
|
const store = useStores()
|
||||||
const {isDesktop} = useWebMediaQueries()
|
const {isDesktop} = useWebMediaQueries()
|
||||||
|
|
||||||
|
const navigator = useNavigation<NavigationProp>()
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
navigator.addListener('state', () => {
|
||||||
|
store.shell.closeAnyActiveElement()
|
||||||
|
})
|
||||||
|
}, [navigator, store.shell])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<View style={s.hContentRegion}>
|
<View style={s.hContentRegion}>
|
||||||
|
|
|
@ -8738,10 +8738,10 @@ expo-image-picker@^14.1.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
expo-image-loader "~4.1.0"
|
expo-image-loader "~4.1.0"
|
||||||
|
|
||||||
expo-image@^1.2.1:
|
expo-image@^1.2.3:
|
||||||
version "1.2.1"
|
version "1.2.3"
|
||||||
resolved "https://registry.yarnpkg.com/expo-image/-/expo-image-1.2.1.tgz#3f377cb3142de2107903f4e4f88a7f44785dee18"
|
resolved "https://registry.yarnpkg.com/expo-image/-/expo-image-1.2.3.tgz#f3582d725ffb7437f8ce946ad44fe33f0aa0603d"
|
||||||
integrity sha512-pYZFN0ctuIBA+sqUiw70rHQQ04WDyEcF549ObArdj0MNgSUCBJMFmu/jrWDmxOpEMF40lfLVIZKigJT7Bw+GYA==
|
integrity sha512-+Mnx6rcneWSUGfHkUDV3cQ3R4lVwoIDFs/tcXVqnlxyNJdNxpW2cge9pS2Hpj3UDoZVhZPLR8LHS8E9wEaC0NA==
|
||||||
|
|
||||||
expo-json-utils@~0.5.0:
|
expo-json-utils@~0.5.0:
|
||||||
version "0.5.1"
|
version "0.5.1"
|
||||||
|
|
Loading…
Reference in New Issue