diff --git a/docs/build.md b/docs/build.md index 3fc3b123ad..33e7f6751b 100644 --- a/docs/build.md +++ b/docs/build.md @@ -21,7 +21,7 @@ - If you are cloning or forking this repo as an open source developer, please check the tips below as well - Run e2e tests - Start in various console tabs: - - `yarn e2e:server` + - `yarn e2e:mock-server` - `yarn e2e:metro` - Run once: `yarn e2e:build` - Each test run: `yarn e2e:run` @@ -31,7 +31,7 @@ - `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}` - 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 diff --git a/package.json b/package.json index 5c5f30574f..aeeac30a41 100644 --- a/package.json +++ b/package.json @@ -73,7 +73,7 @@ "expo-constants": "~14.2.1", "expo-dev-client": "~2.1.1", "expo-device": "~5.2.1", - "expo-image": "^1.2.1", + "expo-image": "^1.2.3", "expo-image-manipulator": "^11.1.1", "expo-image-picker": "^14.1.1", "expo-localization": "~14.1.1", diff --git a/src/Navigation.tsx b/src/Navigation.tsx index 17bb3c1590..09631701fc 100644 --- a/src/Navigation.tsx +++ b/src/Navigation.tsx @@ -28,7 +28,6 @@ import {isNative} from 'platform/detection' import {useColorSchemeStyle} from 'lib/hooks/useColorSchemeStyle' import {router} from './routes' import {usePalette} from 'lib/hooks/usePalette' -import {useUnreadCountLabel} from 'lib/hooks/useUnreadCountLabel' import {useStores} from './state' import {HomeScreen} from './view/screens/Home' @@ -296,9 +295,9 @@ const MyProfileTabNavigator = observer(() => { * The FlatNavigator is used by Web to represent the routes * in a single ("flat") stack. */ -function FlatNavigator() { +const FlatNavigator = observer(() => { const pal = usePalette('default') - const unreadCountLabel = useUnreadCountLabel() + const unreadCountLabel = useStores().me.notifications.unreadCountLabel const title = (page: string) => bskyTitle(page, unreadCountLabel) return ( ) -} +}) /** * The RoutesContainer should wrap all components which need access diff --git a/src/lib/hooks/useSetTitle.ts b/src/lib/hooks/useSetTitle.ts index 85ba44d299..c5c7a5ca16 100644 --- a/src/lib/hooks/useSetTitle.ts +++ b/src/lib/hooks/useSetTitle.ts @@ -3,11 +3,15 @@ import {useNavigation} from '@react-navigation/native' import {NavigationProp} from 'lib/routes/types' 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) { const navigation = useNavigation() - const unreadCountLabel = useUnreadCountLabel() + const {unreadCountLabel} = useStores().me.notifications useEffect(() => { if (title) { navigation.setOptions({title: bskyTitle(title, unreadCountLabel)}) diff --git a/src/lib/hooks/useUnreadCountLabel.ts b/src/lib/hooks/useUnreadCountLabel.ts deleted file mode 100644 index e2bf77885d..0000000000 --- a/src/lib/hooks/useUnreadCountLabel.ts +++ /dev/null @@ -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 - // 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 -} diff --git a/src/lib/icons.tsx b/src/lib/icons.tsx index 606d27ea4b..06f1950114 100644 --- a/src/lib/icons.tsx +++ b/src/lib/icons.tsx @@ -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 + size?: string | number + strokeWidth?: number +}) { + return ( + + + + ) +} + // Copyright (c) 2020 Refactoring UI Inc. // https://github.com/tailwindlabs/heroicons/blob/master/LICENSE export function UserIcon({ diff --git a/src/view/com/lightbox/Lightbox.web.tsx b/src/view/com/lightbox/Lightbox.web.tsx index eff9af2d22..d389279b1e 100644 --- a/src/view/com/lightbox/Lightbox.web.tsx +++ b/src/view/com/lightbox/Lightbox.web.tsx @@ -21,6 +21,9 @@ interface Img { export const Lightbox = observer(function Lightbox() { const store = useStores() + + const onClose = useCallback(() => store.shell.closeLightbox(), [store.shell]) + if (!store.shell.isLightboxActive) { return null } @@ -29,8 +32,6 @@ export const Lightbox = observer(function Lightbox() { const initialIndex = activeLightbox instanceof models.ImagesLightbox ? activeLightbox.index : 0 - const onClose = () => store.shell.closeLightbox() - let imgs: Img[] | undefined if (activeLightbox instanceof models.ProfileImageLightbox) { const opts = activeLightbox diff --git a/src/view/com/util/forms/Button.tsx b/src/view/com/util/forms/Button.tsx index a8f1f363f9..6a5f19f998 100644 --- a/src/view/com/util/forms/Button.tsx +++ b/src/view/com/util/forms/Button.tsx @@ -128,6 +128,7 @@ export function Button({ }, }, ) + const onPressWrapped = React.useCallback( (event: Event) => { event.stopPropagation() @@ -136,9 +137,23 @@ export function Button({ }, [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 ( { } label="Notifications" accessibilityLabel="Notifications" - accessibilityHint={`${store.me.notifications.unreadCountLabel} unread`} + accessibilityHint={ + notifications.unreadCountLabel === '' + ? '' + : `${notifications.unreadCountLabel} unread` + } count={notifications.unreadCountLabel} bold={isAtNotifications} onPress={onPressNotifications} diff --git a/src/view/shell/bottom-bar/BottomBar.tsx b/src/view/shell/bottom-bar/BottomBar.tsx index c11a0128c6..ef9499f9fc 100644 --- a/src/view/shell/bottom-bar/BottomBar.tsx +++ b/src/view/shell/bottom-bar/BottomBar.tsx @@ -38,6 +38,7 @@ export const BottomBar = observer(({navigation}: BottomTabBarProps) => { useNavigationTabState() const {footerMinimalShellTransform} = useMinimalShellMode() + const {notifications} = store.me const onPressTab = React.useCallback( (tab: string) => { @@ -138,11 +139,15 @@ export const BottomBar = observer(({navigation}: BottomTabBarProps) => { ) } onPress={onPressNotifications} - notificationCount={store.me.notifications.unreadCountLabel} + notificationCount={notifications.unreadCountLabel} accessible={true} accessibilityRole="tab" accessibilityLabel="Notifications" - accessibilityHint={`${store.me.notifications.unreadCountLabel} unread`} + accessibilityHint={ + notifications.unreadCountLabel === '' + ? '' + : `${notifications.unreadCountLabel} unread` + } /> { const store = useStores() const {isDesktop} = useWebMediaQueries() + const navigator = useNavigation() + + useEffect(() => { + navigator.addListener('state', () => { + store.shell.closeAnyActiveElement() + }) + }, [navigator, store.shell]) + return ( <> diff --git a/yarn.lock b/yarn.lock index 54006d89d2..541f587027 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8738,10 +8738,10 @@ expo-image-picker@^14.1.1: dependencies: expo-image-loader "~4.1.0" -expo-image@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/expo-image/-/expo-image-1.2.1.tgz#3f377cb3142de2107903f4e4f88a7f44785dee18" - integrity sha512-pYZFN0ctuIBA+sqUiw70rHQQ04WDyEcF549ObArdj0MNgSUCBJMFmu/jrWDmxOpEMF40lfLVIZKigJT7Bw+GYA== +expo-image@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/expo-image/-/expo-image-1.2.3.tgz#f3582d725ffb7437f8ce946ad44fe33f0aa0603d" + integrity sha512-+Mnx6rcneWSUGfHkUDV3cQ3R4lVwoIDFs/tcXVqnlxyNJdNxpW2cge9pS2Hpj3UDoZVhZPLR8LHS8E9wEaC0NA== expo-json-utils@~0.5.0: version "0.5.1"