From f01d43f9e8107160088296fe6b0a9bb753d61032 Mon Sep 17 00:00:00 2001 From: Paul Frazee Date: Thu, 16 Mar 2023 19:09:19 -0500 Subject: [PATCH 01/24] Get home screen's swipable pager working with the drawer --- ios/Podfile.lock | 6 ++ package.json | 5 +- patches/react-native-pager-view+6.1.4.patch | 54 ++++++++++++++++ src/App.native.tsx | 10 ++- src/lib/api/feed-manip.ts | 3 +- src/state/models/ui/shell.ts | 5 ++ src/view/screens/Home.tsx | 61 +++++++++++++++++- src/view/shell/index.tsx | 6 +- yarn.lock | 71 ++++++++++++++++++--- 9 files changed, 206 insertions(+), 15 deletions(-) create mode 100644 patches/react-native-pager-view+6.1.4.patch diff --git a/ios/Podfile.lock b/ios/Podfile.lock index d6d28c5e..a27db8a6 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -388,6 +388,8 @@ PODS: - React-Core - react-native-image-resizer (3.0.5): - React-Core + - react-native-pager-view (6.1.4): + - React-Core - react-native-paste-input (0.6.2): - React-Core - Swime (= 3.0.6) @@ -614,6 +616,7 @@ DEPENDENCIES: - "react-native-blur (from `../node_modules/@react-native-community/blur`)" - "react-native-cameraroll (from `../node_modules/@react-native-camera-roll/camera-roll`)" - "react-native-image-resizer (from `../node_modules/@bam.tech/react-native-image-resizer`)" + - react-native-pager-view (from `../node_modules/react-native-pager-view`) - "react-native-paste-input (from `../node_modules/@mattermost/react-native-paste-input`)" - react-native-safe-area-context (from `../node_modules/react-native-safe-area-context`) - react-native-splash-screen (from `../node_modules/react-native-splash-screen`) @@ -747,6 +750,8 @@ EXTERNAL SOURCES: :path: "../node_modules/@react-native-camera-roll/camera-roll" react-native-image-resizer: :path: "../node_modules/@bam.tech/react-native-image-resizer" + react-native-pager-view: + :path: "../node_modules/react-native-pager-view" react-native-paste-input: :path: "../node_modules/@mattermost/react-native-paste-input" react-native-safe-area-context: @@ -865,6 +870,7 @@ SPEC CHECKSUMS: react-native-blur: 50c9feabacbc5f49b61337ebc32192c6be7ec3c3 react-native-cameraroll: cb752fda6d5268f1646b4390bd5be1f27706b9a0 react-native-image-resizer: 00ceb0e05586c7aadf061eea676957a6c2ec60fa + react-native-pager-view: b58cb9e9f42f64e50cab3040815772c1d119a2e2 react-native-paste-input: 3392800944a47c00dddbff23c31c281482209679 react-native-safe-area-context: 39c2d8be3328df5d437ac1700f4f3a4f75716acc react-native-splash-screen: 4312f786b13a81b5169ef346d76d33bc0c6dc457 diff --git a/package.json b/package.json index 30f2c354..56886861 100644 --- a/package.json +++ b/package.json @@ -3,6 +3,7 @@ "version": "1.7.0", "private": true, "scripts": { + "postinstall": "patch-package", "android": "expo run:android", "ios": "expo run:ios", "web": "expo start --web", @@ -75,6 +76,8 @@ "mobx": "^6.6.1", "mobx-react-lite": "^3.4.0", "normalize-url": "^8.0.0", + "patch-package": "^6.5.1", + "postinstall-postinstall": "^2.1.0", "react": "18.2.0", "react-avatar-editor": "^13.0.0", "react-circular-progressbar": "^2.1.0", @@ -90,6 +93,7 @@ "react-native-image-crop-picker": "^0.38.1", "react-native-inappbrowser-reborn": "^3.6.3", "react-native-linear-gradient": "^2.6.2", + "react-native-pager-view": "^6.1.4", "react-native-progress": "bluesky-social/react-native-progress", "react-native-reanimated": "~2.14.4", "react-native-root-siblings": "^4.1.1", @@ -97,7 +101,6 @@ "react-native-screens": "^3.13.1", "react-native-splash-screen": "^3.3.0", "react-native-svg": "^13.4.0", - "react-native-tab-view": "^3.3.0", "react-native-url-polyfill": "^1.3.0", "react-native-uuid": "^2.0.1", "react-native-version-number": "^0.3.6", diff --git a/patches/react-native-pager-view+6.1.4.patch b/patches/react-native-pager-view+6.1.4.patch new file mode 100644 index 00000000..adee2533 --- /dev/null +++ b/patches/react-native-pager-view+6.1.4.patch @@ -0,0 +1,54 @@ +diff --git a/node_modules/react-native-pager-view/ios/ReactNativePageView.m b/node_modules/react-native-pager-view/ios/ReactNativePageView.m +index ab0fc7f..fbbf19f 100644 +--- a/node_modules/react-native-pager-view/ios/ReactNativePageView.m ++++ b/node_modules/react-native-pager-view/ios/ReactNativePageView.m +@@ -1,6 +1,6 @@ + + #import "ReactNativePageView.h" +-#import "React/RCTLog.h" ++#import + #import + + #import "UIViewController+CreateExtension.h" +@@ -9,7 +9,7 @@ + #import "RCTOnPageSelected.h" + #import + +-@interface ReactNativePageView () ++@interface ReactNativePageView () + + @property(nonatomic, strong) UIPageViewController *reactPageViewController; + @property(nonatomic, strong) RCTEventDispatcher *eventDispatcher; +@@ -80,6 +80,10 @@ + [self setupInitialController]; + } + ++ UIPanGestureRecognizer* panGestureRecognizer = [UIPanGestureRecognizer new]; ++ panGestureRecognizer.delegate = self; ++ [self addGestureRecognizer: panGestureRecognizer]; ++ + if (self.reactViewController.navigationController != nil && self.reactViewController.navigationController.interactivePopGestureRecognizer != nil) { + [self.scrollView.panGestureRecognizer requireGestureRecognizerToFail:self.reactViewController.navigationController.interactivePopGestureRecognizer]; + } +@@ -463,4 +467,21 @@ + - (BOOL)isLtrLayout { + return [_layoutDirection isEqualToString:@"ltr"]; + } ++ ++- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { ++ if (otherGestureRecognizer == self.scrollView.panGestureRecognizer) { ++ UIPanGestureRecognizer* p = (UIPanGestureRecognizer*) gestureRecognizer; ++ CGPoint velocity = [p velocityInView:self]; ++ if (self.currentIndex == 0 && velocity.x > 0) { ++ self.scrollView.panGestureRecognizer.enabled = false; ++ return NO; ++ } else { ++ self.scrollView.panGestureRecognizer.enabled = self.scrollEnabled; ++ } ++ } else { ++ self.scrollView.panGestureRecognizer.enabled = self.scrollEnabled; ++ } ++ ++ return YES; ++} + @end diff --git a/src/App.native.tsx b/src/App.native.tsx index fcd6e787..ebe6a7cd 100644 --- a/src/App.native.tsx +++ b/src/App.native.tsx @@ -4,8 +4,10 @@ import {Linking} from 'react-native' import {RootSiblingParent} from 'react-native-root-siblings' import SplashScreen from 'react-native-splash-screen' import {SafeAreaProvider} from 'react-native-safe-area-context' +import {GestureHandlerRootView} from 'react-native-gesture-handler' import {observer} from 'mobx-react-lite' import {ThemeProvider} from 'lib/ThemeContext' +import {s} from 'lib/styles' import * as view from './view/index' import {RootStoreModel, setupState, RootStoreProvider} from './state' import {Shell} from './view/shell' @@ -51,9 +53,11 @@ const App = observer(() => { - - - + + + + + diff --git a/src/lib/api/feed-manip.ts b/src/lib/api/feed-manip.ts index 00938be9..7abcaffc 100644 --- a/src/lib/api/feed-manip.ts +++ b/src/lib/api/feed-manip.ts @@ -140,7 +140,8 @@ export class FeedTuner { for (const item of slice.items) { this.seenUris.add(item.post.uri) } - slice.logSelf() + // DEBUG uncomment to get a quick view of the data + // slice.logSelf() } return slices diff --git a/src/state/models/ui/shell.ts b/src/state/models/ui/shell.ts index d6fefb85..4e3aa533 100644 --- a/src/state/models/ui/shell.ts +++ b/src/state/models/ui/shell.ts @@ -122,6 +122,7 @@ export class ShellUiModel { darkMode = false minimalShellMode = false isDrawerOpen = false + isDrawerSwipeDisabled = false isModalActive = false activeModals: Modal[] = [] isLightboxActive = false @@ -168,6 +169,10 @@ export class ShellUiModel { this.isDrawerOpen = false } + setIsDrawerSwipeDisabled(v: boolean) { + this.isDrawerSwipeDisabled = v + } + openModal(modal: Modal) { this.rootStore.emitNavigation() this.isModalActive = true diff --git a/src/view/screens/Home.tsx b/src/view/screens/Home.tsx index adc73315..49915cd0 100644 --- a/src/view/screens/Home.tsx +++ b/src/view/screens/Home.tsx @@ -1,5 +1,5 @@ import React from 'react' -import {FlatList, View} from 'react-native' +import {FlatList, StyleSheet, View, useWindowDimensions} from 'react-native' import {useFocusEffect, useIsFocused} from '@react-navigation/native' import {observer} from 'mobx-react-lite' import useAppState from 'react-native-appstate-hook' @@ -9,15 +9,73 @@ import {ViewHeader} from '../com/util/ViewHeader' import {Feed} from '../com/posts/Feed' import {LoadLatestBtn} from '../com/util/LoadLatestBtn' import {WelcomeBanner} from '../com/util/WelcomeBanner' +import {UserAvatar} from 'view/com/util/UserAvatar' import {FAB} from '../com/util/FAB' import {useStores} from 'state/index' +import {usePalette} from 'lib/hooks/usePalette' import {s} from 'lib/styles' import {useOnMainScroll} from 'lib/hooks/useOnMainScroll' import {useAnalytics} from 'lib/analytics' import {ComposeIcon2} from 'lib/icons' +import PagerView, {PagerViewOnPageSelectedEvent} from 'react-native-pager-view' +import {Text} from 'view/com/util/text/Text' + const HEADER_HEIGHT = 42 +type Props = NativeStackScreenProps +export const HomeScreen = withAuthRequired((_opts: Props) => { + const store = useStores() + const onPageSelected = React.useCallback( + (e: PagerViewOnPageSelectedEvent) => { + store.shell.setIsDrawerSwipeDisabled(e.nativeEvent.position > 0) + }, + [store], + ) + + useFocusEffect( + React.useCallback(() => { + return () => { + store.shell.setIsDrawerSwipeDisabled(false) + } + }, [store]), + ) + + return ( + + + First page + + + Second page + + + ) +}) +function MyPage({children}) { + return ( + + {children} + + ) +} + +const styles = StyleSheet.create({ + tabBar: { + flexDirection: 'row', + }, +}) +/* type Props = NativeStackScreenProps export const HomeScreen = withAuthRequired( observer(function Home(_opts: Props) { @@ -113,3 +171,4 @@ export const HomeScreen = withAuthRequired( ) }), ) +*/ diff --git a/src/view/shell/index.tsx b/src/view/shell/index.tsx index d7877804..eec0f8ed 100644 --- a/src/view/shell/index.tsx +++ b/src/view/shell/index.tsx @@ -46,7 +46,11 @@ const ShellInner = observer(() => { onOpen={onOpenDrawer} onClose={onCloseDrawer} swipeEdgeWidth={winDim.width} - swipeEnabled={!canGoBack && store.session.hasSession}> + swipeEnabled={ + !canGoBack && + store.session.hasSession && + !store.shell.isDrawerSwipeDisabled + }> diff --git a/yarn.lock b/yarn.lock index 43600fa9..8c1b9152 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4002,6 +4002,11 @@ resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== +"@yarnpkg/lockfile@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz#e77a97fbd345b76d83245edcd17d393b1b41fb31" + integrity sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ== + "@zxing/text-encoding@^0.9.0": version "0.9.0" resolved "https://registry.yarnpkg.com/@zxing/text-encoding/-/text-encoding-0.9.0.tgz#fb50ffabc6c7c66a0c96b4c03e3d9be74864b70b" @@ -7742,7 +7747,7 @@ find-up@^5.0.0, find-up@~5.0.0: locate-path "^6.0.0" path-exists "^4.0.0" -find-yarn-workspace-root@~2.0.0: +find-yarn-workspace-root@^2.0.0, find-yarn-workspace-root@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz#f47fb8d239c900eb78179aa81b66673eac88f7bd" integrity sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ== @@ -8786,6 +8791,13 @@ is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7: resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== +is-ci@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" + integrity sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w== + dependencies: + ci-info "^2.0.0" + is-core-module@^2.11.0, is-core-module@^2.9.0: version "2.11.0" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.11.0.tgz#ad4cb3e3863e814523c96f3f58d26cc570ff0144" @@ -10435,6 +10447,13 @@ kind-of@^6.0.0, kind-of@^6.0.2: resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== +klaw-sync@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/klaw-sync/-/klaw-sync-6.0.0.tgz#1fd2cfd56ebb6250181114f0a581167099c2b28c" + integrity sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ== + dependencies: + graceful-fs "^4.1.11" + kleur@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" @@ -11912,6 +11931,14 @@ open@^6.2.0: dependencies: is-wsl "^1.1.0" +open@^7.4.2: + version "7.4.2" + resolved "https://registry.yarnpkg.com/open/-/open-7.4.2.tgz#b8147e26dcf3e426316c730089fd71edd29c2321" + integrity sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q== + dependencies: + is-docker "^2.0.0" + is-wsl "^2.1.1" + open@^8.0.4, open@^8.0.9, open@^8.3.0, open@^8.4.0: version "8.4.2" resolved "https://registry.yarnpkg.com/open/-/open-8.4.2.tgz#5b5ffe2a8f793dcd2aad73e550cb87b59cb084f9" @@ -12170,6 +12197,26 @@ password-prompt@^1.0.4: ansi-escapes "^3.1.0" cross-spawn "^6.0.5" +patch-package@^6.5.1: + version "6.5.1" + resolved "https://registry.yarnpkg.com/patch-package/-/patch-package-6.5.1.tgz#3e5d00c16997e6160291fee06a521c42ac99b621" + integrity sha512-I/4Zsalfhc6bphmJTlrLoOcAF87jcxko4q0qsv4bGcurbr8IskEOtdnt9iCmsQVGL1B+iUhSQqweyTLJfCF9rA== + dependencies: + "@yarnpkg/lockfile" "^1.1.0" + chalk "^4.1.2" + cross-spawn "^6.0.5" + find-yarn-workspace-root "^2.0.0" + fs-extra "^9.0.0" + is-ci "^2.0.0" + klaw-sync "^6.0.0" + minimist "^1.2.6" + open "^7.4.2" + rimraf "^2.6.3" + semver "^5.6.0" + slash "^2.0.0" + tmp "^0.0.33" + yaml "^1.10.2" + path-browserify@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-1.0.1.tgz#d98454a9c3753d5790860f16f68867b9e46be1fd" @@ -12981,6 +13028,11 @@ postgres-interval@^1.1.0: dependencies: xtend "^4.0.0" +postinstall-postinstall@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/postinstall-postinstall/-/postinstall-postinstall-2.1.0.tgz#4f7f77441ef539d1512c40bd04c71b06a4704ca3" + integrity sha512-7hQX6ZlZXIoRiWNrbMQaLzUUfH+sSx39u8EJ9HYuDc1kLo9IXKWjM5RSquZN1ad5GnH8CGFM78fsAAQi3OKEEQ== + prebuild-install@^7.1.0, prebuild-install@^7.1.1: version "7.1.1" resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-7.1.1.tgz#de97d5b34a70a0c81334fd24641f2a1702352e45" @@ -13618,6 +13670,11 @@ react-native-linear-gradient@^2.6.2: resolved "https://registry.yarnpkg.com/react-native-linear-gradient/-/react-native-linear-gradient-2.6.2.tgz#56598a76832724b2afa7889747635b5c80948f38" integrity sha512-Z8Xxvupsex+9BBFoSYS87bilNPWcRfRsGC0cpJk72Nxb5p2nEkGSBv73xZbEHnW2mUFvP+huYxrVvjZkr/gRjQ== +react-native-pager-view@^6.1.4: + version "6.1.4" + resolved "https://registry.yarnpkg.com/react-native-pager-view/-/react-native-pager-view-6.1.4.tgz#3a63ebd1b72f81991157ea552bb9c887e529bc8c" + integrity sha512-fmTwgGwPxGCBusKAq7gHzm+s1Yp0qh5rKPoQszaCuxrb+76KgK4Qe82jJNPUp2xTZOKSw+FbJU2QahF8ncTl+w== + react-native-progress@bluesky-social/react-native-progress: version "5.0.0" resolved "https://codeload.github.com/bluesky-social/react-native-progress/tar.gz/5a372f4f2ce5feb26f4f47b6a4d187ab9b923ab4" @@ -13668,13 +13725,6 @@ react-native-svg@^13.4.0: css-select "^5.1.0" css-tree "^1.1.3" -react-native-tab-view@^3.3.0: - version "3.5.1" - resolved "https://registry.yarnpkg.com/react-native-tab-view/-/react-native-tab-view-3.5.1.tgz#2ad454afc0e186b43ea8b89053f39180d480d48b" - integrity sha512-qdrS5t+AEhfuKQyuCXkwHu4IVppkuTvzWWlkSZKrPaSkjjIa32xrsGxt1UW9YDdro2w4AMw5hKn1hFmg/5mvzA== - dependencies: - use-latest-callback "^0.1.5" - react-native-url-polyfill@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/react-native-url-polyfill/-/react-native-url-polyfill-1.3.0.tgz#c1763de0f2a8c22cc3e959b654c8790622b6ef6a" @@ -14686,6 +14736,11 @@ sisteransi@^1.0.5: resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== +slash@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44" + integrity sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A== + slash@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" From ad9da82612a33a796bcb2c679dbff357f4829dc8 Mon Sep 17 00:00:00 2001 From: Paul Frazee Date: Thu, 16 Mar 2023 19:54:32 -0500 Subject: [PATCH 02/24] Add tab bar to pager --- src/view/com/util/Pager.tsx | 72 +++++++++++++++++++++ src/view/com/util/TabBar.tsx | 119 +++++++++++++++++++++++++++++++++++ src/view/screens/Home.tsx | 14 ++--- 3 files changed, 198 insertions(+), 7 deletions(-) create mode 100644 src/view/com/util/Pager.tsx create mode 100644 src/view/com/util/TabBar.tsx diff --git a/src/view/com/util/Pager.tsx b/src/view/com/util/Pager.tsx new file mode 100644 index 00000000..1a3ff642 --- /dev/null +++ b/src/view/com/util/Pager.tsx @@ -0,0 +1,72 @@ +import React from 'react' +import {Animated, StyleSheet, View} from 'react-native' +import PagerView, {PagerViewOnPageSelectedEvent} from 'react-native-pager-view' +import {useAnimatedValue} from 'lib/hooks/useAnimatedValue' +import {TabBar} from './TabBar' + +export type PageSelectedEvent = PagerViewOnPageSelectedEvent +const AnimatedPagerView = Animated.createAnimatedComponent(PagerView) + +interface Props { + onPageSelected?: (e: PageSelectedEvent) => void +} +export const Pager = ({ + children, + onPageSelected, +}: React.PropsWithChildren) => { + const [selectedPage, setSelectedPage] = React.useState(0) + const position = useAnimatedValue(0) + const offset = useAnimatedValue(0) + const pagerView = React.useRef() + + const onPageSelectedInner = React.useCallback( + (e: PageSelectedEvent) => { + setSelectedPage(e.nativeEvent.position) + onPageSelected?.(e) + }, + [setSelectedPage, onPageSelected], + ) + + const onTabBarSelect = React.useCallback( + (index: number) => { + pagerView.current?.setPage(index) + }, + [pagerView], + ) + + return ( + + + + {children} + + + ) +} + +const styles = StyleSheet.create({ + tabBar: { + flexDirection: 'row', + }, +}) diff --git a/src/view/com/util/TabBar.tsx b/src/view/com/util/TabBar.tsx new file mode 100644 index 00000000..3a823e42 --- /dev/null +++ b/src/view/com/util/TabBar.tsx @@ -0,0 +1,119 @@ +import React, {createRef, useState, useMemo} from 'react' +import { + Animated, + StyleSheet, + TouchableWithoutFeedback, + View, +} from 'react-native' +import {Text} from './text/Text' +import {usePalette} from 'lib/hooks/usePalette' + +interface Layout { + x: number + width: number +} + +export function TabBar({ + selectedPage, + items, + position, + offset, + onSelect, +}: { + selectedPage: number + items: string[] + position: Animated.Value + offset: Animated.Value + onSelect?: (index: number) => void +}) { + const pal = usePalette('default') + const [itemLayouts, setItemLayouts] = useState( + items.map(() => ({x: 0, width: 0})), + ) + const itemRefs = useMemo( + () => Array.from({length: items.length}).map(() => createRef()), + [items.length], + ) + const panX = Animated.add(position, offset) + + const underlineStyle = { + backgroundColor: pal.colors.text, + left: panX.interpolate({ + inputRange: items.map((_item, i) => i), + outputRange: itemLayouts.map(l => l.x), + }), + width: panX.interpolate({ + inputRange: items.map((_item, i) => i), + outputRange: itemLayouts.map(l => l.width), + }), + } + + const onLayout = () => { + const promises = [] + for (let i = 0; i < items.length; i++) { + promises.push( + new Promise(resolve => { + itemRefs[i].current?.measure( + (x: number, _y: number, width: number) => { + resolve({x, width}) + }, + ) + }), + ) + } + Promise.all(promises).then((layouts: Layout[]) => { + setItemLayouts(layouts) + }) + } + + const onPressItem = (index: number) => { + onSelect?.(index) + } + + return ( + + + {items.map((item, i) => { + const selected = i === selectedPage + return ( + onPressItem(i)}> + + + {item} + + + + ) + })} + + ) +} + +const styles = StyleSheet.create({ + outer: { + flexDirection: 'row', + paddingHorizontal: 14, + }, + item: { + paddingTop: 8, + paddingBottom: 12, + marginRight: 14, + paddingHorizontal: 10, + }, + label: { + fontWeight: '600', + }, + labelSelected: { + fontWeight: '600', + }, + underline: { + position: 'absolute', + height: 4, + bottom: 0, + }, +}) diff --git a/src/view/screens/Home.tsx b/src/view/screens/Home.tsx index 49915cd0..6c708e2f 100644 --- a/src/view/screens/Home.tsx +++ b/src/view/screens/Home.tsx @@ -18,7 +18,7 @@ import {useOnMainScroll} from 'lib/hooks/useOnMainScroll' import {useAnalytics} from 'lib/analytics' import {ComposeIcon2} from 'lib/icons' -import PagerView, {PagerViewOnPageSelectedEvent} from 'react-native-pager-view' +import {Pager, PageSelectedEvent} from 'view/com/util/Pager' import {Text} from 'view/com/util/text/Text' const HEADER_HEIGHT = 42 @@ -27,7 +27,7 @@ type Props = NativeStackScreenProps export const HomeScreen = withAuthRequired((_opts: Props) => { const store = useStores() const onPageSelected = React.useCallback( - (e: PagerViewOnPageSelectedEvent) => { + (e: PageSelectedEvent) => { store.shell.setIsDrawerSwipeDisabled(e.nativeEvent.position > 0) }, [store], @@ -42,17 +42,17 @@ export const HomeScreen = withAuthRequired((_opts: Props) => { ) return ( - + First page Second page - + + Third page + + ) }) function MyPage({children}) { From 71209bb3aca1104773ee9fab20ec9f9ab4fc3ad2 Mon Sep 17 00:00:00 2001 From: Paul Frazee Date: Thu, 16 Mar 2023 21:47:11 -0500 Subject: [PATCH 03/24] Implement popular & following views on home screen --- src/state/models/feed-view.ts | 12 +- src/view/com/profile/FollowButton.tsx | 2 +- src/view/com/util/Pager.tsx | 27 +- src/view/com/util/PostMeta.tsx | 8 +- src/view/com/util/TabBar.tsx | 25 +- src/view/screens/Home.tsx | 362 +++++++++++++++++--------- 6 files changed, 273 insertions(+), 163 deletions(-) diff --git a/src/state/models/feed-view.ts b/src/state/models/feed-view.ts index 42b753b2..81760132 100644 --- a/src/state/models/feed-view.ts +++ b/src/state/models/feed-view.ts @@ -257,7 +257,7 @@ export class FeedModel { constructor( public rootStore: RootStoreModel, - public feedType: 'home' | 'author' | 'suggested', + public feedType: 'home' | 'author' | 'suggested' | 'goodstuff', params: GetTimeline.QueryParams | GetAuthorFeed.QueryParams, ) { makeAutoObservable( @@ -634,6 +634,16 @@ export class FeedModel { return this.rootStore.api.app.bsky.feed.getTimeline( params as GetTimeline.QueryParams, ) + } else if (this.feedType === 'goodstuff') { + const res = await this.rootStore.api.app.bsky.feed.getAuthorFeed({ + ...params, + author: 'jay.bsky.social', + } as GetAuthorFeed.QueryParams) + res.data.feed = mergePosts([res], {repostsOnly: true}) + res.data.feed.forEach(item => { + delete item.reason + }) + return res } else { return this.rootStore.api.app.bsky.feed.getAuthorFeed( params as GetAuthorFeed.QueryParams, diff --git a/src/view/com/profile/FollowButton.tsx b/src/view/com/profile/FollowButton.tsx index f24c3d0c..7a194cee 100644 --- a/src/view/com/profile/FollowButton.tsx +++ b/src/view/com/profile/FollowButton.tsx @@ -42,7 +42,7 @@ const FollowButton = observer( return ( - - ) : ( - <> - - Follow at least {remaining} {remaining === 1 ? 'person' : 'people'}{' '} - to build your feed. - - - - - - )} - - ) -}) - -const styles = StyleSheet.create({ - container: { - paddingTop: 16, - paddingBottom: 16, - paddingHorizontal: 20, - borderTopWidth: 1, - borderBottomWidth: 1, - }, - controls: { - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'center', - marginTop: 10, - }, - progress: { - marginTop: 12, - }, -}) diff --git a/src/view/screens/Home.tsx b/src/view/screens/Home.tsx index f1d03233..5250f115 100644 --- a/src/view/screens/Home.tsx +++ b/src/view/screens/Home.tsx @@ -14,7 +14,6 @@ import {FeedModel} from 'state/models/feed-view' import {withAuthRequired} from 'view/com/auth/withAuthRequired' import {Feed} from '../com/posts/Feed' import {LoadLatestBtn} from '../com/util/LoadLatestBtn' -import {WelcomeBanner} from '../com/util/WelcomeBanner' import {TabBar} from 'view/com/util/TabBar' import {Pager, PageSelectedEvent, TabBarProps} from 'view/com/util/Pager' import {FAB} from '../com/util/FAB' @@ -202,7 +201,6 @@ const FeedPage = observer( return ( - {store.shell.isOnboarding && } Date: Fri, 17 Mar 2023 15:20:34 -0500 Subject: [PATCH 12/24] Choose good stuff based on service --- src/lib/constants.ts | 10 ++++++++++ src/state/models/feed-view.ts | 4 ++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/lib/constants.ts b/src/lib/constants.ts index 0cde9b01..ffc1aaed 100644 --- a/src/lib/constants.ts +++ b/src/lib/constants.ts @@ -161,6 +161,16 @@ export function SUGGESTED_FOLLOWS(serviceUrl: string) { } } +export function GOOD_STUFF(serviceUrl: string) { + if (serviceUrl.includes('localhost')) { + return 'alice.test' + } else if (serviceUrl.includes('staging')) { + return 'paul.staging.bsky.dev' + } else { + return 'jay.bsky.social' + } +} + export const POST_IMG_MAX_WIDTH = 2000 export const POST_IMG_MAX_HEIGHT = 2000 export const POST_IMG_MAX_SIZE = 1000000 diff --git a/src/state/models/feed-view.ts b/src/state/models/feed-view.ts index a62dbc98..3d7680fb 100644 --- a/src/state/models/feed-view.ts +++ b/src/state/models/feed-view.ts @@ -16,7 +16,7 @@ import {RootStoreModel} from './root-store' import * as apilib from 'lib/api/index' import {cleanError} from 'lib/strings/errors' import {RichText} from 'lib/strings/rich-text' -import {SUGGESTED_FOLLOWS} from 'lib/constants' +import {SUGGESTED_FOLLOWS, GOOD_STUFF} from 'lib/constants' import { getCombinedCursors, getMultipleAuthorsPosts, @@ -643,7 +643,7 @@ export class FeedModel { } else if (this.feedType === 'goodstuff') { const res = await this.rootStore.api.app.bsky.feed.getAuthorFeed({ ...params, - author: 'jay.bsky.social', + author: GOOD_STUFF(String(this.rootStore.agent.service)), } as GetAuthorFeed.QueryParams) res.data.feed = mergePosts([res], {repostsOnly: true}) res.data.feed.forEach(item => { From ff39b072f3110f018edd6797ee642728f0dae259 Mon Sep 17 00:00:00 2001 From: Paul Frazee Date: Fri, 17 Mar 2023 18:01:53 -0500 Subject: [PATCH 13/24] Add foaf-based follow discovery --- src/lib/hooks/usePalette.ts | 4 + src/state/models/discovery/foafs.ts | 98 +++++++++++++ src/view/com/discover/SuggestedFollows.tsx | 159 +++++++-------------- src/view/com/profile/ProfileCard.tsx | 62 ++++++-- src/view/com/util/LoadingPlaceholder.tsx | 49 +++++++ src/view/screens/Search.tsx | 93 +++++++++--- 6 files changed, 335 insertions(+), 130 deletions(-) create mode 100644 src/state/models/discovery/foafs.ts diff --git a/src/lib/hooks/usePalette.ts b/src/lib/hooks/usePalette.ts index 5b9929c7..7eeb7422 100644 --- a/src/lib/hooks/usePalette.ts +++ b/src/lib/hooks/usePalette.ts @@ -4,6 +4,7 @@ import {useTheme, PaletteColorName, PaletteColor} from '../ThemeContext' export interface UsePaletteValue { colors: PaletteColor view: ViewStyle + viewLight: ViewStyle btn: ViewStyle border: ViewStyle borderDark: ViewStyle @@ -20,6 +21,9 @@ export function usePalette(color: PaletteColorName): UsePaletteValue { view: { backgroundColor: palette.background, }, + viewLight: { + backgroundColor: palette.backgroundLight, + }, btn: { backgroundColor: palette.backgroundLight, }, diff --git a/src/state/models/discovery/foafs.ts b/src/state/models/discovery/foafs.ts new file mode 100644 index 00000000..4a46ae9d --- /dev/null +++ b/src/state/models/discovery/foafs.ts @@ -0,0 +1,98 @@ +import {AppBskyActorProfile, AppBskyActorRef} from '@atproto/api' +import {makeAutoObservable, runInAction} from 'mobx' +import sampleSize from 'lodash.samplesize' +import {bundleAsync} from 'lib/async/bundle' +import {RootStoreModel} from '../root-store' + +export type RefWithInfoAndFollowers = AppBskyActorRef.WithInfo & { + followers: AppBskyActorProfile.View[] +} + +export type ProfileViewFollows = AppBskyActorProfile.View & { + follows: AppBskyActorRef.WithInfo[] +} + +export class FoafsModel { + isLoading = false + hasData = false + sources: string[] = [] + foafs: Map = new Map() + popular: RefWithInfoAndFollowers[] = [] + + constructor(public rootStore: RootStoreModel) { + makeAutoObservable(this) + } + + fetch = bundleAsync(async () => { + try { + this.isLoading = true + await this.rootStore.me.follows.fetchIfNeeded() + // grab 10 of the users followed by the user + this.sources = sampleSize( + Object.keys(this.rootStore.me.follows.followDidToRecordMap), + 10, + ) + if (this.sources.length === 0) { + return + } + this.foafs.clear() + this.popular.length = 0 + + // fetch their profiles + const profiles = await this.rootStore.api.app.bsky.actor.getProfiles({ + actors: this.sources, + }) + + // fetch their follows + const results = await Promise.allSettled( + this.sources.map(source => + this.rootStore.api.app.bsky.graph.getFollows({user: source}), + ), + ) + + // store the follows and construct a "most followed" set + const popular: RefWithInfoAndFollowers[] = [] + for (let i = 0; i < results.length; i++) { + const res = results[i] + const profile = profiles.data.profiles[i] + const source = this.sources[i] + if (res.status === 'fulfilled' && profile) { + // filter out users already followed by the user or that *is* the user + res.value.data.follows = res.value.data.follows.filter(follow => { + return ( + follow.did !== this.rootStore.me.did && + !this.rootStore.me.follows.isFollowing(follow.did) + ) + }) + + runInAction(() => { + this.foafs.set(source, { + ...profile, + follows: res.value.data.follows, + }) + }) + for (const follow of res.value.data.follows) { + let item = popular.find(p => p.did === follow.did) + if (!item) { + item = {...follow, followers: []} + popular.push(item) + } + item.followers.push(profile) + } + } + } + + popular.sort((a, b) => b.followers.length - a.followers.length) + runInAction(() => { + this.popular = popular.filter(p => p.followers.length > 1).slice(0, 20) + }) + this.hasData = true + } catch (e) { + console.error('Failed to fetch FOAFs', e) + } finally { + runInAction(() => { + this.isLoading = false + }) + } + }) +} diff --git a/src/view/com/discover/SuggestedFollows.tsx b/src/view/com/discover/SuggestedFollows.tsx index 1e40956c..dd1136a4 100644 --- a/src/view/com/discover/SuggestedFollows.tsx +++ b/src/view/com/discover/SuggestedFollows.tsx @@ -1,116 +1,67 @@ import React from 'react' -import {ActivityIndicator, StyleSheet, View} from 'react-native' -import {CenteredView, FlatList} from '../util/Views' -import {observer} from 'mobx-react-lite' -import {ErrorScreen} from '../util/error/ErrorScreen' +import {StyleSheet, View} from 'react-native' +import {AppBskyActorRef, AppBskyActorProfile} from '@atproto/api' +import {RefWithInfoAndFollowers} from 'state/models/discovery/foafs' import {ProfileCardWithFollowBtn} from '../profile/ProfileCard' -import {useStores} from 'state/index' -import { - SuggestedActorsViewModel, - SuggestedActor, -} from 'state/models/suggested-actors-view' -import {s} from 'lib/styles' +import {Text} from '../util/text/Text' import {usePalette} from 'lib/hooks/usePalette' -export const SuggestedFollows = observer( - ({onNoSuggestions}: {onNoSuggestions?: () => void}) => { - const pal = usePalette('default') - const store = useStores() - - const view = React.useMemo( - () => new SuggestedActorsViewModel(store), - [store], - ) - - React.useEffect(() => { - view - .loadMore() - .catch((err: any) => - store.log.error('Failed to fetch suggestions', err), - ) - }, [view, store.log]) - - React.useEffect(() => { - if (!view.isLoading && !view.hasError && !view.hasContent) { - onNoSuggestions?.() - } - }, [view, view.isLoading, view.hasError, view.hasContent, onNoSuggestions]) - - const onRefresh = () => { - view - .refresh() - .catch((err: any) => - store.log.error('Failed to fetch suggestions', err), - ) - } - const onEndReached = () => { - view - .loadMore() - .catch(err => - view?.rootStore.log.error('Failed to load more suggestions', err), - ) - } - - const renderItem = ({item}: {item: SuggestedActor}) => { - return ( - - ) - } - return ( - - {view.hasError ? ( - - - - ) : view.isEmpty ? ( - - ) : ( - - item.did} - refreshing={view.isRefreshing} - onRefresh={onRefresh} - onEndReached={onEndReached} - renderItem={renderItem} - initialNumToRender={15} - ListFooterComponent={() => ( - - {view.isLoading && } - - )} - contentContainerStyle={s.contentContainer} - /> - - )} - - ) - }, -) +export const SuggestedFollows = ({ + title, + suggestions, +}: { + title: string + suggestions: (AppBskyActorRef.WithInfo | RefWithInfoAndFollowers)[] +}) => { + const pal = usePalette('default') + return ( + + + {title} + + {suggestions.map(item => ( + + + + ))} + + ) +} const styles = StyleSheet.create({ container: { - height: '100%', + paddingVertical: 10, + paddingHorizontal: 4, }, - suggestionsContainer: { - height: '100%', + heading: { + fontWeight: 'bold', + paddingHorizontal: 4, + paddingBottom: 8, }, - footer: { - height: 200, - paddingTop: 20, + + card: { + borderRadius: 12, + marginBottom: 2, + borderWidth: 1, + }, + + loadMore: { + paddingLeft: 16, + paddingVertical: 12, }, }) diff --git a/src/view/com/profile/ProfileCard.tsx b/src/view/com/profile/ProfileCard.tsx index 087536c3..ebb42766 100644 --- a/src/view/com/profile/ProfileCard.tsx +++ b/src/view/com/profile/ProfileCard.tsx @@ -1,6 +1,7 @@ import React from 'react' import {StyleSheet, View} from 'react-native' import {observer} from 'mobx-react-lite' +import {AppBskyActorProfile} from '@atproto/api' import {Link} from '../util/Link' import {Text} from '../util/text/Text' import {UserAvatar} from '../util/UserAvatar' @@ -16,6 +17,7 @@ export function ProfileCard({ description, isFollowedBy, noBorder, + followers, renderButton, }: { handle: string @@ -24,17 +26,13 @@ export function ProfileCard({ description?: string isFollowedBy?: boolean noBorder?: boolean + followers?: AppBskyActorProfile.View[] | undefined renderButton?: () => JSX.Element }) { const pal = usePalette('default') return ( ) : undefined} + {followers?.length ? ( + + + Followed by{' '} + {followers.map(f => f.displayName || f.handle).join(', ')} + + {followers.slice(0, 3).map(f => ( + + + + + + ))} + + ) : undefined} ) } @@ -86,6 +103,8 @@ export const ProfileCardWithFollowBtn = observer( avatar, description, isFollowedBy, + noBorder, + followers, }: { did: string declarationCid: string @@ -94,6 +113,8 @@ export const ProfileCardWithFollowBtn = observer( avatar?: string description?: string isFollowedBy?: boolean + noBorder?: boolean + followers?: AppBskyActorProfile.View[] | undefined }) => { const store = useStores() const isMe = store.me.handle === handle @@ -105,6 +126,8 @@ export const ProfileCardWithFollowBtn = observer( avatar={avatar} description={description} isFollowedBy={isFollowedBy} + noBorder={noBorder} + followers={followers} renderButton={ isMe ? undefined @@ -128,8 +151,8 @@ const styles = StyleSheet.create({ alignItems: 'center', }, layoutAvi: { - width: 60, - paddingLeft: 10, + width: 54, + paddingLeft: 4, paddingTop: 8, paddingBottom: 10, }, @@ -164,4 +187,27 @@ const styles = StyleSheet.create({ marginLeft: 6, paddingHorizontal: 14, }, + + followedBy: { + flexDirection: 'row', + alignItems: 'flex-start', + paddingLeft: 54, + paddingRight: 20, + marginBottom: 10, + marginTop: -6, + }, + followedByAviContainer: { + width: 24, + height: 36, + }, + followedByAvi: { + width: 36, + height: 36, + borderRadius: 18, + padding: 2, + }, + followsByDesc: { + flex: 1, + paddingRight: 10, + }, }) diff --git a/src/view/com/util/LoadingPlaceholder.tsx b/src/view/com/util/LoadingPlaceholder.tsx index 9e72640d..2f653ee0 100644 --- a/src/view/com/util/LoadingPlaceholder.tsx +++ b/src/view/com/util/LoadingPlaceholder.tsx @@ -128,6 +128,46 @@ export function NotificationFeedLoadingPlaceholder() { ) } +export function ProfileCardLoadingPlaceholder({ + style, +}: { + style?: StyleProp +}) { + const pal = usePalette('default') + return ( + + + + + + + + + ) +} + +export function ProfileCardFeedLoadingPlaceholder() { + return ( + <> + + + + + + + + + + + + + ) +} + const styles = StyleSheet.create({ loadingPlaceholder: { borderRadius: 6, @@ -147,6 +187,15 @@ const styles = StyleSheet.create({ paddingLeft: 46, margin: 1, }, + profileCard: { + flexDirection: 'row', + padding: 10, + margin: 1, + }, + profileCardAvi: { + borderRadius: 20, + marginRight: 10, + }, smallAvatar: { borderRadius: 15, marginRight: 10, diff --git a/src/view/screens/Search.tsx b/src/view/screens/Search.tsx index 19535a16..246aa13f 100644 --- a/src/view/screens/Search.tsx +++ b/src/view/screens/Search.tsx @@ -1,6 +1,7 @@ import React from 'react' import { Keyboard, + RefreshControl, StyleSheet, TextInput, TouchableOpacity, @@ -13,21 +14,23 @@ import { FontAwesomeIconStyle, } from '@fortawesome/react-native-fontawesome' import {withAuthRequired} from 'view/com/auth/withAuthRequired' -import {ScrollView} from '../com/util/Views' +import {ScrollView} from 'view/com/util/Views' import { NativeStackScreenProps, SearchTabNavigatorParams, } from 'lib/routes/types' import {observer} from 'mobx-react-lite' -import {UserAvatar} from '../com/util/UserAvatar' -import {Text} from '../com/util/text/Text' +import {UserAvatar} from 'view/com/util/UserAvatar' +import {Text} from 'view/com/util/text/Text' import {useStores} from 'state/index' import {UserAutocompleteViewModel} from 'state/models/user-autocomplete-view' +import {FoafsModel} from 'state/models/discovery/foafs' import {s} from 'lib/styles' import {MagnifyingGlassIcon} from 'lib/icons' -import {WhoToFollow} from '../com/discover/WhoToFollow' -import {SuggestedPosts} from '../com/discover/SuggestedPosts' -import {ProfileCard} from '../com/profile/ProfileCard' +import {WhoToFollow} from 'view/com/discover/WhoToFollow' +import {SuggestedFollows} from 'view/com/discover/SuggestedFollows' +import {ProfileCard} from 'view/com/profile/ProfileCard' +import {ProfileCardFeedLoadingPlaceholder} from 'view/com/util/LoadingPlaceholder' import {usePalette} from 'lib/hooks/usePalette' import {useTheme} from 'lib/ThemeContext' import {useOnMainScroll} from 'lib/hooks/useOnMainScroll' @@ -53,6 +56,11 @@ export const SearchScreen = withAuthRequired( () => new UserAutocompleteViewModel(store), [store], ) + const foafsView = React.useMemo( + () => new FoafsModel(store), + [store], + ) + const [refreshing, setRefreshing] = React.useState(false) const onSoftReset = () => { scrollElRef.current?.scrollTo({x: 0, y: 0}) @@ -71,9 +79,12 @@ export const SearchScreen = withAuthRequired( } store.shell.setMinimalShellMode(false) autocompleteView.setup() + if (!foafsView.hasData) { + foafsView.fetch() + } return cleanup - }, [store, autocompleteView, lastRenderTime, setRenderTime]), + }, [store, autocompleteView, foafsView, lastRenderTime, setRenderTime]), ) const onPressMenu = () => { @@ -98,15 +109,18 @@ export const SearchScreen = withAuthRequired( autocompleteView.setActive(false) textInput.current?.blur() } + const onRefresh = React.useCallback(async () => { + setRefreshing(true) + try { + await foafsView.fetch() + } finally { + setRefreshing(false) + } + }, [foafsView, setRefreshing]) return ( - + ) : ( - - - + + }> + {foafsView.isLoading ? ( + + ) : foafsView.sources.length ? ( + <> + {foafsView.popular.length > 0 && ( + + + + )} + {foafsView.sources.map((source, i) => { + const item = foafsView.foafs.get(source) + if (!item || item.follows.length === 0) { + return + } + return ( + + + + ) + })} + + ) : ( + + + + )} )} - - + ) }), @@ -235,4 +288,8 @@ const styles = StyleSheet.create({ textAlign: 'center', paddingTop: 10, }, + + suggestions: { + marginBottom: 8, + }, }) From 025681c2f2c161325bac7fa7c435c580b947d6f4 Mon Sep 17 00:00:00 2001 From: Paul Frazee Date: Fri, 17 Mar 2023 18:09:27 -0500 Subject: [PATCH 14/24] Fall back to who to follow --- src/state/models/discovery/foafs.ts | 12 ++++++++++++ src/view/screens/Search.tsx | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/state/models/discovery/foafs.ts b/src/state/models/discovery/foafs.ts index 4a46ae9d..241338a1 100644 --- a/src/state/models/discovery/foafs.ts +++ b/src/state/models/discovery/foafs.ts @@ -23,6 +23,18 @@ export class FoafsModel { makeAutoObservable(this) } + get hasContent() { + if (this.popular.length > 0) { + return true + } + for (const foaf of this.foafs.values()) { + if (foaf.follows.length) { + return true + } + } + return false + } + fetch = bundleAsync(async () => { try { this.isLoading = true diff --git a/src/view/screens/Search.tsx b/src/view/screens/Search.tsx index 246aa13f..6ae5fba0 100644 --- a/src/view/screens/Search.tsx +++ b/src/view/screens/Search.tsx @@ -205,7 +205,7 @@ export const SearchScreen = withAuthRequired( }> {foafsView.isLoading ? ( - ) : foafsView.sources.length ? ( + ) : foafsView.hasContent ? ( <> {foafsView.popular.length > 0 && ( From 8364e1a081affa2f51efb216688650410a3122b3 Mon Sep 17 00:00:00 2001 From: Paul Frazee Date: Fri, 17 Mar 2023 18:11:57 -0500 Subject: [PATCH 15/24] Fix backgrounds --- src/view/com/discover/SuggestedFollows.tsx | 1 + src/view/com/profile/ProfileCard.tsx | 12 +++++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/view/com/discover/SuggestedFollows.tsx b/src/view/com/discover/SuggestedFollows.tsx index dd1136a4..7a64a15f 100644 --- a/src/view/com/discover/SuggestedFollows.tsx +++ b/src/view/com/discover/SuggestedFollows.tsx @@ -28,6 +28,7 @@ export const SuggestedFollows = ({ handle={item.handle} displayName={item.displayName} avatar={item.avatar} + noBg noBorder description="" followers={ diff --git a/src/view/com/profile/ProfileCard.tsx b/src/view/com/profile/ProfileCard.tsx index ebb42766..53f45fb1 100644 --- a/src/view/com/profile/ProfileCard.tsx +++ b/src/view/com/profile/ProfileCard.tsx @@ -16,6 +16,7 @@ export function ProfileCard({ avatar, description, isFollowedBy, + noBg, noBorder, followers, renderButton, @@ -25,6 +26,7 @@ export function ProfileCard({ avatar?: string description?: string isFollowedBy?: boolean + noBg?: boolean noBorder?: boolean followers?: AppBskyActorProfile.View[] | undefined renderButton?: () => JSX.Element @@ -32,7 +34,12 @@ export function ProfileCard({ const pal = usePalette('default') return ( { @@ -126,6 +135,7 @@ export const ProfileCardWithFollowBtn = observer( avatar={avatar} description={description} isFollowedBy={isFollowedBy} + noBg={noBg} noBorder={noBorder} followers={followers} renderButton={ From 808affc78b9f1e0ed07c8cfdc8787f6f1c84d497 Mon Sep 17 00:00:00 2001 From: Paul Frazee Date: Fri, 17 Mar 2023 18:38:16 -0500 Subject: [PATCH 16/24] Switch to the off-spec goodstuff route --- src/lib/constants.ts | 10 ------ src/state/models/feed-view.ts | 60 +++++++++++++++++++++++++++++------ 2 files changed, 51 insertions(+), 19 deletions(-) diff --git a/src/lib/constants.ts b/src/lib/constants.ts index ffc1aaed..0cde9b01 100644 --- a/src/lib/constants.ts +++ b/src/lib/constants.ts @@ -161,16 +161,6 @@ export function SUGGESTED_FOLLOWS(serviceUrl: string) { } } -export function GOOD_STUFF(serviceUrl: string) { - if (serviceUrl.includes('localhost')) { - return 'alice.test' - } else if (serviceUrl.includes('staging')) { - return 'paul.staging.bsky.dev' - } else { - return 'jay.bsky.social' - } -} - export const POST_IMG_MAX_WIDTH = 2000 export const POST_IMG_MAX_HEIGHT = 2000 export const POST_IMG_MAX_SIZE = 1000000 diff --git a/src/state/models/feed-view.ts b/src/state/models/feed-view.ts index 3d7680fb..cff9680f 100644 --- a/src/state/models/feed-view.ts +++ b/src/state/models/feed-view.ts @@ -16,7 +16,7 @@ import {RootStoreModel} from './root-store' import * as apilib from 'lib/api/index' import {cleanError} from 'lib/strings/errors' import {RichText} from 'lib/strings/rich-text' -import {SUGGESTED_FOLLOWS, GOOD_STUFF} from 'lib/constants' +import {SUGGESTED_FOLLOWS} from 'lib/constants' import { getCombinedCursors, getMultipleAuthorsPosts, @@ -399,6 +399,7 @@ export class FeedModel { params: this.params, e, }) + this.hasMore = false } } finally { this.lock.release() @@ -641,14 +642,13 @@ export class FeedModel { params as GetTimeline.QueryParams, ) } else if (this.feedType === 'goodstuff') { - const res = await this.rootStore.api.app.bsky.feed.getAuthorFeed({ - ...params, - author: GOOD_STUFF(String(this.rootStore.agent.service)), - } as GetAuthorFeed.QueryParams) - res.data.feed = mergePosts([res], {repostsOnly: true}) - res.data.feed.forEach(item => { - delete item.reason - }) + const res = await getGoodStuff( + this.rootStore.session.currentSession?.accessJwt || '', + params as GetTimeline.QueryParams, + ) + res.data.feed = res.data.feed.filter( + item => !item.post.author.viewer?.muted, + ) return res } else { return this.rootStore.api.app.bsky.feed.getAuthorFeed( @@ -657,3 +657,45 @@ export class FeedModel { } } } + +// HACK +// temporary off-spec route to get the good stuff +// -prf +async function getGoodStuff( + accessJwt: string, + params: GetTimeline.QueryParams, +): Promise { + const controller = new AbortController() + const to = setTimeout(() => controller.abort(), 15e3) + + const uri = new URL('https://bsky.social/xrpc/app.bsky.unspecced.getPopular') + let k: keyof GetTimeline.QueryParams + for (k in params) { + if (typeof params[k] !== 'undefined') { + uri.searchParams.set(k, String(params[k])) + } + } + + const res = await fetch(String(uri), { + method: 'get', + headers: { + accept: 'application/json', + authorization: `Bearer ${accessJwt}`, + }, + signal: controller.signal, + }) + + const resHeaders: Record = {} + res.headers.forEach((value: string, key: string) => { + resHeaders[key] = value + }) + let resBody = await res.json() + + clearTimeout(to) + + return { + success: res.status === 200, + headers: resHeaders, + data: resBody, + } +} From a2462498c083496df24a066a638e3af39677bd65 Mon Sep 17 00:00:00 2001 From: Paul Frazee Date: Fri, 17 Mar 2023 18:39:31 -0500 Subject: [PATCH 17/24] 1.8 --- app.json | 2 +- ios/bluesky/Info.plist | 2 +- package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app.json b/app.json index ebf4224b..8d9bc028 100644 --- a/app.json +++ b/app.json @@ -2,7 +2,7 @@ "expo": { "name": "bluesky", "slug": "bluesky", - "version": "1.7.0", + "version": "1.8.0", "orientation": "portrait", "icon": "./assets/icon.png", "userInterfaceStyle": "light", diff --git a/ios/bluesky/Info.plist b/ios/bluesky/Info.plist index dced58dd..e578aa25 100644 --- a/ios/bluesky/Info.plist +++ b/ios/bluesky/Info.plist @@ -21,7 +21,7 @@ CFBundlePackageType $(PRODUCT_BUNDLE_PACKAGE_TYPE) CFBundleShortVersionString - 1.7 + 1.8 CFBundleSignature ???? CFBundleURLTypes diff --git a/package.json b/package.json index 56886861..3c1cd252 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "bsky.app", - "version": "1.7.0", + "version": "1.8.0", "private": true, "scripts": { "postinstall": "patch-package", From 5def9eb238ed51a45a781f6c91520526bb3ae7df Mon Sep 17 00:00:00 2001 From: Paul Frazee Date: Fri, 17 Mar 2023 18:40:26 -0500 Subject: [PATCH 18/24] Fix for dev & staging --- src/state/models/feed-view.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/state/models/feed-view.ts b/src/state/models/feed-view.ts index cff9680f..664d6bd0 100644 --- a/src/state/models/feed-view.ts +++ b/src/state/models/feed-view.ts @@ -646,7 +646,7 @@ export class FeedModel { this.rootStore.session.currentSession?.accessJwt || '', params as GetTimeline.QueryParams, ) - res.data.feed = res.data.feed.filter( + res.data.feed = (res.data.feed || []).filter( item => !item.post.author.viewer?.muted, ) return res From 6578d2bfadaa0aa937a5467973f4c44505634afe Mon Sep 17 00:00:00 2001 From: Paul Frazee Date: Sun, 19 Mar 2023 16:25:42 -0500 Subject: [PATCH 19/24] Swap the tab bar items and rename suggested to what's hot --- src/view/com/util/Pager.tsx | 10 ++-------- src/view/com/util/TabBar.tsx | 22 ++++++++++++---------- src/view/screens/Home.tsx | 23 +++++++++++++---------- 3 files changed, 27 insertions(+), 28 deletions(-) diff --git a/src/view/com/util/Pager.tsx b/src/view/com/util/Pager.tsx index 47b786fb..c4f17ce6 100644 --- a/src/view/com/util/Pager.tsx +++ b/src/view/com/util/Pager.tsx @@ -1,19 +1,13 @@ import React from 'react' -import {Animated, StyleSheet, View} from 'react-native' +import {Animated, View} from 'react-native' import PagerView, {PagerViewOnPageSelectedEvent} from 'react-native-pager-view' +import {TabBarProps} from './TabBar' import {useAnimatedValue} from 'lib/hooks/useAnimatedValue' import {s} from 'lib/styles' export type PageSelectedEvent = PagerViewOnPageSelectedEvent const AnimatedPagerView = Animated.createAnimatedComponent(PagerView) -export interface TabBarProps { - selectedPage: number - position: Animated.Value - offset: Animated.Value - onSelect?: (index: number) => void -} - interface Props { tabBarPosition?: 'top' | 'bottom' renderTabBar: (props: TabBarProps) => JSX.Element diff --git a/src/view/com/util/TabBar.tsx b/src/view/com/util/TabBar.tsx index 67c9276c..dd8fdcb5 100644 --- a/src/view/com/util/TabBar.tsx +++ b/src/view/com/util/TabBar.tsx @@ -13,6 +13,17 @@ interface Layout { width: number } +export interface TabBarProps { + selectedPage: number + items: string[] + position: Animated.Value + offset: Animated.Value + indicatorPosition?: 'top' | 'bottom' + indicatorColor?: string + onSelect?: (index: number) => void + onPressSelected?: () => void +} + export function TabBar({ selectedPage, items, @@ -22,16 +33,7 @@ export function TabBar({ indicatorColor, onSelect, onPressSelected, -}: { - selectedPage: number - items: string[] - position: Animated.Value - offset: Animated.Value - indicatorPosition?: 'top' | 'bottom' - indicatorColor?: string - onSelect?: (index: number) => void - onPressSelected?: () => void -}) { +}: TabBarProps) { const pal = usePalette('default') const [itemLayouts, setItemLayouts] = useState( items.map(() => ({x: 0, width: 0})), diff --git a/src/view/screens/Home.tsx b/src/view/screens/Home.tsx index 5250f115..1c3ee091 100644 --- a/src/view/screens/Home.tsx +++ b/src/view/screens/Home.tsx @@ -14,8 +14,8 @@ import {FeedModel} from 'state/models/feed-view' import {withAuthRequired} from 'view/com/auth/withAuthRequired' import {Feed} from '../com/posts/Feed' import {LoadLatestBtn} from '../com/util/LoadLatestBtn' -import {TabBar} from 'view/com/util/TabBar' -import {Pager, PageSelectedEvent, TabBarProps} from 'view/com/util/Pager' +import {TabBar, TabBarProps} from 'view/com/util/TabBar' +import {Pager, PageSelectedEvent} from 'view/com/util/Pager' import {FAB} from '../com/util/FAB' import {useStores} from 'state/index' import {usePalette} from 'lib/hooks/usePalette' @@ -62,21 +62,24 @@ export const HomeScreen = withAuthRequired((_opts: Props) => { store.emitScreenSoftReset() }, [store]) - const renderTabBar = React.useCallback((props: TabBarProps) => { - return - }, []) + const renderTabBar = React.useCallback( + (props: TabBarProps) => { + return + }, + [onPressSelected], + ) return ( - + ) }) @@ -112,8 +115,8 @@ const FloatingTabBar = observer((props: TabBarProps) => { @@ -232,7 +235,7 @@ const styles = StyleSheet.create({ bottom: 0, flexDirection: 'row', alignItems: 'center', - paddingHorizontal: 8, + paddingHorizontal: 10, borderTopWidth: 1, paddingTop: 0, paddingBottom: 30, From 7a754850bc71a46f4b198e942b7427536b253587 Mon Sep 17 00:00:00 2001 From: Paul Frazee Date: Sun, 19 Mar 2023 17:30:58 -0500 Subject: [PATCH 20/24] Go to whats-hot by default if you have no follows --- src/state/models/me.ts | 1 + src/state/models/my-follows.ts | 6 ++ src/state/models/session.ts | 10 +- src/view/com/posts/Feed.tsx | 68 ++----------- src/view/com/posts/FollowingEmptyState.tsx | 81 ++++++++++++++++ src/view/com/util/Pager.tsx | 15 ++- src/view/screens/Home.tsx | 105 +++++++++++++-------- 7 files changed, 177 insertions(+), 109 deletions(-) create mode 100644 src/view/com/posts/FollowingEmptyState.tsx diff --git a/src/state/models/me.ts b/src/state/models/me.ts index 077c6559..192e8f19 100644 --- a/src/state/models/me.ts +++ b/src/state/models/me.ts @@ -33,6 +33,7 @@ export class MeModel { clear() { this.mainFeed.clear() this.notifications.clear() + this.follows.clear() this.did = '' this.handle = '' this.displayName = '' diff --git a/src/state/models/my-follows.ts b/src/state/models/my-follows.ts index 732c2fe7..bf1bf960 100644 --- a/src/state/models/my-follows.ts +++ b/src/state/models/my-follows.ts @@ -35,6 +35,12 @@ export class MyFollowsModel { // public api // = + clear() { + this.followDidToRecordMap = {} + this.lastSync = 0 + this.myDid = undefined + } + fetchIfNeeded = bundleAsync(async () => { if ( this.myDid !== this.rootStore.me.did || diff --git a/src/state/models/session.ts b/src/state/models/session.ts index efd7a5fa..e131b2b2 100644 --- a/src/state/models/session.ts +++ b/src/state/models/session.ts @@ -154,13 +154,13 @@ export class SessionModel { /** * Sets the active session */ - setActiveSession(agent: AtpAgent, did: string) { + async setActiveSession(agent: AtpAgent, did: string) { this._log('SessionModel:setActiveSession') this.data = { service: agent.service.toString(), did, } - this.rootStore.handleSessionChange(agent) + await this.rootStore.handleSessionChange(agent) } /** @@ -304,7 +304,7 @@ export class SessionModel { return false } - this.setActiveSession(agent, account.did) + await this.setActiveSession(agent, account.did) return true } @@ -337,7 +337,7 @@ export class SessionModel { }, ) - this.setActiveSession(agent, did) + await this.setActiveSession(agent, did) this._log('SessionModel:login succeeded') } @@ -376,7 +376,7 @@ export class SessionModel { }, ) - this.setActiveSession(agent, did) + await this.setActiveSession(agent, did) this._log('SessionModel:createAccount succeeded') } diff --git a/src/view/com/posts/Feed.tsx b/src/view/com/posts/Feed.tsx index d23455b5..c910b70e 100644 --- a/src/view/com/posts/Feed.tsx +++ b/src/view/com/posts/Feed.tsx @@ -7,23 +7,15 @@ import { StyleSheet, ViewStyle, } from 'react-native' -import {useNavigation} from '@react-navigation/native' -import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' -import {FontAwesomeIconStyle} from '@fortawesome/react-native-fontawesome' import {CenteredView, FlatList} from '../util/Views' import {PostFeedLoadingPlaceholder} from '../util/LoadingPlaceholder' import {ViewHeader} from '../util/ViewHeader' -import {Text} from '../util/text/Text' import {ErrorMessage} from '../util/error/ErrorMessage' -import {Button} from '../util/forms/Button' import {FeedModel} from 'state/models/feed-view' import {FeedSlice} from './FeedSlice' import {OnScrollCb} from 'lib/hooks/useOnMainScroll' import {s} from 'lib/styles' import {useAnalytics} from 'lib/analytics' -import {usePalette} from 'lib/hooks/usePalette' -import {MagnifyingGlassIcon} from 'lib/icons' -import {NavigationProp} from 'lib/routes/types' const HEADER_ITEM = {_reactKey: '__header__'} const EMPTY_FEED_ITEM = {_reactKey: '__empty__'} @@ -36,6 +28,7 @@ export const Feed = observer(function Feed({ scrollElRef, onPressTryAgain, onScroll, + renderEmptyState, testID, headerOffset = 0, }: { @@ -45,14 +38,12 @@ export const Feed = observer(function Feed({ scrollElRef?: MutableRefObject | null> onPressTryAgain?: () => void onScroll?: OnScrollCb + renderEmptyState?: () => JSX.Element testID?: string headerOffset?: number }) { - const pal = usePalette('default') - const palInverted = usePalette('inverted') const {track} = useAnalytics() const [isRefreshing, setIsRefreshing] = React.useState(false) - const navigation = useNavigation() const data = React.useMemo(() => { let feedItems: any[] = [HEADER_ITEM] @@ -82,6 +73,7 @@ export const Feed = observer(function Feed({ } setIsRefreshing(false) }, [feed, track, setIsRefreshing]) + const onEndReached = React.useCallback(async () => { track('Feed:onEndReached') try { @@ -97,37 +89,10 @@ export const Feed = observer(function Feed({ const renderItem = React.useCallback( ({item}: {item: any}) => { if (item === EMPTY_FEED_ITEM) { - return ( - - - - - - Your feed is empty! You should follow some accounts to fix this. - - - - ) + if (renderEmptyState) { + return renderEmptyState() + } + return } else if (item === ERROR_FEED_ITEM) { return ( }, - [feed, onPressTryAgain, showPostFollowBtn, pal, palInverted, navigation], + [feed, onPressTryAgain, showPostFollowBtn, renderEmptyState], ) const FeedFooter = React.useCallback( @@ -187,21 +152,4 @@ export const Feed = observer(function Feed({ const styles = StyleSheet.create({ feedFooter: {paddingTop: 20}, - emptyContainer: { - paddingVertical: 40, - paddingHorizontal: 30, - }, - emptyIconContainer: { - marginBottom: 16, - }, - emptyIcon: { - marginLeft: 'auto', - marginRight: 'auto', - }, - emptyBtn: { - marginTop: 20, - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'space-between', - }, }) diff --git a/src/view/com/posts/FollowingEmptyState.tsx b/src/view/com/posts/FollowingEmptyState.tsx new file mode 100644 index 00000000..acd035f2 --- /dev/null +++ b/src/view/com/posts/FollowingEmptyState.tsx @@ -0,0 +1,81 @@ +import React from 'react' +import {StyleSheet, View} from 'react-native' +import {useNavigation} from '@react-navigation/native' +import { + FontAwesomeIcon, + FontAwesomeIconStyle, +} from '@fortawesome/react-native-fontawesome' +import {Text} from '../util/text/Text' +import {Button} from '../util/forms/Button' +import {MagnifyingGlassIcon} from 'lib/icons' +import {NavigationProp} from 'lib/routes/types' +import {usePalette} from 'lib/hooks/usePalette' +import {s} from 'lib/styles' + +export function FollowingEmptyState() { + const pal = usePalette('default') + const palInverted = usePalette('inverted') + const navigation = useNavigation() + + const onPressFindAccounts = React.useCallback(() => { + navigation.navigate('SearchTab') + navigation.popToTop() + }, [navigation]) + + return ( + + + + + + Your following feed is empty! Find some accounts to follow to fix this. + + + + ) +} +const styles = StyleSheet.create({ + emptyContainer: { + // flex: 1, + height: '100%', + paddingVertical: 40, + paddingHorizontal: 30, + }, + emptyIconContainer: { + marginBottom: 16, + }, + emptyIcon: { + marginLeft: 'auto', + marginRight: 'auto', + }, + emptyBtn: { + marginVertical: 20, + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'space-between', + paddingVertical: 18, + paddingHorizontal: 24, + borderRadius: 30, + }, + + feedsTip: { + position: 'absolute', + left: 22, + }, + feedsTipArrow: { + marginLeft: 32, + marginTop: 8, + }, +}) diff --git a/src/view/com/util/Pager.tsx b/src/view/com/util/Pager.tsx index c4f17ce6..d71cb7f7 100644 --- a/src/view/com/util/Pager.tsx +++ b/src/view/com/util/Pager.tsx @@ -1,21 +1,30 @@ import React from 'react' import {Animated, View} from 'react-native' import PagerView, {PagerViewOnPageSelectedEvent} from 'react-native-pager-view' -import {TabBarProps} from './TabBar' import {useAnimatedValue} from 'lib/hooks/useAnimatedValue' import {s} from 'lib/styles' export type PageSelectedEvent = PagerViewOnPageSelectedEvent const AnimatedPagerView = Animated.createAnimatedComponent(PagerView) +export interface RenderTabBarFnProps { + selectedPage: number + position: Animated.Value + offset: Animated.Value + onSelect?: (index: number) => void +} +export type RenderTabBarFn = (props: RenderTabBarFnProps) => JSX.Element + interface Props { tabBarPosition?: 'top' | 'bottom' - renderTabBar: (props: TabBarProps) => JSX.Element + initialPage?: number + renderTabBar: RenderTabBarFn onPageSelected?: (e: PageSelectedEvent) => void } export const Pager = ({ children, tabBarPosition = 'top', + initialPage = 0, renderTabBar, onPageSelected, }: React.PropsWithChildren) => { @@ -51,7 +60,7 @@ export const Pager = ({ { }, [store]) const renderTabBar = React.useCallback( - (props: TabBarProps) => { + (props: RenderTabBarFnProps) => { return }, [onPressSelected], ) + const renderFollowingEmptyState = React.useCallback(() => { + return + }, []) + + const initialPage = store.me.follows.isEmpty ? 1 : 0 return ( + tabBarPosition="bottom" + initialPage={initialPage}> ) }) -const FloatingTabBar = observer((props: TabBarProps) => { - const store = useStores() - const safeAreaInsets = useSafeAreaInsets() - const pal = usePalette('default') - const interp = useAnimatedValue(0) +const FloatingTabBar = observer( + (props: RenderTabBarFnProps & {onPressSelected: () => void}) => { + const store = useStores() + const safeAreaInsets = useSafeAreaInsets() + const pal = usePalette('default') + const interp = useAnimatedValue(0) - const pad = React.useMemo( - () => ({ - paddingBottom: clamp(safeAreaInsets.bottom, 15, 20), - }), - [safeAreaInsets], - ) + const pad = React.useMemo( + () => ({ + paddingBottom: clamp(safeAreaInsets.bottom, 15, 20), + }), + [safeAreaInsets], + ) - React.useEffect(() => { - Animated.timing(interp, { - toValue: store.shell.minimalShellMode ? 0 : 1, - duration: 100, - useNativeDriver: true, - isInteraction: false, - }).start() - }, [interp, store.shell.minimalShellMode]) - const transform = { - transform: [ - {translateY: Animated.multiply(interp, -1 * BOTTOM_BAR_HEIGHT)}, - ], - } + React.useEffect(() => { + Animated.timing(interp, { + toValue: store.shell.minimalShellMode ? 0 : 1, + duration: 100, + useNativeDriver: true, + isInteraction: false, + }).start() + }, [interp, store.shell.minimalShellMode]) + const transform = { + transform: [ + {translateY: Animated.multiply(interp, -1 * BOTTOM_BAR_HEIGHT)}, + ], + } - return ( - - - - ) -}) + return ( + + + + ) + }, +) const FeedPage = observer( - ({isPageFocused, feed}: {feed: FeedModel; isPageFocused: boolean}) => { + ({ + isPageFocused, + feed, + renderEmptyState, + }: { + feed: FeedModel + isPageFocused: boolean + renderEmptyState?: () => JSX.Element + }) => { const store = useStores() const onMainScroll = useOnMainScroll(store) const {screen, track} = useAnalytics() @@ -213,6 +235,7 @@ const FeedPage = observer( showPostFollowBtn onPressTryAgain={onPressTryAgain} onScroll={onMainScroll} + renderEmptyState={renderEmptyState} /> {feed.hasNewLatest && !feed.isRefreshing && ( From 23e8484986acc2926d795d0406dd3c820ec83a6c Mon Sep 17 00:00:00 2001 From: Paul Frazee Date: Sun, 19 Mar 2023 18:11:33 -0500 Subject: [PATCH 21/24] Implement pager and tabbar for desktop web --- ios/Podfile.lock | 48 ++++++------ src/lib/styles.ts | 1 + src/view/com/util/TabBar.tsx | 75 ++++++++++++------ src/view/com/util/{ => pager}/Pager.tsx | 4 +- src/view/com/util/pager/Pager.web.tsx | 65 ++++++++++++++++ src/view/screens/Home.tsx | 94 +++-------------------- src/view/screens/home/FeedsTabBar.tsx | 72 +++++++++++++++++ src/view/screens/home/FeedsTabBar.web.tsx | 22 ++++++ 8 files changed, 246 insertions(+), 135 deletions(-) rename src/view/com/util/{ => pager}/Pager.tsx (96%) create mode 100644 src/view/com/util/pager/Pager.web.tsx create mode 100644 src/view/screens/home/FeedsTabBar.tsx create mode 100644 src/view/screens/home/FeedsTabBar.web.tsx diff --git a/ios/Podfile.lock b/ios/Podfile.lock index a27db8a6..12f262dd 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -19,10 +19,10 @@ PODS: - EXJSONUtils (0.5.1) - EXManifests (0.5.2): - EXJSONUtils - - EXMediaLibrary (15.2.2): + - EXMediaLibrary (15.2.3): - ExpoModulesCore - React-Core - - Expo (48.0.6): + - Expo (48.0.7): - ExpoModulesCore - expo-dev-client (2.1.5): - EXManifests @@ -100,7 +100,7 @@ PODS: - ExpoModulesCore - ExpoKeepAwake (12.0.1): - ExpoModulesCore - - ExpoModulesCore (1.2.4): + - ExpoModulesCore (1.2.5): - React-Core - React-RCTAppDelegate - ReactCommon/turbomodule/core @@ -384,11 +384,11 @@ PODS: - glog - react-native-blur (4.3.0): - React-Core - - react-native-cameraroll (5.2.4): + - react-native-cameraroll (5.3.1): - React-Core - react-native-image-resizer (3.0.5): - React-Core - - react-native-pager-view (6.1.4): + - react-native-pager-view (6.1.2): - React-Core - react-native-paste-input (0.6.2): - React-Core @@ -403,7 +403,7 @@ PODS: - React-Core - react-native-version-number (0.3.6): - React - - react-native-webview (11.26.1): + - react-native-webview (11.26.0): - React-Core - React-perflogger (0.71.3) - React-RCTActionSheet (0.71.3): @@ -491,9 +491,9 @@ PODS: - React-perflogger (= 0.71.3) - rn-fetch-blob (0.12.0): - React-Core - - RNBackgroundFetch (4.1.8): + - RNBackgroundFetch (4.1.9): - React-Core - - RNCAsyncStorage (1.17.11): + - RNCAsyncStorage (1.17.12): - React-Core - RNCClipboard (1.11.2): - React-Core @@ -516,10 +516,10 @@ PODS: - TOCropViewController - RNInAppBrowser (3.7.0): - React-Core - - RNNotifee (7.5.0): + - RNNotifee (7.6.1): - React-Core - - RNNotifee/NotifeeCore (= 7.5.0) - - RNNotifee/NotifeeCore (7.5.0): + - RNNotifee/NotifeeCore (= 7.6.1) + - RNNotifee/NotifeeCore (7.6.1): - React-Core - RNReactNativeHapticFeedback (1.14.0): - React-Core @@ -553,7 +553,7 @@ PODS: - RNScreens (3.20.0): - React-Core - React-RCTImage - - RNSVG (13.8.0): + - RNSVG (13.4.0): - React-Core - SDWebImage (5.11.1): - SDWebImage/Core (= 5.11.1) @@ -561,7 +561,7 @@ PODS: - SDWebImageWebPCoder (0.8.5): - libwebp (~> 1.0) - SDWebImage/Core (~> 5.10) - - segment-analytics-react-native (2.13.1): + - segment-analytics-react-native (2.13.4): - React-Core - sovran-react-native - sovran-react-native (0.4.5): @@ -835,15 +835,15 @@ SPEC CHECKSUMS: EXImageLoader: fd053169a8ee932dd83bf1fe5487a50c26d27c2b EXJSONUtils: 48b1e764ac35160e6f54d21ab60d7d9501f3e473 EXManifests: 500666d48e8dd7ca5a482c9e729e4a7a6c34081b - EXMediaLibrary: 792fe9b828b5bfa2c5a8b629730f175af2938285 - Expo: 04ba1ddde0be07aff4306ae636a1804810679145 + EXMediaLibrary: 587cd8aad27a6fc8d7c38b950bc75bc1845a7480 + Expo: 707f9b0039eacc6a1dce90c08c9e37b9c417bba2 expo-dev-client: 7c1ef51516853465f4d448c14ddf365167d20361 expo-dev-launcher: 90de99d9e5d1a883d81355ca10e87c2f3c81d46e expo-dev-menu: d4369e74d8d21a0ccdee35f7c732e7118b0fee16 expo-dev-menu-interface: 6c82ae323c4b8724dead4763ce3ff24a2108bdb1 ExpoImagePicker: 270dea232b3a072d981dd564e2cafc63a864edb1 ExpoKeepAwake: 69f5f627670d62318410392d03e0b5db0f85759a - ExpoModulesCore: 1667335d4f4c9b7801990930e6f0eea42c916a21 + ExpoModulesCore: 397fc99e9d6c9dcc010f36d5802097c17b90424c EXSplashScreen: cd7fb052dff5ba8311d5c2455ecbebffe1b7a8ca EXUpdatesInterface: dd699d1930e28639dcbd70a402caea98e86364ca FBLazyVector: 60195509584153283780abdac5569feffb8f08cc @@ -868,14 +868,14 @@ SPEC CHECKSUMS: React-jsinspector: 9f7c9137605e72ca0343db4cea88006cb94856dd React-logger: 957e5dc96d9dbffc6e0f15e0ee4d2b42829ff207 react-native-blur: 50c9feabacbc5f49b61337ebc32192c6be7ec3c3 - react-native-cameraroll: cb752fda6d5268f1646b4390bd5be1f27706b9a0 + react-native-cameraroll: f3050460fe1708378698c16686bfaa5f34099be2 react-native-image-resizer: 00ceb0e05586c7aadf061eea676957a6c2ec60fa - react-native-pager-view: b58cb9e9f42f64e50cab3040815772c1d119a2e2 + react-native-pager-view: 54bed894cecebe28cede54c01038d9d1e122de43 react-native-paste-input: 3392800944a47c00dddbff23c31c281482209679 react-native-safe-area-context: 39c2d8be3328df5d437ac1700f4f3a4f75716acc react-native-splash-screen: 4312f786b13a81b5169ef346d76d33bc0c6dc457 react-native-version-number: b415bbec6a13f2df62bf978e85bc0d699462f37f - react-native-webview: 9f111dfbcfc826084d6c507f569e5e03342ee1c1 + react-native-webview: 994b9f8fbb504d6314dc40d83f94f27c6831b3bf React-perflogger: af8a3d31546077f42d729b949925cc4549f14def React-RCTActionSheet: 57cc5adfefbaaf0aae2cf7e10bccd746f2903673 React-RCTAnimation: 11c61e94da700c4dc915cf134513764d87fc5e2b @@ -890,22 +890,22 @@ SPEC CHECKSUMS: React-runtimeexecutor: 7bf0dafc7b727d93c8cb94eb00a9d3753c446c3e ReactCommon: 6f65ea5b7d84deb9e386f670dd11ce499ded7b40 rn-fetch-blob: f065bb7ab7fb48dd002629f8bdcb0336602d3cba - RNBackgroundFetch: 8e16176ff415daac743a6eb57afc8e9e14dbe623 - RNCAsyncStorage: 8616bd5a58af409453ea4e1b246521bb76578d60 + RNBackgroundFetch: 642777e4e76435773c149d565a043d66f1781237 + RNCAsyncStorage: 09fc8595e6d6f6d5abf16b23a56b257d9c6b7c5b RNCClipboard: 3f0451a8100393908bea5c5c5b16f96d45f30bfc RNFastImage: 5c9c9fed9c076e521b3f509fe79e790418a544e8 RNFS: 4ac0f0ea233904cb798630b3c077808c06931688 RNGestureHandler: 071d7a9ad81e8b83fe7663b303d132406a7d8f39 RNImageCropPicker: 648356d68fbf9911a1016b3e3723885d28373eda RNInAppBrowser: e36d6935517101ccba0e875bac8ad7b0cb655364 - RNNotifee: 053c0ace9c73634709a0214fd9c436a5777a562f + RNNotifee: bdc064c29f4d558046f51f0c3ae02bab4fd3cd85 RNReactNativeHapticFeedback: 1e3efeca9628ff9876ee7cdd9edec1b336913f8c RNReanimated: cc5e3aa479cb9170bcccf8204291a6950a3be128 RNScreens: 218801c16a2782546d30bd2026bb625c0302d70f - RNSVG: c1e76b81c76cdcd34b4e1188852892dc280eb902 + RNSVG: 07dbd870b0dcdecc99b3a202fa37c8ca163caec2 SDWebImage: a7f831e1a65eb5e285e3fb046a23fcfbf08e696d SDWebImageWebPCoder: 908b83b6adda48effe7667cd2b7f78c897e5111d - segment-analytics-react-native: f962dff3a084655a29f9403b8c139c75a3362524 + segment-analytics-react-native: cc12d9422f7ce863ee57c1b650ab48eec4b6d5bd sovran-react-native: fd3dc8f1a4b14acdc4ad25fc6b4ac4f52a2a2a15 Swime: d7b2c277503b6cea317774aedc2dce05613f8b0b TOCropViewController: edfd4f25713d56905ad1e0b9f5be3fbe0f59c863 diff --git a/src/lib/styles.ts b/src/lib/styles.ts index 5d7f7f82..aa255b21 100644 --- a/src/lib/styles.ts +++ b/src/lib/styles.ts @@ -70,6 +70,7 @@ export const s = StyleSheet.create({ borderRight1: {borderRightWidth: 1}, borderBottom1: {borderBottomWidth: 1}, borderLeft1: {borderLeftWidth: 1}, + hidden: {display: 'none'}, // font weights fw600: {fontWeight: '600'}, diff --git a/src/view/com/util/TabBar.tsx b/src/view/com/util/TabBar.tsx index dd8fdcb5..4b67b8a8 100644 --- a/src/view/com/util/TabBar.tsx +++ b/src/view/com/util/TabBar.tsx @@ -7,6 +7,7 @@ import { } from 'react-native' import {Text} from './text/Text' import {usePalette} from 'lib/hooks/usePalette' +import {isDesktopWeb} from 'platform/detection' interface Layout { x: number @@ -46,8 +47,9 @@ export function TabBar({ const indicatorStyle = { backgroundColor: indicatorColor || pal.colors.link, - bottom: indicatorPosition === 'bottom' ? -1 : undefined, - top: indicatorPosition === 'top' ? -1 : undefined, + bottom: + indicatorPosition === 'bottom' ? (isDesktopWeb ? 0 : -1) : undefined, + top: indicatorPosition === 'top' ? (isDesktopWeb ? 0 : -1) : undefined, transform: [ { translateX: panX.interpolate({ @@ -112,26 +114,49 @@ export function TabBar({ ) } -const styles = StyleSheet.create({ - outer: { - flexDirection: 'row', - paddingHorizontal: 14, - }, - itemTop: { - paddingTop: 10, - paddingBottom: 10, - marginRight: 24, - }, - itemBottom: { - paddingTop: 8, - paddingBottom: 12, - marginRight: 24, - }, - indicator: { - position: 'absolute', - left: 0, - width: 1, - height: 3, - borderRadius: 4, - }, -}) +const styles = isDesktopWeb + ? StyleSheet.create({ + outer: { + flexDirection: 'row', + paddingHorizontal: 18, + }, + itemTop: { + paddingTop: 16, + paddingBottom: 14, + marginRight: 24, + }, + itemBottom: { + paddingTop: 14, + paddingBottom: 16, + marginRight: 24, + }, + indicator: { + position: 'absolute', + left: 0, + width: 1, + height: 3, + }, + }) + : StyleSheet.create({ + outer: { + flexDirection: 'row', + paddingHorizontal: 14, + }, + itemTop: { + paddingTop: 10, + paddingBottom: 10, + marginRight: 24, + }, + itemBottom: { + paddingTop: 8, + paddingBottom: 12, + marginRight: 24, + }, + indicator: { + position: 'absolute', + left: 0, + width: 1, + height: 3, + borderRadius: 4, + }, + }) diff --git a/src/view/com/util/Pager.tsx b/src/view/com/util/pager/Pager.tsx similarity index 96% rename from src/view/com/util/Pager.tsx rename to src/view/com/util/pager/Pager.tsx index d71cb7f7..416828a2 100644 --- a/src/view/com/util/Pager.tsx +++ b/src/view/com/util/pager/Pager.tsx @@ -19,7 +19,7 @@ interface Props { tabBarPosition?: 'top' | 'bottom' initialPage?: number renderTabBar: RenderTabBarFn - onPageSelected?: (e: PageSelectedEvent) => void + onPageSelected?: (index: number) => void } export const Pager = ({ children, @@ -36,7 +36,7 @@ export const Pager = ({ const onPageSelectedInner = React.useCallback( (e: PageSelectedEvent) => { setSelectedPage(e.nativeEvent.position) - onPageSelected?.(e) + onPageSelected?.(e.nativeEvent.position) }, [setSelectedPage, onPageSelected], ) diff --git a/src/view/com/util/pager/Pager.web.tsx b/src/view/com/util/pager/Pager.web.tsx new file mode 100644 index 00000000..d50100de --- /dev/null +++ b/src/view/com/util/pager/Pager.web.tsx @@ -0,0 +1,65 @@ +import React from 'react' +import {Animated, View} from 'react-native' +import {useAnimatedValue} from 'lib/hooks/useAnimatedValue' +import {s} from 'lib/styles' + +export interface RenderTabBarFnProps { + selectedPage: number + position: Animated.Value + offset: Animated.Value + onSelect?: (index: number) => void +} +export type RenderTabBarFn = (props: RenderTabBarFnProps) => JSX.Element + +interface Props { + tabBarPosition?: 'top' | 'bottom' + initialPage?: number + renderTabBar: RenderTabBarFn + onPageSelected?: (index: number) => void +} +export const Pager = ({ + children, + tabBarPosition = 'top', + initialPage = 0, + renderTabBar, + onPageSelected, +}: React.PropsWithChildren) => { + const [selectedPage, setSelectedPage] = React.useState(initialPage) + const position = useAnimatedValue(0) + const offset = useAnimatedValue(0) + + const onTabBarSelect = React.useCallback( + (index: number) => { + setSelectedPage(index) + onPageSelected?.(index) + Animated.timing(position, { + toValue: index, + duration: 200, + useNativeDriver: true, + }).start() + }, + [setSelectedPage, onPageSelected, position], + ) + + return ( + + {tabBarPosition === 'top' && + renderTabBar({ + selectedPage, + position, + offset, + onSelect: onTabBarSelect, + })} + {children.map((child, i) => ( + {child} + ))} + {tabBarPosition === 'bottom' && + renderTabBar({ + selectedPage, + position, + offset, + onSelect: onTabBarSelect, + })} + + ) +} diff --git a/src/view/screens/Home.tsx b/src/view/screens/Home.tsx index 82217444..4950bc0f 100644 --- a/src/view/screens/Home.tsx +++ b/src/view/screens/Home.tsx @@ -1,11 +1,5 @@ import React from 'react' -import { - Animated, - FlatList, - StyleSheet, - View, - useWindowDimensions, -} from 'react-native' +import {FlatList, View, useWindowDimensions} from 'react-native' import {useFocusEffect, useIsFocused} from '@react-navigation/native' import {observer} from 'mobx-react-lite' import useAppState from 'react-native-appstate-hook' @@ -15,25 +9,17 @@ import {withAuthRequired} from 'view/com/auth/withAuthRequired' import {Feed} from '../com/posts/Feed' import {FollowingEmptyState} from 'view/com/posts/FollowingEmptyState' import {LoadLatestBtn} from '../com/util/LoadLatestBtn' -import {TabBar} from 'view/com/util/TabBar' -import { - Pager, - PageSelectedEvent, - RenderTabBarFnProps, -} from 'view/com/util/Pager' +import {FeedsTabBar} from './home/FeedsTabBar' +import {Pager, RenderTabBarFnProps} from 'view/com/util/pager/Pager' import {FAB} from '../com/util/FAB' import {useStores} from 'state/index' -import {usePalette} from 'lib/hooks/usePalette' import {s} from 'lib/styles' import {useOnMainScroll} from 'lib/hooks/useOnMainScroll' -import {useSafeAreaInsets} from 'react-native-safe-area-context' -import {useAnimatedValue} from 'lib/hooks/useAnimatedValue' import {useAnalytics} from 'lib/analytics' import {ComposeIcon2} from 'lib/icons' -import {clamp} from 'lodash' +import {isDesktopWeb} from 'platform/detection' const TAB_BAR_HEIGHT = 82 -const BOTTOM_BAR_HEIGHT = 48 type Props = NativeStackScreenProps export const HomeScreen = withAuthRequired((_opts: Props) => { @@ -56,9 +42,9 @@ export const HomeScreen = withAuthRequired((_opts: Props) => { ) const onPageSelected = React.useCallback( - (e: PageSelectedEvent) => { - setSelectedPage(e.nativeEvent.position) - store.shell.setIsDrawerSwipeDisabled(e.nativeEvent.position > 0) + (index: number) => { + setSelectedPage(index) + store.shell.setIsDrawerSwipeDisabled(index > 0) }, [store], ) @@ -69,7 +55,7 @@ export const HomeScreen = withAuthRequired((_opts: Props) => { const renderTabBar = React.useCallback( (props: RenderTabBarFnProps) => { - return + return }, [onPressSelected], ) @@ -83,7 +69,7 @@ export const HomeScreen = withAuthRequired((_opts: Props) => { { ) }) -const FloatingTabBar = observer( - (props: RenderTabBarFnProps & {onPressSelected: () => void}) => { - const store = useStores() - const safeAreaInsets = useSafeAreaInsets() - const pal = usePalette('default') - const interp = useAnimatedValue(0) - - const pad = React.useMemo( - () => ({ - paddingBottom: clamp(safeAreaInsets.bottom, 15, 20), - }), - [safeAreaInsets], - ) - - React.useEffect(() => { - Animated.timing(interp, { - toValue: store.shell.minimalShellMode ? 0 : 1, - duration: 100, - useNativeDriver: true, - isInteraction: false, - }).start() - }, [interp, store.shell.minimalShellMode]) - const transform = { - transform: [ - {translateY: Animated.multiply(interp, -1 * BOTTOM_BAR_HEIGHT)}, - ], - } - - return ( - - - - ) - }, -) - const FeedPage = observer( ({ isPageFocused, @@ -158,7 +102,7 @@ const FeedPage = observer( const isScreenFocused = useIsFocused() const winDim = useWindowDimensions() const containerStyle = React.useMemo( - () => ({height: winDim.height - TAB_BAR_HEIGHT}), + () => ({height: winDim.height - (isDesktopWeb ? 0 : TAB_BAR_HEIGHT)}), [winDim], ) @@ -249,21 +193,3 @@ const FeedPage = observer( ) }, ) - -const styles = StyleSheet.create({ - tabBar: { - position: 'absolute', - left: 0, - right: 0, - bottom: 0, - flexDirection: 'row', - alignItems: 'center', - paddingHorizontal: 10, - borderTopWidth: 1, - paddingTop: 0, - paddingBottom: 30, - }, - tabBarAvi: { - marginRight: 4, - }, -}) diff --git a/src/view/screens/home/FeedsTabBar.tsx b/src/view/screens/home/FeedsTabBar.tsx new file mode 100644 index 00000000..d3403410 --- /dev/null +++ b/src/view/screens/home/FeedsTabBar.tsx @@ -0,0 +1,72 @@ +import React from 'react' +import {Animated, StyleSheet} from 'react-native' +import {observer} from 'mobx-react-lite' +import {TabBar} from 'view/com/util/TabBar' +import {RenderTabBarFnProps} from 'view/com/util/pager/Pager' +import {useStores} from 'state/index' +import {usePalette} from 'lib/hooks/usePalette' +import {useSafeAreaInsets} from 'react-native-safe-area-context' +import {useAnimatedValue} from 'lib/hooks/useAnimatedValue' +import {clamp} from 'lodash' + +const BOTTOM_BAR_HEIGHT = 48 + +export const FeedsTabBar = observer( + (props: RenderTabBarFnProps & {onPressSelected: () => void}) => { + const store = useStores() + const safeAreaInsets = useSafeAreaInsets() + const pal = usePalette('default') + const interp = useAnimatedValue(0) + + const pad = React.useMemo( + () => ({ + paddingBottom: clamp(safeAreaInsets.bottom, 15, 20), + }), + [safeAreaInsets], + ) + + React.useEffect(() => { + Animated.timing(interp, { + toValue: store.shell.minimalShellMode ? 0 : 1, + duration: 100, + useNativeDriver: true, + isInteraction: false, + }).start() + }, [interp, store.shell.minimalShellMode]) + const transform = { + transform: [ + {translateY: Animated.multiply(interp, -1 * BOTTOM_BAR_HEIGHT)}, + ], + } + + return ( + + + + ) + }, +) + +const styles = StyleSheet.create({ + tabBar: { + position: 'absolute', + left: 0, + right: 0, + bottom: 0, + flexDirection: 'row', + alignItems: 'center', + paddingHorizontal: 10, + borderTopWidth: 1, + paddingTop: 0, + paddingBottom: 30, + }, + tabBarAvi: { + marginRight: 4, + }, +}) diff --git a/src/view/screens/home/FeedsTabBar.web.tsx b/src/view/screens/home/FeedsTabBar.web.tsx new file mode 100644 index 00000000..59ea4298 --- /dev/null +++ b/src/view/screens/home/FeedsTabBar.web.tsx @@ -0,0 +1,22 @@ +import React from 'react' +import {observer} from 'mobx-react-lite' +import {TabBar} from 'view/com/util/TabBar' +import {CenteredView} from 'view/com/util/Views' +import {RenderTabBarFnProps} from 'view/com/util/pager/Pager' +import {usePalette} from 'lib/hooks/usePalette' + +export const FeedsTabBar = observer( + (props: RenderTabBarFnProps & {onPressSelected: () => void}) => { + const pal = usePalette('default') + return ( + + + + ) + }, +) From a811c57480afc79f72f0792aa998bb9932c0d607 Mon Sep 17 00:00:00 2001 From: Paul Frazee Date: Sun, 19 Mar 2023 18:11:45 -0500 Subject: [PATCH 22/24] Pin deps to make expo happy --- package.json | 8 +- yarn.lock | 633 +++++++++++++++++++++++++++------------------------ 2 files changed, 341 insertions(+), 300 deletions(-) diff --git a/package.json b/package.json index 3c1cd252..796c7aee 100644 --- a/package.json +++ b/package.json @@ -59,7 +59,7 @@ "expo-camera": "~13.2.1", "expo-dev-client": "~2.1.1", "expo-image-picker": "~14.1.1", - "expo-media-library": "~15.2.1", + "expo-media-library": "~15.2.3", "expo-splash-screen": "~0.18.1", "expo-status-bar": "~1.4.4", "he": "^1.2.0", @@ -93,21 +93,21 @@ "react-native-image-crop-picker": "^0.38.1", "react-native-inappbrowser-reborn": "^3.6.3", "react-native-linear-gradient": "^2.6.2", - "react-native-pager-view": "^6.1.4", + "react-native-pager-view": "6.1.2", "react-native-progress": "bluesky-social/react-native-progress", "react-native-reanimated": "~2.14.4", "react-native-root-siblings": "^4.1.1", "react-native-safe-area-context": "^4.4.1", "react-native-screens": "^3.13.1", "react-native-splash-screen": "^3.3.0", - "react-native-svg": "^13.4.0", + "react-native-svg": "13.4.0", "react-native-url-polyfill": "^1.3.0", "react-native-uuid": "^2.0.1", "react-native-version-number": "^0.3.6", "react-native-web": "^0.18.11", "react-native-web-linear-gradient": "^1.1.2", "react-native-web-webview": "^1.0.2", - "react-native-webview": "^11.26.1", + "react-native-webview": "11.26.0", "react-native-youtube-iframe": "^2.2.2", "rn-fetch-blob": "^0.12.0", "tippy.js": "^6.3.7", diff --git a/yarn.lock b/yarn.lock index 8c1b9152..6d7564be 100644 --- a/yarn.lock +++ b/yarn.lock @@ -208,20 +208,20 @@ integrity sha512-gMuZsmsgxk/ENC3O/fRw5QY8A9/uxQbbCEypnLIiYYc/qVJtEV7ouxC3EllIIwNzMqAQee5tanFabWsUOutS7g== "@babel/core@^7.1.0", "@babel/core@^7.11.1", "@babel/core@^7.11.6", "@babel/core@^7.12.3", "@babel/core@^7.13.16", "@babel/core@^7.14.0", "@babel/core@^7.16.0", "@babel/core@^7.20.0", "@babel/core@^7.7.2", "@babel/core@^7.8.0": - version "7.21.0" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.21.0.tgz#1341aefdcc14ccc7553fcc688dd8986a2daffc13" - integrity sha512-PuxUbxcW6ZYe656yL3EAhpy7qXKq0DmYsrJLpbB8XrsCP9Nm+XCg9XFMb5vIDliPD7+U/+M+QJlH17XOcB7eXA== + version "7.21.3" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.21.3.tgz#cf1c877284a469da5d1ce1d1e53665253fae712e" + integrity sha512-qIJONzoa/qiHghnm0l1n4i/6IIziDpzqc36FBs4pzMhDUraHqponwJLiAKm1hGLP3OSB/TVNz6rMwVGpwxxySw== dependencies: "@ampproject/remapping" "^2.2.0" "@babel/code-frame" "^7.18.6" - "@babel/generator" "^7.21.0" + "@babel/generator" "^7.21.3" "@babel/helper-compilation-targets" "^7.20.7" - "@babel/helper-module-transforms" "^7.21.0" + "@babel/helper-module-transforms" "^7.21.2" "@babel/helpers" "^7.21.0" - "@babel/parser" "^7.21.0" + "@babel/parser" "^7.21.3" "@babel/template" "^7.20.7" - "@babel/traverse" "^7.21.0" - "@babel/types" "^7.21.0" + "@babel/traverse" "^7.21.3" + "@babel/types" "^7.21.3" convert-source-map "^1.7.0" debug "^4.1.0" gensync "^1.0.0-beta.2" @@ -229,20 +229,20 @@ semver "^6.3.0" "@babel/eslint-parser@^7.16.3", "@babel/eslint-parser@^7.18.2": - version "7.19.1" - resolved "https://registry.yarnpkg.com/@babel/eslint-parser/-/eslint-parser-7.19.1.tgz#4f68f6b0825489e00a24b41b6a1ae35414ecd2f4" - integrity sha512-AqNf2QWt1rtu2/1rLswy6CDP7H9Oh3mMhk177Y67Rg8d7RD9WfOLLv8CGn6tisFvS2htm86yIe1yLF6I1UDaGQ== + version "7.21.3" + resolved "https://registry.yarnpkg.com/@babel/eslint-parser/-/eslint-parser-7.21.3.tgz#d79e822050f2de65d7f368a076846e7184234af7" + integrity sha512-kfhmPimwo6k4P8zxNs8+T7yR44q1LdpsZdE1NkCsVlfiuTPRfnGgjaF8Qgug9q9Pou17u6wneYF0lDCZJATMFg== dependencies: "@nicolo-ribaudo/eslint-scope-5-internals" "5.1.1-v1" eslint-visitor-keys "^2.1.0" semver "^6.3.0" -"@babel/generator@^7.20.0", "@babel/generator@^7.21.0", "@babel/generator@^7.21.1", "@babel/generator@^7.7.2": - version "7.21.1" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.21.1.tgz#951cc626057bc0af2c35cd23e9c64d384dea83dd" - integrity sha512-1lT45bAYlQhFn/BHivJs43AiW2rg3/UbLyShGfF3C0KmHvO5fSghWd5kBJy30kpRRucGzXStvnnCFniCR2kXAA== +"@babel/generator@^7.20.0", "@babel/generator@^7.21.3", "@babel/generator@^7.7.2": + version "7.21.3" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.21.3.tgz#232359d0874b392df04045d72ce2fd9bb5045fce" + integrity sha512-QS3iR1GYC/YGUnW7IdggFeN5c1poPUurnGttOV/bZgPGV+izC/D8HnD6DLwod0fsatNyVn1G3EVWMYIF0nHbeA== dependencies: - "@babel/types" "^7.21.0" + "@babel/types" "^7.21.3" "@jridgewell/gen-mapping" "^0.3.2" "@jridgewell/trace-mapping" "^0.3.17" jsesc "^2.5.1" @@ -348,7 +348,7 @@ dependencies: "@babel/types" "^7.18.6" -"@babel/helper-module-transforms@^7.18.6", "@babel/helper-module-transforms@^7.20.11", "@babel/helper-module-transforms@^7.21.0", "@babel/helper-module-transforms@^7.21.2": +"@babel/helper-module-transforms@^7.18.6", "@babel/helper-module-transforms@^7.20.11", "@babel/helper-module-transforms@^7.21.2": version "7.21.2" resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.21.2.tgz#160caafa4978ac8c00ac66636cb0fa37b024e2d2" integrity sha512-79yj2AR4U/Oqq/WOV7Lx6hUjau1Zfo4cI+JLAVYeMV5XIlbOhmjEk5ulbTc9fMpmlojzZHkUUxAiK+UKn+hNQQ== @@ -460,10 +460,10 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.1.0", "@babel/parser@^7.13.16", "@babel/parser@^7.14.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.0", "@babel/parser@^7.20.7", "@babel/parser@^7.21.0", "@babel/parser@^7.21.2": - version "7.21.2" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.21.2.tgz#dacafadfc6d7654c3051a66d6fe55b6cb2f2a0b3" - integrity sha512-URpaIJQwEkEC2T9Kn+Ai6Xe/02iNaVCuT/PtoRz3GPVJVDpPd7mLo+VddTbhCRU9TXqW5mSrQfXZyi8kDKOVpQ== +"@babel/parser@^7.1.0", "@babel/parser@^7.13.16", "@babel/parser@^7.14.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.0", "@babel/parser@^7.20.7", "@babel/parser@^7.21.3": + version "7.21.3" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.21.3.tgz#1d285d67a19162ff9daa358d4cb41d50c06220b3" + integrity sha512-lobG0d7aOfQRXh8AyklEAgZGvA4FShxo6xQbUrrT/cNBPUdIDojlokwJsQyCC/eKia7ifqM0yP+2DRZ4WKw2RQ== "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.18.6": version "7.18.6" @@ -837,9 +837,9 @@ "@babel/template" "^7.20.7" "@babel/plugin-transform-destructuring@^7.0.0", "@babel/plugin-transform-destructuring@^7.20.2": - version "7.20.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.20.7.tgz#8bda578f71620c7de7c93af590154ba331415454" - integrity sha512-Xwg403sRrZb81IVB79ZPqNQME23yhugYVqgTxAhT99h485F4f+GMELFhhOsscDUB7HCswepKeCKLn/GZvUKoBA== + version "7.21.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.21.3.tgz#73b46d0fd11cd6ef57dea8a381b1215f4959d401" + integrity sha512-bp6hwMFzuiE4HqYEyoGJ/V2LeIWn+hLVKc4pnj++E5XQptwhtcGmSayM029d/j2X1bPKGTlsyPwAubuU22KhMA== dependencies: "@babel/helper-plugin-utils" "^7.20.2" @@ -970,9 +970,9 @@ "@babel/helper-replace-supers" "^7.18.6" "@babel/plugin-transform-parameters@^7.0.0", "@babel/plugin-transform-parameters@^7.20.1", "@babel/plugin-transform-parameters@^7.20.7": - version "7.20.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.20.7.tgz#0ee349e9d1bc96e78e3b37a7af423a4078a7083f" - integrity sha512-WiWBIkeHKVOSYPO0pWkxGPfKeWrCJyD3NJ53+Lrp/QMSZbsVPovrVl2aWZ19D/LTVnaDv5Ap7GJ/B2CTOZdrfA== + version "7.21.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.21.3.tgz#18fc4e797cf6d6d972cb8c411dbe8a809fa157db" + integrity sha512-Wxc+TvppQG9xWFYatvCGPvZ6+SIUxQ2ZdiBP+PHYMIjnPXD+uThCshaz4NZOnODAtBjjcVQQ/3OKs9LW28purQ== dependencies: "@babel/helper-plugin-utils" "^7.20.2" @@ -984,9 +984,9 @@ "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-transform-react-constant-elements@^7.12.1": - version "7.20.2" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.20.2.tgz#3f02c784e0b711970d7d8ccc96c4359d64e27ac7" - integrity sha512-KS/G8YI8uwMGKErLFOHS/ekhqdHhpEloxs43NecQHVgo2QuQSyJhGIY1fL8UGl9wy5ItVwwoUL4YxVqsplGq2g== + version "7.21.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.21.3.tgz#b32a5556100d424b25e388dd689050d78396884d" + integrity sha512-4DVcFeWe/yDYBLp0kBmOGFJ6N2UYg7coGid1gdxb4co62dy/xISDMaYBXBVXEDhfgMk7qkbcYiGtwd5Q/hwDDQ== dependencies: "@babel/helper-plugin-utils" "^7.20.2" @@ -1101,10 +1101,11 @@ "@babel/helper-plugin-utils" "^7.18.9" "@babel/plugin-transform-typescript@^7.21.0", "@babel/plugin-transform-typescript@^7.5.0": - version "7.21.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.21.0.tgz#f0956a153679e3b377ae5b7f0143427151e4c848" - integrity sha512-xo///XTPp3mDzTtrqXoBlK9eiAYW3wv9JXglcn/u1bi60RW11dEUxIgA8cbnDhutS1zacjMRmAwxE0gMklLnZg== + version "7.21.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.21.3.tgz#316c5be579856ea890a57ebc5116c5d064658f2b" + integrity sha512-RQxPz6Iqt8T0uw/WsJNReuBpWpBqs/n7mNo18sKLoTbMp+UrEekhH+pKSVC7gWz+DNjo9gryfV8YzCiT45RgMw== dependencies: + "@babel/helper-annotate-as-pure" "^7.18.6" "@babel/helper-create-class-features-plugin" "^7.21.0" "@babel/helper-plugin-utils" "^7.20.2" "@babel/plugin-syntax-typescript" "^7.20.0" @@ -1278,26 +1279,26 @@ "@babel/parser" "^7.20.7" "@babel/types" "^7.20.7" -"@babel/traverse@^7.20.0", "@babel/traverse@^7.20.5", "@babel/traverse@^7.20.7", "@babel/traverse@^7.21.0", "@babel/traverse@^7.21.2", "@babel/traverse@^7.7.2", "@babel/traverse@^7.7.4": - version "7.21.2" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.21.2.tgz#ac7e1f27658750892e815e60ae90f382a46d8e75" - integrity sha512-ts5FFU/dSUPS13tv8XiEObDu9K+iagEKME9kAbaP7r0Y9KtZJZ+NGndDvWoRAYNpeWafbpFeki3q9QoMD6gxyw== +"@babel/traverse@^7.20.0", "@babel/traverse@^7.20.5", "@babel/traverse@^7.20.7", "@babel/traverse@^7.21.0", "@babel/traverse@^7.21.2", "@babel/traverse@^7.21.3", "@babel/traverse@^7.7.2", "@babel/traverse@^7.7.4": + version "7.21.3" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.21.3.tgz#4747c5e7903d224be71f90788b06798331896f67" + integrity sha512-XLyopNeaTancVitYZe2MlUEvgKb6YVVPXzofHgqHijCImG33b/uTurMS488ht/Hbsb2XK3U2BnSTxKVNGV3nGQ== dependencies: "@babel/code-frame" "^7.18.6" - "@babel/generator" "^7.21.1" + "@babel/generator" "^7.21.3" "@babel/helper-environment-visitor" "^7.18.9" "@babel/helper-function-name" "^7.21.0" "@babel/helper-hoist-variables" "^7.18.6" "@babel/helper-split-export-declaration" "^7.18.6" - "@babel/parser" "^7.21.2" - "@babel/types" "^7.21.2" + "@babel/parser" "^7.21.3" + "@babel/types" "^7.21.3" debug "^4.1.0" globals "^11.1.0" -"@babel/types@^7.0.0", "@babel/types@^7.12.6", "@babel/types@^7.18.6", "@babel/types@^7.18.9", "@babel/types@^7.20.0", "@babel/types@^7.20.2", "@babel/types@^7.20.5", "@babel/types@^7.20.7", "@babel/types@^7.21.0", "@babel/types@^7.21.2", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4": - version "7.21.2" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.21.2.tgz#92246f6e00f91755893c2876ad653db70c8310d1" - integrity sha512-3wRZSs7jiFaB8AjxiiD+VqN5DTG2iRvJGQ+qYFrs/654lg6kGTQWIOFjlBo5RaXuAZjBmP3+OQH4dmhqiiyYxw== +"@babel/types@^7.0.0", "@babel/types@^7.12.6", "@babel/types@^7.18.6", "@babel/types@^7.18.9", "@babel/types@^7.20.0", "@babel/types@^7.20.2", "@babel/types@^7.20.5", "@babel/types@^7.20.7", "@babel/types@^7.21.0", "@babel/types@^7.21.2", "@babel/types@^7.21.3", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4": + version "7.21.3" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.21.3.tgz#4865a5357ce40f64e3400b0f3b737dc6d4f64d05" + integrity sha512-sBGdETxC+/M4o/zKC0sl6sjWv62WFR/uzxrJ6uYyMLZOUlPnwzw0tKgVHOXxaAd5l2g8pEDM5RZ495GPQI77kg== dependencies: "@babel/helper-string-parser" "^7.19.4" "@babel/helper-validator-identifier" "^7.19.1" @@ -1436,14 +1437,26 @@ dependencies: "@types/hammerjs" "^2.0.36" -"@eslint/eslintrc@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.0.0.tgz#943309d8697c52fc82c076e90c1c74fbbe69dbff" - integrity sha512-fluIaaV+GyV24CCu/ggiHdV+j4RNh85yQnAYS/G2mZODZgGmmlrgCydjUcV3YvxCm9x8nMAfThsqTni4KiXT4A== +"@eslint-community/eslint-utils@^4.2.0": + version "4.3.0" + resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.3.0.tgz#a556790523a351b4e47e9d385f47265eaaf9780a" + integrity sha512-v3oplH6FYCULtFuCeqyuTd9D2WKO937Dxdq+GmHOLL72TTRriLxz2VLlNfkZRsvj6PKnOPAtuT6dwrs/pA5DvA== + dependencies: + eslint-visitor-keys "^3.3.0" + +"@eslint-community/regexpp@^4.4.0": + version "4.4.0" + resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.4.0.tgz#3e61c564fcd6b921cb789838631c5ee44df09403" + integrity sha512-A9983Q0LnDGdLPjxyXQ00sbV+K+O+ko2Dr+CZigbHWtX9pNfxlaBkMR8X1CztI73zuEyEBXTVjx7CE+/VSwDiQ== + +"@eslint/eslintrc@^2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.0.1.tgz#7888fe7ec8f21bc26d646dbd2c11cd776e21192d" + integrity sha512-eFRmABvW2E5Ho6f5fHLqgena46rOj7r7OKHYfLElqcBfGFHHpjBhivyi5+jOEQuSpdc/1phIZJlbC2te+tZNIw== dependencies: ajv "^6.12.4" debug "^4.3.2" - espree "^9.4.0" + espree "^9.5.0" globals "^13.19.0" ignore "^5.2.0" import-fresh "^3.2.1" @@ -1451,10 +1464,10 @@ minimatch "^3.1.2" strip-json-comments "^3.1.1" -"@eslint/js@8.35.0": - version "8.35.0" - resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.35.0.tgz#b7569632b0b788a0ca0e438235154e45d42813a7" - integrity sha512-JXdzbRiWclLVoD8sNUjR443VVlYqiYmDVT6rGUEIEHU5YJW0gaVZwV2xgM7D4arkvASqD0IlLUVjHiFuxaftRw== +"@eslint/js@8.36.0": + version "8.36.0" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.36.0.tgz#9837f768c03a1e4a30bd304a64fb8844f0e72efe" + integrity sha512-lxJ9R5ygVm8ZWgYdUweoq5ownDlJ4upvoWmO4eLxBYHdMo+vZ/Rx0EN6MbKWDJOSUGrqJy2Gt+Dyv/VKml0fjg== "@expo/bunyan@4.0.0", "@expo/bunyan@^4.0.0": version "4.0.0" @@ -1831,9 +1844,9 @@ cross-spawn "^6.0.5" "@expo/spawn-async@^1.5.0": - version "1.7.0" - resolved "https://registry.yarnpkg.com/@expo/spawn-async/-/spawn-async-1.7.0.tgz#3ab6082b24318cccc4e73b13464da91325555500" - integrity sha512-sqPAjOEFTrjaTybrh9SnPFLInDXcoMC06psEFmH68jLTmoipSQCq8GCEfIoHhxRDALWB+DsiwXJSbXlE/iVIIQ== + version "1.7.2" + resolved "https://registry.yarnpkg.com/@expo/spawn-async/-/spawn-async-1.7.2.tgz#fcfe66c3e387245e72154b1a7eae8cada6a47f58" + integrity sha512-QdWi16+CHB9JYP7gma19OVVg0BFkvU8zNj9GjWorYI8Iv8FUxjOCcYRuAmX4s/h91e4e7BPsskc8cSrZYho9Ew== dependencies: cross-spawn "^7.0.3" @@ -2502,9 +2515,9 @@ semver "7.3.8" "@miblanchard/react-native-slider@^2.2.0": - version "2.3.0" - resolved "https://registry.yarnpkg.com/@miblanchard/react-native-slider/-/react-native-slider-2.3.0.tgz#91a3294487a9b91e9ff2f841c7ed855ebadfccc9" - integrity sha512-KiAESUOP69eft8U43iD6xeX+s9ZetwiY/cXkGq1xL4nywb37cVnrxQeSi3+rAix8aHeJwXXeyPZkxmZQe0Hjbw== + version "2.3.1" + resolved "https://registry.yarnpkg.com/@miblanchard/react-native-slider/-/react-native-slider-2.3.1.tgz#79e0f1f9b1ce43ef25ee51ee9256c012e5dfa412" + integrity sha512-J/hZDBWmXq8fJeOnTVHqIUVDHshqMSpJVxJ4WqwuCBKl5Rke9OBYXIdkSlgi75OgtScAr8FKK5KNkDKHUf6JIg== "@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1": version "5.1.1-v1" @@ -2540,9 +2553,9 @@ fastq "^1.6.0" "@notifee/react-native@^7.4.0": - version "7.5.0" - resolved "https://registry.yarnpkg.com/@notifee/react-native/-/react-native-7.5.0.tgz#3d846b6a607a6352e798a3440cd3880c005a7d56" - integrity sha512-FR1xzQI2KpMyLuM7YZyHHjCcOXbjAcBWMeRlarro8peujr6gJZSg4j2Aw4o8O4ifMHDopFrovwyK1uYBaB9MUg== + version "7.6.1" + resolved "https://registry.yarnpkg.com/@notifee/react-native/-/react-native-7.6.1.tgz#e215428787396ec57ea424106cc88666f7efe70d" + integrity sha512-OjhLPODh6FICYZmF9/0UZbcl2JPaPpcrWi1Cvs/OLFbPSJTIEwPZgXFrCHv/cA3wUX4YQCXreSqQGSVQgvNItQ== "@npmcli/fs@^1.0.0": version "1.1.1" @@ -2580,17 +2593,17 @@ resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.6.tgz#cee20bd55e68a1720bdab363ecf0c821ded4cd45" integrity sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw== -"@react-native-async-storage/async-storage@^1.15.15", "@react-native-async-storage/async-storage@^1.15.17", "@react-native-async-storage/async-storage@^1.17.6": - version "1.17.11" - resolved "https://registry.yarnpkg.com/@react-native-async-storage/async-storage/-/async-storage-1.17.11.tgz#7ec329c1b9f610e344602e806b04d7c928a2341d" - integrity sha512-bzs45n5HNcDq6mxXnSsOHysZWn1SbbebNxldBXCQs8dSvF8Aor9KCdpm+TpnnGweK3R6diqsT8lFhX77VX0NFw== +"@react-native-async-storage/async-storage@^1.15.15", "@react-native-async-storage/async-storage@^1.17.6": + version "1.17.12" + resolved "https://registry.yarnpkg.com/@react-native-async-storage/async-storage/-/async-storage-1.17.12.tgz#a39e4df5b06795ce49b2ca5b7ca9b8faadf8e621" + integrity sha512-BXg4OxFdjPTRt+8MvN6jz4muq0/2zII3s7HeT/11e4Zeh3WCgk/BleLzUcDfVqF3OzFHUqEkSrb76d6Ndjd/Nw== dependencies: merge-options "^3.0.4" "@react-native-camera-roll/camera-roll@^5.2.2": - version "5.2.4" - resolved "https://registry.yarnpkg.com/@react-native-camera-roll/camera-roll/-/camera-roll-5.2.4.tgz#216d0ea4656b6538c10b60f057118c6f5e704c0d" - integrity sha512-pEQDartgO8Nqy6QDm1efvIPpv4q5W+AtTgS05JGK/9x8VzSj8fJ/cvHmMZBlm/4sFpJyvJZ+1KYxKsvFJLbGuQ== + version "5.3.1" + resolved "https://registry.yarnpkg.com/@react-native-camera-roll/camera-roll/-/camera-roll-5.3.1.tgz#0b6d363c0f6c83fc93ff033826f8fa96274a01a7" + integrity sha512-2XKMkb/pLBC6vYkNh+bJ4UEj49V2ZSyWFHmaxsUJU9beLo1QbM3XJnySV6F1uv7aC+I2RBlDuAusCqNiTQiCOw== "@react-native-clipboard/clipboard@^1.10.0": version "1.11.2" @@ -2632,12 +2645,12 @@ serve-static "^1.13.1" "@react-native-community/cli-doctor@^10.1.1": - version "10.2.0" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-doctor/-/cli-doctor-10.2.0.tgz#6050030eea9200ce3c35de360cf8455e126b4d45" - integrity sha512-yLxJazUmNSPslHxeeev0gLvsK0nQan8BmGWbtqPz2WwbIbD89vbytC7G96OxiQXr46iWEWAwEJiTTdgA7jlA5Q== + version "10.2.1" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-doctor/-/cli-doctor-10.2.1.tgz#b6b7a3f0f9cef1a05f1adc6393eb29c6f8f2972c" + integrity sha512-IwhdSD+mtgWdxg2eMr0fpkn08XN7r70DC1riGSmqK/DXNyWBzIZlCkDN+/TwlaUEsiFk6LQTjgCiqZSMpmDrsg== dependencies: "@react-native-community/cli-config" "^10.1.1" - "@react-native-community/cli-platform-ios" "^10.2.0" + "@react-native-community/cli-platform-ios" "^10.2.1" "@react-native-community/cli-tools" "^10.1.1" chalk "^4.1.2" command-exists "^1.2.8" @@ -2697,10 +2710,10 @@ glob "^7.1.3" ora "^5.4.1" -"@react-native-community/cli-platform-ios@^10.2.0": - version "10.2.0" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-ios/-/cli-platform-ios-10.2.0.tgz#be21c0e3bbf17358d540cc23e5556bf679f6322e" - integrity sha512-hIPK3iL/mL+0ChXmQ9uqqzNOKA48H+TAzg+hrxQLll/6dNMxDeK9/wZpktcsh8w+CyhqzKqVernGcQs7tPeKGw== +"@react-native-community/cli-platform-ios@^10.2.1": + version "10.2.1" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-ios/-/cli-platform-ios-10.2.1.tgz#2e6bd2cb6d48cbb8720d7b7265bb1bab80745f72" + integrity sha512-hz4zu4Y6eyj7D0lnZx8Mf2c2si8y+zh/zUTgCTaPPLzQD8jSZNNBtUUiA1cARm2razpe8marCZ1QbTMAGbf3mg== dependencies: "@react-native-community/cli-tools" "^10.1.1" chalk "^4.1.2" @@ -2963,15 +2976,14 @@ integrity sha512-sXo/qW2/pAcmT43VoRKOJbDOfV3cYpq3szSVfIThQXNt+E4DfKj361vaAt3c88U5tPUxzEswam7GW48PJqtKAg== "@segment/analytics-react-native@^2.10.1": - version "2.13.1" - resolved "https://registry.yarnpkg.com/@segment/analytics-react-native/-/analytics-react-native-2.13.1.tgz#c093c145cb1a5a87041fbbfc5fa61c3fb370787c" - integrity sha512-IRg0k8rVTNj2U4jpA0VKGioUKYAbvvYf3FNR8BsHDB3Jutmxdh/SPYAttFU1APJ9mQsqMEIEfocbDtwCAL0kAg== + version "2.13.4" + resolved "https://registry.yarnpkg.com/@segment/analytics-react-native/-/analytics-react-native-2.13.4.tgz#52216972bf0a1f8722ddf18088340c9d4d90ca5a" + integrity sha512-47z2TmODJpeA7Pf1P8kE5dNTiqmxJ7khQ/NgiFR3eoiSy/ir0QOpT49QFrwVMeG35fEl+wDGLXUoYWoAMvBy6w== dependencies: - "@react-native-async-storage/async-storage" "^1.15.17" - "@segment/sovran-react-native" "^0.4.5" + "@segment/sovran-react-native" "^1" deepmerge "^4.2.2" js-base64 "^3.7.2" - react-native-uuid "^2.0.1" + uuid "^9.0.0" "@segment/loosely-validate-event@^2.0.0": version "2.0.0" @@ -2991,6 +3003,15 @@ deepmerge "^4.2.2" shell-quote "1.7.3" +"@segment/sovran-react-native@^1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@segment/sovran-react-native/-/sovran-react-native-1.0.1.tgz#4311f0af2e2b606d2c17e535b293c096c6a3c2e8" + integrity sha512-7VZrIa7/VP59d4QDvAs0ZOhiadlJ+2YC8K8dKOF0fGwiFC0UmQUZVs4IN9GZfbBavXsagVVMgL2GzjVGLLQdBw== + dependencies: + ansi-regex "5.0.1" + deepmerge "^4.2.2" + shell-quote "1.7.3" + "@sideway/address@^4.1.3": version "4.1.4" resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.4.tgz#03dccebc6ea47fdc226f7d3d1ad512955d4783f0" @@ -3370,9 +3391,9 @@ "@types/estree" "*" "@types/eslint@*", "@types/eslint@^7.29.0 || ^8.4.1": - version "8.21.1" - resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.21.1.tgz#110b441a210d53ab47795124dbc3e9bb993d1e7c" - integrity sha512-rc9K8ZpVjNcLs8Fp0dkozd5Pt2Apk1glO4Vgz8ix1u6yFByxfqo5Yavpy65o+93TAe24jr7v+eSBtFLvOQtCRQ== + version "8.21.3" + resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.21.3.tgz#5794b3911f0f19e34e3a272c49cbdf48d6f543f2" + integrity sha512-fa7GkppZVEByMWGbTtE5MbmXWJTVbrjjaS8K6uQj+XtuuUv1fsuPAxhygfqLmsb/Ufb3CV8deFCpiMfAgi00Sw== dependencies: "@types/estree" "*" "@types/json-schema" "*" @@ -3468,9 +3489,9 @@ "@types/istanbul-lib-report" "*" "@types/jest@^29.4.0": - version "29.4.0" - resolved "https://registry.yarnpkg.com/@types/jest/-/jest-29.4.0.tgz#a8444ad1704493e84dbf07bb05990b275b3b9206" - integrity sha512-VaywcGQ9tPorCX/Jkkni7RWGFfI11whqzs8dvxF41P17Z+z872thvEvlIbznjPJ02kl1HMX3LmLOonsj2n7HeQ== + version "29.5.0" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-29.5.0.tgz#337b90bbcfe42158f39c2fb5619ad044bbb518ac" + integrity sha512-3Emr5VOl/aoBwnWcH/EFQvlSAmjV+XtV9GGu5mwdYew5vhQh0IUZx/60x0TzHDu09Bi7HMx10t/namdJw5QIcg== dependencies: expect "^29.0.0" pretty-format "^29.0.0" @@ -3559,9 +3580,9 @@ integrity sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA== "@types/node@*": - version "18.14.6" - resolved "https://registry.yarnpkg.com/@types/node/-/node-18.14.6.tgz#ae1973dd2b1eeb1825695bb11ebfb746d27e3e93" - integrity sha512-93+VvleD3mXwlLI/xASjw0FzKcwzl3OdTCzm1LaRfqgS21gfFtK3zDXM5Op9TeeMsJVOaJ2VRDpT9q4Y3d0AvA== + version "18.15.3" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.15.3.tgz#f0b991c32cfc6a4e7f3399d6cb4b8cf9a0315014" + integrity sha512-p6ua9zBxz5otCmbpb5D3U4B5Nanw6Pk3PPyX05xnxbB/fRv71N7CPmORg7uAD5P70T0xmx1pzAx/FUfa5X+3cw== "@types/object.omit@^3.0.0": version "3.0.0" @@ -3731,94 +3752,94 @@ "@types/yargs-parser" "*" "@typescript-eslint/eslint-plugin@^5.30.5", "@typescript-eslint/eslint-plugin@^5.48.2", "@typescript-eslint/eslint-plugin@^5.5.0": - version "5.54.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.54.1.tgz#0c5091289ce28372e38ab8d28e861d2dbe1ab29e" - integrity sha512-a2RQAkosH3d3ZIV08s3DcL/mcGc2M/UC528VkPULFxR9VnVPT8pBu0IyBAJJmVsCmhVfwQX1v6q+QGnmSe1bew== + version "5.55.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.55.0.tgz#bc2400c3a23305e8c9a9c04aa40933868aaaeb47" + integrity sha512-IZGc50rtbjk+xp5YQoJvmMPmJEYoC53SiKPXyqWfv15XoD2Y5Kju6zN0DwlmaGJp1Iw33JsWJcQ7nw0lGCGjVg== dependencies: - "@typescript-eslint/scope-manager" "5.54.1" - "@typescript-eslint/type-utils" "5.54.1" - "@typescript-eslint/utils" "5.54.1" + "@eslint-community/regexpp" "^4.4.0" + "@typescript-eslint/scope-manager" "5.55.0" + "@typescript-eslint/type-utils" "5.55.0" + "@typescript-eslint/utils" "5.55.0" debug "^4.3.4" grapheme-splitter "^1.0.4" ignore "^5.2.0" natural-compare-lite "^1.4.0" - regexpp "^3.2.0" semver "^7.3.7" tsutils "^3.21.0" "@typescript-eslint/experimental-utils@^5.0.0": - version "5.54.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-5.54.1.tgz#a45609ce43fc6b24b4c4dde215446eaad7805223" - integrity sha512-oqSc2Gr4TL/2M0XRJ9abA1o3Wf1cFJTNqWq0kjdStIIvgMQGZ3TSaFFJ2Cvy3Fgqi9UfDZ8u5idbACssIIyHaw== + version "5.55.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-5.55.0.tgz#ea2dd8737834af3a36b6a7be5bee57f57160c942" + integrity sha512-3ZqXIZhdGyGQAIIGATeMtg7prA6VlyxGtcy5hYIR/3qUqp3t18pWWUYhL9mpsDm7y8F9mr3ISMt83TiqCt7OPQ== dependencies: - "@typescript-eslint/utils" "5.54.1" + "@typescript-eslint/utils" "5.55.0" "@typescript-eslint/parser@^5.30.5", "@typescript-eslint/parser@^5.48.2", "@typescript-eslint/parser@^5.5.0": - version "5.54.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.54.1.tgz#05761d7f777ef1c37c971d3af6631715099b084c" - integrity sha512-8zaIXJp/nG9Ff9vQNh7TI+C3nA6q6iIsGJ4B4L6MhZ7mHnTMR4YP5vp2xydmFXIy8rpyIVbNAG44871LMt6ujg== + version "5.55.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.55.0.tgz#8c96a0b6529708ace1dcfa60f5e6aec0f5ed2262" + integrity sha512-ppvmeF7hvdhUUZWSd2EEWfzcFkjJzgNQzVST22nzg958CR+sphy8A6K7LXQZd6V75m1VKjp+J4g/PCEfSCmzhw== dependencies: - "@typescript-eslint/scope-manager" "5.54.1" - "@typescript-eslint/types" "5.54.1" - "@typescript-eslint/typescript-estree" "5.54.1" + "@typescript-eslint/scope-manager" "5.55.0" + "@typescript-eslint/types" "5.55.0" + "@typescript-eslint/typescript-estree" "5.55.0" debug "^4.3.4" -"@typescript-eslint/scope-manager@5.54.1": - version "5.54.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.54.1.tgz#6d864b4915741c608a58ce9912edf5a02bb58735" - integrity sha512-zWKuGliXxvuxyM71UA/EcPxaviw39dB2504LqAmFDjmkpO8qNLHcmzlh6pbHs1h/7YQ9bnsO8CCcYCSA8sykUg== +"@typescript-eslint/scope-manager@5.55.0": + version "5.55.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.55.0.tgz#e863bab4d4183ddce79967fe10ceb6c829791210" + integrity sha512-OK+cIO1ZGhJYNCL//a3ROpsd83psf4dUJ4j7pdNVzd5DmIk+ffkuUIX2vcZQbEW/IR41DYsfJTB19tpCboxQuw== dependencies: - "@typescript-eslint/types" "5.54.1" - "@typescript-eslint/visitor-keys" "5.54.1" + "@typescript-eslint/types" "5.55.0" + "@typescript-eslint/visitor-keys" "5.55.0" -"@typescript-eslint/type-utils@5.54.1": - version "5.54.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.54.1.tgz#4825918ec27e55da8bb99cd07ec2a8e5f50ab748" - integrity sha512-WREHsTz0GqVYLIbzIZYbmUUr95DKEKIXZNH57W3s+4bVnuF1TKe2jH8ZNH8rO1CeMY3U4j4UQeqPNkHMiGem3g== +"@typescript-eslint/type-utils@5.55.0": + version "5.55.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.55.0.tgz#74bf0233523f874738677bb73cb58094210e01e9" + integrity sha512-ObqxBgHIXj8rBNm0yh8oORFrICcJuZPZTqtAFh0oZQyr5DnAHZWfyw54RwpEEH+fD8suZaI0YxvWu5tYE/WswA== dependencies: - "@typescript-eslint/typescript-estree" "5.54.1" - "@typescript-eslint/utils" "5.54.1" + "@typescript-eslint/typescript-estree" "5.55.0" + "@typescript-eslint/utils" "5.55.0" debug "^4.3.4" tsutils "^3.21.0" -"@typescript-eslint/types@5.54.1": - version "5.54.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.54.1.tgz#29fbac29a716d0f08c62fe5de70c9b6735de215c" - integrity sha512-G9+1vVazrfAfbtmCapJX8jRo2E4MDXxgm/IMOF4oGh3kq7XuK3JRkOg6y2Qu1VsTRmWETyTkWt1wxy7X7/yLkw== +"@typescript-eslint/types@5.55.0": + version "5.55.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.55.0.tgz#9830f8d3bcbecf59d12f821e5bc6960baaed41fd" + integrity sha512-M4iRh4AG1ChrOL6Y+mETEKGeDnT7Sparn6fhZ5LtVJF1909D5O4uqK+C5NPbLmpfZ0XIIxCdwzKiijpZUOvOug== -"@typescript-eslint/typescript-estree@5.54.1": - version "5.54.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.54.1.tgz#df7b6ae05fd8fef724a87afa7e2f57fa4a599be1" - integrity sha512-bjK5t+S6ffHnVwA0qRPTZrxKSaFYocwFIkZx5k7pvWfsB1I57pO/0M0Skatzzw1sCkjJ83AfGTL0oFIFiDX3bg== +"@typescript-eslint/typescript-estree@5.55.0": + version "5.55.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.55.0.tgz#8db7c8e47ecc03d49b05362b8db6f1345ee7b575" + integrity sha512-I7X4A9ovA8gdpWMpr7b1BN9eEbvlEtWhQvpxp/yogt48fy9Lj3iE3ild/1H3jKBBIYj5YYJmS2+9ystVhC7eaQ== dependencies: - "@typescript-eslint/types" "5.54.1" - "@typescript-eslint/visitor-keys" "5.54.1" + "@typescript-eslint/types" "5.55.0" + "@typescript-eslint/visitor-keys" "5.55.0" debug "^4.3.4" globby "^11.1.0" is-glob "^4.0.3" semver "^7.3.7" tsutils "^3.21.0" -"@typescript-eslint/utils@5.54.1", "@typescript-eslint/utils@^5.10.0", "@typescript-eslint/utils@^5.43.0": - version "5.54.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.54.1.tgz#7a3ee47409285387b9d4609ea7e1020d1797ec34" - integrity sha512-IY5dyQM8XD1zfDe5X8jegX6r2EVU5o/WJnLu/znLPWCBF7KNGC+adacXnt5jEYS9JixDcoccI6CvE4RCjHMzCQ== +"@typescript-eslint/utils@5.55.0", "@typescript-eslint/utils@^5.10.0", "@typescript-eslint/utils@^5.43.0": + version "5.55.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.55.0.tgz#34e97322e7ae5b901e7a870aabb01dad90023341" + integrity sha512-FkW+i2pQKcpDC3AY6DU54yl8Lfl14FVGYDgBTyGKB75cCwV3KpkpTMFi9d9j2WAJ4271LR2HeC5SEWF/CZmmfw== dependencies: + "@eslint-community/eslint-utils" "^4.2.0" "@types/json-schema" "^7.0.9" "@types/semver" "^7.3.12" - "@typescript-eslint/scope-manager" "5.54.1" - "@typescript-eslint/types" "5.54.1" - "@typescript-eslint/typescript-estree" "5.54.1" + "@typescript-eslint/scope-manager" "5.55.0" + "@typescript-eslint/types" "5.55.0" + "@typescript-eslint/typescript-estree" "5.55.0" eslint-scope "^5.1.1" - eslint-utils "^3.0.0" semver "^7.3.7" -"@typescript-eslint/visitor-keys@5.54.1": - version "5.54.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.54.1.tgz#d7a8a0f7181d6ac748f4d47b2306e0513b98bf8b" - integrity sha512-q8iSoHTgwCfgcRJ2l2x+xCbu8nBlRAlsQ33k24Adj8eoVBE0f8dUeI+bAa8F84Mv05UGbAx57g2zrRsYIooqQg== +"@typescript-eslint/visitor-keys@5.55.0": + version "5.55.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.55.0.tgz#01ad414fca8367706d76cdb94adf788dc5b664a2" + integrity sha512-q2dlHHwWgirKh1D3acnuApXG+VNXpEY5/AwRxDVuEQpxWaB0jCDe0jFMVMALJ3ebSfuOVE8/rMS+9ZOYGg1GWw== dependencies: - "@typescript-eslint/types" "5.54.1" + "@typescript-eslint/types" "5.55.0" eslint-visitor-keys "^3.3.0" "@ucans/core@0.11.0": @@ -3837,9 +3858,9 @@ wonka "^4.0.14" "@urql/core@>=2.3.1": - version "3.1.1" - resolved "https://registry.yarnpkg.com/@urql/core/-/core-3.1.1.tgz#a49cd572360d01f2469a786b294fba2269a65e53" - integrity sha512-Mnxtq4I4QeFJsgs7Iytw+HyhiGxISR6qtyk66c9tipozLZ6QVxrCiUPF2HY4BxNIabaxcp+rivadvm8NAnXj4Q== + version "3.2.2" + resolved "https://registry.yarnpkg.com/@urql/core/-/core-3.2.2.tgz#2a44015b536d72981822f715c96393d8e0ddc576" + integrity sha512-i046Cz8cZ4xIzGMTyHZrbdgzcFMcKD7+yhCAH5FwWBRjcKrc+RjEOuR9X5AMuBvr8c6IAaE92xAqa4wmlGfWTQ== dependencies: wonka "^6.1.2" @@ -4177,9 +4198,9 @@ ansi-escapes@^4.2.1, ansi-escapes@^4.3.0, ansi-escapes@^4.3.1: type-fest "^0.21.3" ansi-escapes@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-6.0.0.tgz#68c580e87a489f6df3d761028bb93093fde6bd8a" - integrity sha512-IG23inYII3dWlU2EyiAiGj6Bwal5GzsgPMwjYGvc1HPE2dgbj4ZB5ToWBKSquKw74nB3TIuOwaI6/jSULzfgrw== + version "6.1.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-6.1.0.tgz#f2912cdaa10785f3f51f4b562a2497b885aadc5e" + integrity sha512-bQyg9bzRntwR/8b89DOEhGwctcwCrbWW/TuqTQnpqpy5Fz3aovcOTj5i8NJV6AHc8OGNdMaqdxAWww8pz2kiKg== dependencies: type-fest "^3.0.0" @@ -4298,6 +4319,14 @@ arr-union@^3.1.0: resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" integrity sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q== +array-buffer-byte-length@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz#fabe8bc193fea865f317fe7807085ee0dee5aead" + integrity sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A== + dependencies: + call-bind "^1.0.2" + is-array-buffer "^3.0.1" + array-flatten@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" @@ -4453,12 +4482,12 @@ atomic-sleep@^1.0.0: integrity sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ== autoprefixer@^10.4.13: - version "10.4.13" - resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.13.tgz#b5136b59930209a321e9fa3dca2e7c4d223e83a8" - integrity sha512-49vKpMqcZYsJjwotvt4+h/BCjJVnhGwcLpDt5xkcaOG3eLrG/HUYLagrihYsQ+qrIBgIzX1Rw7a6L8I/ZA1Atg== + version "10.4.14" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.14.tgz#e28d49902f8e759dd25b153264e862df2705f79d" + integrity sha512-FQzyfOsTlwVzjHxKEqRIAdJx9niO6VCBCoEwax/VLSoQF29ggECcPuBqUMZ+u8jCZOPSy8b8/8KnuFbp0SaFZQ== dependencies: - browserslist "^4.21.4" - caniuse-lite "^1.0.30001426" + browserslist "^4.21.5" + caniuse-lite "^1.0.30001464" fraction.js "^4.2.0" normalize-range "^0.1.2" picocolors "^1.0.0" @@ -5190,10 +5219,10 @@ caniuse-api@^3.0.0: lodash.memoize "^4.1.2" lodash.uniq "^4.5.0" -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001426, caniuse-lite@^1.0.30001449: - version "1.0.30001462" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001462.tgz#b2e801e37536d453731286857c8520d3dcee15fe" - integrity sha512-PDd20WuOBPiasZ7KbFnmQRyuLE7cFXW2PVd7dmALzbkUXEP46upAuCDm9eY9vho8fgNMGmbAX92QBZHzcnWIqw== +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001449, caniuse-lite@^1.0.30001464: + version "1.0.30001468" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001468.tgz#0101837c6a4e38e6331104c33dcfb3bdf367a4b7" + integrity sha512-zgAo8D5kbOyUcRAgSmgyuvBkjrGk5CGYG5TYgFdpQv+ywcyEpo1LOWoG8YmoflGnh+V+UsNuKYedsoYs0hzV5A== case-anything@^2.1.10: version "2.1.10" @@ -5206,9 +5235,9 @@ case-sensitive-paths-webpack-plugin@^2.4.0: integrity sha512-roIFONhcxog0JSSWbvVAh3OocukmSgpqOH6YpMkCvav/ySIV3JKg4Dc8vYtQjYi/UxpNE36r/9v+VqTQqgkYmw== cborg@^1.6.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/cborg/-/cborg-1.10.0.tgz#0fe157961dd47b537ccb84dc9ba681de8b699013" - integrity sha512-/eM0JCaL99HDHxjySNQJLaolZFVdl6VA0/hEKIoiQPcQzE5LrG5QHdml0HaBt31brgB9dNe1zMr3f8IVrpotRQ== + version "1.10.1" + resolved "https://registry.yarnpkg.com/cborg/-/cborg-1.10.1.tgz#24cfe52c69ec0f66f95e23dc57f2086954c8d718" + integrity sha512-et6Qm8MOUY2kCWa5GKk2MlBVoPjHv0hQBmlzI/Z7+5V3VJCeIkGehIB3vWknNsm2kOkAIs6wEKJFJo8luWQQ/w== chalk@^2.0.0, chalk@^2.0.1, chalk@^2.4.1, chalk@^2.4.2: version "2.4.2" @@ -5662,21 +5691,21 @@ copy-webpack-plugin@^10.2.0: serialize-javascript "^6.0.0" core-js-compat@^3.25.1: - version "3.29.0" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.29.0.tgz#1b8d9eb4191ab112022e7f6364b99b65ea52f528" - integrity sha512-ScMn3uZNAFhK2DGoEfErguoiAHhV2Ju+oJo/jK08p7B3f3UhocUrCCkTvnZaiS+edl5nlIoiBXKcwMc6elv4KQ== + version "3.29.1" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.29.1.tgz#15c0fb812ea27c973c18d425099afa50b934b41b" + integrity sha512-QmchCua884D8wWskMX8tW5ydINzd8oSJVx38lx/pVkFGqztxt73GYre3pm/hyYq8bPf+MW5In4I/uRShFDsbrA== dependencies: browserslist "^4.21.5" core-js-pure@^3.23.3: - version "3.29.0" - resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.29.0.tgz#0e1ac889214398641ea4bb1c6cf25ff0959ec1d2" - integrity sha512-v94gUjN5UTe1n0yN/opTihJ8QBWD2O8i19RfTZR7foONPWArnjB96QA/wk5ozu1mm6ja3udQCzOzwQXTxi3xOQ== + version "3.29.1" + resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.29.1.tgz#1be6ca2b8772f6b4df7fc4621743286e676c6162" + integrity sha512-4En6zYVi0i0XlXHVz/bi6l1XDjCqkKRq765NXuX+SnaIatlE96Odt5lMLjdxUiNI1v9OXI5DSLWYPlmTfkTktg== core-js@^3.19.2: - version "3.29.0" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.29.0.tgz#0273e142b67761058bcde5615c503c7406b572d6" - integrity sha512-VG23vuEisJNkGl6XQmFJd3rEG/so/CNatqeE+7uZAwTSwFeB/qaO0be8xZYUNWprJ/GIwL8aMt9cj1kvbpTZhg== + version "3.29.1" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.29.1.tgz#40ff3b41588b091aaed19ca1aa5cb111803fa9a6" + integrity sha512-+jwgnhg6cQxKYIIjGtAHq2nwUOolo9eoFZ4sHfUH09BLXBgxnH4gA0zEd+t+BO2cNB8idaBtZFcFTRjQJRJmAw== core-util-is@~1.0.0: version "1.0.3" @@ -6129,9 +6158,9 @@ deepmerge@^3.2.0: integrity sha512-GRQOafGHwMHpjPx9iCvTgpu9NojZ49q794EEL94JVEw6VaeA8XTUyBKvAkOOjBX9oJNiV6G3P+T+tihFjo2TqA== deepmerge@^4.2.2: - version "4.3.0" - resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.0.tgz#65491893ec47756d44719ae520e0e2609233b59b" - integrity sha512-z2wJZXrmeHdvYJp/Ux55wIjqo81G5Bp4c+oELTW+7ar6SogWHajt5a9gO3s3IDaGSAXjDk0vlQKN3rms8ab3og== + version "4.3.1" + resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" + integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== default-gateway@^4.2.0: version "4.2.0" @@ -6553,16 +6582,16 @@ ee-first@1.1.1: integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== ejs@^3.1.6: - version "3.1.8" - resolved "https://registry.yarnpkg.com/ejs/-/ejs-3.1.8.tgz#758d32910c78047585c7ef1f92f9ee041c1c190b" - integrity sha512-/sXZeMlhS0ArkfX2Aw780gJzXSMPnKjtspYZv+f3NiKLlubezAHDU5+9xz6gd3/NhG3txQCo6xlglmTS+oTGEQ== + version "3.1.9" + resolved "https://registry.yarnpkg.com/ejs/-/ejs-3.1.9.tgz#03c9e8777fe12686a9effcef22303ca3d8eeb361" + integrity sha512-rC+QVNMJWv+MtPgkt0y+0rVEIdbtxVADApW9JXrUVlzHetgcyczP/E7DJmWJ4fJCZF2cPcBk0laWO9ZHMG3DmQ== dependencies: jake "^10.8.5" electron-to-chromium@^1.4.284: - version "1.4.325" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.325.tgz#7b97238a61192d85d055d97f3149832b3617d37b" - integrity sha512-K1C03NT4I7BuzsRdCU5RWkgZxtswnKDYM6/eMhkEXqKu4e5T+ck610x3FPzu1y7HVFSiQKZqP16gnJzPpji1TQ== + version "1.4.333" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.333.tgz#ebb21f860f8a29923717b06ec0cb54e77ed34c04" + integrity sha512-YyE8+GKyGtPEP1/kpvqsdhD6rA/TP1DUFDN4uiU/YI52NzDxmwHkEb3qjId8hLBa5siJvG0sfC3O66501jMruQ== email-validator@^2.0.4: version "2.0.4" @@ -6672,17 +6701,17 @@ errorhandler@^1.5.0: escape-html "~1.0.3" es-abstract@^1.17.2, es-abstract@^1.19.0, es-abstract@^1.20.4: - version "1.21.1" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.21.1.tgz#e6105a099967c08377830a0c9cb589d570dd86c6" - integrity sha512-QudMsPOz86xYz/1dG1OuGBKOELjCh99IIWHLzy5znUB6j8xG2yMA7bfTV86VSqKF+Y/H08vQPR+9jyXpuC6hfg== + version "1.21.2" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.21.2.tgz#a56b9695322c8a185dc25975aa3b8ec31d0e7eff" + integrity sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg== dependencies: + array-buffer-byte-length "^1.0.0" available-typed-arrays "^1.0.5" call-bind "^1.0.2" es-set-tostringtag "^2.0.1" es-to-primitive "^1.2.1" - function-bind "^1.1.1" function.prototype.name "^1.1.5" - get-intrinsic "^1.1.3" + get-intrinsic "^1.2.0" get-symbol-description "^1.0.0" globalthis "^1.0.3" gopd "^1.0.1" @@ -6690,8 +6719,8 @@ es-abstract@^1.17.2, es-abstract@^1.19.0, es-abstract@^1.20.4: has-property-descriptors "^1.0.0" has-proto "^1.0.1" has-symbols "^1.0.3" - internal-slot "^1.0.4" - is-array-buffer "^3.0.1" + internal-slot "^1.0.5" + is-array-buffer "^3.0.2" is-callable "^1.2.7" is-negative-zero "^2.0.2" is-regex "^1.1.4" @@ -6699,11 +6728,12 @@ es-abstract@^1.17.2, es-abstract@^1.19.0, es-abstract@^1.20.4: is-string "^1.0.7" is-typed-array "^1.1.10" is-weakref "^1.0.2" - object-inspect "^1.12.2" + object-inspect "^1.12.3" object-keys "^1.1.1" object.assign "^4.1.4" regexp.prototype.flags "^1.4.3" safe-regex-test "^1.0.0" + string.prototype.trim "^1.2.7" string.prototype.trimend "^1.0.6" string.prototype.trimstart "^1.0.6" typed-array-length "^1.0.4" @@ -6995,14 +7025,7 @@ eslint-scope@^7.1.1: esrecurse "^4.3.0" estraverse "^5.2.0" -eslint-utils@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-3.0.0.tgz#8aebaface7345bb33559db0a1f13a1d2d48c3672" - integrity sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA== - dependencies: - eslint-visitor-keys "^2.0.0" - -eslint-visitor-keys@^2.0.0, eslint-visitor-keys@^2.1.0: +eslint-visitor-keys@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== @@ -7024,12 +7047,14 @@ eslint-webpack-plugin@^3.1.1: schema-utils "^4.0.0" eslint@^8.19.0, eslint@^8.3.0: - version "8.35.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.35.0.tgz#fffad7c7e326bae606f0e8f436a6158566d42323" - integrity sha512-BxAf1fVL7w+JLRQhWl2pzGeSiGqbWumV4WNvc9Rhp6tiCtm4oHnyPBSEtMGZwrQgudFQ+otqzWoPB7x+hxoWsw== + version "8.36.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.36.0.tgz#1bd72202200a5492f91803b113fb8a83b11285cf" + integrity sha512-Y956lmS7vDqomxlaaQAHVmeb4tNMp2FWIvU/RnU5BD3IKMD/MJPr76xdyr68P8tV1iNMvN2mRK0yy3c+UjL+bw== dependencies: - "@eslint/eslintrc" "^2.0.0" - "@eslint/js" "8.35.0" + "@eslint-community/eslint-utils" "^4.2.0" + "@eslint-community/regexpp" "^4.4.0" + "@eslint/eslintrc" "^2.0.1" + "@eslint/js" "8.36.0" "@humanwhocodes/config-array" "^0.11.8" "@humanwhocodes/module-importer" "^1.0.1" "@nodelib/fs.walk" "^1.2.8" @@ -7040,9 +7065,8 @@ eslint@^8.19.0, eslint@^8.3.0: doctrine "^3.0.0" escape-string-regexp "^4.0.0" eslint-scope "^7.1.1" - eslint-utils "^3.0.0" eslint-visitor-keys "^3.3.0" - espree "^9.4.0" + espree "^9.5.0" esquery "^1.4.2" esutils "^2.0.2" fast-deep-equal "^3.1.3" @@ -7064,15 +7088,14 @@ eslint@^8.19.0, eslint@^8.3.0: minimatch "^3.1.2" natural-compare "^1.4.0" optionator "^0.9.1" - regexpp "^3.2.0" strip-ansi "^6.0.1" strip-json-comments "^3.1.0" text-table "^0.2.0" -espree@^9.4.0: - version "9.4.1" - resolved "https://registry.yarnpkg.com/espree/-/espree-9.4.1.tgz#51d6092615567a2c2cff7833445e37c28c0065bd" - integrity sha512-XwctdmTO6SIvCzd9810yyNzIrOrqNYV9Koizx4C/mRhf9uq0o4yHoCEU/670pOxOL/MSraektvSAji79kX90Vg== +espree@^9.5.0: + version "9.5.0" + resolved "https://registry.yarnpkg.com/espree/-/espree-9.5.0.tgz#3646d4e3f58907464edba852fa047e6a27bdf113" + integrity sha512-JPbJGhKc47++oo4JkEoTe2wjy4fmMwvFpgJT9cQzmfXKp22Dr6Hf1tdCteLz1h0P3t+mGvWZ+4Uankvh8+c6zw== dependencies: acorn "^8.8.0" acorn-jsx "^5.3.2" @@ -7329,10 +7352,10 @@ expo-manifests@~0.5.0: dependencies: expo-json-utils "~0.5.0" -expo-media-library@~15.2.1: - version "15.2.2" - resolved "https://registry.yarnpkg.com/expo-media-library/-/expo-media-library-15.2.2.tgz#71ece905e425f606422cd16019d78b135040e003" - integrity sha512-GebBavV9H+m0Qzoy4G7++BWmwUcddLnCee1qGYkCyHT6CvuLNhXUgC3FV9NINEwlii3HGAuCzk1auaEY60SGDA== +expo-media-library@~15.2.3: + version "15.2.3" + resolved "https://registry.yarnpkg.com/expo-media-library/-/expo-media-library-15.2.3.tgz#188f3c77f58b354f0ea6250f6756ac1e1a226291" + integrity sha512-Oz8b8Xsvfj7YcutUBtI84NUIqSnt7iCM5HZ5DyKoWKKiDK/+aUuj3RXNQELG8jUw6pQPgEwgbZ1+J8SdH/y9jw== expo-modules-autolinking@1.1.2: version "1.1.2" @@ -7345,10 +7368,10 @@ expo-modules-autolinking@1.1.2: find-up "^5.0.0" fs-extra "^9.1.0" -expo-modules-core@1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/expo-modules-core/-/expo-modules-core-1.2.4.tgz#06c0e92b952ae2d3b3329dbeadb6da4f01965d63" - integrity sha512-AV0NCTy9O8xQqpKgX6gvsDzV1ogpCzYpGxqM85Vw1xHsOF51s7Avu7NdNjBPUZOVuDderUXAvd97dWrtefSKcA== +expo-modules-core@1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/expo-modules-core/-/expo-modules-core-1.2.5.tgz#3f9166f4c32c68ab8ef3e120c70ce9890b711650" + integrity sha512-5pXNlLHNKLayOusAFMbqr27gjgymHuKuWl/Dtbw2MjoyJY1MZCGD2nIJxd1TTcfnyxNxLg6OQmgkyqoBUFqBuw== dependencies: compare-versions "^3.4.0" invariant "^2.2.4" @@ -7382,9 +7405,9 @@ expo-updates-interface@~0.9.0: integrity sha512-wk88LLhseQ7LJvxdN7BTKiryyqALxnrvr+lyHK3/prg76Yy0EGi2Q/oE/rtFyyZ1JmQDRbO/5pdX0EE6QqVQXQ== expo@~48.0.0-beta.2: - version "48.0.6" - resolved "https://registry.yarnpkg.com/expo/-/expo-48.0.6.tgz#374e51a6791bc15e998cd66c335d304ea9c4472a" - integrity sha512-ylm91v/xYjBBEqFHH+mpNyGijJgFXx4NwgKgHCIEfcAQyTZLXpGCL6teOVzAmHCCVF7EdalLl3If/+n09jOi4g== + version "48.0.7" + resolved "https://registry.yarnpkg.com/expo/-/expo-48.0.7.tgz#7900bfda316d25127ed9c412daa31db66dc4a869" + integrity sha512-4sPW+HWm03z72FKIG9IddwEhF9+RlAUsTh8pnsoZjZbXALVikmV3QjD4zp/Dkt9YuiCAnJN1VBaT2AlhbYk2Rg== dependencies: "@babel/runtime" "^7.20.0" "@expo/cli" "0.6.2" @@ -7400,7 +7423,7 @@ expo@~48.0.0-beta.2: expo-font "~11.1.1" expo-keep-awake "~12.0.1" expo-modules-autolinking "1.1.2" - expo-modules-core "1.2.4" + expo-modules-core "1.2.5" fbemitter "^3.0.0" getenv "^1.0.0" invariant "^2.2.4" @@ -7773,9 +7796,9 @@ flatted@^3.1.0: integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ== flow-parser@0.*: - version "0.201.0" - resolved "https://registry.yarnpkg.com/flow-parser/-/flow-parser-0.201.0.tgz#d2005d4dae6fddf60d30f9ae0fb49a13c9c51cfe" - integrity sha512-G4oeDNpNGyIrweF9EnoHatncAihMT0tQgV6NMdyM5I7fhrz9Pr13PJ2KLQ673O4wj9KooTdBpeeYHdDNAQoyyw== + version "0.202.0" + resolved "https://registry.yarnpkg.com/flow-parser/-/flow-parser-0.202.0.tgz#534178266d3ceec5368415e59990db97eece5bd0" + integrity sha512-ZiXxSIXK3zPmY3zrzCofFonM2T+/3Jz5QZKJyPVtUERQEJUnYkXBQ+0H3FzyqiyJs+VXqb/UNU6/K6sziVYdxw== flow-parser@^0.185.0: version "0.185.2" @@ -8191,9 +8214,9 @@ gopd@^1.0.1: get-intrinsic "^1.1.3" graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.3, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.9: - version "4.2.10" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" - integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== grapheme-splitter@^1.0.4: version "1.0.4" @@ -8677,7 +8700,7 @@ internal-ip@4.3.0: default-gateway "^4.2.0" ipaddr.js "^1.9.0" -internal-slot@^1.0.3, internal-slot@^1.0.4: +internal-slot@^1.0.3, internal-slot@^1.0.4, internal-slot@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.5.tgz#f2a2ee21f668f8627a4667f309dc0f4fb6674986" integrity sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ== @@ -8740,7 +8763,7 @@ is-arguments@^1.1.1: call-bind "^1.0.2" has-tostringtag "^1.0.0" -is-array-buffer@^3.0.1: +is-array-buffer@^3.0.1, is-array-buffer@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.2.tgz#f2653ced8412081638ecb0ebbd0c41c6e0aecbbe" integrity sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w== @@ -10128,9 +10151,9 @@ jimp-compact@0.16.1: integrity sha512-dZ6Ra7u1G8c4Letq/B5EzAxj4tLFHL+cGtdpR+PVm4yzPDj+lCk+AbivWt1eOM+ikzkowtyV7qSqX6qr3t71Ww== joi@^17.2.1: - version "17.8.3" - resolved "https://registry.yarnpkg.com/joi/-/joi-17.8.3.tgz#d772fe27a87a5cda21aace5cf11eee8671ca7e6f" - integrity sha512-q5Fn6Tj/jR8PfrLrx4fpGH4v9qM6o+vDUfD4/3vxxyg34OmKcNqYZ1qn2mpLza96S8tL0p0rIw2gOZX+/cTg9w== + version "17.8.4" + resolved "https://registry.yarnpkg.com/joi/-/joi-17.8.4.tgz#f2d91ab8acd3cca4079ba70669c65891739234aa" + integrity sha512-jjdRHb5WtL+KgSHvOULQEPPv4kcl+ixd1ybOFQq3rWLgEEqc03QMmilodL0GVJE14U/SQDXkUhQUSZANGDH/AA== dependencies: "@hapi/hoek" "^9.0.0" "@hapi/topo" "^5.0.0" @@ -10481,6 +10504,14 @@ language-tags@=1.0.5: dependencies: language-subtag-registry "~0.3.2" +launch-editor@^2.6.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/launch-editor/-/launch-editor-2.6.0.tgz#4c0c1a6ac126c572bd9ff9a30da1d2cae66defd7" + integrity sha512-JpDCcQnyAAzZZaZ7vEiSqL690w7dAEyLao+KC96zBplnYbJS7TYNjvM3M7y3dGz+v7aIsJk3hllWuc0kWAjyRQ== + dependencies: + picocolors "^1.0.0" + shell-quote "^1.7.3" + leven@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" @@ -11329,9 +11360,9 @@ min-indent@^1.0.0: integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== mini-css-extract-plugin@^2.4.5, mini-css-extract-plugin@^2.5.2: - version "2.7.3" - resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-2.7.3.tgz#794aa4d598bf178a66b2a35fe287c3df3eac394e" - integrity sha512-CD9cXeKeXLcnMw8FZdtfrRrLaM7gwCl4nKuKn2YkY2Bw5wdlB8zU2cCzw+w2zS9RFvbrufTBkMCJACNPwqQA0w== + version "2.7.5" + resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-2.7.5.tgz#afbb344977659ec0f1f6e050c7aea456b121cfc5" + integrity sha512-9HaR++0mlgom81s95vvNjxkg52n2b5s//3ZTI1EtzFb98awsLSivs2LMsVqnQ3ay0PVhqWcGNyDaTE961FOcjQ== dependencies: schema-utils "^4.0.0" @@ -11395,9 +11426,9 @@ minipass@^3.0.0, minipass@^3.1.1: yallist "^4.0.0" minipass@^4.0.0: - version "4.2.4" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-4.2.4.tgz#7d0d97434b6a19f59c5c3221698b48bbf3b2cd06" - integrity sha512-lwycX3cBMTvcejsHITUgYj6Gy6A7Nh4Q6h9NP4sTHY1ccJlC7yKzDmiShEHsJ16Jf1nKGDEaiHxiltsJEvk0nQ== + version "4.2.5" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-4.2.5.tgz#9e0e5256f1e3513f8c34691dd68549e85b2c8ceb" + integrity sha512-+yQl7SX3bIT83Lhb4BVorMAHVuqsskxRdlmO9kTpyukp8vsm2Sn/fUOV9xlnG8/a5JsypJzap21lz/y3FBMJ8Q== minizlib@^2.1.1: version "2.1.2" @@ -11775,7 +11806,7 @@ object-hash@^3.0.0: resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-3.0.0.tgz#73f97f753e7baffc0e2cc9d6e079079744ac82e9" integrity sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw== -object-inspect@^1.12.2, object-inspect@^1.9.0: +object-inspect@^1.12.3, object-inspect@^1.9.0: version "1.12.3" resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.3.tgz#ba62dffd67ee256c8c086dfae69e016cd1f198b9" integrity sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g== @@ -13340,9 +13371,9 @@ prosemirror-transform@^1.0.0, prosemirror-transform@^1.1.0, prosemirror-transfor prosemirror-model "^1.0.0" prosemirror-view@^1.0.0, prosemirror-view@^1.1.0, prosemirror-view@^1.13.3, prosemirror-view@^1.27.0, prosemirror-view@^1.28.2: - version "1.30.1" - resolved "https://registry.yarnpkg.com/prosemirror-view/-/prosemirror-view-1.30.1.tgz#7cf0ae8dc8553a02c32961e82eca25079c4d8fc9" - integrity sha512-pZUfr7lICJkEY7XwzldAKrkflZDeIvnbfuu2RIS01N5NwJmR/dfZzDzJRzhb3SM2QtT/bM8b4Nnib8X3MGpAhA== + version "1.30.2" + resolved "https://registry.yarnpkg.com/prosemirror-view/-/prosemirror-view-1.30.2.tgz#57a9d15c5baa454f0d0f4a3028ddbd9be1e8ed9b" + integrity sha512-nTNzZvalQf9kHeEyO407LiV6DoOs/pXsid88UqW9Vvybo4ozJW2PJhkfZUxCUF1hR/9vJLdhxX84wuw9P9HsXA== dependencies: prosemirror-model "^1.16.0" prosemirror-state "^1.0.0" @@ -13380,9 +13411,9 @@ punycode@^2.1.0, punycode@^2.1.1: integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA== pure-rand@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/pure-rand/-/pure-rand-6.0.0.tgz#701996ceefa253507923a0e864c17ab421c04a7c" - integrity sha512-rLSBxJjP+4DQOgcJAx6RZHT2he2pkhQdSnofG5VWyVl6GRq/K02ISOuOLcsMOrtKDIJb8JN2zm3FFzWNbezdPw== + version "6.0.1" + resolved "https://registry.yarnpkg.com/pure-rand/-/pure-rand-6.0.1.tgz#31207dddd15d43f299fdcdb2f572df65030c19af" + integrity sha512-t+x1zEHDjBwkDGY5v5ApnZ/utcd4XYDiJsaQQoptTXgUXX95sDg1elCdJghzicm7n2mbCBJ3uYWr6M22SO19rg== q@^1.1.2: version "1.5.1" @@ -13590,9 +13621,9 @@ react-native-appstate-hook@^1.0.6: integrity sha512-0hPVyf5yLxCSVrrNEuGqN1ZnSSj3Ye2gZex0NtcK/AHYwMc0rXWFNZjBKOoZSouspqu3hXBbQ6NOUSTzrME1AQ== react-native-background-fetch@^4.1.8: - version "4.1.8" - resolved "https://registry.yarnpkg.com/react-native-background-fetch/-/react-native-background-fetch-4.1.8.tgz#a21858e5d876de8d9d15a37f40714b244f73713c" - integrity sha512-/qe86laa0n4AbD6mrLL8SCGR+K5693URX95e02/bTJh3UkdS3+sU1Jyc/XTlz4MQwlquI929/lm5EZh8AOUqzQ== + version "4.1.9" + resolved "https://registry.yarnpkg.com/react-native-background-fetch/-/react-native-background-fetch-4.1.9.tgz#10ebff9ca45a8868f1a72b2aa6cea40d499ece6e" + integrity sha512-sk4MCXRhGghBXu9ReabuT8U0WRzjsMt2i/nqCwR9eHi0hux+4kUh5ubpLKLByw5G8WifUv1sp6qsA7uvQERrrQ== react-native-codegen@^0.71.5: version "0.71.5" @@ -13670,10 +13701,10 @@ react-native-linear-gradient@^2.6.2: resolved "https://registry.yarnpkg.com/react-native-linear-gradient/-/react-native-linear-gradient-2.6.2.tgz#56598a76832724b2afa7889747635b5c80948f38" integrity sha512-Z8Xxvupsex+9BBFoSYS87bilNPWcRfRsGC0cpJk72Nxb5p2nEkGSBv73xZbEHnW2mUFvP+huYxrVvjZkr/gRjQ== -react-native-pager-view@^6.1.4: - version "6.1.4" - resolved "https://registry.yarnpkg.com/react-native-pager-view/-/react-native-pager-view-6.1.4.tgz#3a63ebd1b72f81991157ea552bb9c887e529bc8c" - integrity sha512-fmTwgGwPxGCBusKAq7gHzm+s1Yp0qh5rKPoQszaCuxrb+76KgK4Qe82jJNPUp2xTZOKSw+FbJU2QahF8ncTl+w== +react-native-pager-view@6.1.2: + version "6.1.2" + resolved "https://registry.yarnpkg.com/react-native-pager-view/-/react-native-pager-view-6.1.2.tgz#3522079b9a9d6634ca5e8d153bc0b4d660254552" + integrity sha512-qs2KSFc+7N7B+UZ6SG2sTvCkppagm5fVyRclv1KFKc7lDtrhXLzN59tXJw575LDP/dRJoXsNwqUAhZJdws6ABQ== react-native-progress@bluesky-social/react-native-progress: version "5.0.0" @@ -13717,10 +13748,10 @@ react-native-splash-screen@^3.3.0: resolved "https://registry.yarnpkg.com/react-native-splash-screen/-/react-native-splash-screen-3.3.0.tgz#3af71ed17afe50fee69590a45aec399d071ead02" integrity sha512-rGjt6HkoSXxMqH4SQUJ1gnPQlPJV8+J47+4yhgTIan4bVvAwJhEeJH7wWt9hXSdH4+VfwTS0GTaflj1Tw83IhA== -react-native-svg@^13.4.0: - version "13.8.0" - resolved "https://registry.yarnpkg.com/react-native-svg/-/react-native-svg-13.8.0.tgz#b6a22cf77f8098f910490a13aeb160a37e182f97" - integrity sha512-G8Mx6W86da+vFimZBJvA93POw8yz0fgDS5biy6oIjMWVJVQSDzCyzwO/zY0yuZmCDhKSZzogl5m0wXXvW2OcTA== +react-native-svg@13.4.0: + version "13.4.0" + resolved "https://registry.yarnpkg.com/react-native-svg/-/react-native-svg-13.4.0.tgz#82399ba0956c454144618aa581e2d748dd3f010a" + integrity sha512-B3TwK+H0+JuRhYPzF21AgqMt4fjhCwDZ9QUtwNstT5XcslJBXC0FoTkdZo8IEb1Sv4suSqhZwlAY6lwOv3tHag== dependencies: css-select "^5.1.0" css-tree "^1.1.3" @@ -13767,10 +13798,10 @@ react-native-web@^0.18.11: postcss-value-parser "^4.2.0" styleq "^0.1.2" -react-native-webview@^11.26.1: - version "11.26.1" - resolved "https://registry.yarnpkg.com/react-native-webview/-/react-native-webview-11.26.1.tgz#658c09ed5162dc170b361e48c2dd26c9712879da" - integrity sha512-hC7BkxOpf+z0UKhxFSFTPAM4shQzYmZHoELa6/8a/MspcjEP7ukYKpuSUTLDywQditT8yI9idfcKvfZDKQExGw== +react-native-webview@11.26.0: + version "11.26.0" + resolved "https://registry.yarnpkg.com/react-native-webview/-/react-native-webview-11.26.0.tgz#e524992876fe4a79e69905f0fab8949b470e9f16" + integrity sha512-4T4CKRm8xlaQDz9h/bCMPGAvtkesrhkRWqCX9FDJEzBToaVUIsV0ZOqtC4w/JSnCtFKKYiaC1ReJtCGv+4mFeQ== dependencies: escape-string-regexp "2.0.0" invariant "2.2.4" @@ -13932,9 +13963,9 @@ readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@~2.3.6: util-deprecate "~1.0.1" readable-stream@^3.0.6, readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.6.0: - version "3.6.1" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.1.tgz#f9f9b5f536920253b3d26e7660e7da4ccff9bb62" - integrity sha512-+rQmrWMYGA90yenhTYsLWAsLsqVC8osOw6PKE1HDYiO0gdPeKe/xDHNzIAIn4C91YQ6oenEhfYqqc1883qHbjQ== + version "3.6.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== dependencies: inherits "^2.0.3" string_decoder "^1.1.1" @@ -14052,15 +14083,10 @@ regexp.prototype.flags@^1.4.3: define-properties "^1.1.3" functions-have-names "^1.2.2" -regexpp@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" - integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== - regexpu-core@^5.3.1: - version "5.3.1" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-5.3.1.tgz#66900860f88def39a5cb79ebd9490e84f17bcdfb" - integrity sha512-nCOzW2V/X15XpLsK2rlgdwrysrBq+AauCn+omItIz4R1pIcmeot5zvjdmOBRLzEH/CkC6IxMJVmxDe3QcMuNVQ== + version "5.3.2" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-5.3.2.tgz#11a2b06884f3527aec3e93dbbf4a3b958a95546b" + integrity sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ== dependencies: "@babel/regjsgen" "^0.8.0" regenerate "^1.4.2" @@ -14396,9 +14422,9 @@ safe-regex@^1.1.0: ret "~0.1.10" safe-stable-stringify@^2.3.1, safe-stable-stringify@^2.4.1: - version "2.4.2" - resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.4.2.tgz#ec7b037768098bf65310d1d64370de0dc02353aa" - integrity sha512-gMxvPJYhP0O9n2pvcfYfIuYgbledAOJFcqRThtPRmjscaipiwcwPPKLytpVzMkG2HAN87Qmo2d4PtGiri1dSLA== + version "2.4.3" + resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz#138c84b6f6edb3db5f8ef3ef7115b8f55ccbf886" + integrity sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g== "safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0": version "2.1.2" @@ -15078,6 +15104,15 @@ string.prototype.matchall@^4.0.6, string.prototype.matchall@^4.0.8: regexp.prototype.flags "^1.4.3" side-channel "^1.0.4" +string.prototype.trim@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz#a68352740859f6893f14ce3ef1bb3037f7a90533" + integrity sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + string.prototype.trimend@^1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz#c4a27fa026d979d79c04f17397f250a462944533" @@ -15201,9 +15236,9 @@ structured-headers@^0.4.1: integrity sha512-0MP/Cxx5SzeeZ10p/bZI0S6MpgD+yxAhi1BOQ34jgnMXsCq3j1t6tQnZu+KdlL7dvJTLT3g9xN8tl10TqgFMcg== style-loader@^3.3.1: - version "3.3.1" - resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-3.3.1.tgz#057dfa6b3d4d7c7064462830f9113ed417d38575" - integrity sha512-GPcQ+LDJbrcxHORTRes6Jy2sfvK2kS6hpSfI/fXhPt+spVzxF6LJ1dHLN9zIGmVaaP044YKaIatFaufENRiDoQ== + version "3.3.2" + resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-3.3.2.tgz#eaebca714d9e462c19aa1e3599057bc363924899" + integrity sha512-RHs/vcrKdQK8wZliteNK4NKzxvLBzpuHMqYmUVWeKa6MkaIQ97ZTOS0b+zapZhy6GcrgWnvWYCMHRirC3FsUmw== stylehacks@^5.1.1: version "5.1.1" @@ -15483,9 +15518,9 @@ terser-webpack-plugin@^5.1.3, terser-webpack-plugin@^5.2.5, terser-webpack-plugi terser "^5.16.5" terser@^5.0.0, terser@^5.10.0, terser@^5.15.0, terser@^5.16.5: - version "5.16.5" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.16.5.tgz#1c285ca0655f467f92af1bbab46ab72d1cb08e5a" - integrity sha512-qcwfg4+RZa3YvlFh0qjifnzBHjKGNbtDo9yivMqMFDy9Q6FSaQWSB/j1xKhsoUFJIqDOM3TsN6D5xbrMrFcHbg== + version "5.16.6" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.16.6.tgz#f6c7a14a378ee0630fbe3ac8d1f41b4681109533" + integrity sha512-IBZ+ZQIA9sMaXmRZCUMDjNH0D5AQQfdn4WUjHL0+1lF4TP1IHRJbrhb6fNaXWikrYQTSkb7SLxkeXAiy1p7mbg== dependencies: "@jridgewell/source-map" "^0.3.2" acorn "^8.5.0" @@ -15568,9 +15603,9 @@ tippy.js@^6.3.7: "@popperjs/core" "^2.9.0" tlds@^1.234.0: - version "1.237.0" - resolved "https://registry.yarnpkg.com/tlds/-/tlds-1.237.0.tgz#71e5ca558878a046bc9e253db7a1f2b602ce1a2d" - integrity sha512-4IA6zR7jQop4pEdziQaptOgkIwnnZ537fXM3MKAzOXjXLjiHm77SA3/E0nXWJGSVRnKcn/JxDJmwTqyPgQ+ozg== + version "1.238.0" + resolved "https://registry.yarnpkg.com/tlds/-/tlds-1.238.0.tgz#ffe7c19c8940c35b497cda187a6927f9450325a4" + integrity sha512-lFPF9pZFhLrPodaJ0wt9QIN0l8jOxqmUezGZnm7BfkDSVd9q667oVIJukLVzhF+4oW7uDlrLlfJrL5yu9RWwew== tmp@^0.0.33: version "0.0.33" @@ -16088,6 +16123,11 @@ uuid@^8.0.0, uuid@^8.3.2: resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== +uuid@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.0.tgz#592f550650024a38ceb0c562f2f6aa435761efb5" + integrity sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg== + v8-to-istanbul@^8.1.0: version "8.1.1" resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz#77b752fd3975e31bbcef938f85e9bd1c7a8d60ed" @@ -16249,9 +16289,9 @@ webpack-dev-middleware@^5.3.1: schema-utils "^4.0.0" webpack-dev-server@^4.11.1, webpack-dev-server@^4.6.0: - version "4.11.1" - resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-4.11.1.tgz#ae07f0d71ca0438cf88446f09029b92ce81380b5" - integrity sha512-lILVz9tAUy1zGFwieuaQtYiadImb5M3d+H+L1zDYalYoDl0cksAB1UNyuE5MMWJrG6zR1tXkCP2fitl7yoUJiw== + version "4.13.1" + resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-4.13.1.tgz#6417a9b5d2f528e7644b68d6ed335e392dccffe8" + integrity sha512-5tWg00bnWbYgkN+pd5yISQKDejRBYGEw15RaEEslH+zdbNDxxaZvEAO2WulaSaFKb5n3YG8JXsGaDsut1D0xdA== dependencies: "@types/bonjour" "^3.5.9" "@types/connect-history-api-fallback" "^1.3.5" @@ -16272,6 +16312,7 @@ webpack-dev-server@^4.11.1, webpack-dev-server@^4.6.0: html-entities "^2.3.2" http-proxy-middleware "^2.0.3" ipaddr.js "^2.0.1" + launch-editor "^2.6.0" open "^8.0.9" p-retry "^4.5.0" rimraf "^3.0.2" @@ -16281,7 +16322,7 @@ webpack-dev-server@^4.11.1, webpack-dev-server@^4.6.0: sockjs "^0.3.24" spdy "^4.0.2" webpack-dev-middleware "^5.3.1" - ws "^8.4.2" + ws "^8.13.0" webpack-manifest-plugin@^4.0.2, webpack-manifest-plugin@^4.1.1: version "4.1.1" @@ -16321,9 +16362,9 @@ webpack-sources@^3.2.3: integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== webpack@^5.64.4, webpack@^5.75.0: - version "5.76.0" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.76.0.tgz#f9fb9fb8c4a7dbdcd0d56a98e56b8a942ee2692c" - integrity sha512-l5sOdYBDunyf72HW8dF23rFtWq/7Zgvt/9ftMof71E/yUb1YLOBmTgA2K4vQthB3kotMrSj609txVE0dnr2fjA== + version "5.76.2" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.76.2.tgz#6f80d1c1d1e3bf704db571b2504a0461fac80230" + integrity sha512-Th05ggRm23rVzEOlX8y67NkYCHa9nTNcwHPBhdg+lKG+mtiW7XgggjAeeLnADAe7mLjJ6LUNfgHAuRRh+Z6J7w== dependencies: "@types/eslint-scope" "^3.7.3" "@types/estree" "^0.0.51" @@ -16499,9 +16540,9 @@ wonka@^4.0.14: integrity sha512-U0IUQHKXXn6PFo9nqsHphVCE5m3IntqZNB9Jjn7EB1lrR7YTDY3YWgFvEvwniTzXSvOH/XMzAZaIfJF/LvHYXg== wonka@^6.1.2: - version "6.2.3" - resolved "https://registry.yarnpkg.com/wonka/-/wonka-6.2.3.tgz#88f7852a23a3d53bca7411c70d66e9ce8f93a366" - integrity sha512-EFOYiqDeYLXSzGYt2X3aVe9Hq1XJG+Hz/HjTRRT4dZE9q95khHl5+7pzUSXI19dbMO1/2UMrTf7JT7/7JrSQSQ== + version "6.2.5" + resolved "https://registry.yarnpkg.com/wonka/-/wonka-6.2.5.tgz#26e54a6827b96a6164b845106f4d925ede4089bb" + integrity sha512-adhGYKm5xWIZYXRkzEqHbRbRl2gXHqOudjQJMXpRgSyboFmaKOjGm3RIThBk4tZdiZx1DXuKK0H9wKBgXHhzZg== word-wrap@^1.2.3, word-wrap@~1.2.3: version "1.2.3" @@ -16744,10 +16785,10 @@ ws@^7, ws@^7.0.0, ws@^7.4.6, ws@^7.5.1: resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591" integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q== -ws@^8.11.0, ws@^8.4.2: - version "8.12.1" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.12.1.tgz#c51e583d79140b5e42e39be48c934131942d4a8f" - integrity sha512-1qo+M9Ba+xNhPB+YTWUlK6M17brTut5EXbcBaMRN5pH5dFrXz7lzz1ChFSUq3bOUl8yEvSenhHmYUNJxFzdJew== +ws@^8.11.0, ws@^8.13.0: + version "8.13.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.13.0.tgz#9a9fb92f93cf41512a0735c8f4dd09b8a1211cd0" + integrity sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA== xcode@^3.0.0, xcode@^3.0.1: version "3.0.1" From 4787c8383d09550e0ec845a7926298e6cc084d7d Mon Sep 17 00:00:00 2001 From: Paul Frazee Date: Sun, 19 Mar 2023 18:47:49 -0500 Subject: [PATCH 23/24] Add language filtering to goodstuff --- package.json | 1 + src/lib/api/feed-manip.ts | 29 ++++++++++++++++++++++ src/state/models/feed-view.ts | 35 +++++++++++++-------------- src/view/com/util/pager/Pager.web.tsx | 6 ++++- yarn.lock | 12 +++++++++ 5 files changed, 64 insertions(+), 19 deletions(-) diff --git a/package.json b/package.json index 796c7aee..33c72458 100644 --- a/package.json +++ b/package.json @@ -65,6 +65,7 @@ "he": "^1.2.0", "history": "^5.3.0", "js-sha256": "^0.9.0", + "lande": "^1.0.10", "lodash.chunk": "^4.2.0", "lodash.clonedeep": "^4.5.0", "lodash.debounce": "^4.0.8", diff --git a/src/lib/api/feed-manip.ts b/src/lib/api/feed-manip.ts index 7abcaffc..67ca8f95 100644 --- a/src/lib/api/feed-manip.ts +++ b/src/lib/api/feed-manip.ts @@ -1,5 +1,7 @@ import {AppBskyFeedFeedViewPost} from '@atproto/api' +import lande from 'lande' type FeedViewPost = AppBskyFeedFeedViewPost.Main +import {hasProp} from '@atproto/lexicon' export type FeedTunerFn = ( tuner: FeedTuner, @@ -178,6 +180,33 @@ export class FeedTuner { } } } + + static englishOnly(tuner: FeedTuner, slices: FeedViewPostsSlice[]) { + // TEMP + // remove slices with no english in them + // we very soon need to get the local user's language and filter + // according to their preferences, but for the moment + // we're just rolling with english + // -prf + for (let i = slices.length - 1; i >= 0; i--) { + let hasEnglish = false + for (const item of slices[i].items) { + if ( + hasProp(item.post.record, 'text') && + typeof item.post.record.text === 'string' + ) { + const res = lande(item.post.record.text) + if (res[0][0] === 'eng') { + hasEnglish = true + break + } + } + } + if (!hasEnglish) { + slices.splice(i, 1) + } + } + } } function getSelfReplyUri(item: FeedViewPost): string | undefined { diff --git a/src/state/models/feed-view.ts b/src/state/models/feed-view.ts index 664d6bd0..c412065d 100644 --- a/src/state/models/feed-view.ts +++ b/src/state/models/feed-view.ts @@ -336,6 +336,20 @@ export class FeedModel { return this.setup() } + private get feedTuners() { + if (this.feedType === 'goodstuff') { + return [ + FeedTuner.dedupReposts, + FeedTuner.likedRepliesOnly, + FeedTuner.englishOnly, + ] + } + if (this.feedType === 'home') { + return [FeedTuner.dedupReposts, FeedTuner.likedRepliesOnly] + } + return [] + } + /** * Load for first render */ @@ -477,12 +491,7 @@ export class FeedModel { } const res = await this._getFeed({limit: 1}) const currentLatestUri = this.pollCursor - const slices = this.tuner.tune( - res.data.feed, - this.feedType === 'home' - ? [FeedTuner.dedupReposts, FeedTuner.likedRepliesOnly] - : [], - ) + const slices = this.tuner.tune(res.data.feed, this.feedTuners) const item = slices[0]?.rootItem if (!item) { return @@ -548,12 +557,7 @@ export class FeedModel { this.loadMoreCursor = res.data.cursor this.hasMore = !!this.loadMoreCursor - const slices = this.tuner.tune( - res.data.feed, - this.feedType === 'home' - ? [FeedTuner.dedupReposts, FeedTuner.likedRepliesOnly] - : [], - ) + const slices = this.tuner.tune(res.data.feed, this.feedTuners) const toAppend: FeedSliceModel[] = [] for (const slice of slices) { @@ -578,12 +582,7 @@ export class FeedModel { ) { this.pollCursor = res.data.feed[0]?.post.uri - const slices = this.tuner.tune( - res.data.feed, - this.feedType === 'home' - ? [FeedTuner.dedupReposts, FeedTuner.likedRepliesOnly] - : [], - ) + const slices = this.tuner.tune(res.data.feed, this.feedTuners) const toPrepend: FeedSliceModel[] = [] for (const slice of slices) { diff --git a/src/view/com/util/pager/Pager.web.tsx b/src/view/com/util/pager/Pager.web.tsx index d50100de..3c280583 100644 --- a/src/view/com/util/pager/Pager.web.tsx +++ b/src/view/com/util/pager/Pager.web.tsx @@ -51,7 +51,11 @@ export const Pager = ({ onSelect: onTabBarSelect, })} {children.map((child, i) => ( - {child} + + {child} + ))} {tabBarPosition === 'bottom' && renderTabBar({ diff --git a/yarn.lock b/yarn.lock index 6d7564be..f3b747e8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10492,6 +10492,13 @@ kysely@^0.22.0: resolved "https://registry.yarnpkg.com/kysely/-/kysely-0.22.0.tgz#8aac53942da3cadc604d7d154a746d983fe8f7b9" integrity sha512-ZE3qWtnqLOalodzfK5QUEcm7AEulhxsPNuKaGFsC3XiqO92vMLm+mAHk/NnbSIOtC4RmGm0nsv700i8KDp1gfQ== +lande@^1.0.10: + version "1.0.10" + resolved "https://registry.yarnpkg.com/lande/-/lande-1.0.10.tgz#1f6c6542e628338eb18def22edd1038f5fce9e7a" + integrity sha512-yT52DQh+UV2pEp08jOYrA4drDv0DbjpiRyZYgl25ak9G2cVR2AimzrqkYQWrD9a7Ud+qkAcaiDDoNH9DXfHPmw== + dependencies: + toygrad "^2.6.0" + language-subtag-registry@~0.3.2: version "0.3.22" resolved "https://registry.yarnpkg.com/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz#2e1500861b2e457eba7e7ae86877cbd08fa1fd1d" @@ -15679,6 +15686,11 @@ tough-cookie@^4.0.0, tough-cookie@^4.1.2: universalify "^0.2.0" url-parse "^1.5.3" +toygrad@^2.6.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/toygrad/-/toygrad-2.6.0.tgz#e814bb7da026db8e08dc7da14c7155f49cdb4d54" + integrity sha512-g4zBmlSbvzOE5FOILxYkAybTSxijKLkj1WoNqVGnbMcWDyj4wWQ+eYSr3ik7XOpIgMq/7eBcPRTJX3DM2E0YMg== + tr46@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/tr46/-/tr46-1.0.1.tgz#a8b13fd6bfd2489519674ccde55ba3693b706d09" From 994332af917418c833ffd092e8ded904a0030212 Mon Sep 17 00:00:00 2001 From: Paul Frazee Date: Sun, 19 Mar 2023 19:02:55 -0500 Subject: [PATCH 24/24] Add missing deps and an atob polyfill --- ios/Podfile.lock | 6 +++++ package.json | 1 + src/platform/polyfills.ts | 49 +++++++++++++++++++++++++++++++++++++++ yarn.lock | 12 ++++++++++ 4 files changed, 68 insertions(+) diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 12f262dd..f0de3762 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -386,6 +386,8 @@ PODS: - React-Core - react-native-cameraroll (5.3.1): - React-Core + - react-native-get-random-values (1.8.0): + - React-Core - react-native-image-resizer (3.0.5): - React-Core - react-native-pager-view (6.1.2): @@ -615,6 +617,7 @@ DEPENDENCIES: - React-logger (from `../node_modules/react-native/ReactCommon/logger`) - "react-native-blur (from `../node_modules/@react-native-community/blur`)" - "react-native-cameraroll (from `../node_modules/@react-native-camera-roll/camera-roll`)" + - react-native-get-random-values (from `../node_modules/react-native-get-random-values`) - "react-native-image-resizer (from `../node_modules/@bam.tech/react-native-image-resizer`)" - react-native-pager-view (from `../node_modules/react-native-pager-view`) - "react-native-paste-input (from `../node_modules/@mattermost/react-native-paste-input`)" @@ -748,6 +751,8 @@ EXTERNAL SOURCES: :path: "../node_modules/@react-native-community/blur" react-native-cameraroll: :path: "../node_modules/@react-native-camera-roll/camera-roll" + react-native-get-random-values: + :path: "../node_modules/react-native-get-random-values" react-native-image-resizer: :path: "../node_modules/@bam.tech/react-native-image-resizer" react-native-pager-view: @@ -869,6 +874,7 @@ SPEC CHECKSUMS: React-logger: 957e5dc96d9dbffc6e0f15e0ee4d2b42829ff207 react-native-blur: 50c9feabacbc5f49b61337ebc32192c6be7ec3c3 react-native-cameraroll: f3050460fe1708378698c16686bfaa5f34099be2 + react-native-get-random-values: a6ea6a8a65dc93e96e24a11105b1a9c8cfe1d72a react-native-image-resizer: 00ceb0e05586c7aadf061eea676957a6c2ec60fa react-native-pager-view: 54bed894cecebe28cede54c01038d9d1e122de43 react-native-paste-input: 3392800944a47c00dddbff23c31c281482209679 diff --git a/package.json b/package.json index 33c72458..194c649e 100644 --- a/package.json +++ b/package.json @@ -90,6 +90,7 @@ "react-native-fast-image": "^8.6.3", "react-native-fs": "^2.20.0", "react-native-gesture-handler": "~2.9.0", + "react-native-get-random-values": "^1.8.0", "react-native-haptic-feedback": "^1.14.0", "react-native-image-crop-picker": "^0.38.1", "react-native-inappbrowser-reborn": "^3.6.3", diff --git a/src/platform/polyfills.ts b/src/platform/polyfills.ts index 336ce12b..3dbd1398 100644 --- a/src/platform/polyfills.ts +++ b/src/platform/polyfills.ts @@ -1 +1,50 @@ export {} + +/** +https://github.com/MaxArt2501/base64-js +The MIT License (MIT) +Copyright (c) 2014 MaxArt2501 + */ + +const b64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=' +// Regular expression to check formal correctness of base64 encoded strings +const b64re = + /^(?:[A-Za-z\d+\/]{4})*?(?:[A-Za-z\d+\/]{2}(?:==)?|[A-Za-z\d+\/]{3}=?)?$/ + +globalThis.atob = (str: string): string => { + // atob can work with strings with whitespaces, even inside the encoded part, + // but only \t, \n, \f, \r and ' ', which can be stripped. + str = String(str).replace(/[\t\n\f\r ]+/g, '') + if (!b64re.test(str)) { + throw new TypeError( + "Failed to execute 'atob' on 'Window': The string to be decoded is not correctly encoded.", + ) + } + + // Adding the padding if missing, for semplicity + str += '=='.slice(2 - (str.length & 3)) + var bitmap, + result = '', + r1, + r2, + i = 0 + for (; i < str.length; ) { + bitmap = + (b64.indexOf(str.charAt(i++)) << 18) | + (b64.indexOf(str.charAt(i++)) << 12) | + ((r1 = b64.indexOf(str.charAt(i++))) << 6) | + (r2 = b64.indexOf(str.charAt(i++))) + + result += + r1 === 64 + ? String.fromCharCode((bitmap >> 16) & 255) + : r2 === 64 + ? String.fromCharCode((bitmap >> 16) & 255, (bitmap >> 8) & 255) + : String.fromCharCode( + (bitmap >> 16) & 255, + (bitmap >> 8) & 255, + bitmap & 255, + ) + } + return result +} diff --git a/yarn.lock b/yarn.lock index f3b747e8..19ed4cda 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7503,6 +7503,11 @@ extglob@^2.0.4: snapdragon "^0.8.1" to-regex "^3.0.1" +fast-base64-decode@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fast-base64-decode/-/fast-base64-decode-1.0.0.tgz#b434a0dd7d92b12b43f26819300d2dafb83ee418" + integrity sha512-qwaScUgUGBYeDNRnbc/KyllVU88Jk1pRHPStuF/lO7B0/RTRLj7U0lkdTAutlBblY08rwZDff6tNU9cjv6j//Q== + fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" @@ -13680,6 +13685,13 @@ react-native-gesture-handler@~2.9.0: lodash "^4.17.21" prop-types "^15.7.2" +react-native-get-random-values@^1.8.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/react-native-get-random-values/-/react-native-get-random-values-1.8.0.tgz#1cb4bd4bd3966a356e59697b8f372999fe97cb16" + integrity sha512-H/zghhun0T+UIJLmig3+ZuBCvF66rdbiWUfRSNS6kv5oDSpa1ZiVyvRWtuPesQpT8dXj+Bv7WJRQOUP+5TB1sA== + dependencies: + fast-base64-decode "^1.0.0" + react-native-gradle-plugin@^0.71.15: version "0.71.16" resolved "https://registry.yarnpkg.com/react-native-gradle-plugin/-/react-native-gradle-plugin-0.71.16.tgz#822bb0c680e03b5df5aa65f2e5ffc2bc2930854a"