diff --git a/.envrc.example b/.envrc.example index 0cf681c7..70045951 100644 --- a/.envrc.example +++ b/.envrc.example @@ -5,6 +5,8 @@ export SENTRY_PROJECT="" export SENTRY_AUTH_TOKEN="" export SENTRY_DSN="" +export TRANSLATE_KEY="" + # Fastlane start export LC_ALL="" export LANG="" diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 089a1ea3..9bd506fc 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -40,6 +40,7 @@ jobs: SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }} SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} SENTRY_DSN: ${{ secrets.SENTRY_DSN }} + TRANSLATE_KEY: ${{ secrets.TRANSLATE_KEY }} FASTLANE_USER: ${{ secrets.FASTLANE_USER }} MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} MATCH_GIT_URL: ${{ secrets.MATCH_GIT_URL }} diff --git a/Gemfile.lock b/Gemfile.lock index d11b8c6b..2fe8dde7 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -15,7 +15,7 @@ GEM artifactory (3.0.15) atomos (0.1.3) aws-eventstream (1.1.1) - aws-partitions (1.445.0) + aws-partitions (1.455.0) aws-sdk-core (3.114.0) aws-eventstream (~> 1, >= 1.0.2) aws-partitions (~> 1, >= 1.239.0) @@ -24,7 +24,7 @@ GEM aws-sdk-kms (1.43.0) aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-s3 (1.93.1) + aws-sdk-s3 (1.94.1) aws-sdk-core (~> 3, >= 3.112.0) aws-sdk-kms (~> 1) aws-sigv4 (~> 1.1) @@ -71,10 +71,9 @@ GEM cocoapods-try (1.2.0) colored (1.2) colored2 (3.1.2) - commander-fastlane (4.4.6) - highline (~> 1.7.2) + commander (4.6.0) + highline (~> 2.0.0) concurrent-ruby (1.1.8) - connection_pool (2.2.5) declarative (0.0.20) digest-crc (0.6.3) rake (>= 12.0.0, < 14.0.0) @@ -85,25 +84,23 @@ GEM escape (0.0.4) ethon (0.12.0) ffi (>= 1.3.0) - excon (0.80.1) - faraday (1.4.0) - faraday-excon (~> 1.0) + excon (0.81.0) + faraday (1.4.1) + faraday-excon (~> 1.1) faraday-net_http (~> 1.0) - faraday-net_http_persistent (~> 1.0) + faraday-net_http_persistent (~> 1.1) multipart-post (>= 1.2, < 3) ruby2_keywords (>= 0.0.4) faraday-cookie_jar (0.0.7) faraday (>= 0.8.0) http-cookie (~> 1.0.0) - faraday-excon (1.0.0) - excon (>= 0.27.4) + faraday-excon (1.1.0) faraday-net_http (1.0.1) - faraday-net_http_persistent (1.0.3) - net-http-persistent (>= 3.1) + faraday-net_http_persistent (1.1.0) faraday_middleware (1.0.0) faraday (~> 1.0) fastimage (2.2.3) - fastlane (2.180.1) + fastlane (2.182.0) CFPropertyList (>= 2.3, < 4.0.0) addressable (>= 2.3, < 3.0.0) artifactory (~> 3.0) @@ -111,7 +108,7 @@ GEM babosa (>= 1.0.3, < 2.0.0) bundler (>= 1.12.0, < 3.0.0) colored - commander-fastlane (>= 4.4.6, < 5.0.0) + commander (~> 4.6) dotenv (>= 2.1.1, < 3.0.0) emoji_regex (>= 0.1, < 4.0) excon (>= 0.71.0, < 1.0.0) @@ -122,7 +119,7 @@ GEM gh_inspector (>= 1.1.2, < 2.0.0) google-api-client (>= 0.37.0, < 0.39.0) google-cloud-storage (>= 1.15.0, < 2.0.0) - highline (>= 1.7.2, < 2.0.0) + highline (~> 2.0) json (< 3.0.0) jwt (>= 2.1.0, < 3) mini_magick (>= 4.9.4, < 5.0.0) @@ -132,7 +129,6 @@ GEM rubyzip (>= 2.0.0, < 3.0.0) security (= 0.1.3) simctl (~> 1.6.3) - slack-notifier (>= 2.0.0, < 3.0.0) terminal-notifier (>= 2.0.0, < 3.0.0) terminal-table (>= 1.4.5, < 2.0.0) tty-screen (>= 0.6.3, < 1.0.0) @@ -185,14 +181,14 @@ GEM google-cloud-core (~> 1.2) googleauth (~> 0.9) mini_mime (~> 1.0) - googleauth (0.16.1) + googleauth (0.16.2) faraday (>= 0.17.3, < 2.0) jwt (>= 1.4, < 3.0) memoist (~> 0.16) multi_json (~> 1.11) os (>= 0.9, < 2.0) signet (~> 0.14) - highline (1.7.10) + highline (2.0.3) http-cookie (1.0.3) domain_name (~> 0.5) httpclient (2.8.3) @@ -200,7 +196,7 @@ GEM concurrent-ruby (~> 1.0) jmespath (1.4.0) json (2.5.1) - jwt (2.2.2) + jwt (2.2.3) memoist (0.16.2) mini_magick (4.11.0) mini_mime (1.1.0) @@ -211,8 +207,6 @@ GEM nanaimo (0.3.0) nap (1.1.0) naturally (2.2.1) - net-http-persistent (4.0.1) - connection_pool (~> 2.2) netrc (0.11.0) os (1.1.1) plist (3.6.0) @@ -237,7 +231,6 @@ GEM simctl (1.6.8) CFPropertyList naturally - slack-notifier (2.3.2) terminal-notifier (2.0.0) terminal-table (1.8.0) unicode-display_width (~> 1.1, >= 1.1.1) diff --git a/README.md b/README.md index a3292129..88871488 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # [tooot](https://tooot.app/) app for Mastodon -[![GPL-3.0](https://img.shields.io/github/license/tooot-app/push?style=flat-square)](LICENSE) ![GitHub issues](https://img.shields.io/github/issues/tooot-app/app?style=flat-square) ![GitHub release (latest by date including pre-releases)](https://img.shields.io/github/v/release/tooot-app/app?include_prereleases&style=flat-square) ![Code Climate maintainability](https://img.shields.io/codeclimate/maintainability/tooot-app/app?style=flat-square) [![Crowdin](https://badges.crowdin.net/tooot/localized.svg)](https://crowdin.tooot.app/project/tooot) +[![GPL-3.0](https://img.shields.io/github/license/tooot-app/push)](LICENSE) ![GitHub issues](https://img.shields.io/github/issues/tooot-app/app) ![GitHub release (latest by date including pre-releases)](https://img.shields.io/github/v/release/tooot-app/app?include_prereleases) ![Code Climate maintainability](https://img.shields.io/codeclimate/maintainability/tooot-app/app) [![Crowdin](https://badges.crowdin.net/tooot/localized.svg)](https://crowdin.tooot.app/project/tooot) -![GitHub Workflow Status](https://img.shields.io/github/workflow/status/tooot-app/app/build?style=flat-square) ![GitHub Workflow Status (branch)](https://img.shields.io/github/workflow/status/tooot-app/app/build/candidate?label=build%20candidate&style=flat-square) ![GitHub Workflow Status (branch)](https://img.shields.io/github/workflow/status/tooot-app/app/build/release?label=build%20release&style=flat-square) +![GitHub Workflow Status](https://img.shields.io/github/workflow/status/tooot-app/app/build) ![GitHub Workflow Status (branch)](https://img.shields.io/github/workflow/status/tooot-app/app/build/candidate?label=build%20candidate) ![GitHub Workflow Status (branch)](https://img.shields.io/github/workflow/status/tooot-app/app/build/release?label=build%20release) diff --git a/android/app/src/main/java/com/xmflsct/app/tooot/generated/BasePackageList.java b/android/app/src/main/java/com/xmflsct/app/tooot/generated/BasePackageList.java index 08d117d7..b7aecbc5 100644 --- a/android/app/src/main/java/com/xmflsct/app/tooot/generated/BasePackageList.java +++ b/android/app/src/main/java/com/xmflsct/app/tooot/generated/BasePackageList.java @@ -8,8 +8,8 @@ public class BasePackageList { public List getPackageList() { return Arrays.asList( new expo.modules.application.ApplicationPackage(), - new expo.modules.constants.ConstantsPackage(), new expo.modules.av.AVPackage(), + new expo.modules.constants.ConstantsPackage(), new expo.modules.crypto.CryptoPackage(), new expo.modules.device.DevicePackage(), new expo.modules.errorrecovery.ErrorRecoveryPackage(), @@ -19,17 +19,15 @@ public class BasePackageList { new expo.modules.font.FontLoaderPackage(), new expo.modules.haptics.HapticsPackage(), new expo.modules.imageloader.ImageLoaderPackage(), - new expo.modules.permissions.PermissionsPackage(), + new expo.modules.imagemanipulator.ImageManipulatorPackage(), new expo.modules.imagepicker.ImagePickerPackage(), new expo.modules.keepawake.KeepAwakePackage(), - new expo.modules.lineargradient.LinearGradientPackage(), new expo.modules.localization.LocalizationPackage(), - new expo.modules.location.LocationPackage(), new expo.modules.notifications.NotificationsPackage(), + new expo.modules.permissions.PermissionsPackage(), new expo.modules.screencapture.ScreenCapturePackage(), new expo.modules.securestore.SecureStorePackage(), new expo.modules.splashscreen.SplashScreenPackage(), - new expo.modules.sqlite.SQLitePackage(), new expo.modules.storereview.StoreReviewPackage(), new expo.modules.updates.UpdatesPackage(), new expo.modules.videothumbnails.VideoThumbnailsPackage(), diff --git a/android/build.gradle b/android/build.gradle index de819db2..014c558e 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -4,8 +4,8 @@ buildscript { ext { buildToolsVersion = "29.0.3" minSdkVersion = 21 - compileSdkVersion = 29 - targetSdkVersion = 29 + compileSdkVersion = 30 + targetSdkVersion = 30 ndkVersion = "20.1.5948944" } repositories { diff --git a/app.config.ts b/app.config.ts index 692a247b..7882a256 100644 --- a/app.config.ts +++ b/app.config.ts @@ -13,7 +13,8 @@ export default (): ExpoConfig => ({ privacy: 'hidden', assetBundlePatterns: ['assets/*'], extra: { - sentryDSN: process.env.SENTRY_DSN + sentryDSN: process.env.SENTRY_DSN, + translateKey: process.env.TRANSLATE_KEY }, hooks: { postPublish: [ diff --git a/babel.config.js b/babel.config.js index dd162868..576c1c12 100644 --- a/babel.config.js +++ b/babel.config.js @@ -11,6 +11,7 @@ module.exports = function (api) { '@assets': './assets', '@root': './src', '@api': './src/api', + '@helpers': './src/helpers', '@components': './src/components', '@screens': './src/screens', '@utils': './src/utils' diff --git a/fastlane/Deliverfile b/fastlane/Deliverfile index 76ebd1fa..966e0dd0 100644 --- a/fastlane/Deliverfile +++ b/fastlane/Deliverfile @@ -27,9 +27,4 @@ submission_information({ add_id_info_tracks_action: false, add_id_info_tracks_install: false, add_id_info_uses_idfa: true -}) - -release_notes({ - 'zh-Hans' => "添加支持修改账户信息", - 'en-US' => "Added the possibility to update account information" }) \ No newline at end of file diff --git a/fastlane/Fastfile b/fastlane/Fastfile index a2a11877..ba915952 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -109,8 +109,8 @@ private_lane :build_ios do upload_to_app_store( ipa: IPA_FILE, app_version: VERSION ) else if !is_ci - match( type: "development", readonly: true ) - build_ios_app( export_method: "development", output_directory: BUILD_DIRECTORY, silent: true ) + match( type: "adhoc", readonly: true ) + build_ios_app( export_method: "ad-hoc", output_directory: BUILD_DIRECTORY, silent: true ) install_on_device( skip_wifi: true ) end end diff --git a/fastlane/metadata/en-US/release_notes.txt b/fastlane/metadata/en-US/release_notes.txt index 8b137891..bd3b8146 100644 --- a/fastlane/metadata/en-US/release_notes.txt +++ b/fastlane/metadata/en-US/release_notes.txt @@ -1 +1,2 @@ - +Added translation option, translation service is provided by various providers +When updating profile, now avatar and banner can be uploaded diff --git a/fastlane/metadata/zh-Hans/release_notes.txt b/fastlane/metadata/zh-Hans/release_notes.txt index 8b137891..74a22c55 100644 --- a/fastlane/metadata/zh-Hans/release_notes.txt +++ b/fastlane/metadata/zh-Hans/release_notes.txt @@ -1 +1,2 @@ - +加入翻译嘟文支持,翻译服务由多个服务商提供 +修改个人信息里可以上传头像及横幅 diff --git a/ios/Podfile.lock b/ios/Podfile.lock index eaec2492..b70113fb 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -1,166 +1,159 @@ PODS: - boost-for-react-native (1.63.0) - DoubleConversion (1.1.6) - - EXApplication (3.0.0): + - EXApplication (3.1.2): - UMCore - - EXAV (9.0.0): + - EXAV (9.1.2): - UMCore - UMFileSystemInterface - UMPermissionsInterface - - EXConstants (10.0.1): + - EXConstants (10.1.3): - UMConstantsInterface - UMCore - - EXCrypto (9.0.0): + - EXCrypto (9.1.0): - UMCore - EXDevice (2.4.0): - UMCore - - EXErrorRecovery (1.4.0): + - EXErrorRecovery (2.1.0): - UMCore - - EXFileSystem (9.3.0): + - EXFileSystem (11.0.2): - UMCore - UMFileSystemInterface - - EXFirebaseAnalytics (3.0.0): + - EXFirebaseAnalytics (4.0.2): - EXFirebaseCore - - Firebase/Core (= 6.14.0) + - Firebase/Core (= 7.7.0) - UMCore - - EXFirebaseCore (2.0.0): - - Firebase/Core (= 6.14.0) + - EXFirebaseCore (3.0.0): + - Firebase/Core (= 7.7.0) - UMCore - - EXFont (8.4.0): + - EXFont (9.1.0): - UMCore - UMFontInterface - - EXHaptics (9.0.0): + - EXHaptics (10.0.0): - UMCore - - EXImageLoader (1.3.0): + - EXImageLoader (2.1.1): - React-Core - UMCore - UMImageLoaderInterface - - EXImagePicker (10.0.0): + - EXImageManipulator (9.1.0): + - UMCore + - UMFileSystemInterface + - UMImageLoaderInterface + - EXImagePicker (10.1.4): - UMCore - UMFileSystemInterface - UMPermissionsInterface - - EXKeepAwake (8.4.0): + - EXKeepAwake (9.1.2): - UMCore - - EXLinearGradient (8.4.0): + - EXLocalization (10.1.0): - UMCore - - EXLocalization (10.0.0): - - UMCore - - EXLocation (10.0.0): + - EXNotifications (0.11.6): - UMCore - UMPermissionsInterface - - UMTaskManagerInterface - - EXNotifications (0.9.0): + - EXPermissions (12.0.1): - UMCore - UMPermissionsInterface - - EXPermissions (11.0.0): - - UMCore - - UMPermissionsInterface - - EXRandom (11.0.0): + - EXRandom (11.1.2): - React-Core - - EXScreenCapture (3.0.0): + - EXScreenCapture (3.1.0): - UMCore - - EXSecureStore (9.3.0): + - EXSecureStore (10.1.0): - UMCore - - EXSplashScreen (0.9.0): + - EXSplashScreen (0.10.2): - React-Core - UMCore - - EXSQLite (8.5.0): - - UMCore - - UMFileSystemInterface - - EXStoreReview (3.0.0): + - EXStoreReview (4.0.2): - UMCore - EXUpdates (0.3.5): - React - UMCore - - EXVideoThumbnails (5.0.0): + - EXVideoThumbnails (5.1.0): - UMCore - UMFileSystemInterface - - EXWebBrowser (9.0.0): + - EXWebBrowser (9.1.0): - UMCore - - FBLazyVector (0.64.0) - - FBReactNativeSpec (0.64.0): + - FBLazyVector (0.64.1) + - FBReactNativeSpec (0.64.1): - RCT-Folly (= 2020.01.13.00) - - RCTRequired (= 0.64.0) - - RCTTypeSafety (= 0.64.0) - - React-Core (= 0.64.0) - - React-jsi (= 0.64.0) - - ReactCommon/turbomodule/core (= 0.64.0) - - Firebase/Core (6.14.0): + - RCTRequired (= 0.64.1) + - RCTTypeSafety (= 0.64.1) + - React-Core (= 0.64.1) + - React-jsi (= 0.64.1) + - ReactCommon/turbomodule/core (= 0.64.1) + - Firebase/Core (7.7.0): - Firebase/CoreOnly - - FirebaseAnalytics (= 6.1.7) - - Firebase/CoreOnly (6.14.0): - - FirebaseCore (= 6.5.0) - - FirebaseAnalytics (6.1.7): - - FirebaseCore (~> 6.5) - - FirebaseInstanceID (~> 4.2) - - GoogleAppMeasurement (= 6.1.7) - - GoogleUtilities/AppDelegateSwizzler (~> 6.0) - - GoogleUtilities/MethodSwizzler (~> 6.0) - - GoogleUtilities/Network (~> 6.0) - - "GoogleUtilities/NSData+zlib (~> 6.0)" - - nanopb (= 0.3.9011) - - FirebaseCore (6.5.0): - - FirebaseCoreDiagnostics (~> 1.0) - - FirebaseCoreDiagnosticsInterop (~> 1.0) - - GoogleUtilities/Environment (~> 6.4) - - GoogleUtilities/Logger (~> 6.4) - - FirebaseCoreDiagnostics (1.2.4): - - FirebaseCoreDiagnosticsInterop (~> 1.2) - - GoogleDataTransportCCTSupport (~> 3.0) - - GoogleUtilities/Environment (~> 6.5) - - GoogleUtilities/Logger (~> 6.5) - - nanopb (~> 0.3.901) - - FirebaseCoreDiagnosticsInterop (1.2.0) - - FirebaseInstanceID (4.2.8): - - FirebaseCore (~> 6.5) - - GoogleUtilities/Environment (~> 6.4) - - GoogleUtilities/UserDefaults (~> 6.4) + - FirebaseAnalytics (= 7.7.0) + - Firebase/CoreOnly (7.7.0): + - FirebaseCore (= 7.7.0) + - FirebaseAnalytics (7.7.0): + - FirebaseCore (~> 7.0) + - FirebaseInstallations (~> 7.0) + - GoogleAppMeasurement (= 7.7.0) + - GoogleUtilities/AppDelegateSwizzler (~> 7.0) + - GoogleUtilities/MethodSwizzler (~> 7.0) + - GoogleUtilities/Network (~> 7.0) + - "GoogleUtilities/NSData+zlib (~> 7.0)" + - nanopb (~> 2.30907.0) + - FirebaseCore (7.7.0): + - FirebaseCoreDiagnostics (~> 7.4) + - GoogleUtilities/Environment (~> 7.0) + - GoogleUtilities/Logger (~> 7.0) + - FirebaseCoreDiagnostics (7.9.0): + - GoogleDataTransport (~> 8.0) + - GoogleUtilities/Environment (~> 7.0) + - GoogleUtilities/Logger (~> 7.0) + - nanopb (~> 2.30907.0) + - FirebaseInstallations (7.11.0): + - FirebaseCore (~> 7.0) + - GoogleUtilities/Environment (~> 7.0) + - GoogleUtilities/UserDefaults (~> 7.0) + - PromisesObjC (~> 1.2) - glog (0.3.5) - - GoogleAppMeasurement (6.1.7): - - GoogleUtilities/AppDelegateSwizzler (~> 6.0) - - GoogleUtilities/MethodSwizzler (~> 6.0) - - GoogleUtilities/Network (~> 6.0) - - "GoogleUtilities/NSData+zlib (~> 6.0)" - - nanopb (= 0.3.9011) - - GoogleDataTransport (6.2.1) - - GoogleDataTransportCCTSupport (3.0.0): - - GoogleDataTransport (~> 6.0) - - nanopb (~> 0.3.901) - - GoogleUtilities/AppDelegateSwizzler (6.7.2): + - GoogleAppMeasurement (7.7.0): + - GoogleUtilities/AppDelegateSwizzler (~> 7.0) + - GoogleUtilities/MethodSwizzler (~> 7.0) + - GoogleUtilities/Network (~> 7.0) + - "GoogleUtilities/NSData+zlib (~> 7.0)" + - nanopb (~> 2.30907.0) + - GoogleDataTransport (8.3.1): + - GoogleUtilities/Environment (~> 7.2) + - nanopb (~> 2.30907.0) + - PromisesObjC (~> 1.2) + - GoogleUtilities/AppDelegateSwizzler (7.4.1): - GoogleUtilities/Environment - GoogleUtilities/Logger - GoogleUtilities/Network - - GoogleUtilities/Environment (6.7.2): + - GoogleUtilities/Environment (7.4.1): - PromisesObjC (~> 1.2) - - GoogleUtilities/Logger (6.7.2): + - GoogleUtilities/Logger (7.4.1): - GoogleUtilities/Environment - - GoogleUtilities/MethodSwizzler (6.7.2): + - GoogleUtilities/MethodSwizzler (7.4.1): - GoogleUtilities/Logger - - GoogleUtilities/Network (6.7.2): + - GoogleUtilities/Network (7.4.1): - GoogleUtilities/Logger - "GoogleUtilities/NSData+zlib" - GoogleUtilities/Reachability - - "GoogleUtilities/NSData+zlib (6.7.2)" - - GoogleUtilities/Reachability (6.7.2): + - "GoogleUtilities/NSData+zlib (7.4.1)" + - GoogleUtilities/Reachability (7.4.1): - GoogleUtilities/Logger - - GoogleUtilities/UserDefaults (6.7.2): + - GoogleUtilities/UserDefaults (7.4.1): - GoogleUtilities/Logger - hermes-engine (0.7.2) - libevent (2.1.12) - - libwebp (1.1.0): - - libwebp/demux (= 1.1.0) - - libwebp/mux (= 1.1.0) - - libwebp/webp (= 1.1.0) - - libwebp/demux (1.1.0): + - libwebp (1.2.0): + - libwebp/demux (= 1.2.0) + - libwebp/mux (= 1.2.0) + - libwebp/webp (= 1.2.0) + - libwebp/demux (1.2.0): - libwebp/webp - - libwebp/mux (1.1.0): + - libwebp/mux (1.2.0): - libwebp/demux - - libwebp/webp (1.1.0) - - nanopb (0.3.9011): - - nanopb/decode (= 0.3.9011) - - nanopb/encode (= 0.3.9011) - - nanopb/decode (0.3.9011) - - nanopb/encode (0.3.9011) + - libwebp/webp (1.2.0) + - nanopb (2.30907.0): + - nanopb/decode (= 2.30907.0) + - nanopb/encode (= 2.30907.0) + - nanopb/decode (2.30907.0) + - nanopb/encode (2.30907.0) - PromisesObjC (1.2.12) - RCT-Folly (2020.01.13.00): - boost-for-react-native @@ -176,281 +169,281 @@ PODS: - DoubleConversion - glog - libevent - - RCTRequired (0.64.0) - - RCTTypeSafety (0.64.0): - - FBLazyVector (= 0.64.0) + - RCTRequired (0.64.1) + - RCTTypeSafety (0.64.1): + - FBLazyVector (= 0.64.1) - RCT-Folly (= 2020.01.13.00) - - RCTRequired (= 0.64.0) - - React-Core (= 0.64.0) - - React (0.64.0): - - React-Core (= 0.64.0) - - React-Core/DevSupport (= 0.64.0) - - React-Core/RCTWebSocket (= 0.64.0) - - React-RCTActionSheet (= 0.64.0) - - React-RCTAnimation (= 0.64.0) - - React-RCTBlob (= 0.64.0) - - React-RCTImage (= 0.64.0) - - React-RCTLinking (= 0.64.0) - - React-RCTNetwork (= 0.64.0) - - React-RCTSettings (= 0.64.0) - - React-RCTText (= 0.64.0) - - React-RCTVibration (= 0.64.0) - - React-callinvoker (0.64.0) - - React-Core (0.64.0): + - RCTRequired (= 0.64.1) + - React-Core (= 0.64.1) + - React (0.64.1): + - React-Core (= 0.64.1) + - React-Core/DevSupport (= 0.64.1) + - React-Core/RCTWebSocket (= 0.64.1) + - React-RCTActionSheet (= 0.64.1) + - React-RCTAnimation (= 0.64.1) + - React-RCTBlob (= 0.64.1) + - React-RCTImage (= 0.64.1) + - React-RCTLinking (= 0.64.1) + - React-RCTNetwork (= 0.64.1) + - React-RCTSettings (= 0.64.1) + - React-RCTText (= 0.64.1) + - React-RCTVibration (= 0.64.1) + - React-callinvoker (0.64.1) + - React-Core (0.64.1): - glog - RCT-Folly (= 2020.01.13.00) - - React-Core/Default (= 0.64.0) - - React-cxxreact (= 0.64.0) - - React-jsi (= 0.64.0) - - React-jsiexecutor (= 0.64.0) - - React-perflogger (= 0.64.0) + - React-Core/Default (= 0.64.1) + - React-cxxreact (= 0.64.1) + - React-jsi (= 0.64.1) + - React-jsiexecutor (= 0.64.1) + - React-perflogger (= 0.64.1) - Yoga - - React-Core/CoreModulesHeaders (0.64.0): + - React-Core/CoreModulesHeaders (0.64.1): - glog - RCT-Folly (= 2020.01.13.00) - React-Core/Default - - React-cxxreact (= 0.64.0) - - React-jsi (= 0.64.0) - - React-jsiexecutor (= 0.64.0) - - React-perflogger (= 0.64.0) + - React-cxxreact (= 0.64.1) + - React-jsi (= 0.64.1) + - React-jsiexecutor (= 0.64.1) + - React-perflogger (= 0.64.1) - Yoga - - React-Core/Default (0.64.0): + - React-Core/Default (0.64.1): - glog - RCT-Folly (= 2020.01.13.00) - - React-cxxreact (= 0.64.0) - - React-jsi (= 0.64.0) - - React-jsiexecutor (= 0.64.0) - - React-perflogger (= 0.64.0) + - React-cxxreact (= 0.64.1) + - React-jsi (= 0.64.1) + - React-jsiexecutor (= 0.64.1) + - React-perflogger (= 0.64.1) - Yoga - - React-Core/DevSupport (0.64.0): + - React-Core/DevSupport (0.64.1): - glog - RCT-Folly (= 2020.01.13.00) - - React-Core/Default (= 0.64.0) - - React-Core/RCTWebSocket (= 0.64.0) - - React-cxxreact (= 0.64.0) - - React-jsi (= 0.64.0) - - React-jsiexecutor (= 0.64.0) - - React-jsinspector (= 0.64.0) - - React-perflogger (= 0.64.0) + - React-Core/Default (= 0.64.1) + - React-Core/RCTWebSocket (= 0.64.1) + - React-cxxreact (= 0.64.1) + - React-jsi (= 0.64.1) + - React-jsiexecutor (= 0.64.1) + - React-jsinspector (= 0.64.1) + - React-perflogger (= 0.64.1) - Yoga - - React-Core/Hermes (0.64.0): + - React-Core/Hermes (0.64.1): - glog - hermes-engine - RCT-Folly (= 2020.01.13.00) - RCT-Folly/Futures - - React-cxxreact (= 0.64.0) - - React-jsi (= 0.64.0) - - React-jsiexecutor (= 0.64.0) - - React-perflogger (= 0.64.0) + - React-cxxreact (= 0.64.1) + - React-jsi (= 0.64.1) + - React-jsiexecutor (= 0.64.1) + - React-perflogger (= 0.64.1) - Yoga - - React-Core/RCTActionSheetHeaders (0.64.0): + - React-Core/RCTActionSheetHeaders (0.64.1): - glog - RCT-Folly (= 2020.01.13.00) - React-Core/Default - - React-cxxreact (= 0.64.0) - - React-jsi (= 0.64.0) - - React-jsiexecutor (= 0.64.0) - - React-perflogger (= 0.64.0) + - React-cxxreact (= 0.64.1) + - React-jsi (= 0.64.1) + - React-jsiexecutor (= 0.64.1) + - React-perflogger (= 0.64.1) - Yoga - - React-Core/RCTAnimationHeaders (0.64.0): + - React-Core/RCTAnimationHeaders (0.64.1): - glog - RCT-Folly (= 2020.01.13.00) - React-Core/Default - - React-cxxreact (= 0.64.0) - - React-jsi (= 0.64.0) - - React-jsiexecutor (= 0.64.0) - - React-perflogger (= 0.64.0) + - React-cxxreact (= 0.64.1) + - React-jsi (= 0.64.1) + - React-jsiexecutor (= 0.64.1) + - React-perflogger (= 0.64.1) - Yoga - - React-Core/RCTBlobHeaders (0.64.0): + - React-Core/RCTBlobHeaders (0.64.1): - glog - RCT-Folly (= 2020.01.13.00) - React-Core/Default - - React-cxxreact (= 0.64.0) - - React-jsi (= 0.64.0) - - React-jsiexecutor (= 0.64.0) - - React-perflogger (= 0.64.0) + - React-cxxreact (= 0.64.1) + - React-jsi (= 0.64.1) + - React-jsiexecutor (= 0.64.1) + - React-perflogger (= 0.64.1) - Yoga - - React-Core/RCTImageHeaders (0.64.0): + - React-Core/RCTImageHeaders (0.64.1): - glog - RCT-Folly (= 2020.01.13.00) - React-Core/Default - - React-cxxreact (= 0.64.0) - - React-jsi (= 0.64.0) - - React-jsiexecutor (= 0.64.0) - - React-perflogger (= 0.64.0) + - React-cxxreact (= 0.64.1) + - React-jsi (= 0.64.1) + - React-jsiexecutor (= 0.64.1) + - React-perflogger (= 0.64.1) - Yoga - - React-Core/RCTLinkingHeaders (0.64.0): + - React-Core/RCTLinkingHeaders (0.64.1): - glog - RCT-Folly (= 2020.01.13.00) - React-Core/Default - - React-cxxreact (= 0.64.0) - - React-jsi (= 0.64.0) - - React-jsiexecutor (= 0.64.0) - - React-perflogger (= 0.64.0) + - React-cxxreact (= 0.64.1) + - React-jsi (= 0.64.1) + - React-jsiexecutor (= 0.64.1) + - React-perflogger (= 0.64.1) - Yoga - - React-Core/RCTNetworkHeaders (0.64.0): + - React-Core/RCTNetworkHeaders (0.64.1): - glog - RCT-Folly (= 2020.01.13.00) - React-Core/Default - - React-cxxreact (= 0.64.0) - - React-jsi (= 0.64.0) - - React-jsiexecutor (= 0.64.0) - - React-perflogger (= 0.64.0) + - React-cxxreact (= 0.64.1) + - React-jsi (= 0.64.1) + - React-jsiexecutor (= 0.64.1) + - React-perflogger (= 0.64.1) - Yoga - - React-Core/RCTSettingsHeaders (0.64.0): + - React-Core/RCTSettingsHeaders (0.64.1): - glog - RCT-Folly (= 2020.01.13.00) - React-Core/Default - - React-cxxreact (= 0.64.0) - - React-jsi (= 0.64.0) - - React-jsiexecutor (= 0.64.0) - - React-perflogger (= 0.64.0) + - React-cxxreact (= 0.64.1) + - React-jsi (= 0.64.1) + - React-jsiexecutor (= 0.64.1) + - React-perflogger (= 0.64.1) - Yoga - - React-Core/RCTTextHeaders (0.64.0): + - React-Core/RCTTextHeaders (0.64.1): - glog - RCT-Folly (= 2020.01.13.00) - React-Core/Default - - React-cxxreact (= 0.64.0) - - React-jsi (= 0.64.0) - - React-jsiexecutor (= 0.64.0) - - React-perflogger (= 0.64.0) + - React-cxxreact (= 0.64.1) + - React-jsi (= 0.64.1) + - React-jsiexecutor (= 0.64.1) + - React-perflogger (= 0.64.1) - Yoga - - React-Core/RCTVibrationHeaders (0.64.0): + - React-Core/RCTVibrationHeaders (0.64.1): - glog - RCT-Folly (= 2020.01.13.00) - React-Core/Default - - React-cxxreact (= 0.64.0) - - React-jsi (= 0.64.0) - - React-jsiexecutor (= 0.64.0) - - React-perflogger (= 0.64.0) + - React-cxxreact (= 0.64.1) + - React-jsi (= 0.64.1) + - React-jsiexecutor (= 0.64.1) + - React-perflogger (= 0.64.1) - Yoga - - React-Core/RCTWebSocket (0.64.0): + - React-Core/RCTWebSocket (0.64.1): - glog - RCT-Folly (= 2020.01.13.00) - - React-Core/Default (= 0.64.0) - - React-cxxreact (= 0.64.0) - - React-jsi (= 0.64.0) - - React-jsiexecutor (= 0.64.0) - - React-perflogger (= 0.64.0) + - React-Core/Default (= 0.64.1) + - React-cxxreact (= 0.64.1) + - React-jsi (= 0.64.1) + - React-jsiexecutor (= 0.64.1) + - React-perflogger (= 0.64.1) - Yoga - - React-CoreModules (0.64.0): - - FBReactNativeSpec (= 0.64.0) + - React-CoreModules (0.64.1): + - FBReactNativeSpec (= 0.64.1) - RCT-Folly (= 2020.01.13.00) - - RCTTypeSafety (= 0.64.0) - - React-Core/CoreModulesHeaders (= 0.64.0) - - React-jsi (= 0.64.0) - - React-RCTImage (= 0.64.0) - - ReactCommon/turbomodule/core (= 0.64.0) - - React-cxxreact (0.64.0): + - RCTTypeSafety (= 0.64.1) + - React-Core/CoreModulesHeaders (= 0.64.1) + - React-jsi (= 0.64.1) + - React-RCTImage (= 0.64.1) + - ReactCommon/turbomodule/core (= 0.64.1) + - React-cxxreact (0.64.1): - boost-for-react-native (= 1.63.0) - DoubleConversion - glog - RCT-Folly (= 2020.01.13.00) - - React-callinvoker (= 0.64.0) - - React-jsi (= 0.64.0) - - React-jsinspector (= 0.64.0) - - React-perflogger (= 0.64.0) - - React-runtimeexecutor (= 0.64.0) - - React-jsi (0.64.0): + - React-callinvoker (= 0.64.1) + - React-jsi (= 0.64.1) + - React-jsinspector (= 0.64.1) + - React-perflogger (= 0.64.1) + - React-runtimeexecutor (= 0.64.1) + - React-jsi (0.64.1): - boost-for-react-native (= 1.63.0) - DoubleConversion - glog - RCT-Folly (= 2020.01.13.00) - - React-jsi/Default (= 0.64.0) - - React-jsi/Default (0.64.0): + - React-jsi/Default (= 0.64.1) + - React-jsi/Default (0.64.1): - boost-for-react-native (= 1.63.0) - DoubleConversion - glog - RCT-Folly (= 2020.01.13.00) - - React-jsiexecutor (0.64.0): + - React-jsiexecutor (0.64.1): - DoubleConversion - glog - RCT-Folly (= 2020.01.13.00) - - React-cxxreact (= 0.64.0) - - React-jsi (= 0.64.0) - - React-perflogger (= 0.64.0) - - React-jsinspector (0.64.0) + - React-cxxreact (= 0.64.1) + - React-jsi (= 0.64.1) + - React-perflogger (= 0.64.1) + - React-jsinspector (0.64.1) - react-native-blur (0.8.0): - React - react-native-blurhash (1.1.4): - React-Core - - react-native-cameraroll (4.0.2): + - react-native-cameraroll (4.0.4): - React-Core - react-native-netinfo (6.0.0): - React-Core - - react-native-pager-view (5.1.2): + - react-native-pager-view (5.1.9): - React-Core - react-native-safe-area-context (3.2.0): - React-Core - react-native-segmented-control (2.2.2): - React-Core - - React-perflogger (0.64.0) - - React-RCTActionSheet (0.64.0): - - React-Core/RCTActionSheetHeaders (= 0.64.0) - - React-RCTAnimation (0.64.0): - - FBReactNativeSpec (= 0.64.0) + - React-perflogger (0.64.1) + - React-RCTActionSheet (0.64.1): + - React-Core/RCTActionSheetHeaders (= 0.64.1) + - React-RCTAnimation (0.64.1): + - FBReactNativeSpec (= 0.64.1) - RCT-Folly (= 2020.01.13.00) - - RCTTypeSafety (= 0.64.0) - - React-Core/RCTAnimationHeaders (= 0.64.0) - - React-jsi (= 0.64.0) - - ReactCommon/turbomodule/core (= 0.64.0) - - React-RCTBlob (0.64.0): - - FBReactNativeSpec (= 0.64.0) + - RCTTypeSafety (= 0.64.1) + - React-Core/RCTAnimationHeaders (= 0.64.1) + - React-jsi (= 0.64.1) + - ReactCommon/turbomodule/core (= 0.64.1) + - React-RCTBlob (0.64.1): + - FBReactNativeSpec (= 0.64.1) - RCT-Folly (= 2020.01.13.00) - - React-Core/RCTBlobHeaders (= 0.64.0) - - React-Core/RCTWebSocket (= 0.64.0) - - React-jsi (= 0.64.0) - - React-RCTNetwork (= 0.64.0) - - ReactCommon/turbomodule/core (= 0.64.0) - - React-RCTImage (0.64.0): - - FBReactNativeSpec (= 0.64.0) + - React-Core/RCTBlobHeaders (= 0.64.1) + - React-Core/RCTWebSocket (= 0.64.1) + - React-jsi (= 0.64.1) + - React-RCTNetwork (= 0.64.1) + - ReactCommon/turbomodule/core (= 0.64.1) + - React-RCTImage (0.64.1): + - FBReactNativeSpec (= 0.64.1) - RCT-Folly (= 2020.01.13.00) - - RCTTypeSafety (= 0.64.0) - - React-Core/RCTImageHeaders (= 0.64.0) - - React-jsi (= 0.64.0) - - React-RCTNetwork (= 0.64.0) - - ReactCommon/turbomodule/core (= 0.64.0) - - React-RCTLinking (0.64.0): - - FBReactNativeSpec (= 0.64.0) - - React-Core/RCTLinkingHeaders (= 0.64.0) - - React-jsi (= 0.64.0) - - ReactCommon/turbomodule/core (= 0.64.0) - - React-RCTNetwork (0.64.0): - - FBReactNativeSpec (= 0.64.0) + - RCTTypeSafety (= 0.64.1) + - React-Core/RCTImageHeaders (= 0.64.1) + - React-jsi (= 0.64.1) + - React-RCTNetwork (= 0.64.1) + - ReactCommon/turbomodule/core (= 0.64.1) + - React-RCTLinking (0.64.1): + - FBReactNativeSpec (= 0.64.1) + - React-Core/RCTLinkingHeaders (= 0.64.1) + - React-jsi (= 0.64.1) + - ReactCommon/turbomodule/core (= 0.64.1) + - React-RCTNetwork (0.64.1): + - FBReactNativeSpec (= 0.64.1) - RCT-Folly (= 2020.01.13.00) - - RCTTypeSafety (= 0.64.0) - - React-Core/RCTNetworkHeaders (= 0.64.0) - - React-jsi (= 0.64.0) - - ReactCommon/turbomodule/core (= 0.64.0) - - React-RCTSettings (0.64.0): - - FBReactNativeSpec (= 0.64.0) + - RCTTypeSafety (= 0.64.1) + - React-Core/RCTNetworkHeaders (= 0.64.1) + - React-jsi (= 0.64.1) + - ReactCommon/turbomodule/core (= 0.64.1) + - React-RCTSettings (0.64.1): + - FBReactNativeSpec (= 0.64.1) - RCT-Folly (= 2020.01.13.00) - - RCTTypeSafety (= 0.64.0) - - React-Core/RCTSettingsHeaders (= 0.64.0) - - React-jsi (= 0.64.0) - - ReactCommon/turbomodule/core (= 0.64.0) - - React-RCTText (0.64.0): - - React-Core/RCTTextHeaders (= 0.64.0) - - React-RCTVibration (0.64.0): - - FBReactNativeSpec (= 0.64.0) + - RCTTypeSafety (= 0.64.1) + - React-Core/RCTSettingsHeaders (= 0.64.1) + - React-jsi (= 0.64.1) + - ReactCommon/turbomodule/core (= 0.64.1) + - React-RCTText (0.64.1): + - React-Core/RCTTextHeaders (= 0.64.1) + - React-RCTVibration (0.64.1): + - FBReactNativeSpec (= 0.64.1) - RCT-Folly (= 2020.01.13.00) - - React-Core/RCTVibrationHeaders (= 0.64.0) - - React-jsi (= 0.64.0) - - ReactCommon/turbomodule/core (= 0.64.0) - - React-runtimeexecutor (0.64.0): - - React-jsi (= 0.64.0) - - ReactCommon/turbomodule/core (0.64.0): + - React-Core/RCTVibrationHeaders (= 0.64.1) + - React-jsi (= 0.64.1) + - ReactCommon/turbomodule/core (= 0.64.1) + - React-runtimeexecutor (0.64.1): + - React-jsi (= 0.64.1) + - ReactCommon/turbomodule/core (0.64.1): - DoubleConversion - glog - RCT-Folly (= 2020.01.13.00) - - React-callinvoker (= 0.64.0) - - React-Core (= 0.64.0) - - React-cxxreact (= 0.64.0) - - React-jsi (= 0.64.0) - - React-perflogger (= 0.64.0) - - RNCAsyncStorage (1.14.1): + - React-callinvoker (= 0.64.1) + - React-Core (= 0.64.1) + - React-cxxreact (= 0.64.1) + - React-jsi (= 0.64.1) + - React-perflogger (= 0.64.1) + - RNCAsyncStorage (1.15.4): - React-Core - - RNCMaskedView (0.1.10): + - RNCMaskedView (0.1.11): - React - RNFastImage (8.3.4): - React-Core @@ -458,7 +451,7 @@ PODS: - SDWebImageWebPCoder (~> 0.6.1) - RNGestureHandler (1.10.3): - React-Core - - RNReanimated (2.0.0): + - RNReanimated (2.1.0): - DoubleConversion - FBLazyVector - FBReactNativeSpec @@ -487,46 +480,52 @@ PODS: - React-RCTVibration - ReactCommon/turbomodule/core - Yoga - - RNScreens (2.17.1): + - RNScreens (3.3.0): - React-Core - - RNSentry (2.3.0): + - React-RCTImage + - RNSentry (2.4.3): - React-Core - Sentry (= 6.1.4) - - RNSVG (12.1.0): + - RNSVG (12.1.1): - React - - SDWebImage (5.10.3): - - SDWebImage/Core (= 5.10.3) - - SDWebImage/Core (5.10.3) + - SDWebImage (5.11.1): + - SDWebImage/Core (= 5.11.1) + - SDWebImage/Core (5.11.1) - SDWebImageWebPCoder (0.6.1): - libwebp (~> 1.0) - SDWebImage/Core (~> 5.7) - Sentry (6.1.4): - Sentry/Core (= 6.1.4) - Sentry/Core (6.1.4) - - UMAppLoader (1.4.0) - - UMBarCodeScannerInterface (5.4.0) - - UMCameraInterface (5.4.0) - - UMConstantsInterface (5.4.0) - - UMCore (7.0.0) - - UMFaceDetectorInterface (5.4.0) - - UMFileSystemInterface (5.4.0) - - UMFontInterface (5.4.0) - - UMImageLoaderInterface (5.4.0) - - UMPermissionsInterface (5.4.0): + - UMAppLoader (2.1.0) + - UMBarCodeScannerInterface (6.1.0): - UMCore - - UMReactNativeAdapter (5.7.0): + - UMCameraInterface (6.1.0): + - UMCore + - UMConstantsInterface (6.1.0): + - UMCore + - UMCore (7.1.0) + - UMFaceDetectorInterface (6.1.0) + - UMFileSystemInterface (6.1.0) + - UMFontInterface (6.1.0) + - UMImageLoaderInterface (6.1.0) + - UMPermissionsInterface (6.1.0): + - UMCore + - UMReactNativeAdapter (6.2.2): - React-Core - UMCore - UMFontInterface - - UMSensorsInterface (5.4.0) - - UMTaskManagerInterface (5.4.0) + - UMSensorsInterface (6.1.0): + - UMCore + - UMTaskManagerInterface (6.1.0): + - UMCore - Yoga (1.14.0) DEPENDENCIES: - DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`) - - EXApplication (from `../node_modules/expo-notifications/node_modules/expo-application/ios`) + - EXApplication (from `../node_modules/expo-application/ios`) - EXAV (from `../node_modules/expo-av/ios`) - - EXConstants (from `../node_modules/expo-linking/node_modules/expo-constants/ios`) + - EXConstants (from `../node_modules/expo-constants/ios`) - EXCrypto (from `../node_modules/expo-crypto/ios`) - EXDevice (from `../node_modules/expo-device/ios`) - EXErrorRecovery (from `../node_modules/expo-error-recovery/ios`) @@ -536,18 +535,16 @@ DEPENDENCIES: - EXFont (from `../node_modules/expo-font/ios`) - EXHaptics (from `../node_modules/expo-haptics/ios`) - EXImageLoader (from `../node_modules/expo-image-loader/ios`) + - EXImageManipulator (from `../node_modules/expo-image-manipulator/ios`) - EXImagePicker (from `../node_modules/expo-image-picker/ios`) - EXKeepAwake (from `../node_modules/expo-keep-awake/ios`) - - EXLinearGradient (from `../node_modules/expo-linear-gradient/ios`) - EXLocalization (from `../node_modules/expo-localization/ios`) - - EXLocation (from `../node_modules/expo-location/ios`) - EXNotifications (from `../node_modules/expo-notifications/ios`) - - EXPermissions (from `../node_modules/expo-image-picker/node_modules/expo-permissions/ios`) + - EXPermissions (from `../node_modules/expo-permissions/ios`) - EXRandom (from `../node_modules/expo-random/ios`) - EXScreenCapture (from `../node_modules/expo-screen-capture/ios`) - EXSecureStore (from `../node_modules/expo-secure-store/ios`) - EXSplashScreen (from `../node_modules/expo-splash-screen/ios`) - - EXSQLite (from `../node_modules/expo-sqlite/ios`) - EXStoreReview (from `../node_modules/expo-store-review/ios`) - EXUpdates (from `../node_modules/expo-updates/ios`) - EXVideoThumbnails (from `../node_modules/expo-video-thumbnails/ios`) @@ -602,7 +599,7 @@ DEPENDENCIES: - UMBarCodeScannerInterface (from `../node_modules/unimodules-barcode-scanner-interface/ios`) - UMCameraInterface (from `../node_modules/unimodules-camera-interface/ios`) - UMConstantsInterface (from `../node_modules/unimodules-constants-interface/ios`) - - "UMCore (from `../node_modules/expo-screen-capture/node_modules/@unimodules/core/ios`)" + - "UMCore (from `../node_modules/@unimodules/core/ios`)" - UMFaceDetectorInterface (from `../node_modules/unimodules-face-detector-interface/ios`) - UMFileSystemInterface (from `../node_modules/unimodules-file-system-interface/ios`) - UMFontInterface (from `../node_modules/unimodules-font-interface/ios`) @@ -620,11 +617,9 @@ SPEC REPOS: - FirebaseAnalytics - FirebaseCore - FirebaseCoreDiagnostics - - FirebaseCoreDiagnosticsInterop - - FirebaseInstanceID + - FirebaseInstallations - GoogleAppMeasurement - GoogleDataTransport - - GoogleDataTransportCCTSupport - GoogleUtilities - hermes-engine - libevent @@ -639,11 +634,11 @@ EXTERNAL SOURCES: DoubleConversion: :podspec: "../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec" EXApplication: - :path: "../node_modules/expo-notifications/node_modules/expo-application/ios" + :path: "../node_modules/expo-application/ios" EXAV: :path: "../node_modules/expo-av/ios" EXConstants: - :path: "../node_modules/expo-linking/node_modules/expo-constants/ios" + :path: "../node_modules/expo-constants/ios" EXCrypto: :path: "../node_modules/expo-crypto/ios" EXDevice: @@ -662,20 +657,18 @@ EXTERNAL SOURCES: :path: "../node_modules/expo-haptics/ios" EXImageLoader: :path: "../node_modules/expo-image-loader/ios" + EXImageManipulator: + :path: "../node_modules/expo-image-manipulator/ios" EXImagePicker: :path: "../node_modules/expo-image-picker/ios" EXKeepAwake: :path: "../node_modules/expo-keep-awake/ios" - EXLinearGradient: - :path: "../node_modules/expo-linear-gradient/ios" EXLocalization: :path: "../node_modules/expo-localization/ios" - EXLocation: - :path: "../node_modules/expo-location/ios" EXNotifications: :path: "../node_modules/expo-notifications/ios" EXPermissions: - :path: "../node_modules/expo-image-picker/node_modules/expo-permissions/ios" + :path: "../node_modules/expo-permissions/ios" EXRandom: :path: "../node_modules/expo-random/ios" EXScreenCapture: @@ -684,8 +677,6 @@ EXTERNAL SOURCES: :path: "../node_modules/expo-secure-store/ios" EXSplashScreen: :path: "../node_modules/expo-splash-screen/ios" - EXSQLite: - :path: "../node_modules/expo-sqlite/ios" EXStoreReview: :path: "../node_modules/expo-store-review/ios" EXUpdates: @@ -785,7 +776,7 @@ EXTERNAL SOURCES: UMConstantsInterface: :path: "../node_modules/unimodules-constants-interface/ios" UMCore: - :path: "../node_modules/expo-screen-capture/node_modules/@unimodules/core/ios" + :path: "../node_modules/@unimodules/core/ios" UMFaceDetectorInterface: :path: "../node_modules/unimodules-face-detector-interface/ios" UMFileSystemInterface: @@ -808,107 +799,103 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: boost-for-react-native: 39c7adb57c4e60d6c5479dd8623128eb5b3f0f2c DoubleConversion: cf9b38bf0b2d048436d9a82ad2abe1404f11e7de - EXApplication: e3a06b6d81f94e526f029a57b2121d6cde044004 - EXAV: 398170ec4fb575be375f76b65a7218e097f89b30 - EXConstants: d9483a8fe0a963dd7ee3389f371303773e6ecd37 - EXCrypto: 77fb158996b02292902cc6c4fef59b21c663c673 + EXApplication: 4797b8b37f0b0470f587fdccf6407f44b50d18b5 + EXAV: f7c1b9af3aff7834cbdbe3e002d1f70e21c38320 + EXConstants: c4dd28acc12039c999612507a5f935556f2c86ce + EXCrypto: 9cbeb90f6c60a8ae9f26242fd2db916b21c55700 EXDevice: 01f54314f618aa4098893f66cd8f2a8a411f33ee - EXErrorRecovery: b46af4b91e2b4ec598ab1fa51d2cf088aaf5511f - EXFileSystem: 0e4974ab77bff04cda68d2886d070cbe64b93a6b - EXFirebaseAnalytics: db3028d0b0b87e4f2a6605947f943417befcad72 - EXFirebaseCore: 2600f770440abaf0ef7b4a6df69f9e6cc2ea76b6 - EXFont: 30c64ed8735a180e3f20046e4fdac4ea074d71d3 - EXHaptics: 685bcf63881af13bbd657ad148292db1f7370268 - EXImageLoader: f96ec9992733a4224418bbd9382e5485c8948944 - EXImagePicker: 50e8688af1278af72d3235753a825a49465b4a84 - EXKeepAwake: 615c5a6fca5c2afedf611bb6f7f2ca323246de94 - EXLinearGradient: c803fbd1aa974be038177b1e45524bc35759fe9c - EXLocalization: 0470b3cb25dac6cdbe6f12ca15408134dba03c91 - EXLocation: d55e2a37f61bcfb4eba9c813b3f4621d896c4c00 - EXNotifications: 3a88b7b898fa842cae3c5a895a255fab554bc0c8 - EXPermissions: 015f1129f80266f6c38e3691102546232b641614 - EXRandom: 4f71ea72eaeea674c4597e536e3014b4387af21a - EXScreenCapture: 5b8447139e56e2b922e93ccdc7c773c103fb44fd - EXSecureStore: 1b571851e6068b30b8ec097be848a04603c03bae - EXSplashScreen: ab5984afcca91e0af6b3138f01a8c47dc4955c51 - EXSQLite: bda6a286dded0637bb312ee781239dcca163ff4b - EXStoreReview: b552c0d512e1b5c2c7371041a033a2827dc01d46 + EXErrorRecovery: 720641265b8cf95e6cdeb1884ac38e794a352488 + EXFileSystem: dcf2273f49431e5037347c733a2dc5d08e0d0a9e + EXFirebaseAnalytics: aa820eafe8527a32f65a285047ce475e622c7e8f + EXFirebaseCore: 7865e37021ddcff5c575a4598686a2939d6c4183 + EXFont: d6fb79f9863120f0d0b26b0c2d1453bc9511e9df + EXHaptics: 2de40c5f50a9e78da92c209db06db5134d8cac0b + EXImageLoader: da941c9399e01ec28f2d5b270bdd21f2c8ca596c + EXImageManipulator: a099e4694070c7cb86aa0b0b1afa3ea184153a7d + EXImagePicker: dd05b8a5cb782c79d07d1d72e5850c6acc2b9a37 + EXKeepAwake: d4e4a3ed8c1c4fd940dd62fc5a8be2a190371fd4 + EXLocalization: f139efe4a06be1041815879959346e3d437a6e93 + EXNotifications: c13e078d83ce01c7aeb8e3f44a48c13f50099291 + EXPermissions: 8f8c1c05580c4e02d4ee2c8dd74bfe173ff6a723 + EXRandom: cbd66cd45434a494f5ef98650eec1f8d78b90270 + EXScreenCapture: 2903dace06f2d06cc161017637cc4cbfcaa98986 + EXSecureStore: da5a255445bb6ee8b8ac54f65412bc803272bd87 + EXSplashScreen: a9baaf4fa866003884c90ba049f18760d6a8ce39 + EXStoreReview: b1f68ed0369b0f1c443214ac8d6881ef3b64de9a EXUpdates: 74b39409f68eca207075d87b0077bdf37865a8bf - EXVideoThumbnails: 0be939563a5d46ce0d1fa9baea7d454b99475763 - EXWebBrowser: 2e708935a91ae0f51f5f8ffc85ba673950f34833 - FBLazyVector: 49cbe4b43e445b06bf29199b6ad2057649e4c8f5 - FBReactNativeSpec: 9602ea8381acd3aad740e6464663687fad779f80 - Firebase: 0219bb4782eb1406f1b9b0628a2e625484ce910d - FirebaseAnalytics: f68b9f3f1241385129ae0a83b63627fc420c05e5 - FirebaseCore: 632e05cc5e1199d9147122c16d92305eb04c34bd - FirebaseCoreDiagnostics: b59c024493a409f8aecba02c99928d0d8431d159 - FirebaseCoreDiagnosticsInterop: 296e2c5f5314500a850ad0b83e9e7c10b011a850 - FirebaseInstanceID: ce993a3c3670a8f5d47ce371ac5d143c560608c5 + EXVideoThumbnails: cd257fc6e07884a704a5674d362a6410933acb68 + EXWebBrowser: 0b466c50e5ff61c9758095d49d5081e3229d77ac + FBLazyVector: 7b423f9e248eae65987838148c36eec1dbfe0b53 + FBReactNativeSpec: 5058d1917c80dca4b9ed89bdf94385315939ab80 + Firebase: cd2ab85eec8170dc260186159f21072ecb679ad5 + FirebaseAnalytics: f3f8f75de34fe04141a69bb1c4bd7e24a80178e1 + FirebaseCore: ac35d680a0bf32319a59966a1478e0741536b97b + FirebaseCoreDiagnostics: 3d36e05da74cb8b7ce30e6594a8f201b982c725c + FirebaseInstallations: a58d4f72ec5861840b84df489f2668d970df558a glog: 73c2498ac6884b13ede40eda8228cb1eee9d9d62 - GoogleAppMeasurement: db118eb61a97dd8c4f7014e368d3c335cbbcf80a - GoogleDataTransport: 9a8a16f79feffc7f42096743de2a7c4815e84020 - GoogleDataTransportCCTSupport: 0f39025e8cf51f168711bd3fb773938d7e62ddb5 - GoogleUtilities: 7f2f5a07f888cdb145101d6042bc4422f57e70b3 + GoogleAppMeasurement: 0c3b134b2c0a90c4c24833873894bfe0e42a0384 + GoogleDataTransport: 8b0e733ea77c9218778e5a9e34ba9508b8328939 + GoogleUtilities: f8a43108b38a68eebe8b3540e1f4f2d28843ce20 hermes-engine: 7d97ba46a1e29bacf3e3c61ecb2804a5ddd02d4f libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913 - libwebp: 946cb3063cea9236285f7e9a8505d806d30e07f3 - nanopb: 18003b5e52dab79db540fe93fe9579f399bd1ccd + libwebp: e90b9c01d99205d03b6bb8f2c8c415e5a4ef66f0 + nanopb: 59221d7f958fb711001e6a449489542d92ae113e PromisesObjC: 3113f7f76903778cf4a0586bd1ab89329a0b7b97 RCT-Folly: ec7a233ccc97cc556cf7237f0db1ff65b986f27c - RCTRequired: 2f8cb5b7533219bf4218a045f92768129cf7050a - RCTTypeSafety: 512728b73549e72ad7330b92f3d42936f2a4de5b - React: 98eac01574128a790f0bbbafe2d1a8607291ac24 - React-callinvoker: def3f7fae16192df68d9b69fd4bbb59092ee36bc - React-Core: 70a52aa5dbe9b83befae82038451a7df9fd54c5a - React-CoreModules: 052edef46117862e2570eb3a0f06d81c61d2c4b8 - React-cxxreact: c1dc71b30653cfb4770efdafcbdc0ad6d388baab - React-jsi: 74341196d9547cbcbcfa4b3bbbf03af56431d5a1 - React-jsiexecutor: 06a9c77b56902ae7ffcdd7a4905f664adc5d237b - React-jsinspector: 0ae35a37b20d5e031eb020a69cc5afdbd6406301 + RCTRequired: ec2ebc96b7bfba3ca5c32740f5a0c6a014a274d2 + RCTTypeSafety: 22567f31e67c3e088c7ac23ea46ab6d4779c0ea5 + React: a241e3dbb1e91d06332f1dbd2b3ab26e1a4c4b9d + React-callinvoker: da4d1c6141696a00163960906bc8a55b985e4ce4 + React-Core: 46ba164c437d7dac607b470c83c8308b05799748 + React-CoreModules: 217bd14904491c7b9940ff8b34a3fe08013c2f14 + React-cxxreact: 0090588ae6660c4615d3629fdd5c768d0983add4 + React-jsi: 5de8204706bd872b78ea646aee5d2561ca1214b6 + React-jsiexecutor: 124e8f99992490d0d13e0649d950d3e1aae06fe9 + React-jsinspector: 500a59626037be5b3b3d89c5151bc3baa9abf1a9 react-native-blur: cad4d93b364f91e7b7931b3fa935455487e5c33c react-native-blurhash: ec98d751a9cb9075cef0b9e3188244c517d6ab22 - react-native-cameraroll: 1965db75c851b15e77a22ca0ac78e32af6b571ae + react-native-cameraroll: 88f4e62d9ecd0e1f253abe4f685474f2ea14bfa2 react-native-netinfo: e849fc21ca2f4128a5726c801a82fc6f4a6db50d - react-native-pager-view: c1ec84a464024641ccb1102e9ec12be020d3d74c + react-native-pager-view: 14653de580178af7e65aa7e3fa08b4f243c86d4d react-native-safe-area-context: f0906bf8bc9835ac9a9d3f97e8bde2a997d8da79 react-native-segmented-control: 65df6cd0619b780b3843d574a72d4c7cec396097 - React-perflogger: 9c547d8f06b9bf00cb447f2b75e8d7f19b7e02af - React-RCTActionSheet: 3080b6e12e0e1a5b313c8c0050699b5c794a1b11 - React-RCTAnimation: 3f96f21a497ae7dabf4d2f150ee43f906aaf516f - React-RCTBlob: 283b8e5025e7f954176bc48164f846909002f3ed - React-RCTImage: 5088a484faac78f2d877e1b79125d3bb1ea94a16 - React-RCTLinking: 5e8fbb3e9a8bc2e4e3eb15b1eb8bda5fcac27b8c - React-RCTNetwork: 38ec277217b1e841d5e6a1fa78da65b9212ccb28 - React-RCTSettings: 242d6e692108c3de4f3bb74b7586a8799e9ab070 - React-RCTText: 8746736ac8eb5a4a74719aa695b7a236a93a83d2 - React-RCTVibration: 0fd6b21751a33cb72fce1a4a33ab9678416d307a - React-runtimeexecutor: cad74a1eaa53ee6e7a3620231939d8fe2c6afcf0 - ReactCommon: cfe2b7fd20e0dbd2d1185cd7d8f99633fbc5ff05 - RNCAsyncStorage: fe58eec522885718d6b297b7b658bf87d7ca557b - RNCMaskedView: 5a8ec07677aa885546a0d98da336457e2bea557f + React-perflogger: aad6d4b4a267936b3667260d1f649b6f6069a675 + React-RCTActionSheet: fc376be462c9c8d6ad82c0905442fd77f82a9d2a + React-RCTAnimation: ba0a1c3a2738be224a08092fa7f1b444ab77d309 + React-RCTBlob: f758d4403fc5828a326dc69e27b41e1a92f34947 + React-RCTImage: ce57088705f4a8d03f6594b066a59c29143ba73e + React-RCTLinking: 852a3a95c65fa63f657a4b4e2d3d83a815e00a7c + React-RCTNetwork: 9d7ccb8a08d522d71700b4fb677d9fa28cccd118 + React-RCTSettings: d8aaf4389ff06114dee8c42ef5f0f2915946011e + React-RCTText: 809c12ed6b261796ba056c04fcd20d8b90bcc81d + React-RCTVibration: 4b99a7f5c6c0abbc5256410cc5425fb8531986e1 + React-runtimeexecutor: ff951a0c241bfaefc4940a3f1f1a229e7cb32fa6 + ReactCommon: bedc99ed4dae329c4fcf128d0c31b9115e5365ca + RNCAsyncStorage: f47a7e8f927f7c9da947491fc55752eb9ce17f2d + RNCMaskedView: 0e1bc4bfa8365eba5fbbb71e07fbdc0555249489 RNFastImage: d4870d58f5936111c56218dbd7fcfc18e65b58ff RNGestureHandler: a479ebd5ed4221a810967000735517df0d2db211 - RNReanimated: 64f6c5789f82818c07ba3c71864b73619cb23c76 - RNScreens: b6c9607e6fe47c1b6e2f1910d2acd46dd7ecea3a - RNSentry: 4f6907f9a4a41058988ebaa17666e9a402b50ff2 - RNSVG: ce9d996113475209013317e48b05c21ee988d42e - SDWebImage: e378178472b735e84b007bfb55514c97948a0598 + RNReanimated: b8c8004b43446e3c2709fe64b2b41072f87428ad + RNScreens: bf59f17fbf001f1025243eeed5f19419d3c11ef2 + RNSentry: 6f8f9ee7e4c939dcd35e5633b94d0e3782888e46 + RNSVG: 551acb6562324b1d52a4e0758f7ca0ec234e278f + SDWebImage: a7f831e1a65eb5e285e3fb046a23fcfbf08e696d SDWebImageWebPCoder: d0dac55073088d24b2ac1b191a71a8f8d0adac21 Sentry: 9d055e2de30a77685e86b219acf02e59b82091fc - UMAppLoader: 92d044af52626af3d81a69796ad666fc7a9a7d78 - UMBarCodeScannerInterface: 3f6c1b09ef4b867ce752b8c0b3893bcf9cd85f32 - UMCameraInterface: d516032121192fee9a6c93bdfff0bb2cc7282796 - UMConstantsInterface: 6825ea3832d26ed392ca6eff2df84edd69968fd0 - UMCore: a882a262c77a535d46b058c150f957eface073f4 - UMFaceDetectorInterface: 60b36b07faa539205efce30b20c192e058b31c23 - UMFileSystemInterface: ab01294ce58a3c773aefb4a5b131ce589c199559 - UMFontInterface: 85fe1b845fb7caab45e04d9ce47e1677a5ce90a5 - UMImageLoaderInterface: 18f37df089b7e6d301e3acac025a8264d26b66d6 - UMPermissionsInterface: 807e5733b4c6607f35757b1dd128f370718d2f94 - UMReactNativeAdapter: 172def7895b2cb44a7dd021336e316d5fa8ea958 - UMSensorsInterface: 4df9ec662134de5614ae61acc249d6912db87ca5 - UMTaskManagerInterface: 4c60b43eaf3cb05a164bc9113258a171c18b7bf7 - Yoga: 8c8436d4171c87504c648ae23b1d81242bdf3bbf + UMAppLoader: fe2708bb0ac5cd70052bc207d06aa3b7e72b9e97 + UMBarCodeScannerInterface: 79f92bea5f7af39b381a4c82298105ceb537408a + UMCameraInterface: 81ff46700da88435f17afedfc88915eaede7e6a6 + UMConstantsInterface: bb94dd46039dcde276ed50225b29e22785e604bf + UMCore: 60b35f4d217461f7b54934b0c5be67442871f01f + UMFaceDetectorInterface: 791eec55ffca1171992976b7eceb73e69e391c58 + UMFileSystemInterface: f72245e90ce78fa6427180ff0b0904ead13d8161 + UMFontInterface: 5843cff7db85a42ba629aaac53d33091c35524d3 + UMImageLoaderInterface: 9ddffeb644b3f45d4eb0c2f51a2fd95fd5c8d1a4 + UMPermissionsInterface: 40b72935a7d12a3f60dc6b7bb99ce47908380cb1 + UMReactNativeAdapter: 65ada852a648fcb6674acfbfe72ccb095f2f5b75 + UMSensorsInterface: a5e9db661e5d9ae214762033d725989880ae6993 + UMTaskManagerInterface: 203c11259d2699b5b3a4eda4adbc466f5cb5c561 + Yoga: a7de31c64fe738607e7a3803e3f591a4b1df7393 PODFILE CHECKSUM: 34cad1fa3f14caa5b138177b6379ac2cba0e1087 diff --git a/ios/tooot.xcodeproj/project.pbxproj b/ios/tooot.xcodeproj/project.pbxproj index 6c0f8b0b..0e2771ea 100644 --- a/ios/tooot.xcodeproj/project.pbxproj +++ b/ios/tooot.xcodeproj/project.pbxproj @@ -346,7 +346,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = tooot/tooot.entitlements; - CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_IDENTITY = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; CURRENT_PROJECT_VERSION = 2102022230; DEVELOPMENT_TEAM = 8EGBLQ2MA6; @@ -366,7 +366,7 @@ ); PRODUCT_BUNDLE_IDENTIFIER = com.xmflsct.app.tooot; PRODUCT_NAME = tooot; - PROVISIONING_PROFILE_SPECIFIER = "match Development com.xmflsct.app.tooot"; + PROVISIONING_PROFILE_SPECIFIER = "match AdHoc com.xmflsct.app.tooot"; SWIFT_OBJC_BRIDGING_HEADER = "tooot-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; diff --git a/package.json b/package.json index 6f8c2355..cf04a80d 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,11 @@ { "name": "tooot", "versions": { - "native": "210317", - "major": 1, - "minor": 1, - "patch": 0, - "expo": "40.0.0" + "native": "210511", + "major": 2, + "minor": 0, + "patch": 1, + "expo": "41.0.0" }, "description": "tooot app for Mastodon", "author": "xmflsct ", @@ -26,43 +26,45 @@ "dependencies": { "@expo/react-native-action-sheet": "^3.9.0", "@neverdull-agency/expo-unlimited-secure-store": "^1.0.10", - "@react-native-async-storage/async-storage": "^1.14.1", + "@react-native-async-storage/async-storage": "^1.15.4", "@react-native-community/blur": "^3.6.0", - "@react-native-community/cameraroll": "^4.0.2", - "@react-native-community/masked-view": "0.1.10", - "@react-native-community/netinfo": "^6.0.0", + "@react-native-community/cameraroll": "^4.0.4", + "@react-native-community/masked-view": "0.1.11", + "@react-native-community/netinfo": "6.0.0", "@react-native-community/segmented-control": "2.2.2", - "@react-navigation/bottom-tabs": "^5.11.8", - "@react-navigation/native": "^5.9.3", - "@react-navigation/stack": "^5.14.3", - "@reduxjs/toolkit": "^1.5.0", - "@sentry/react-native": "^2.3.0", - "@sharcoux/slider": "^5.1.3", + "@react-navigation/bottom-tabs": "^5.11.11", + "@react-navigation/native": "^5.9.4", + "@react-navigation/stack": "^5.14.5", + "@reduxjs/toolkit": "^1.5.1", + "@sentry/react-native": "^2.4.3", + "@sharcoux/slider": "^5.3.0", "axios": "^0.21.1", - "expo": "^40.0.1", - "expo-auth-session": "~3.1.0", - "expo-av": "~9.0.0", - "expo-crypto": "~9.0.0", - "expo-firebase-analytics": "~3.0.0", - "expo-haptics": "~9.0.0", - "expo-image-picker": "~10.0.0", - "expo-linking": "~2.1.1", - "expo-localization": "~10.0.0", - "expo-notifications": "~0.9.0", - "expo-random": "~11.0.0", - "expo-screen-capture": "^3.0.0", - "expo-splash-screen": "~0.9.0", - "expo-status-bar": "~1.0.3", - "expo-store-review": "~3.0.0", - "expo-video-thumbnails": "~5.0.0", - "expo-web-browser": "~9.0.0", - "i18next": "^19.9.2", + "expo": "^41.0.1", + "expo-auth-session": "~3.2.3", + "expo-av": "~9.1.2", + "expo-crypto": "~9.1.0", + "expo-firebase-analytics": "~4.0.2", + "expo-haptics": "~10.0.0", + "expo-image-manipulator": "~9.1.0", + "expo-image-picker": "~10.1.4", + "expo-linking": "~2.2.3", + "expo-localization": "~10.1.0", + "expo-notifications": "~0.11.6", + "expo-random": "~11.1.2", + "expo-screen-capture": "^3.1.0", + "expo-secure-store": "~10.1.0", + "expo-splash-screen": "~0.10.2", + "expo-status-bar": "~1.0.4", + "expo-store-review": "~4.0.2", + "expo-video-thumbnails": "~5.1.0", + "expo-web-browser": "~9.1.0", + "i18next": "^20.3.0", "li": "^1.3.0", "lodash": "^4.17.21", - "react": "17.0.1", - "react-dom": "17.0.1", - "react-i18next": "^11.8.10", - "react-native": "~0.64.0", + "react": "17.0.2", + "react-dom": "17.0.2", + "react-i18next": "^11.9.0", + "react-native": "~0.64.1", "react-native-animated-spinkit": "^1.5.2", "react-native-blurhash": "^1.1.4", "react-native-fast-image": "^8.3.4", @@ -70,56 +72,55 @@ "react-native-flash-message": "^0.1.23", "react-native-gesture-handler": "~1.10.3", "react-native-htmlview": "^0.16.0", - "react-native-pager-view": "^5.1.2", - "react-native-reanimated": "^2.0.0", + "react-native-pager-view": "5.1.9", + "react-native-reanimated": "~2.1.0", "react-native-safe-area-context": "3.2.0", - "react-native-screens": "~2.17.1", - "react-native-svg": "12.1.0", - "react-native-swipe-list-view": "^3.2.6", - "react-native-tab-view": "^3.0.0", - "react-native-unimodules": "~0.12.0", - "react-query": "^3.12.2", - "react-redux": "^7.2.2", + "react-native-screens": "~3.3.0", + "react-native-svg": "12.1.1", + "react-native-swipe-list-view": "^3.2.7", + "react-native-tab-view": "^3.0.1", + "react-native-unimodules": "~0.13.3", + "react-query": "^3.16.0", + "react-redux": "^7.2.4", "react-timeago": "^5.2.0", "redux-persist": "^6.0.0", "rn-placeholder": "^3.0.3", - "sentry-expo": "^3.0.5", - "tslib": "^2.1.0", + "sentry-expo": "^3.1.3", + "tslib": "^2.2.0", "valid-url": "^1.0.9" }, "devDependencies": { - "@babel/core": "~7.13.10", - "@babel/plugin-proposal-optional-chaining": "^7.13.8", + "@babel/core": "~7.14.3", + "@babel/plugin-proposal-optional-chaining": "^7.14.2", "@babel/preset-typescript": "^7.13.0", - "@expo/config": "^3.3.31", + "@expo/config": "^3.3.43", "@jest/types": "^26.6.2", "@testing-library/jest-native": "^4.0.1", - "@testing-library/react-hooks": "^5.1.0", + "@testing-library/react-hooks": "^5.1.2", "@testing-library/react-native": "^7.2.0", - "@types/jest": "^26.0.20", - "@types/lodash": "^4.14.168", - "@types/react": "~17.0.3", - "@types/react-dom": "~17.0.2", - "@types/react-native": "~0.63.52", + "@types/jest": "^26.0.23", + "@types/lodash": "^4.14.170", + "@types/react": "~17.0.8", + "@types/react-dom": "~17.0.5", + "@types/react-native": "~0.64.6", "@types/react-navigation": "^3.4.0", "@types/react-redux": "^7.1.16", "@types/react-test-renderer": "^17.0.1", "@types/react-timeago": "^4.1.2", "@types/valid-url": "^1.0.3", - "@welldone-software/why-did-you-render": "^6.1.1", + "@welldone-software/why-did-you-render": "^6.1.4", "babel-jest": "~26.6.3", "babel-plugin-module-resolver": "^4.1.0", "babel-plugin-transform-remove-console": "^6.9.4", - "chalk": "^4.1.0", - "dotenv": "^8.2.0", + "chalk": "^4.1.1", + "dotenv": "^10.0.0", "jest": "^26.6.3", - "jest-expo": "^40.0.2", + "jest-expo": "^41.0.0", "nock": "^13.0.11", - "react-native-clean-project": "^3.6.3", + "react-native-clean-project": "^3.6.4", "react-navigation": "^4.4.4", "react-navigation-stack": "^2.10.4", - "react-test-renderer": "^17.0.1", - "typescript": "~4.2.3", - "uri-scheme": "^1.0.68" + "react-test-renderer": "^17.0.2", + "typescript": "~4.2.4" } -} +} \ No newline at end of file diff --git a/src/@types/react-navigation.d.ts b/src/@types/react-navigation.d.ts index 9a0112c6..5f522ea1 100644 --- a/src/@types/react-navigation.d.ts +++ b/src/@types/react-navigation.d.ts @@ -1,6 +1,4 @@ declare namespace Nav { - import { QueryKeyTimeline } from '@utils/queryHooks/timeline' - type RootStackParamList = { 'Screen-Tabs': undefined 'Screen-Actions': @@ -151,8 +149,4 @@ declare namespace Nav { fields?: Mastodon.Source['fields'] } } - - type TabMePushStackParamList = { - 'Tab-Me-Push-Root': undefined - } } diff --git a/src/@types/untyped.d.ts b/src/@types/untyped.d.ts index 24592684..9220fed3 100644 --- a/src/@types/untyped.d.ts +++ b/src/@types/untyped.d.ts @@ -1,4 +1,5 @@ declare module 'gl-react-blurhash' +declare module 'htmlparser2-without-node-native' declare module 'li' declare module 'react-native-feather' declare module 'react-native-htmlview' diff --git a/src/App.tsx b/src/App.tsx index 399cf6ea..b035ff10 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,4 +1,5 @@ import { ActionSheetProvider } from '@expo/react-native-action-sheet' +import queryClient from '@helpers/queryClient' import i18n from '@root/i18n/i18n' import Screens from '@root/Screens' import audio from '@root/startup/audio' @@ -14,8 +15,7 @@ import * as Notifications from 'expo-notifications' import * as SplashScreen from 'expo-splash-screen' import React, { useCallback, useEffect, useState } from 'react' import { AppState, LogBox, Platform } from 'react-native' -import { enableScreens } from 'react-native-screens' -import { QueryClient, QueryClientProvider } from 'react-query' +import { QueryClientProvider } from 'react-query' import { Provider } from 'react-redux' import { PersistGate } from 'redux-persist/integration/react' import push from './startup/push' @@ -29,12 +29,6 @@ sentry() audio() push() -log('log', 'react-query', 'initializing') -export const queryClient = new QueryClient() - -log('log', 'react-native-screens', 'initializing') -enableScreens() - const App: React.FC = () => { log('log', 'App', 'rendering App') const [localCorrupt, setLocalCorrupt] = useState() diff --git a/src/Screens.tsx b/src/Screens.tsx index 0a4d0693..5cf8cf5b 100644 --- a/src/Screens.tsx +++ b/src/Screens.tsx @@ -1,9 +1,8 @@ +import { HeaderCenter, HeaderLeft } from '@components/Header' import { displayMessage, Message, removeMessage } from '@components/Message' +import navigationRef from '@helpers/navigationRef' import { useNetInfo } from '@react-native-community/netinfo' -import { - NavigationContainer, - NavigationContainerRef -} from '@react-navigation/native' +import { NavigationContainer } from '@react-navigation/native' import ScreenActions from '@screens/Actions' import ScreenAnnouncements from '@screens/Announcements' import ScreenCompose from '@screens/Compose' @@ -19,7 +18,7 @@ import { useTheme } from '@utils/styles/ThemeManager' import { themes } from '@utils/styles/themes' import * as Analytics from 'expo-firebase-analytics' import { addScreenshotListener } from 'expo-screen-capture' -import React, { createRef, useCallback, useEffect, useRef } from 'react' +import React, { useCallback, useEffect, useRef } from 'react' import { useTranslation } from 'react-i18next' import { Alert, Platform, StatusBar } from 'react-native' import { createNativeStackNavigator } from 'react-native-screens/native-stack' @@ -28,7 +27,6 @@ import { useDispatch, useSelector } from 'react-redux' import * as Sentry from 'sentry-expo' const Stack = createNativeStackNavigator() -export const navigationRef = createRef() export interface Props { localCorrupt?: string @@ -174,18 +172,30 @@ const Screens: React.FC = ({ localCorrupt }) => { ({ stackPresentation: 'transparentModal', stackAnimation: 'fade', - headerShown: false - }} + headerShown: true, + headerHideShadow: true, + headerTopInsetEnabled: false, + headerStyle: { backgroundColor: 'transparent' }, + headerLeft: () => ( + navigation.goBack()} /> + ), + headerTitle: t('screenAnnouncements:heading'), + ...(Platform.OS === 'android' && { + headerCenter: () => ( + + ) + }) + })} /> = ({ localCorrupt }) => { options={{ stackPresentation: 'fullScreenModal', stackAnimation: 'fade', - headerShown: false + ...(Platform.OS === 'android' && { headerShown: false }) }} /> diff --git a/src/api/general.ts b/src/api/general.ts index 59e4c15e..2761f2b4 100644 --- a/src/api/general.ts +++ b/src/api/general.ts @@ -69,12 +69,16 @@ const apiGeneral = async ({ error.response.status, error.response.data.error ) - return Promise.reject(error.response) + return Promise.reject(error.response.data.error) } else if (error.request) { // The request was made but no response was received // `error.request` is an instance of XMLHttpRequest in the browser and an instance of // http.ClientRequest in node.js - console.error(ctx.bold(' API general '), ctx.bold('request'), error) + console.error( + ctx.bold(' API general '), + ctx.bold('request'), + error.request + ) return Promise.reject() } else { console.error( diff --git a/src/api/instance.ts b/src/api/instance.ts index 57736082..af1d7bef 100644 --- a/src/api/instance.ts +++ b/src/api/instance.ts @@ -98,7 +98,7 @@ const apiInstance = async ({ error.response.status, error.response.data.error ) - return Promise.reject(error.response) + return Promise.reject(error.response.data.error) } else if (error.request) { // The request was made but no response was received // `error.request` is an instance of XMLHttpRequest in the browser and an instance of diff --git a/src/components/Emojis.tsx b/src/components/Emojis.tsx index 26afa00f..7854eeca 100644 --- a/src/components/Emojis.tsx +++ b/src/components/Emojis.tsx @@ -4,7 +4,6 @@ import { useAccessibility } from '@utils/accessibility/AccessibilityManager' import { useEmojisQuery } from '@utils/queryHooks/emojis' import { chunk, forEach, groupBy, sortBy } from 'lodash' import React, { - createContext, Dispatch, MutableRefObject, SetStateAction, @@ -13,44 +12,7 @@ import React, { useReducer } from 'react' import FastImage from 'react-native-fast-image' - -type EmojisState = { - enabled: boolean - active: boolean - emojis: { title: string; data: Mastodon.Emoji[][] }[] - shortcode: Mastodon.Emoji['shortcode'] | null -} - -type EmojisAction = - | { - type: 'load' - payload: NonNullable - } - | { - type: 'activate' - payload: EmojisState['active'] - } - | { - type: 'shortcode' - payload: EmojisState['shortcode'] - } - -const emojisReducer = (state: EmojisState, action: EmojisAction) => { - switch (action.type) { - case 'activate': - return { ...state, active: action.payload } - case 'load': - return { ...state, emojis: action.payload } - case 'shortcode': - return { ...state, shortcode: action.payload } - } -} - -type ContextType = { - emojisState: EmojisState - emojisDispatch: Dispatch -} -const EmojisContext = createContext({} as ContextType) +import EmojisContext, { emojisReducer } from './Emojis/helpers/EmojisContext' const prefetchEmojis = ( sortedEmojis: { title: string; data: Mastodon.Emoji[][] }[], @@ -163,4 +125,4 @@ const ComponentEmojis: React.FC = ({ ) } -export { ComponentEmojis, EmojisContext, EmojisButton, EmojisList } +export { ComponentEmojis, EmojisButton, EmojisList } diff --git a/src/components/Emojis/Button.tsx b/src/components/Emojis/Button.tsx index 897273a9..e6d03283 100644 --- a/src/components/Emojis/Button.tsx +++ b/src/components/Emojis/Button.tsx @@ -1,9 +1,9 @@ -import { EmojisContext } from '@components/Emojis' import Icon from '@components/Icon' import { StyleConstants } from '@utils/styles/constants' import { useTheme } from '@utils/styles/ThemeManager' import React, { useContext } from 'react' import { Pressable, StyleSheet } from 'react-native' +import EmojisContext from './helpers/EmojisContext' const EmojisButton = React.memo( () => { diff --git a/src/components/Emojis/List.tsx b/src/components/Emojis/List.tsx index d0fdc749..5e5998d0 100644 --- a/src/components/Emojis/List.tsx +++ b/src/components/Emojis/List.tsx @@ -1,4 +1,3 @@ -import { EmojisContext } from '@components/Emojis' import { useAccessibility } from '@utils/accessibility/AccessibilityManager' import { StyleConstants } from '@utils/styles/constants' import layoutAnimation from '@utils/styles/layoutAnimation' @@ -16,6 +15,7 @@ import { } from 'react-native' import FastImage from 'react-native-fast-image' import validUrl from 'valid-url' +import EmojisContext from './helpers/EmojisContext' const EmojisList = React.memo( () => { diff --git a/src/components/Emojis/helpers/EmojisContext.tsx b/src/components/Emojis/helpers/EmojisContext.tsx new file mode 100644 index 00000000..2e4f5458 --- /dev/null +++ b/src/components/Emojis/helpers/EmojisContext.tsx @@ -0,0 +1,41 @@ +import { createContext, Dispatch } from 'react' + +export type EmojisState = { + enabled: boolean + active: boolean + emojis: { title: string; data: Mastodon.Emoji[][] }[] + shortcode: Mastodon.Emoji['shortcode'] | null +} + +export type EmojisAction = + | { + type: 'load' + payload: NonNullable + } + | { + type: 'activate' + payload: EmojisState['active'] + } + | { + type: 'shortcode' + payload: EmojisState['shortcode'] + } + +type ContextType = { + emojisState: EmojisState + emojisDispatch: Dispatch +} +const EmojisContext = createContext({} as ContextType) + +export const emojisReducer = (state: EmojisState, action: EmojisAction) => { + switch (action.type) { + case 'activate': + return { ...state, active: action.payload } + case 'load': + return { ...state, emojis: action.payload } + case 'shortcode': + return { ...state, shortcode: action.payload } + } +} + +export default EmojisContext diff --git a/src/components/Input.tsx b/src/components/Input.tsx index 795a07b6..dcdd0f20 100644 --- a/src/components/Input.tsx +++ b/src/components/Input.tsx @@ -18,12 +18,8 @@ import { View } from 'react-native' import Animated, { useAnimatedStyle, withTiming } from 'react-native-reanimated' -import { - ComponentEmojis, - EmojisButton, - EmojisContext, - EmojisList -} from './Emojis' +import { ComponentEmojis, EmojisButton, EmojisList } from './Emojis' +import EmojisContext from './Emojis/helpers/EmojisContext' export interface Props { autoFocus?: boolean @@ -114,7 +110,8 @@ const Input: React.FC = ({ styles.base, { borderColor: theme.border, - flexDirection: multiline ? 'column' : 'row' + flexDirection: multiline ? 'column' : 'row', + alignItems: 'stretch' } ]} > @@ -157,7 +154,7 @@ const Input: React.FC = ({ {title} ) : null} - + {options?.maxLength && value?.length ? ( {value?.length} / {options.maxLength} diff --git a/src/components/Menu/Row.tsx b/src/components/Menu/Row.tsx index e7dde35b..04040091 100644 --- a/src/components/Menu/Row.tsx +++ b/src/components/Menu/Row.tsx @@ -76,96 +76,98 @@ const MenuRow: React.FC = ({ } }} > - - - {iconFront && ( - - )} - {badge ? ( - - ) : null} - - - {title} - - - - - {content || switchValue !== undefined || iconBack ? ( - - {content ? ( - typeof content === 'string' ? ( - - {content} - - ) : ( - content - ) - ) : null} - {switchValue !== undefined ? ( - - ) : null} - {iconBack ? ( + + + + {iconFront && ( + )} + {badge ? ( + ) : null} - {loading && loadingSpinkit} + + + {title} + + + + {content || switchValue !== undefined || iconBack ? ( + + {content ? ( + typeof content === 'string' ? ( + + {content} + + ) : ( + content + ) + ) : null} + {switchValue !== undefined ? ( + + ) : null} + {iconBack ? ( + + ) : null} + {loading && loadingSpinkit} + + ) : null} + + {description ? ( + + {description} + ) : null} - {description ? ( - - {description} - - ) : null} ) } const styles = StyleSheet.create({ base: { - minHeight: 46, - paddingVertical: StyleConstants.Spacing.S + minHeight: 50 }, core: { flex: 1, - flexDirection: 'row' + flexDirection: 'row', + paddingVertical: StyleConstants.Spacing.S }, front: { flex: 2, diff --git a/src/components/Message.tsx b/src/components/Message.tsx index 7ba3377f..db350f64 100644 --- a/src/components/Message.tsx +++ b/src/components/Message.tsx @@ -80,7 +80,7 @@ const displayMessage = ({ }) } else { showMessage({ - duration: type === 'error' ? 5000 : duration === 'short' ? 1500 : 3000, + duration: type === 'error' ? 3500 : duration === 'short' ? 1500 : 2500, autoHide, message, description, diff --git a/src/components/Parse/Emojis.tsx b/src/components/Parse/Emojis.tsx index 34c1066f..d98f4ba1 100644 --- a/src/components/Parse/Emojis.tsx +++ b/src/components/Parse/Emojis.tsx @@ -4,7 +4,6 @@ import { StyleConstants } from '@utils/styles/constants' import { adaptiveScale } from '@utils/styles/scaling' import { useTheme } from '@utils/styles/ThemeManager' import React, { useMemo } from 'react' -import { useTranslation } from 'react-i18next' import { StyleSheet, Text } from 'react-native' import FastImage from 'react-native-fast-image' import { useSelector } from 'react-redux' @@ -28,7 +27,6 @@ const ParseEmojis = React.memo( adaptiveSize = false, fontBold = false }: Props) => { - const { t } = useTranslation('componentParse') const { reduceMotionEnabled } = useAccessibility() const adaptiveFontsize = useSelector(getSettingsFontsize) diff --git a/src/components/Parse/HTML.tsx b/src/components/Parse/HTML.tsx index 4d0589be..5c9f90e5 100644 --- a/src/components/Parse/HTML.tsx +++ b/src/components/Parse/HTML.tsx @@ -162,7 +162,9 @@ export interface Props { showFullLink?: boolean numberOfLines?: number expandHint?: string + highlighted?: boolean disableDetails?: boolean + selectable?: boolean } const ParseHTML = React.memo( @@ -176,7 +178,9 @@ const ParseHTML = React.memo( showFullLink = false, numberOfLines = 10, expandHint, - disableDetails = false + highlighted = false, + disableDetails = false, + selectable = false }: Props) => { const adaptiveFontsize = useSelector(getSettingsFontsize) const adaptedFontsize = adaptiveScale( @@ -234,7 +238,7 @@ const ParseHTML = React.memo( const { t } = useTranslation('componentParse') const [expandAllow, setExpandAllow] = useState(false) - const [expanded, setExpanded] = useState(false) + const [expanded, setExpanded] = useState(highlighted) const onTextLayout = useCallback(({ nativeEvent }) => { if ( @@ -253,6 +257,7 @@ const ParseHTML = React.memo( numberOfLines={ expandAllow ? (expanded ? 999 : numberOfLines) : undefined } + selectable={selectable} /> {expandAllow ? ( = ({ {!disableDetails && actualStatus.card && ( )} - + {!disableDetails ? ( + + ) : null} + + - - {queryKey && !disableDetails && ( { analytics('timeline_shared_actionsusers_press_boosted', { count: status.reblogs_count @@ -68,7 +68,7 @@ const TimelineActionsUsers = React.memo( 'shared.actionsUsers.favourited_by.accessibilityHint' )} accessibilityRole='button' - style={[styles.text, { color: theme.secondary }]} + style={[styles.text, { color: theme.blue }]} onPress={() => { analytics('timeline_shared_actionsusers_press_boosted', { count: status.favourites_count @@ -98,10 +98,9 @@ const styles = StyleSheet.create({ base: { flexDirection: 'row' }, - pressable: { margin: StyleConstants.Spacing.M }, text: { - ...StyleConstants.FontStyle.S, - padding: StyleConstants.Spacing.S * 1.5, + ...StyleConstants.FontStyle.M, + padding: StyleConstants.Spacing.S, paddingLeft: 0, marginRight: StyleConstants.Spacing.S } diff --git a/src/components/Timeline/Shared/Content.tsx b/src/components/Timeline/Shared/Content.tsx index c23bdeba..61c46d10 100644 --- a/src/components/Timeline/Shared/Content.tsx +++ b/src/components/Timeline/Shared/Content.tsx @@ -30,7 +30,9 @@ const TimelineContent = React.memo( mentions={status.mentions} tags={status.tags} numberOfLines={999} + highlighted={highlighted} disableDetails={disableDetails} + selectable={highlighted} /> ) : ( @@ -54,6 +58,7 @@ const TimelineContent = React.memo( tags={status.tags} numberOfLines={highlighted ? 999 : numberOfLines} disableDetails={disableDetails} + selectable={highlighted} /> )} diff --git a/src/components/Timeline/Shared/FullConversation.tsx b/src/components/Timeline/Shared/FullConversation.tsx index 79b65c15..7cf2208e 100644 --- a/src/components/Timeline/Shared/FullConversation.tsx +++ b/src/components/Timeline/Shared/FullConversation.tsx @@ -26,7 +26,7 @@ const TimelineFullConversation = React.memo( style={{ ...StyleConstants.FontStyle.S, color: theme.blue, - marginTop: StyleConstants.Font.Size.S + marginTop: StyleConstants.Spacing.S }} > {t('shared.fullConversation')} diff --git a/src/components/Timeline/Shared/Translate.tsx b/src/components/Timeline/Shared/Translate.tsx new file mode 100644 index 00000000..d99e6bf1 --- /dev/null +++ b/src/components/Timeline/Shared/Translate.tsx @@ -0,0 +1,131 @@ +import analytics from '@components/analytics' +import { ParseHTML } from '@components/Parse' +import { useTranslateQuery } from '@utils/queryHooks/translate' +import { getSettingsLanguage } from '@utils/slices/settingsSlice' +import { StyleConstants } from '@utils/styles/constants' +import { useTheme } from '@utils/styles/ThemeManager' +import React, { useState } from 'react' +import { useTranslation } from 'react-i18next' +import { Pressable, StyleSheet, Text } from 'react-native' +import { Circle } from 'react-native-animated-spinkit' +import { useSelector } from 'react-redux' + +export interface Props { + highlighted: boolean + status: Mastodon.Status +} + +const TimelineTranslate = React.memo( + ({ highlighted, status }: Props) => { + if (!highlighted) { + return null + } + if (!status.language) { + return null + } + + const { t } = useTranslation('componentTimeline') + const { theme } = useTheme() + + const tootLanguage = status.language.slice(0, 2) + + const settingsLanguage = useSelector(getSettingsLanguage) + + if (settingsLanguage.includes(tootLanguage)) { + return null + } + + let text = status.spoiler_text + ? [status.spoiler_text, status.content] + : [status.content] + + for (const i in text) { + for (const emoji of status.emojis) { + text[i] = text[i].replaceAll(`:${emoji.shortcode}:`, '') + } + } + + const [enabled, setEnabled] = useState(false) + const { refetch, data, isLoading, isSuccess, isError } = useTranslateQuery({ + uri: status.uri, + source: status.language, + target: settingsLanguage, + text, + options: { enabled } + }) + + return ( + <> + { + if (enabled) { + if (!isSuccess) { + analytics('timeline_shared_translate_retry', { + language: status.language + }) + refetch() + } + } else { + analytics('timeline_shared_translate', { + language: status.language + }) + setEnabled(true) + } + }} + > + + {isError + ? t('shared.translate.failed') + : isSuccess + ? t('shared.translate.succeed', { + provider: data?.provider, + source: data?.sourceLanguage + }) + : t('shared.translate.default')} + {__DEV__ ? ` Source: ${status.language}` : undefined} + + {isLoading ? ( + + ) : null} + + {data + ? data.text.map((d, i) => ( + + )) + : null} + + ) + }, + () => true +) + +const styles = StyleSheet.create({ + button: { + flexDirection: 'row', + alignItems: 'center', + paddingVertical: StyleConstants.Spacing.S + } +}) + +export default TimelineTranslate diff --git a/src/components/mediaSelector.ts b/src/components/mediaSelector.ts index 682c6549..c3c73b18 100644 --- a/src/components/mediaSelector.ts +++ b/src/components/mediaSelector.ts @@ -1,13 +1,14 @@ -import * as ImagePicker from 'expo-image-picker' -import { Alert, Linking } from 'react-native' -import { ActionSheetOptions } from '@expo/react-native-action-sheet' -import i18next from 'i18next' import analytics from '@components/analytics' +import { ActionSheetOptions } from '@expo/react-native-action-sheet' +import * as ImageManipulator from 'expo-image-manipulator' +import * as ImagePicker from 'expo-image-picker' import { ImageInfo } from 'expo-image-picker/build/ImagePicker.types' +import i18next from 'i18next' +import { Alert, Linking } from 'react-native' export interface Props { mediaTypes?: ImagePicker.MediaTypeOptions - uploader: (imageInfo: ImageInfo) => void + resize?: { width?: number; height?: number } // Resize mode contain showActionSheetWithOptions: ( options: ActionSheetOptions, callback: (i: number) => void @@ -16,118 +17,134 @@ export interface Props { const mediaSelector = async ({ mediaTypes = ImagePicker.MediaTypeOptions.All, - uploader, + resize, showActionSheetWithOptions -}: Props): Promise => { - showActionSheetWithOptions( - { - title: i18next.t('componentMediaSelector:title'), - options: [ - i18next.t('componentMediaSelector:options.library'), - i18next.t('componentMediaSelector:options.photo'), - i18next.t('componentMediaSelector:options.cancel') - ], - cancelButtonIndex: 2 - }, - async buttonIndex => { - if (buttonIndex === 0) { - const { - status - } = await ImagePicker.requestMediaLibraryPermissionsAsync() - if (status !== 'granted') { - Alert.alert( - i18next.t('componentMediaSelector:library.alert.title'), - i18next.t('componentMediaSelector:library.alert.message'), - [ - { - text: i18next.t( - 'componentMediaSelector:library.alert.buttons.cancel' - ), - style: 'cancel', - onPress: () => - analytics('mediaSelector_nopermission', { action: 'cancel' }) - }, - { - text: i18next.t( - 'componentMediaSelector:library.alert.buttons.settings' - ), - style: 'default', - onPress: () => { - analytics('mediaSelector_nopermission', { - action: 'settings' - }) - Linking.openURL('app-settings:') - } - } - ] - ) - } else { - const result = await ImagePicker.launchImageLibraryAsync({ - mediaTypes, - exif: false - }) - - if (!result.cancelled) { - // https://github.com/expo/expo/issues/11214 - const fixResult = { - ...result, - uri: result.uri.replace('file:/data', 'file:///data') - } - uploader(fixResult) - return +}: Props): Promise => { + return new Promise((resolve, reject) => { + const resolveResult = async (result: ImageInfo) => { + if (resize && result.type === 'image') { + let newResult: ImageManipulator.ImageResult + if (resize.width && resize.height) { + if (resize.width / resize.height > result.width / result.height) { + newResult = await ImageManipulator.manipulateAsync(result.uri, [ + { resize: { width: resize.width } } + ]) + } else { + newResult = await ImageManipulator.manipulateAsync(result.uri, [ + { resize: { height: resize.height } } + ]) } - } - } else if (buttonIndex === 1) { - const { status } = await ImagePicker.requestCameraPermissionsAsync() - if (status !== 'granted') { - Alert.alert( - i18next.t('componentMediaSelector:photo.alert.title'), - i18next.t('componentMediaSelector:photo.alert.message'), - [ - { - text: i18next.t( - 'componentMediaSelector:photo.alert.buttons.cancel' - ), - style: 'cancel', - onPress: () => { - analytics('compose_addattachment_camera_nopermission', { - action: 'cancel' - }) - } - }, - { - text: i18next.t( - 'componentMediaSelector:photo.alert.buttons.settings' - ), - style: 'default', - onPress: () => { - analytics('compose_addattachment_camera_nopermission', { - action: 'settings' - }) - Linking.openURL('app-settings:') - } - } - ] - ) } else { - const result = await ImagePicker.launchCameraAsync({ - mediaTypes, - exif: false - }) + newResult = await ImageManipulator.manipulateAsync(result.uri, [ + { resize } + ]) + } + resolve(newResult) + } else { + resolve(result) + } + } - if (!result.cancelled) { - // https://github.com/expo/expo/issues/11214 - const fixResult = { - ...result, - uri: result.uri.replace('file:/data', 'file:///data') + showActionSheetWithOptions( + { + title: i18next.t('componentMediaSelector:title'), + options: [ + i18next.t('componentMediaSelector:options.library'), + i18next.t('componentMediaSelector:options.photo'), + i18next.t('componentMediaSelector:options.cancel') + ], + cancelButtonIndex: 2 + }, + async buttonIndex => { + if (buttonIndex === 0) { + const { + status + } = await ImagePicker.requestMediaLibraryPermissionsAsync() + if (status !== 'granted') { + Alert.alert( + i18next.t('componentMediaSelector:library.alert.title'), + i18next.t('componentMediaSelector:library.alert.message'), + [ + { + text: i18next.t( + 'componentMediaSelector:library.alert.buttons.cancel' + ), + style: 'cancel', + onPress: () => + analytics('mediaSelector_nopermission', { + action: 'cancel' + }) + }, + { + text: i18next.t( + 'componentMediaSelector:library.alert.buttons.settings' + ), + style: 'default', + onPress: () => { + analytics('mediaSelector_nopermission', { + action: 'settings' + }) + Linking.openURL('app-settings:') + } + } + ] + ) + } else { + const result = await ImagePicker.launchImageLibraryAsync({ + mediaTypes, + exif: false + }) + + if (!result.cancelled) { + await resolveResult(result) + } + } + } else if (buttonIndex === 1) { + const { status } = await ImagePicker.requestCameraPermissionsAsync() + if (status !== 'granted') { + Alert.alert( + i18next.t('componentMediaSelector:photo.alert.title'), + i18next.t('componentMediaSelector:photo.alert.message'), + [ + { + text: i18next.t( + 'componentMediaSelector:photo.alert.buttons.cancel' + ), + style: 'cancel', + onPress: () => { + analytics('compose_addattachment_camera_nopermission', { + action: 'cancel' + }) + } + }, + { + text: i18next.t( + 'componentMediaSelector:photo.alert.buttons.settings' + ), + style: 'default', + onPress: () => { + analytics('compose_addattachment_camera_nopermission', { + action: 'settings' + }) + Linking.openURL('app-settings:') + } + } + ] + ) + } else { + const result = await ImagePicker.launchCameraAsync({ + mediaTypes, + exif: false + }) + + if (!result.cancelled) { + await resolveResult(result) } - uploader(fixResult) - return } } } - } - ) + ) + }) } export default mediaSelector diff --git a/src/components/openLink.ts b/src/components/openLink.ts index 6327128a..a5e041da 100644 --- a/src/components/openLink.ts +++ b/src/components/openLink.ts @@ -1,6 +1,6 @@ import apiInstance from '@api/instance' +import navigationRef from '@helpers/navigationRef' import { NavigationProp, ParamListBase } from '@react-navigation/native' -import { navigationRef } from '@root/Screens' import { store } from '@root/store' import { SearchResult } from '@utils/queryHooks/search' import { getInstanceUrl } from '@utils/slices/instancesSlice' diff --git a/src/helpers/navigationRef.ts b/src/helpers/navigationRef.ts new file mode 100644 index 00000000..48f0f8c5 --- /dev/null +++ b/src/helpers/navigationRef.ts @@ -0,0 +1,6 @@ +import { NavigationContainerRef } from '@react-navigation/native' +import { createRef } from 'react' + +const navigationRef = createRef() + +export default navigationRef diff --git a/src/helpers/queryClient.ts b/src/helpers/queryClient.ts new file mode 100644 index 00000000..3e018e42 --- /dev/null +++ b/src/helpers/queryClient.ts @@ -0,0 +1,5 @@ +import { QueryClient } from 'react-query' + +const queryClient = new QueryClient() + +export default queryClient diff --git a/src/i18n/en/components/timeline.json b/src/i18n/en/components/timeline.json index aadc68fb..fe7aed9c 100644 --- a/src/i18n/en/components/timeline.json +++ b/src/i18n/en/components/timeline.json @@ -74,6 +74,11 @@ "expandHint": "hidden content" }, "fullConversation": "Read conversations", + "translate": { + "default": "Translate", + "succeed": "Translated by {{provider}} from {{source}}", + "failed": "Translation failed" + }, "header": { "shared": { "account": { diff --git a/src/i18n/en/screens/tabs.json b/src/i18n/en/screens/tabs.json index 18ae1a72..c87a7904 100644 --- a/src/i18n/en/screens/tabs.json +++ b/src/i18n/en/screens/tabs.json @@ -102,11 +102,11 @@ }, "avatar": { "title": "Avatar", - "description": "Available in next version" + "description": "Will be downscaled to 400x400px" }, - "banner": { + "header": { "title": "Banner", - "description": "Available in next version" + "description": "Will be downscaled to 1500x500px" }, "note": { "title": "Description" diff --git a/src/i18n/zh-Hans/components/timeline.json b/src/i18n/zh-Hans/components/timeline.json index 31e4c09a..6a255318 100644 --- a/src/i18n/zh-Hans/components/timeline.json +++ b/src/i18n/zh-Hans/components/timeline.json @@ -74,6 +74,11 @@ "expandHint": "隐藏内容" }, "fullConversation": "阅读全部对话", + "translate": { + "default": "翻译", + "succeed": "由{{provider}}翻译自{{source}}", + "failed": "翻译失败" + }, "header": { "shared": { "account": { diff --git a/src/i18n/zh-Hans/screens/tabs.json b/src/i18n/zh-Hans/screens/tabs.json index 2f8d80dc..820e0b1e 100644 --- a/src/i18n/zh-Hans/screens/tabs.json +++ b/src/i18n/zh-Hans/screens/tabs.json @@ -102,11 +102,11 @@ }, "avatar": { "title": "头像", - "description": "将在下一版中启用" + "description": "将缩小到400x400px" }, - "banner": { + "header": { "title": "横幅", - "description": "将在下一版中启用" + "description": "将缩小到1500x500px" }, "note": { "title": "简介" diff --git a/src/screens/Announcements.tsx b/src/screens/Announcements.tsx index 60468a77..9a3f8429 100644 --- a/src/screens/Announcements.tsx +++ b/src/screens/Announcements.tsx @@ -1,7 +1,6 @@ import analytics from '@components/analytics' import Button from '@components/Button' import haptics from '@components/haptics' -import { HeaderCenter, HeaderLeft, HeaderRight } from '@components/Header' import { ParseHTML } from '@components/Parse' import RelativeTime from '@components/RelativeTime' import { BlurView } from '@react-native-community/blur' @@ -88,6 +87,7 @@ const ScreenAnnouncements: React.FC = ({ emojis={item.emojis} mentions={item.mentions} numberOfLines={999} + selectable /> {item.reactions?.length ? ( @@ -210,28 +210,6 @@ const ScreenAnnouncements: React.FC = ({ reducedTransparencyFallbackColor={theme.backgroundDefault} > - - navigation.goBack()} - /> - - - {}} - /> - - = ({ return { ...composeInitialState, timestamp: Date.now(), + attachments: { + ...composeInitialState.attachments, + sensitive: + localAccount?.preferences && + localAccount?.preferences['posting:default:sensitive'] + ? localAccount?.preferences['posting:default:sensitive'] + : false + }, visibility: localAccount?.preferences && localAccount.preferences['posting:default:visibility'] @@ -397,12 +405,18 @@ const ScreenCompose: React.FC = ({ diff --git a/src/screens/Compose/Root.tsx b/src/screens/Compose/Root.tsx index 951355e0..742b5f62 100644 --- a/src/screens/Compose/Root.tsx +++ b/src/screens/Compose/Root.tsx @@ -3,7 +3,7 @@ import { useEmojisQuery } from '@utils/queryHooks/emojis' import { useSearchQuery } from '@utils/queryHooks/search' import { StyleConstants } from '@utils/styles/constants' import { useTheme } from '@utils/styles/ThemeManager' -import { forEach, groupBy, sortBy } from 'lodash' +import { chunk, forEach, groupBy, sortBy } from 'lodash' import React, { useCallback, useContext, @@ -28,23 +28,26 @@ import ComposeContext from './utils/createContext' import ComposeDrafts from './Root/Drafts' import FastImage from 'react-native-fast-image' import { useAccessibility } from '@utils/accessibility/AccessibilityManager' +import { ComposeState } from './utils/types' const prefetchEmojis = ( - sortedEmojis: { title: string; data: Mastodon.Emoji[] }[], + sortedEmojis: NonNullable, reduceMotionEnabled: boolean ) => { const prefetches: { uri: string }[] = [] let requestedIndex = 0 sortedEmojis.forEach(sorted => { - sorted.data.forEach(emoji => { - if (requestedIndex > 40) { - return - } - prefetches.push({ - uri: reduceMotionEnabled ? emoji.static_url : emoji.url + sorted.data.forEach(emojis => + emojis.forEach(emoji => { + if (requestedIndex > 40) { + return + } + prefetches.push({ + uri: reduceMotionEnabled ? emoji.static_url : emoji.url + }) + requestedIndex++ }) - requestedIndex++ - }) + ) }) try { FastImage.preload(prefetches) @@ -90,10 +93,11 @@ const ComposeRoot = React.memo( const { data: emojisData } = useEmojisQuery({}) useEffect(() => { if (emojisData && emojisData.length) { - let sortedEmojis: { title: string; data: Mastodon.Emoji[] }[] = [] + let sortedEmojis: { title: string; data: Mastodon.Emoji[][] }[] = [] forEach( groupBy(sortBy(emojisData, ['category', 'shortcode']), 'category'), - (value, key) => sortedEmojis.push({ title: key, data: value }) + (value, key) => + sortedEmojis.push({ title: key, data: chunk(value, 5) }) ) composeDispatch({ type: 'emoji', diff --git a/src/screens/Compose/Root/Footer/Emojis.tsx b/src/screens/Compose/Root/Footer/Emojis.tsx index e1ff6fb3..bf9a5ea2 100644 --- a/src/screens/Compose/Root/Footer/Emojis.tsx +++ b/src/screens/Compose/Root/Footer/Emojis.tsx @@ -1,15 +1,8 @@ -import analytics from '@components/analytics' import haptics from '@components/haptics' import { useAccessibility } from '@utils/accessibility/AccessibilityManager' import { StyleConstants } from '@utils/styles/constants' import { useTheme } from '@utils/styles/ThemeManager' -import React, { - RefObject, - useCallback, - useContext, - useEffect, - useMemo -} from 'react' +import React, { RefObject, useCallback, useContext, useEffect } from 'react' import { useTranslation } from 'react-i18next' import { AccessibilityInfo, @@ -25,52 +18,15 @@ import validUrl from 'valid-url' import updateText from '../../updateText' import ComposeContext from '../../utils/createContext' -const SingleEmoji = ({ emoji }: { emoji: Mastodon.Emoji }) => { - const { t } = useTranslation() - const { reduceMotionEnabled } = useAccessibility() - - const { composeState, composeDispatch } = useContext(ComposeContext) - const onPress = useCallback(() => { - analytics('compose_emoji_add') - updateText({ - composeState, - composeDispatch, - newText: `:${emoji.shortcode}:`, - type: 'emoji' - }) - haptics('Light') - }, [composeState]) - const children = useMemo(() => { - const uri = reduceMotionEnabled ? emoji.static_url : emoji.url - if (validUrl.isHttpsUri(uri)) { - return ( - - ) - } else { - return null - } - }, []) - return ( - - ) -} - export interface Props { accessibleRefEmojis: RefObject } const ComposeEmojis: React.FC = ({ accessibleRefEmojis }) => { - const { composeState } = useContext(ComposeContext) + const { composeState, composeDispatch } = useContext(ComposeContext) + const { reduceMotionEnabled } = useAccessibility() const { theme } = useTheme() + const { t } = useTranslation() useEffect(() => { const tagEmojis = findNodeHandle(accessibleRefEmojis.current) @@ -86,21 +42,49 @@ const ComposeEmojis: React.FC = ({ accessibleRefEmojis }) => { [] ) - const emojiList = useCallback( - section => - section.data.map((emoji: Mastodon.Emoji) => ( - - )), - [] - ) const listItem = useCallback( - ({ section, index }) => - index === 0 ? ( - - {emojiList(section)} + ({ index, item }: { item: Mastodon.Emoji[]; index: number }) => { + return ( + + {item.map(emoji => { + const uri = reduceMotionEnabled ? emoji.static_url : emoji.url + if (validUrl.isHttpsUri(uri)) { + return ( + { + updateText({ + composeState, + composeDispatch, + newText: `:${emoji.shortcode}:`, + type: 'emoji' + }) + haptics('Light') + }} + > + + + ) + } else { + return null + } + })} - ) : null, - [] + ) + }, + [composeState] ) return ( @@ -111,7 +95,7 @@ const ComposeEmojis: React.FC = ({ accessibleRefEmojis }) => { horizontal keyboardShouldPersistTaps='always' sections={composeState.emoji.emojis || []} - keyExtractor={item => item.shortcode} + keyExtractor={item => item[0].shortcode} renderSectionHeader={listHeader} renderItem={listItem} windowSize={2} diff --git a/src/screens/Compose/Root/Footer/addAttachment.ts b/src/screens/Compose/Root/Footer/addAttachment.ts index fa2b4f22..72d99aee 100644 --- a/src/screens/Compose/Root/Footer/addAttachment.ts +++ b/src/screens/Compose/Root/Footer/addAttachment.ts @@ -123,7 +123,8 @@ const addAttachment = async ({ }) } - mediaSelector({ uploader, showActionSheetWithOptions }) + const result = await mediaSelector({ showActionSheetWithOptions }) + await uploader(result) } export default addAttachment diff --git a/src/screens/Compose/utils/initialState.ts b/src/screens/Compose/utils/initialState.ts index d340e37f..85306b3b 100644 --- a/src/screens/Compose/utils/initialState.ts +++ b/src/screens/Compose/utils/initialState.ts @@ -31,7 +31,10 @@ const composeInitialState: Omit = { multiple: false, expire: '86400' }, - attachments: { sensitive: false, uploads: [] }, + attachments: { + sensitive: false, + uploads: [] + }, visibility: 'public', visibilityLock: false, replyToStatus: undefined, diff --git a/src/screens/Compose/utils/types.d.ts b/src/screens/Compose/utils/types.d.ts index 713eae6f..866286ae 100644 --- a/src/screens/Compose/utils/types.d.ts +++ b/src/screens/Compose/utils/types.d.ts @@ -40,7 +40,7 @@ export type ComposeState = { } emoji: { active: boolean - emojis: { title: string; data: Mastodon.Emoji[] }[] | undefined + emojis: { title: string; data: Mastodon.Emoji[][] }[] | undefined } poll: { active: boolean diff --git a/src/screens/Tabs/Me.tsx b/src/screens/Tabs/Me.tsx index c512e5e2..73b06e00 100644 --- a/src/screens/Tabs/Me.tsx +++ b/src/screens/Tabs/Me.tsx @@ -109,16 +109,28 @@ const TabMe = React.memo( component={TabMeProfile} options={{ stackPresentation: 'modal', - headerShown: false + ...(Platform.OS === 'android' && { headerShown: false }) }} /> ({ stackPresentation: 'modal', - headerShown: false - }} + headerShown: true, + headerTitle: t('me.stacks.push.name'), + ...(Platform.OS === 'android' && { + headerCenter: () => ( + + ) + }), + headerLeft: () => ( + navigation.goBack()} + /> + ) + })} /> ({ stackPresentation: 'modal', - headerShown: false - }} + headerShown: true, + headerTitle: t('me.stacks.switch.name'), + ...(Platform.OS === 'android' && { + headerCenter: () => ( + + ) + }), + headerLeft: () => ( + navigation.goBack()} + /> + ) + })} /> {sharedScreens(Stack as any)} diff --git a/src/screens/Tabs/Me/Profile.tsx b/src/screens/Tabs/Me/Profile.tsx index 54decf2b..608232a7 100644 --- a/src/screens/Tabs/Me/Profile.tsx +++ b/src/screens/Tabs/Me/Profile.tsx @@ -30,7 +30,6 @@ const TabMeProfile: React.FC ) }} - /> + > + {({ route, navigation }) => ( + + )} + { mutateAsync({ + mode, + messageRef, + message: { + text: 'me.profile.root.note.title', + succeed: true, + failed: true + }, type: 'fields_attributes', data: newFields .filter(field => field.name.length && field.value.length) .map(field => ({ name: field.name, value: field.value })) + }).then(() => { + navigation.navigate('Tab-Me-Profile-Root') }) - .then(() => { - navigation.navigate('Tab-Me-Profile-Root') - displayMessage({ - ref: messageRef, - message: t('me.profile.feedback.succeed', { - type: t('me.profile.root.note.title') - }), - mode, - type: 'success' - }) - }) - .catch(() => { - displayMessage({ - ref: messageRef, - message: t('me.profile.feedback.failed', { - type: t('me.profile.root.note.title') - }), - mode, - type: 'error' - }) - }) }} /> ) diff --git a/src/screens/Tabs/Me/Profile/Name.tsx b/src/screens/Tabs/Me/Profile/Name.tsx index cb915af7..f81c877d 100644 --- a/src/screens/Tabs/Me/Profile/Name.tsx +++ b/src/screens/Tabs/Me/Profile/Name.tsx @@ -1,6 +1,5 @@ import { HeaderLeft, HeaderRight } from '@components/Header' import Input from '@components/Input' -import { displayMessage } from '@components/Message' import { StackScreenProps } from '@react-navigation/stack' import { useProfileMutation } from '@utils/queryHooks/profile' import { StyleConstants } from '@utils/styles/constants' @@ -65,28 +64,19 @@ const TabMeProfileName: React.FC { - mutateAsync({ type: 'display_name', data: displayName }) - .then(() => { - navigation.navigate('Tab-Me-Profile-Root') - displayMessage({ - ref: messageRef, - message: t('me.profile.feedback.succeed', { - type: t('me.profile.root.name.title') - }), - mode, - type: 'success' - }) - }) - .catch(() => { - displayMessage({ - ref: messageRef, - message: t('me.profile.feedback.failed', { - type: t('me.profile.root.name.title') - }), - mode, - type: 'error' - }) - }) + mutateAsync({ + mode, + messageRef, + message: { + text: 'me.profile.root.name.title', + succeed: true, + failed: true + }, + type: 'display_name', + data: displayName + }).then(() => { + navigation.navigate('Tab-Me-Profile-Root') + }) }} /> ) diff --git a/src/screens/Tabs/Me/Profile/Note.tsx b/src/screens/Tabs/Me/Profile/Note.tsx index 98da197d..46df69b9 100644 --- a/src/screens/Tabs/Me/Profile/Note.tsx +++ b/src/screens/Tabs/Me/Profile/Note.tsx @@ -1,6 +1,5 @@ import { HeaderLeft, HeaderRight } from '@components/Header' import Input from '@components/Input' -import { displayMessage } from '@components/Message' import { StackScreenProps } from '@react-navigation/stack' import { useProfileMutation } from '@utils/queryHooks/profile' import { StyleConstants } from '@utils/styles/constants' @@ -65,28 +64,19 @@ const TabMeProfileNote: React.FC { - mutateAsync({ type: 'note', data: newNote }) - .then(() => { - navigation.navigate('Tab-Me-Profile-Root') - displayMessage({ - ref: messageRef, - message: t('me.profile.feedback.succeed', { - type: t('me.profile.root.note.title') - }), - mode, - type: 'success' - }) - }) - .catch(() => { - displayMessage({ - ref: messageRef, - message: t('me.profile.feedback.failed', { - type: t('me.profile.root.note.title') - }), - mode, - type: 'error' - }) - }) + mutateAsync({ + mode, + messageRef, + message: { + text: 'me.profile.root.note.title', + succeed: true, + failed: true + }, + type: 'note', + data: newNote + }).then(() => { + navigation.navigate('Tab-Me-Profile-Root') + }) }} /> ) diff --git a/src/screens/Tabs/Me/Profile/Root.tsx b/src/screens/Tabs/Me/Profile/Root.tsx index f91a3b06..99f3fafc 100644 --- a/src/screens/Tabs/Me/Profile/Root.tsx +++ b/src/screens/Tabs/Me/Profile/Root.tsx @@ -1,21 +1,29 @@ +import analytics from '@components/analytics' import { MenuContainer, MenuRow } from '@components/Menu' import { useActionSheet } from '@expo/react-native-action-sheet' import { StackScreenProps } from '@react-navigation/stack' import { useProfileMutation, useProfileQuery } from '@utils/queryHooks/profile' -import React, { useCallback } from 'react' +import { updateAccountPreferences } from '@utils/slices/instances/updateAccountPreferences' +import { useTheme } from '@utils/styles/ThemeManager' +import React, { RefObject, useCallback } from 'react' import { useTranslation } from 'react-i18next' +import FlashMessage from 'react-native-flash-message' import { ScrollView } from 'react-native-gesture-handler' +import { useDispatch } from 'react-redux' +import ProfileAvatarHeader from './Root/AvatarHeader' const TabMeProfileRoot: React.FC> = ({ navigation }) => { +> & { messageRef: RefObject }> = ({ messageRef, navigation }) => { + const { mode } = useTheme() const { t } = useTranslation('screenTabs') const { showActionSheetWithOptions } = useActionSheet() const { data, isLoading } = useProfileQuery({}) - const { mutate } = useProfileMutation() + const { mutateAsync } = useProfileMutation() + const dispatch = useDispatch() const onPressVisibility = useCallback(() => { showActionSheetWithOptions( @@ -32,41 +40,90 @@ const TabMeProfileRoot: React.FC { switch (buttonIndex) { case 0: - mutate({ type: 'source[privacy]', data: 'public' }) - break case 1: - mutate({ type: 'source[privacy]', data: 'unlisted' }) - break case 2: - mutate({ type: 'source[privacy]', data: 'private' }) + const indexVisibilityMapping = [ + 'public', + 'unlisted', + 'private' + ] as ['public', 'unlisted', 'private'] + if (data?.source.privacy !== indexVisibilityMapping[buttonIndex]) { + analytics('me_profile_visibility', { + current: t( + `me.profile.root.visibility.options.${data?.source.privacy}` + ), + new: indexVisibilityMapping[buttonIndex] + }) + mutateAsync({ + mode, + messageRef, + message: { + text: 'me.profile.root.visibility.title', + succeed: false, + failed: true + }, + type: 'source[privacy]', + data: indexVisibilityMapping[buttonIndex] + }).then(() => dispatch(updateAccountPreferences())) + } break } } ) - }, []) + }, [data?.source.privacy]) const onPressSensitive = useCallback(() => { - if (data?.source.sensitive === undefined) { - mutate({ type: 'source[sensitive]', data: true }) - } else { - mutate({ type: 'source[sensitive]', data: !data.source.sensitive }) - } + analytics('me_profile_sensitive', { + current: data?.source.sensitive, + new: data?.source.sensitive === undefined ? true : !data.source.sensitive + }) + mutateAsync({ + mode, + messageRef, + message: { + text: 'me.profile.root.sensitive.title', + succeed: false, + failed: true + }, + type: 'source[sensitive]', + data: data?.source.sensitive === undefined ? true : !data.source.sensitive + }).then(() => dispatch(updateAccountPreferences())) }, [data?.source.sensitive]) const onPressLock = useCallback(() => { - if (data?.locked === undefined) { - mutate({ type: 'locked', data: true }) - } else { - mutate({ type: 'locked', data: !data.locked }) - } + analytics('me_profile_lock', { + current: data?.locked, + new: data?.locked === undefined ? true : !data.locked + }) + mutateAsync({ + mode, + messageRef, + message: { + text: 'me.profile.root.lock.title', + succeed: false, + failed: true + }, + type: 'locked', + data: data?.locked === undefined ? true : !data.locked + }) }, [data?.locked]) const onPressBot = useCallback(() => { - if (data?.bot === undefined) { - mutate({ type: 'bot', data: true }) - } else { - mutate({ type: 'bot', data: !data?.bot }) - } + analytics('me_profile_bot', { + current: data?.bot, + new: data?.bot === undefined ? true : !data.bot + }) + mutateAsync({ + mode, + messageRef, + message: { + text: 'me.profile.root.bot.title', + succeed: false, + failed: true + }, + type: 'bot', + data: data?.bot === undefined ? true : !data.bot + }) }, [data?.bot]) return ( @@ -84,43 +141,18 @@ const TabMeProfileRoot: React.FC - - // } - // loading={isLoading} - // iconBack='ChevronRight' - /> - - // } - // loading={isLoading} - // iconBack='ChevronRight' - /> + + { - navigation.navigate('Tab-Me-Profile-Note', { - note: data?.source?.note || '' - }) + data && + navigation.navigate('Tab-Me-Profile-Note', { + note: data.source?.note + }) }} /> +} + +const ProfileAvatarHeader: React.FC = ({ type, messageRef }) => { + const { mode } = useTheme() + const { t } = useTranslation('screenTabs') + + const { showActionSheetWithOptions } = useActionSheet() + + const query = useProfileQuery({}) + const mutation = useProfileMutation() + + return ( + { + const image = await mediaSelector({ + showActionSheetWithOptions, + mediaTypes: ImagePicker.MediaTypeOptions.Images, + resize: { width: 400, height: 400 } + }) + mutation.mutate({ + mode, + messageRef, + message: { + text: `me.profile.root.${type}.title`, + succeed: true, + failed: true + }, + type, + data: image.uri + }) + }} + /> + ) +} + +export default ProfileAvatarHeader diff --git a/src/screens/Tabs/Me/Push.tsx b/src/screens/Tabs/Me/Push.tsx index 232bfe06..75e6e26f 100644 --- a/src/screens/Tabs/Me/Push.tsx +++ b/src/screens/Tabs/Me/Push.tsx @@ -1,42 +1,173 @@ -import { HeaderCenter, HeaderLeft } from '@components/Header' -import { StackScreenProps } from '@react-navigation/stack' -import React from 'react' +import analytics from '@components/analytics' +import Button from '@components/Button' +import { MenuContainer, MenuRow } from '@components/Menu' +import { updateInstancePush } from '@utils/slices/instances/updatePush' +import { updateInstancePushAlert } from '@utils/slices/instances/updatePushAlert' +import { updateInstancePushDecode } from '@utils/slices/instances/updatePushDecode' +import { + clearPushLoading, + getInstanceAccount, + getInstancePush, + getInstanceUri +} from '@utils/slices/instancesSlice' +import { StyleConstants } from '@utils/styles/constants' +import layoutAnimation from '@utils/styles/layoutAnimation' +import * as Notifications from 'expo-notifications' +import * as WebBrowser from 'expo-web-browser' +import React, { useState, useEffect, useMemo } from 'react' import { useTranslation } from 'react-i18next' -import { Platform } from 'react-native' -import { createNativeStackNavigator } from 'react-native-screens/native-stack' -import TabMePushRoot from './Push/Root' +import { AppState, Linking, ScrollView } from 'react-native' +import { useDispatch, useSelector } from 'react-redux' -const Stack = createNativeStackNavigator() - -const TabMePush: React.FC> = ({ navigation }) => { +const TabMePush: React.FC = () => { const { t } = useTranslation('screenTabs') + const instanceAccount = useSelector( + getInstanceAccount, + (prev, next) => prev?.acct === next?.acct + ) + const instanceUri = useSelector(getInstanceUri) + + const dispatch = useDispatch() + const instancePush = useSelector(getInstancePush) + + const [pushEnabled, setPushEnabled] = useState() + const [pushCanAskAgain, setPushCanAskAgain] = useState() + const checkPush = async () => { + const settings = await Notifications.getPermissionsAsync() + layoutAnimation() + setPushEnabled(settings.granted) + setPushCanAskAgain(settings.canAskAgain) + } + useEffect(() => { + checkPush() + AppState.addEventListener('change', checkPush) + return () => { + AppState.removeEventListener('change', checkPush) + } + }, []) + + useEffect(() => { + dispatch(clearPushLoading()) + }, []) + + const isLoading = instancePush?.global.loading || instancePush?.decode.loading + + const alerts = useMemo(() => { + return instancePush?.alerts + ? (['follow', 'favourite', 'reblog', 'mention', 'poll'] as [ + 'follow', + 'favourite', + 'reblog', + 'mention', + 'poll' + ]).map(alert => ( + { + analytics(`me_push_${alert}`, { + current: instancePush?.alerts[alert].value, + new: !instancePush?.alerts[alert].value + }) + dispatch( + updateInstancePushAlert({ + changed: alert, + alerts: { + ...instancePush?.alerts, + [alert]: { + ...instancePush?.alerts[alert], + value: !instancePush?.alerts[alert].value + } + } + }) + ) + }} + /> + )) + : null + }, [pushEnabled, instancePush?.global, instancePush?.alerts, isLoading]) return ( - - ( - - ) - }), - headerLeft: () => ( - navigation.goBack()} - /> - ) - }} - /> - + + {pushEnabled === false ? ( + +