Merge branch 'develop' into feat.new-audio-player

This commit is contained in:
Reinaldo Neto 2023-08-23 11:41:37 -03:00
commit fe18a1a3fa
201 changed files with 6037 additions and 4377 deletions

6
.buckconfig Normal file
View File

@ -0,0 +1,6 @@
[android]
target = Google Inc.:Google APIs:23
[maven_repositories]
central = https://repo1.maven.org/maven2

View File

@ -1,10 +1,6 @@
defaults: &defaults
working_directory: ~/repo
android-img: &android-img
docker:
- image: cimg/android:2023.04.1-node
orbs:
android: circleci/android@2.1.2
@ -58,13 +54,14 @@ save-gems-cache: &save-gems-cache
update-fastlane-ios: &update-fastlane-ios
name: Update Fastlane
command: |
echo "ruby-2.7.7" > ~/.ruby-version
bundle install
working_directory: ios
update-fastlane-android: &update-fastlane-android
name: Update Fastlane
command: |
bundle config set --local deployment 'true'
echo "ruby-2.7.7" > ~/.ruby-version
bundle install
working_directory: android
@ -114,10 +111,10 @@ commands:
name: Configure Gradle
command: |
echo -e "" > ./gradle.properties
# echo -e "android.enableAapt2=false" >> ./gradle.properties
echo -e "android.useAndroidX=true" >> ./gradle.properties
echo -e "android.enableJetifier=true" >> ./gradle.properties
echo -e "newArchEnabled=false" >> ./gradle.properties
echo -e "hermesEnabled=true" >> ./gradle.properties
echo -e "FLIPPER_VERSION=0.125.0" >> ./gradle.properties
echo -e "VERSIONCODE=$CIRCLE_BUILD_NUM" >> ./gradle.properties
@ -150,9 +147,7 @@ commands:
- run:
name: Build App
no_output_timeout: 40m
command: |
sudo apt install -y libicu-dev
if [[ $CIRCLE_JOB == "android-build-official" ]]; then
./gradlew bundleOfficialPlayRelease
fi
@ -172,16 +167,16 @@ commands:
--api-key=$BUGSNAG_KEY_OFFICIAL \
--app-version-code=$CIRCLE_BUILD_NUM \
--platform android \
--source-map=android/app/build/generated/sourcemaps/react/officialPlayRelease/index.android.bundle.map \
--bundle android/app/build/ASSETS/createBundleOfficialPlayReleaseJsAndAssets/index.android.bundle
--source-map=android/app/build/generated/sourcemaps/react/officialPlay/release/app.bundle.map \
--bundle android/app/build/generated/assets/react/officialPlay/release/app.bundle
fi
if [[ $CIRCLE_JOB == "android-build-experimental" || "android-automatic-build-experimental" ]]; then
npx bugsnag-source-maps upload-react-native \
--api-key=$BUGSNAG_KEY \
--app-version-code=$CIRCLE_BUILD_NUM \
--platform android \
--source-map=android/app/build/generated/sourcemaps/react/experimentalPlayRelease/index.android.bundle.map \
--bundle android/app/build/ASSETS/createBundleExperimentalPlayReleaseJsAndAssets/index.android.bundle
--source-map=android/app/build/generated/sourcemaps/react/experimentalPlay/release/app.bundle.map \
--bundle android/app/build/generated/assets/react/experimentalPlay/release/app.bundle
fi
- store_artifacts:
@ -389,45 +384,50 @@ jobs:
# Android builds
android-build-experimental:
<<: *defaults
<<: *android-img
docker:
- image: cimg/android:2022.03.1-node
environment:
<<: *android-env
<<: *bash-env
resource_class: xlarge
resource_class: large
steps:
- android-build
# Android automatic builds
android-automatic-build-experimental:
<<: *defaults
<<: *android-img
docker:
- image: circleci/android:api-29-node
environment:
<<: *android-env
<<: *bash-env
resource_class: xlarge
resource_class: large
steps:
- android-build
android-build-official:
<<: *defaults
<<: *android-img
docker:
- image: cimg/android:2022.03.1-node
environment:
<<: *android-env
<<: *bash-env
resource_class: xlarge
resource_class: large
steps:
- android-build
android-internal-app-sharing-experimental:
<<: *defaults
<<: *android-img
docker:
- image: cimg/android:2022.03.1-node
steps:
- upload-to-internal-app-sharing
android-google-play-beta-experimental:
<<: *defaults
<<: *android-img
docker:
- image: cimg/android:2022.03.1-node
steps:
- upload-to-google-play-beta:
@ -435,13 +435,15 @@ jobs:
android-google-play-production-experimental:
<<: *defaults
<<: *android-img
docker:
- image: cimg/android:2022.03.1-node
steps:
- upload-to-google-play-production
android-google-play-beta-official:
<<: *defaults
<<: *android-img
docker:
- image: cimg/android:2022.03.1-node
steps:
- upload-to-google-play-beta:
@ -452,7 +454,7 @@ jobs:
executor:
name: android/android-machine
resource-class: xlarge
tag: 2023.04.1
tag: 2022.12.1
environment:
<<: *android-env
steps:
@ -469,7 +471,6 @@ jobs:
echo -e "android.useAndroidX=true" >> ./gradle.properties
echo -e "android.enableJetifier=true" >> ./gradle.properties
echo -e "newArchEnabled=false" >> ./gradle.properties
echo -e "hermesEnabled=true" >> ./gradle.properties
echo -e "FLIPPER_VERSION=0.125.0" >> ./gradle.properties
echo -e "VERSIONCODE=$CIRCLE_BUILD_NUM" >> ./gradle.properties
echo -e "APPLICATION_ID=chat.rocket.reactnative" >> ./gradle.properties
@ -482,7 +483,6 @@ jobs:
working_directory: android
- run:
name: Build Android
no_output_timeout: 20m
command: |
export RUNNING_E2E_TESTS=true
yarn e2e:android-build
@ -501,7 +501,7 @@ jobs:
executor:
name: android/android-machine
resource-class: xlarge
tag: 2023.04.1
tag: 2022.12.1
parallelism: 4
steps:
- checkout
@ -522,10 +522,6 @@ jobs:
echo "hw.lcd.density = 440" >> ~/.android/avd/Pixel_API_31_AOSP.avd/config.ini
echo "hw.lcd.height = 2280" >> ~/.android/avd/Pixel_API_31_AOSP.avd/config.ini
echo "hw.lcd.width = 1080" >> ~/.android/avd/Pixel_API_31_AOSP.avd/config.ini
- android/start-emulator:
avd-name: Pixel_API_31_AOSP
verbose: true
post-emulator-launch-assemble-command: ''
- run:
name: Run Detox Tests
command: |
@ -582,7 +578,6 @@ jobs:
brew install applesimutils
- run:
name: Build
no_output_timeout: 20m
command: |
/usr/libexec/PlistBuddy -c "Set :bugsnag:apiKey $BUGSNAG_KEY" ./ios/RocketChatRN/Info.plist
/usr/libexec/PlistBuddy -c "Set :bugsnag:apiKey $BUGSNAG_KEY" ./ios/ShareRocketChatRN/Info.plist

2
.env
View File

@ -1,2 +0,0 @@
# DON'T COMMIT CHANGES ON THIS FILE
RUNNING_E2E_TESTS=

19
.gitignore vendored
View File

@ -24,7 +24,6 @@ project.xcworkspace
*.mobileprovision
ios/Pods/
/vendor/bundle/
ios/.xcode.env.local
# Android/IntelliJ
#
@ -33,10 +32,6 @@ build/
.gradle
local.properties
*.iml
.cxx/
*.keystore
!debug.keystore
*.jks
# node.js
#
@ -46,6 +41,12 @@ yarn-error.log
coverage/
# BUCK
buck-out/
\.buckd/
*.keystore
*.jks
# fastlane
#
# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
@ -62,10 +63,10 @@ coverage
artifacts
.vscode/
e2e/docker/rc_test_env/docker-compose.yml
e2e/docker/data/db
e2e/e2e_account.js
e2e/e2e_account.ts
junit.xml
*.p8
# Temporary files created by Metro to check the health of the file watcher
.metro-health-check*
*.p8

View File

@ -1 +0,0 @@
18

1
.ruby-version Normal file
View File

@ -0,0 +1 @@
2.7.7

View File

@ -1,6 +1,4 @@
source 'https://rubygems.org'
# You may use http://rbenv.org/ or https://rvm.io/ to install and use this version
ruby '>= 2.6.10'
gem 'cocoapods', '>= 1.11.3'
ruby '2.7.7'
gem 'cocoapods', '~> 1.11', '>= 1.11.2'

View File

@ -4,8 +4,10 @@ export class MMKVLoader {
}
setProcessingMode = jest.fn().mockImplementation(() => ({
withEncryption: jest.fn().mockImplementation(() => ({
initialize: jest.fn().mockImplementation(() => {})
setAccessibleIOS: jest.fn().mockImplementation(() => ({
withEncryption: jest.fn().mockImplementation(() => ({
initialize: jest.fn().mockImplementation(() => {})
}))
}))
}));
}
@ -14,4 +16,8 @@ export const ProcessingModes = {
MULTI_PROCESS: ''
};
export const IOSAccessibleStates = {
AFTER_FIRST_UNLOCK_THIS_DEVICE_ONLY: ''
};
export const create = jest.fn();

View File

@ -26,7 +26,7 @@ exports[`Storyshots Avatar Room Avatar External Provider Url 1`] = `"{\\"type\\"
exports[`Storyshots Avatar Static 1`] = `"{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"width\\":56,\\"height\\":56,\\"borderRadius\\":4},null],\\"testID\\":\\"avatar\\"},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"overflow\\":\\"hidden\\"},{\\"width\\":56,\\"height\\":56,\\"borderRadius\\":4}]},\\"children\\":[{\\"type\\":\\"FastImageView\\",\\"props\\":{\\"style\\":{\\"position\\":\\"absolute\\",\\"left\\":0,\\"right\\":0,\\"top\\":0,\\"bottom\\":0},\\"source\\":{\\"uri\\":\\"https://user-images.githubusercontent.com/29778115/89444446-14738480-d728-11ea-9412-75fd978d95fb.jpg\\",\\"headers\\":{\\"User-Agent\\":\\"RC Mobile; ios unknown; vunknown (unknown)\\"},\\"priority\\":\\"high\\"},\\"resizeMode\\":\\"cover\\"},\\"children\\":null}]}]}"`;
exports[`Storyshots Avatar Touchable 1`] = `"{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"width\\":56,\\"height\\":56,\\"borderRadius\\":4},null],\\"testID\\":\\"avatar\\"},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityState\\":{},\\"accessibilityValue\\":{},\\"focusable\\":true,\\"collapsable\\":false,\\"style\\":{\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"overflow\\":\\"hidden\\"},{\\"width\\":56,\\"height\\":56,\\"borderRadius\\":4}]},\\"children\\":[{\\"type\\":\\"FastImageView\\",\\"props\\":{\\"style\\":{\\"position\\":\\"absolute\\",\\"left\\":0,\\"right\\":0,\\"top\\":0,\\"bottom\\":0},\\"source\\":{\\"uri\\":\\"https://open.rocket.chat/avatar/Avatar?format=png&size=112\\",\\"headers\\":{\\"User-Agent\\":\\"RC Mobile; ios unknown; vunknown (unknown)\\"},\\"priority\\":\\"high\\"},\\"resizeMode\\":\\"cover\\"},\\"children\\":null}]}]}]}"`;
exports[`Storyshots Avatar Touchable 1`] = `"{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"width\\":56,\\"height\\":56,\\"borderRadius\\":4},null],\\"testID\\":\\"avatar\\"},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"focusable\\":true,\\"collapsable\\":false,\\"style\\":{\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"overflow\\":\\"hidden\\"},{\\"width\\":56,\\"height\\":56,\\"borderRadius\\":4}]},\\"children\\":[{\\"type\\":\\"FastImageView\\",\\"props\\":{\\"style\\":{\\"position\\":\\"absolute\\",\\"left\\":0,\\"right\\":0,\\"top\\":0,\\"bottom\\":0},\\"source\\":{\\"uri\\":\\"https://open.rocket.chat/avatar/Avatar?format=png&size=112\\",\\"headers\\":{\\"User-Agent\\":\\"RC Mobile; ios unknown; vunknown (unknown)\\"},\\"priority\\":\\"high\\"},\\"resizeMode\\":\\"cover\\"},\\"children\\":null}]}]}]}"`;
exports[`Storyshots Avatar With E Tag 1`] = `"{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"width\\":56,\\"height\\":56,\\"borderRadius\\":4},null],\\"testID\\":\\"avatar\\"},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"overflow\\":\\"hidden\\"},{\\"width\\":56,\\"height\\":56,\\"borderRadius\\":4}]},\\"children\\":[{\\"type\\":\\"FastImageView\\",\\"props\\":{\\"style\\":{\\"position\\":\\"absolute\\",\\"left\\":0,\\"right\\":0,\\"top\\":0,\\"bottom\\":0},\\"source\\":{\\"uri\\":\\"https://open.rocket.chat/avatar/djorkaeff.alexandre?format=png&size=112&etag=5ag8KffJcZj9m5rCv\\",\\"headers\\":{\\"User-Agent\\":\\"RC Mobile; ios unknown; vunknown (unknown)\\"},\\"priority\\":\\"high\\"},\\"resizeMode\\":\\"cover\\"},\\"children\\":null}]}]}"`;

View File

@ -1,13 +1,13 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Storyshots Button Custom Button 1`] = `"{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"Press me!\\",\\"accessibilityState\\":{\\"disabled\\":false},\\"accessibilityValue\\":{},\\"testID\\":\\"testButton\\",\\"focusable\\":true,\\"collapsable\\":false,\\"style\\":{\\"paddingHorizontal\\":14,\\"justifyContent\\":\\"center\\",\\"height\\":48,\\"borderRadius\\":4,\\"marginBottom\\":12,\\"backgroundColor\\":\\"purple\\",\\"padding\\":10,\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"textAlign\\":\\"center\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"Inter\\",\\"fontWeight\\":\\"500\\"},{\\"color\\":\\"yellow\\",\\"fontSize\\":18},[{\\"textAlign\\":\\"left\\"}]],\\"accessibilityLabel\\":\\"Press me!\\"},\\"children\\":[\\"Press me!\\"]}]}"`;
exports[`Storyshots Button Custom Button 1`] = `"{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"Press me!\\",\\"accessibilityState\\":{\\"disabled\\":false},\\"testID\\":\\"testButton\\",\\"focusable\\":true,\\"collapsable\\":false,\\"style\\":{\\"paddingHorizontal\\":14,\\"justifyContent\\":\\"center\\",\\"height\\":48,\\"borderRadius\\":4,\\"marginBottom\\":12,\\"backgroundColor\\":\\"purple\\",\\"padding\\":10,\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"textAlign\\":\\"center\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"Inter\\",\\"fontWeight\\":\\"500\\"},{\\"color\\":\\"yellow\\",\\"fontSize\\":18},[{\\"textAlign\\":\\"left\\"}]],\\"accessibilityLabel\\":\\"Press me!\\"},\\"children\\":[\\"Press me!\\"]}]}"`;
exports[`Storyshots Button Disabled Button 1`] = `"{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"Press me!\\",\\"accessibilityState\\":{\\"disabled\\":true},\\"accessibilityValue\\":{},\\"testID\\":\\"testButton\\",\\"focusable\\":true,\\"collapsable\\":false,\\"style\\":{\\"paddingHorizontal\\":14,\\"justifyContent\\":\\"center\\",\\"height\\":48,\\"borderRadius\\":4,\\"marginBottom\\":12,\\"backgroundColor\\":\\"#1d74f5\\",\\"opacity\\":0.3}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"textAlign\\":\\"center\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"Inter\\",\\"fontWeight\\":\\"500\\"},{\\"color\\":\\"#ffffff\\",\\"fontSize\\":16},null],\\"accessibilityLabel\\":\\"Press me!\\"},\\"children\\":[\\"Press me!\\"]}]}"`;
exports[`Storyshots Button Disabled Button 1`] = `"{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"Press me!\\",\\"accessibilityState\\":{\\"disabled\\":true},\\"testID\\":\\"testButton\\",\\"focusable\\":true,\\"collapsable\\":false,\\"style\\":{\\"paddingHorizontal\\":14,\\"justifyContent\\":\\"center\\",\\"height\\":48,\\"borderRadius\\":4,\\"marginBottom\\":12,\\"backgroundColor\\":\\"#1d74f5\\",\\"opacity\\":0.3}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"textAlign\\":\\"center\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"Inter\\",\\"fontWeight\\":\\"500\\"},{\\"color\\":\\"#ffffff\\",\\"fontSize\\":16},null],\\"accessibilityLabel\\":\\"Press me!\\"},\\"children\\":[\\"Press me!\\"]}]}"`;
exports[`Storyshots Button Disabled Loading Button 1`] = `"{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"Press me!\\",\\"accessibilityState\\":{\\"disabled\\":true},\\"accessibilityValue\\":{},\\"testID\\":\\"testButton\\",\\"focusable\\":true,\\"collapsable\\":false,\\"style\\":{\\"paddingHorizontal\\":14,\\"justifyContent\\":\\"center\\",\\"height\\":48,\\"borderRadius\\":4,\\"marginBottom\\":12,\\"backgroundColor\\":\\"#1d74f5\\",\\"opacity\\":0.3}},\\"children\\":[{\\"type\\":\\"ActivityIndicator\\",\\"props\\":{\\"style\\":[{\\"padding\\":16,\\"flex\\":1},null],\\"color\\":\\"#ffffff\\"},\\"children\\":null}]}"`;
exports[`Storyshots Button Disabled Loading Button 1`] = `"{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"Press me!\\",\\"accessibilityState\\":{\\"disabled\\":true},\\"testID\\":\\"testButton\\",\\"focusable\\":true,\\"collapsable\\":false,\\"style\\":{\\"paddingHorizontal\\":14,\\"justifyContent\\":\\"center\\",\\"height\\":48,\\"borderRadius\\":4,\\"marginBottom\\":12,\\"backgroundColor\\":\\"#1d74f5\\",\\"opacity\\":0.3}},\\"children\\":[{\\"type\\":\\"ActivityIndicator\\",\\"props\\":{\\"style\\":[{\\"padding\\":16,\\"flex\\":1},null],\\"color\\":\\"#ffffff\\"},\\"children\\":null}]}"`;
exports[`Storyshots Button Loading Button 1`] = `"{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"Press me!\\",\\"accessibilityState\\":{\\"disabled\\":true},\\"accessibilityValue\\":{},\\"testID\\":\\"testButton\\",\\"focusable\\":true,\\"collapsable\\":false,\\"style\\":{\\"paddingHorizontal\\":14,\\"justifyContent\\":\\"center\\",\\"height\\":48,\\"borderRadius\\":4,\\"marginBottom\\":12,\\"backgroundColor\\":\\"#1d74f5\\",\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"ActivityIndicator\\",\\"props\\":{\\"style\\":[{\\"padding\\":16,\\"flex\\":1},null],\\"color\\":\\"#ffffff\\"},\\"children\\":null}]}"`;
exports[`Storyshots Button Loading Button 1`] = `"{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"Press me!\\",\\"accessibilityState\\":{\\"disabled\\":true},\\"testID\\":\\"testButton\\",\\"focusable\\":true,\\"collapsable\\":false,\\"style\\":{\\"paddingHorizontal\\":14,\\"justifyContent\\":\\"center\\",\\"height\\":48,\\"borderRadius\\":4,\\"marginBottom\\":12,\\"backgroundColor\\":\\"#1d74f5\\",\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"ActivityIndicator\\",\\"props\\":{\\"style\\":[{\\"padding\\":16,\\"flex\\":1},null],\\"color\\":\\"#ffffff\\"},\\"children\\":null}]}"`;
exports[`Storyshots Button Primary Button 1`] = `"{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"Press me!\\",\\"accessibilityState\\":{\\"disabled\\":false},\\"accessibilityValue\\":{},\\"testID\\":\\"testButton\\",\\"focusable\\":true,\\"collapsable\\":false,\\"style\\":{\\"paddingHorizontal\\":14,\\"justifyContent\\":\\"center\\",\\"height\\":48,\\"borderRadius\\":4,\\"marginBottom\\":12,\\"backgroundColor\\":\\"#1d74f5\\",\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"textAlign\\":\\"center\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"Inter\\",\\"fontWeight\\":\\"500\\"},{\\"color\\":\\"#ffffff\\",\\"fontSize\\":16},null],\\"accessibilityLabel\\":\\"Press me!\\"},\\"children\\":[\\"Press me!\\"]}]}"`;
exports[`Storyshots Button Primary Button 1`] = `"{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"Press me!\\",\\"accessibilityState\\":{\\"disabled\\":false},\\"testID\\":\\"testButton\\",\\"focusable\\":true,\\"collapsable\\":false,\\"style\\":{\\"paddingHorizontal\\":14,\\"justifyContent\\":\\"center\\",\\"height\\":48,\\"borderRadius\\":4,\\"marginBottom\\":12,\\"backgroundColor\\":\\"#1d74f5\\",\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"textAlign\\":\\"center\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"Inter\\",\\"fontWeight\\":\\"500\\"},{\\"color\\":\\"#ffffff\\",\\"fontSize\\":16},null],\\"accessibilityLabel\\":\\"Press me!\\"},\\"children\\":[\\"Press me!\\"]}]}"`;
exports[`Storyshots Button Secondary Button 1`] = `"{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"Press me!\\",\\"accessibilityState\\":{\\"disabled\\":false},\\"accessibilityValue\\":{},\\"testID\\":\\"testButton\\",\\"focusable\\":true,\\"collapsable\\":false,\\"style\\":{\\"paddingHorizontal\\":14,\\"justifyContent\\":\\"center\\",\\"height\\":48,\\"borderRadius\\":4,\\"marginBottom\\":12,\\"backgroundColor\\":\\"#ffffff\\",\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"textAlign\\":\\"center\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"Inter\\",\\"fontWeight\\":\\"500\\"},{\\"color\\":\\"#2f343d\\",\\"fontSize\\":16},null],\\"accessibilityLabel\\":\\"Press me!\\"},\\"children\\":[\\"Press me!\\"]}]}"`;
exports[`Storyshots Button Secondary Button 1`] = `"{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"Press me!\\",\\"accessibilityState\\":{\\"disabled\\":false},\\"testID\\":\\"testButton\\",\\"focusable\\":true,\\"collapsable\\":false,\\"style\\":{\\"paddingHorizontal\\":14,\\"justifyContent\\":\\"center\\",\\"height\\":48,\\"borderRadius\\":4,\\"marginBottom\\":12,\\"backgroundColor\\":\\"#ffffff\\",\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"textAlign\\":\\"center\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"Inter\\",\\"fontWeight\\":\\"500\\"},{\\"color\\":\\"#2f343d\\",\\"fontSize\\":16},null],\\"accessibilityLabel\\":\\"Press me!\\"},\\"children\\":[\\"Press me!\\"]}]}"`;

View File

@ -1,11 +1,11 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Storyshots Chip Chip Text 1`] = `"{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1,\\"alignItems\\":\\"flex-start\\",\\"padding\\":16}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityState\\":{\\"disabled\\":false},\\"focusable\\":true,\\"accessibilityValue\\":{},\\"style\\":[{\\"paddingHorizontal\\":8,\\"marginRight\\":8,\\"borderRadius\\":4,\\"justifyContent\\":\\"center\\",\\"maxWidth\\":192},{\\"backgroundColor\\":\\"#efeff4\\"},null],\\"collapsable\\":false},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flexDirection\\":\\"row\\",\\"alignItems\\":\\"center\\"}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"width\\":28,\\"height\\":28,\\"borderRadius\\":4},{\\"marginRight\\":8,\\"marginVertical\\":8}],\\"testID\\":\\"avatar\\"},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"overflow\\":\\"hidden\\"},{\\"width\\":28,\\"height\\":28,\\"borderRadius\\":4}]},\\"children\\":[{\\"type\\":\\"FastImageView\\",\\"props\\":{\\"style\\":{\\"position\\":\\"absolute\\",\\"left\\":0,\\"right\\":0,\\"top\\":0,\\"bottom\\":0},\\"source\\":{\\"uri\\":\\"https://open.rocket.chat/avatar/rocket.cat?format=png&size=56\\",\\"headers\\":{\\"User-Agent\\":\\"RC Mobile; ios unknown; vunknown (unknown)\\"},\\"priority\\":\\"high\\"},\\"resizeMode\\":\\"cover\\"},\\"children\\":null}]}]},{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"marginRight\\":8,\\"maxWidth\\":120}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"fontSize\\":16,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"Inter\\",\\"fontWeight\\":\\"500\\"},{\\"color\\":\\"#2f343d\\"}],\\"numberOfLines\\":1},\\"children\\":[\\"Rocket.Cat\\"]}]},{\\"type\\":\\"Text\\",\\"props\\":{\\"selectable\\":false,\\"allowFontScaling\\":false,\\"style\\":[{\\"fontSize\\":16,\\"color\\":\\"#6C727A\\"},null,{\\"fontFamily\\":\\"custom\\",\\"fontWeight\\":\\"normal\\",\\"fontStyle\\":\\"normal\\"},{}]},\\"children\\":[\\"\\"]}]}]}]}"`;
exports[`Storyshots Chip Chip Text 1`] = `"{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1,\\"alignItems\\":\\"flex-start\\",\\"padding\\":16}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityState\\":{\\"disabled\\":false},\\"focusable\\":true,\\"style\\":[{\\"paddingHorizontal\\":8,\\"marginRight\\":8,\\"borderRadius\\":4,\\"justifyContent\\":\\"center\\",\\"maxWidth\\":192},{\\"backgroundColor\\":\\"#efeff4\\"},null],\\"collapsable\\":false},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flexDirection\\":\\"row\\",\\"alignItems\\":\\"center\\"}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"width\\":28,\\"height\\":28,\\"borderRadius\\":4},{\\"marginRight\\":8,\\"marginVertical\\":8}],\\"testID\\":\\"avatar\\"},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"overflow\\":\\"hidden\\"},{\\"width\\":28,\\"height\\":28,\\"borderRadius\\":4}]},\\"children\\":[{\\"type\\":\\"FastImageView\\",\\"props\\":{\\"style\\":{\\"position\\":\\"absolute\\",\\"left\\":0,\\"right\\":0,\\"top\\":0,\\"bottom\\":0},\\"source\\":{\\"uri\\":\\"https://open.rocket.chat/avatar/rocket.cat?format=png&size=56\\",\\"headers\\":{\\"User-Agent\\":\\"RC Mobile; ios unknown; vunknown (unknown)\\"},\\"priority\\":\\"high\\"},\\"resizeMode\\":\\"cover\\"},\\"children\\":null}]}]},{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"marginRight\\":8,\\"maxWidth\\":120}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"fontSize\\":16,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"Inter\\",\\"fontWeight\\":\\"500\\"},{\\"color\\":\\"#2f343d\\"}],\\"numberOfLines\\":1},\\"children\\":[\\"Rocket.Cat\\"]}]},{\\"type\\":\\"Text\\",\\"props\\":{\\"selectable\\":false,\\"allowFontScaling\\":false,\\"style\\":[{\\"fontSize\\":16,\\"color\\":\\"#6C727A\\"},null,{\\"fontFamily\\":\\"custom\\",\\"fontWeight\\":\\"normal\\",\\"fontStyle\\":\\"normal\\"},{}]},\\"children\\":[\\"\\"]}]}]}]}"`;
exports[`Storyshots Chip Chip With Short Text 1`] = `"{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1,\\"alignItems\\":\\"flex-start\\",\\"padding\\":16}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityState\\":{\\"disabled\\":false},\\"focusable\\":true,\\"accessibilityValue\\":{},\\"style\\":[{\\"paddingHorizontal\\":8,\\"marginRight\\":8,\\"borderRadius\\":4,\\"justifyContent\\":\\"center\\",\\"maxWidth\\":192},{\\"backgroundColor\\":\\"#efeff4\\"},null],\\"collapsable\\":false},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flexDirection\\":\\"row\\",\\"alignItems\\":\\"center\\"}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"width\\":28,\\"height\\":28,\\"borderRadius\\":4},{\\"marginRight\\":8,\\"marginVertical\\":8}],\\"testID\\":\\"avatar\\"},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"overflow\\":\\"hidden\\"},{\\"width\\":28,\\"height\\":28,\\"borderRadius\\":4}]},\\"children\\":[{\\"type\\":\\"FastImageView\\",\\"props\\":{\\"style\\":{\\"position\\":\\"absolute\\",\\"left\\":0,\\"right\\":0,\\"top\\":0,\\"bottom\\":0},\\"source\\":{\\"uri\\":\\"https://open.rocket.chat/avatar/rocket.cat?format=png&size=56\\",\\"headers\\":{\\"User-Agent\\":\\"RC Mobile; ios unknown; vunknown (unknown)\\"},\\"priority\\":\\"high\\"},\\"resizeMode\\":\\"cover\\"},\\"children\\":null}]}]},{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"marginRight\\":8,\\"maxWidth\\":120}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"fontSize\\":16,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"Inter\\",\\"fontWeight\\":\\"500\\"},{\\"color\\":\\"#2f343d\\"}],\\"numberOfLines\\":1},\\"children\\":[\\"Short\\"]}]},{\\"type\\":\\"Text\\",\\"props\\":{\\"selectable\\":false,\\"allowFontScaling\\":false,\\"style\\":[{\\"fontSize\\":16,\\"color\\":\\"#6C727A\\"},null,{\\"fontFamily\\":\\"custom\\",\\"fontWeight\\":\\"normal\\",\\"fontStyle\\":\\"normal\\"},{}]},\\"children\\":[\\"\\"]}]}]}]}"`;
exports[`Storyshots Chip Chip With Short Text 1`] = `"{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1,\\"alignItems\\":\\"flex-start\\",\\"padding\\":16}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityState\\":{\\"disabled\\":false},\\"focusable\\":true,\\"style\\":[{\\"paddingHorizontal\\":8,\\"marginRight\\":8,\\"borderRadius\\":4,\\"justifyContent\\":\\"center\\",\\"maxWidth\\":192},{\\"backgroundColor\\":\\"#efeff4\\"},null],\\"collapsable\\":false},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flexDirection\\":\\"row\\",\\"alignItems\\":\\"center\\"}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"width\\":28,\\"height\\":28,\\"borderRadius\\":4},{\\"marginRight\\":8,\\"marginVertical\\":8}],\\"testID\\":\\"avatar\\"},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"overflow\\":\\"hidden\\"},{\\"width\\":28,\\"height\\":28,\\"borderRadius\\":4}]},\\"children\\":[{\\"type\\":\\"FastImageView\\",\\"props\\":{\\"style\\":{\\"position\\":\\"absolute\\",\\"left\\":0,\\"right\\":0,\\"top\\":0,\\"bottom\\":0},\\"source\\":{\\"uri\\":\\"https://open.rocket.chat/avatar/rocket.cat?format=png&size=56\\",\\"headers\\":{\\"User-Agent\\":\\"RC Mobile; ios unknown; vunknown (unknown)\\"},\\"priority\\":\\"high\\"},\\"resizeMode\\":\\"cover\\"},\\"children\\":null}]}]},{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"marginRight\\":8,\\"maxWidth\\":120}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"fontSize\\":16,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"Inter\\",\\"fontWeight\\":\\"500\\"},{\\"color\\":\\"#2f343d\\"}],\\"numberOfLines\\":1},\\"children\\":[\\"Short\\"]}]},{\\"type\\":\\"Text\\",\\"props\\":{\\"selectable\\":false,\\"allowFontScaling\\":false,\\"style\\":[{\\"fontSize\\":16,\\"color\\":\\"#6C727A\\"},null,{\\"fontFamily\\":\\"custom\\",\\"fontWeight\\":\\"normal\\",\\"fontStyle\\":\\"normal\\"},{}]},\\"children\\":[\\"\\"]}]}]}]}"`;
exports[`Storyshots Chip Chip Without Avatar 1`] = `"{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1,\\"alignItems\\":\\"flex-start\\",\\"padding\\":16}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityState\\":{\\"disabled\\":false},\\"focusable\\":true,\\"accessibilityValue\\":{},\\"style\\":[{\\"paddingHorizontal\\":8,\\"marginRight\\":8,\\"borderRadius\\":4,\\"justifyContent\\":\\"center\\",\\"maxWidth\\":192},{\\"backgroundColor\\":\\"#efeff4\\"},null],\\"collapsable\\":false},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flexDirection\\":\\"row\\",\\"alignItems\\":\\"center\\"}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"marginRight\\":8,\\"maxWidth\\":120}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"fontSize\\":16,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"Inter\\",\\"fontWeight\\":\\"500\\"},{\\"color\\":\\"#2f343d\\"}],\\"numberOfLines\\":1},\\"children\\":[\\"Without Avatar\\"]}]},{\\"type\\":\\"Text\\",\\"props\\":{\\"selectable\\":false,\\"allowFontScaling\\":false,\\"style\\":[{\\"fontSize\\":16,\\"color\\":\\"#6C727A\\"},null,{\\"fontFamily\\":\\"custom\\",\\"fontWeight\\":\\"normal\\",\\"fontStyle\\":\\"normal\\"},{}]},\\"children\\":[\\"\\"]}]}]}]}"`;
exports[`Storyshots Chip Chip Without Avatar 1`] = `"{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1,\\"alignItems\\":\\"flex-start\\",\\"padding\\":16}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityState\\":{\\"disabled\\":false},\\"focusable\\":true,\\"style\\":[{\\"paddingHorizontal\\":8,\\"marginRight\\":8,\\"borderRadius\\":4,\\"justifyContent\\":\\"center\\",\\"maxWidth\\":192},{\\"backgroundColor\\":\\"#efeff4\\"},null],\\"collapsable\\":false},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flexDirection\\":\\"row\\",\\"alignItems\\":\\"center\\"}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"marginRight\\":8,\\"maxWidth\\":120}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"fontSize\\":16,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"Inter\\",\\"fontWeight\\":\\"500\\"},{\\"color\\":\\"#2f343d\\"}],\\"numberOfLines\\":1},\\"children\\":[\\"Without Avatar\\"]}]},{\\"type\\":\\"Text\\",\\"props\\":{\\"selectable\\":false,\\"allowFontScaling\\":false,\\"style\\":[{\\"fontSize\\":16,\\"color\\":\\"#6C727A\\"},null,{\\"fontFamily\\":\\"custom\\",\\"fontWeight\\":\\"normal\\",\\"fontStyle\\":\\"normal\\"},{}]},\\"children\\":[\\"\\"]}]}]}]}"`;
exports[`Storyshots Chip Chip Without Avatar And Icon 1`] = `"{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1,\\"alignItems\\":\\"flex-start\\",\\"padding\\":16}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityState\\":{\\"disabled\\":true},\\"focusable\\":true,\\"accessibilityValue\\":{},\\"style\\":[{\\"paddingHorizontal\\":8,\\"marginRight\\":8,\\"borderRadius\\":4,\\"justifyContent\\":\\"center\\",\\"maxWidth\\":192},{\\"backgroundColor\\":\\"#efeff4\\"},null],\\"collapsable\\":false},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flexDirection\\":\\"row\\",\\"alignItems\\":\\"center\\"}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"marginRight\\":8,\\"maxWidth\\":120}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"fontSize\\":16,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"Inter\\",\\"fontWeight\\":\\"500\\"},{\\"color\\":\\"#2f343d\\"}],\\"numberOfLines\\":1},\\"children\\":[\\"Without Avatar and Icon\\"]}]}]}]}]}"`;
exports[`Storyshots Chip Chip Without Avatar And Icon 1`] = `"{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1,\\"alignItems\\":\\"flex-start\\",\\"padding\\":16}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityState\\":{\\"disabled\\":true},\\"focusable\\":true,\\"style\\":[{\\"paddingHorizontal\\":8,\\"marginRight\\":8,\\"borderRadius\\":4,\\"justifyContent\\":\\"center\\",\\"maxWidth\\":192},{\\"backgroundColor\\":\\"#efeff4\\"},null],\\"collapsable\\":false},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flexDirection\\":\\"row\\",\\"alignItems\\":\\"center\\"}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"marginRight\\":8,\\"maxWidth\\":120}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"fontSize\\":16,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"Inter\\",\\"fontWeight\\":\\"500\\"},{\\"color\\":\\"#2f343d\\"}],\\"numberOfLines\\":1},\\"children\\":[\\"Without Avatar and Icon\\"]}]}]}]}]}"`;
exports[`Storyshots Chip Chip Without Icon 1`] = `"{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1,\\"alignItems\\":\\"flex-start\\",\\"padding\\":16}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityState\\":{\\"disabled\\":true},\\"focusable\\":true,\\"accessibilityValue\\":{},\\"style\\":[{\\"paddingHorizontal\\":8,\\"marginRight\\":8,\\"borderRadius\\":4,\\"justifyContent\\":\\"center\\",\\"maxWidth\\":192},{\\"backgroundColor\\":\\"#efeff4\\"},null],\\"collapsable\\":false},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flexDirection\\":\\"row\\",\\"alignItems\\":\\"center\\"}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"width\\":28,\\"height\\":28,\\"borderRadius\\":4},{\\"marginRight\\":8,\\"marginVertical\\":8}],\\"testID\\":\\"avatar\\"},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"overflow\\":\\"hidden\\"},{\\"width\\":28,\\"height\\":28,\\"borderRadius\\":4}]},\\"children\\":[{\\"type\\":\\"FastImageView\\",\\"props\\":{\\"style\\":{\\"position\\":\\"absolute\\",\\"left\\":0,\\"right\\":0,\\"top\\":0,\\"bottom\\":0},\\"source\\":{\\"uri\\":\\"https://open.rocket.chat/avatar/rocket.cat?format=png&size=56\\",\\"headers\\":{\\"User-Agent\\":\\"RC Mobile; ios unknown; vunknown (unknown)\\"},\\"priority\\":\\"high\\"},\\"resizeMode\\":\\"cover\\"},\\"children\\":null}]}]},{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"marginRight\\":8,\\"maxWidth\\":120}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"fontSize\\":16,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"Inter\\",\\"fontWeight\\":\\"500\\"},{\\"color\\":\\"#2f343d\\"}],\\"numberOfLines\\":1},\\"children\\":[\\"Without Icon\\"]}]}]}]}]}"`;
exports[`Storyshots Chip Chip Without Icon 1`] = `"{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1,\\"alignItems\\":\\"flex-start\\",\\"padding\\":16}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityState\\":{\\"disabled\\":true},\\"focusable\\":true,\\"style\\":[{\\"paddingHorizontal\\":8,\\"marginRight\\":8,\\"borderRadius\\":4,\\"justifyContent\\":\\"center\\",\\"maxWidth\\":192},{\\"backgroundColor\\":\\"#efeff4\\"},null],\\"collapsable\\":false},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flexDirection\\":\\"row\\",\\"alignItems\\":\\"center\\"}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"width\\":28,\\"height\\":28,\\"borderRadius\\":4},{\\"marginRight\\":8,\\"marginVertical\\":8}],\\"testID\\":\\"avatar\\"},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"overflow\\":\\"hidden\\"},{\\"width\\":28,\\"height\\":28,\\"borderRadius\\":4}]},\\"children\\":[{\\"type\\":\\"FastImageView\\",\\"props\\":{\\"style\\":{\\"position\\":\\"absolute\\",\\"left\\":0,\\"right\\":0,\\"top\\":0,\\"bottom\\":0},\\"source\\":{\\"uri\\":\\"https://open.rocket.chat/avatar/rocket.cat?format=png&size=56\\",\\"headers\\":{\\"User-Agent\\":\\"RC Mobile; ios unknown; vunknown (unknown)\\"},\\"priority\\":\\"high\\"},\\"resizeMode\\":\\"cover\\"},\\"children\\":null}]}]},{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"marginRight\\":8,\\"maxWidth\\":120}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"fontSize\\":16,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"Inter\\",\\"fontWeight\\":\\"500\\"},{\\"color\\":\\"#2f343d\\"}],\\"numberOfLines\\":1},\\"children\\":[\\"Without Icon\\"]}]}]}]}]}"`;

View File

@ -1,5 +1,5 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Storyshots Login Services Separators 1`] = `"[{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"More options\\",\\"accessibilityState\\":{\\"disabled\\":false},\\"accessibilityValue\\":{},\\"focusable\\":true,\\"collapsable\\":false,\\"style\\":{\\"paddingHorizontal\\":14,\\"justifyContent\\":\\"center\\",\\"height\\":48,\\"borderRadius\\":4,\\"marginBottom\\":0,\\"backgroundColor\\":\\"#ffffff\\",\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"textAlign\\":\\"center\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"Inter\\",\\"fontWeight\\":\\"500\\"},{\\"color\\":\\"#1d74f5\\",\\"fontSize\\":16},null],\\"accessibilityLabel\\":\\"More options\\"},\\"children\\":[\\"More options\\"]}]},{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flexDirection\\":\\"row\\",\\"alignItems\\":\\"center\\",\\"marginVertical\\":24}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"height\\":1,\\"flex\\":1},{\\"backgroundColor\\":\\"#e1e5e8\\"}]},\\"children\\":null},{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"fontSize\\":14,\\"marginLeft\\":14,\\"marginRight\\":14,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"Inter\\",\\"fontWeight\\":\\"500\\"},{\\"color\\":\\"#9ca2a8\\"}]},\\"children\\":[\\"OR\\"]},{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"height\\":1,\\"flex\\":1},{\\"backgroundColor\\":\\"#e1e5e8\\"}]},\\"children\\":null}]},{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"Less options\\",\\"accessibilityState\\":{\\"disabled\\":false},\\"accessibilityValue\\":{},\\"focusable\\":true,\\"collapsable\\":false,\\"style\\":{\\"paddingHorizontal\\":14,\\"justifyContent\\":\\"center\\",\\"height\\":48,\\"borderRadius\\":4,\\"marginBottom\\":0,\\"backgroundColor\\":\\"#ffffff\\",\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"textAlign\\":\\"center\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"Inter\\",\\"fontWeight\\":\\"500\\"},{\\"color\\":\\"#1d74f5\\",\\"fontSize\\":16},null],\\"accessibilityLabel\\":\\"Less options\\"},\\"children\\":[\\"Less options\\"]}]},{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flexDirection\\":\\"row\\",\\"alignItems\\":\\"center\\",\\"marginVertical\\":24}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"height\\":1,\\"flex\\":1},{\\"backgroundColor\\":\\"#e1e5e8\\"}]},\\"children\\":null},{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"fontSize\\":14,\\"marginLeft\\":14,\\"marginRight\\":14,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"Inter\\",\\"fontWeight\\":\\"500\\"},{\\"color\\":\\"#9ca2a8\\"}]},\\"children\\":[\\"OR\\"]},{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"height\\":1,\\"flex\\":1},{\\"backgroundColor\\":\\"#e1e5e8\\"}]},\\"children\\":null}]}]"`;
exports[`Storyshots Login Services Separators 1`] = `"[{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"More options\\",\\"accessibilityState\\":{\\"disabled\\":false},\\"focusable\\":true,\\"collapsable\\":false,\\"style\\":{\\"paddingHorizontal\\":14,\\"justifyContent\\":\\"center\\",\\"height\\":48,\\"borderRadius\\":4,\\"marginBottom\\":0,\\"backgroundColor\\":\\"#ffffff\\",\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"textAlign\\":\\"center\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"Inter\\",\\"fontWeight\\":\\"500\\"},{\\"color\\":\\"#1d74f5\\",\\"fontSize\\":16},null],\\"accessibilityLabel\\":\\"More options\\"},\\"children\\":[\\"More options\\"]}]},{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flexDirection\\":\\"row\\",\\"alignItems\\":\\"center\\",\\"marginVertical\\":24}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"height\\":1,\\"flex\\":1},{\\"backgroundColor\\":\\"#e1e5e8\\"}]},\\"children\\":null},{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"fontSize\\":14,\\"marginLeft\\":14,\\"marginRight\\":14,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"Inter\\",\\"fontWeight\\":\\"500\\"},{\\"color\\":\\"#9ca2a8\\"}]},\\"children\\":[\\"OR\\"]},{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"height\\":1,\\"flex\\":1},{\\"backgroundColor\\":\\"#e1e5e8\\"}]},\\"children\\":null}]},{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"Less options\\",\\"accessibilityState\\":{\\"disabled\\":false},\\"focusable\\":true,\\"collapsable\\":false,\\"style\\":{\\"paddingHorizontal\\":14,\\"justifyContent\\":\\"center\\",\\"height\\":48,\\"borderRadius\\":4,\\"marginBottom\\":0,\\"backgroundColor\\":\\"#ffffff\\",\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"textAlign\\":\\"center\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"Inter\\",\\"fontWeight\\":\\"500\\"},{\\"color\\":\\"#1d74f5\\",\\"fontSize\\":16},null],\\"accessibilityLabel\\":\\"Less options\\"},\\"children\\":[\\"Less options\\"]}]},{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flexDirection\\":\\"row\\",\\"alignItems\\":\\"center\\",\\"marginVertical\\":24}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"height\\":1,\\"flex\\":1},{\\"backgroundColor\\":\\"#e1e5e8\\"}]},\\"children\\":null},{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"fontSize\\":14,\\"marginLeft\\":14,\\"marginRight\\":14,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"Inter\\",\\"fontWeight\\":\\"500\\"},{\\"color\\":\\"#9ca2a8\\"}]},\\"children\\":[\\"OR\\"]},{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"height\\":1,\\"flex\\":1},{\\"backgroundColor\\":\\"#e1e5e8\\"}]},\\"children\\":null}]}]"`;
exports[`Storyshots Login Services Service List 1`] = `"[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"borderRadius\\":4,\\"width\\":\\"100%\\",\\"height\\":48,\\"flexDirection\\":\\"row\\",\\"alignItems\\":\\"center\\",\\"justifyContent\\":\\"center\\",\\"paddingHorizontal\\":15}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"selectable\\":false,\\"allowFontScaling\\":false,\\"style\\":[{\\"fontSize\\":24,\\"color\\":\\"#0d0e12\\"},{\\"position\\":\\"absolute\\",\\"left\\":15,\\"top\\":12,\\"width\\":24,\\"height\\":24},{\\"fontFamily\\":\\"custom\\",\\"fontWeight\\":\\"normal\\",\\"fontStyle\\":\\"normal\\"},{}]},\\"children\\":[\\"\\"]},{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"Inter\\",\\"fontWeight\\":\\"400\\",\\"fontSize\\":16},{\\"color\\":\\"#0d0e12\\"}]},\\"children\\":[\\"Continue with\\",\\" \\",{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":{\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"Inter\\",\\"fontWeight\\":\\"600\\"}},\\"children\\":[\\"github\\"]}]}]},{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"borderRadius\\":4,\\"width\\":\\"100%\\",\\"height\\":48,\\"flexDirection\\":\\"row\\",\\"alignItems\\":\\"center\\",\\"justifyContent\\":\\"center\\",\\"paddingHorizontal\\":15}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"selectable\\":false,\\"allowFontScaling\\":false,\\"style\\":[{\\"fontSize\\":24,\\"color\\":\\"#0d0e12\\"},{\\"position\\":\\"absolute\\",\\"left\\":15,\\"top\\":12,\\"width\\":24,\\"height\\":24},{\\"fontFamily\\":\\"custom\\",\\"fontWeight\\":\\"normal\\",\\"fontStyle\\":\\"normal\\"},{}]},\\"children\\":[\\"\\"]},{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"Inter\\",\\"fontWeight\\":\\"400\\",\\"fontSize\\":16},{\\"color\\":\\"#0d0e12\\"}]},\\"children\\":[\\"Continue with\\",\\" \\",{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":{\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"Inter\\",\\"fontWeight\\":\\"600\\"}},\\"children\\":[\\"gitlab\\"]}]}]},{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"borderRadius\\":4,\\"width\\":\\"100%\\",\\"height\\":48,\\"flexDirection\\":\\"row\\",\\"alignItems\\":\\"center\\",\\"justifyContent\\":\\"center\\",\\"paddingHorizontal\\":15}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"selectable\\":false,\\"allowFontScaling\\":false,\\"style\\":[{\\"fontSize\\":24,\\"color\\":\\"#0d0e12\\"},{\\"position\\":\\"absolute\\",\\"left\\":15,\\"top\\":12,\\"width\\":24,\\"height\\":24},{\\"fontFamily\\":\\"custom\\",\\"fontWeight\\":\\"normal\\",\\"fontStyle\\":\\"normal\\"},{}]},\\"children\\":[\\"\\"]},{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"Inter\\",\\"fontWeight\\":\\"400\\",\\"fontSize\\":16},{\\"color\\":\\"#0d0e12\\"}]},\\"children\\":[\\"Continue with\\",\\" \\",{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":{\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"Inter\\",\\"fontWeight\\":\\"600\\"}},\\"children\\":[\\"google\\"]}]}]},{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"borderRadius\\":4,\\"width\\":\\"100%\\",\\"height\\":48,\\"flexDirection\\":\\"row\\",\\"alignItems\\":\\"center\\",\\"justifyContent\\":\\"center\\",\\"paddingHorizontal\\":15}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"selectable\\":false,\\"allowFontScaling\\":false,\\"style\\":[{\\"fontSize\\":24,\\"color\\":\\"#0d0e12\\"},{\\"position\\":\\"absolute\\",\\"left\\":15,\\"top\\":12,\\"width\\":24,\\"height\\":24},{\\"fontFamily\\":\\"custom\\",\\"fontWeight\\":\\"normal\\",\\"fontStyle\\":\\"normal\\"},{}]},\\"children\\":[\\"\\"]},{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"Inter\\",\\"fontWeight\\":\\"400\\",\\"fontSize\\":16},{\\"color\\":\\"#0d0e12\\"}]},\\"children\\":[\\"Continue with\\",\\" \\",{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":{\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"Inter\\",\\"fontWeight\\":\\"600\\"}},\\"children\\":[\\"apple\\"]}]}]}]"`;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,3 +1,3 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Storyshots CollapsibleQuote Item 1`] = `"{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"padding\\":10}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityState\\":{},\\"accessibilityValue\\":{},\\"testID\\":\\"collapsibleQuoteTouchable-Engineering (9 today)\\",\\"hitSlop\\":{\\"top\\":4,\\"right\\":4,\\"bottom\\":4,\\"left\\":4},\\"focusable\\":true,\\"collapsable\\":false,\\"style\\":{\\"flexDirection\\":\\"row\\",\\"alignItems\\":\\"center\\",\\"marginTop\\":6,\\"borderWidth\\":1,\\"borderRadius\\":4,\\"minHeight\\":40,\\"backgroundColor\\":\\"#f3f4f5\\",\\"borderLeftColor\\":\\"#CBCED1\\",\\"borderTopColor\\":\\"#e1e5e8\\",\\"borderRightColor\\":\\"#e1e5e8\\",\\"borderBottomColor\\":\\"#e1e5e8\\",\\"borderLeftWidth\\":2,\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flexDirection\\":\\"row\\"}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1,\\"borderRadius\\":4,\\"padding\\":8}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flexDirection\\":\\"row\\"}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"fontSize\\":16,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"Inter\\",\\"fontWeight\\":\\"500\\"},{\\"color\\":\\"#6C727A\\"}]},\\"children\\":[\\"Engineering (9 today)\\"]}]}]},{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"width\\":20,\\"height\\":20,\\"right\\":8,\\"top\\":8,\\"justifyContent\\":\\"center\\",\\"alignItems\\":\\"center\\"}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"selectable\\":false,\\"allowFontScaling\\":false,\\"style\\":[{\\"fontSize\\":22,\\"color\\":\\"#6C727A\\"},null,{\\"fontFamily\\":\\"custom\\",\\"fontWeight\\":\\"normal\\",\\"fontStyle\\":\\"normal\\"},{}]},\\"children\\":[\\"\\"]}]}]}]}]}"`;
exports[`Storyshots CollapsibleQuote Item 1`] = `"{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"padding\\":10}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"testID\\":\\"collapsibleQuoteTouchable-Engineering (9 today)\\",\\"hitSlop\\":{\\"top\\":4,\\"right\\":4,\\"bottom\\":4,\\"left\\":4},\\"focusable\\":true,\\"collapsable\\":false,\\"style\\":{\\"flexDirection\\":\\"row\\",\\"alignItems\\":\\"center\\",\\"marginTop\\":6,\\"borderWidth\\":1,\\"borderRadius\\":4,\\"minHeight\\":40,\\"backgroundColor\\":\\"#f3f4f5\\",\\"borderLeftColor\\":\\"#CBCED1\\",\\"borderTopColor\\":\\"#e1e5e8\\",\\"borderRightColor\\":\\"#e1e5e8\\",\\"borderBottomColor\\":\\"#e1e5e8\\",\\"borderLeftWidth\\":2,\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flexDirection\\":\\"row\\"}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1,\\"borderRadius\\":4,\\"padding\\":8}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flexDirection\\":\\"row\\"}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"fontSize\\":16,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"Inter\\",\\"fontWeight\\":\\"500\\"},{\\"color\\":\\"#6C727A\\"}]},\\"children\\":[\\"Engineering (9 today)\\"]}]}]},{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"width\\":20,\\"height\\":20,\\"right\\":8,\\"top\\":8,\\"justifyContent\\":\\"center\\",\\"alignItems\\":\\"center\\"}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"selectable\\":false,\\"allowFontScaling\\":false,\\"style\\":[{\\"fontSize\\":22,\\"color\\":\\"#6C727A\\"},null,{\\"fontFamily\\":\\"custom\\",\\"fontWeight\\":\\"normal\\",\\"fontStyle\\":\\"normal\\"},{}]},\\"children\\":[\\"\\"]}]}]}]}]}"`;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,27 +1,27 @@
GEM
remote: https://rubygems.org/
specs:
CFPropertyList (3.0.6)
CFPropertyList (3.0.5)
rexml
addressable (2.8.4)
public_suffix (>= 2.0.2, < 6.0)
addressable (2.8.0)
public_suffix (>= 2.0.2, < 5.0)
artifactory (3.0.15)
atomos (0.1.3)
aws-eventstream (1.2.0)
aws-partitions (1.750.0)
aws-sdk-core (3.171.0)
aws-partitions (1.600.0)
aws-sdk-core (3.131.2)
aws-eventstream (~> 1, >= 1.0.2)
aws-partitions (~> 1, >= 1.651.0)
aws-sigv4 (~> 1.5)
jmespath (~> 1, >= 1.6.1)
aws-sdk-kms (1.63.0)
aws-sdk-core (~> 3, >= 3.165.0)
aws-partitions (~> 1, >= 1.525.0)
aws-sigv4 (~> 1.1)
aws-sdk-s3 (1.121.0)
aws-sdk-core (~> 3, >= 3.165.0)
jmespath (~> 1, >= 1.6.1)
aws-sdk-kms (1.57.0)
aws-sdk-core (~> 3, >= 3.127.0)
aws-sigv4 (~> 1.1)
aws-sdk-s3 (1.114.0)
aws-sdk-core (~> 3, >= 3.127.0)
aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.4)
aws-sigv4 (1.5.2)
aws-sigv4 (1.5.0)
aws-eventstream (~> 1, >= 1.0.2)
babosa (1.0.4)
claide (1.1.0)
@ -34,10 +34,10 @@ GEM
rake (>= 12.0.0, < 14.0.0)
domain_name (0.5.20190701)
unf (>= 0.0.5, < 1.0.0)
dotenv (2.8.1)
dotenv (2.7.6)
emoji_regex (3.2.3)
excon (0.99.0)
faraday (1.10.3)
excon (0.92.3)
faraday (1.10.0)
faraday-em_http (~> 1.0)
faraday-em_synchrony (~> 1.0)
faraday-excon (~> 1.1)
@ -66,7 +66,7 @@ GEM
faraday_middleware (1.2.0)
faraday (~> 1.0)
fastimage (2.2.6)
fastlane (2.212.2)
fastlane (2.206.2)
CFPropertyList (>= 2.3, < 4.0.0)
addressable (>= 2.8, < 3.0.0)
artifactory (~> 3.0)
@ -106,9 +106,9 @@ GEM
xcpretty (~> 0.3.0)
xcpretty-travis-formatter (>= 0.0.3)
gh_inspector (1.1.3)
google-apis-androidpublisher_v3 (0.39.0)
google-apis-core (>= 0.11.0, < 2.a)
google-apis-core (0.11.0)
google-apis-androidpublisher_v3 (0.22.0)
google-apis-core (>= 0.5, < 2.a)
google-apis-core (0.6.0)
addressable (~> 2.5, >= 2.5.1)
googleauth (>= 0.16.2, < 2.a)
httpclient (>= 2.8.1, < 3.a)
@ -117,27 +117,27 @@ GEM
retriable (>= 2.0, < 4.a)
rexml
webrick
google-apis-iamcredentials_v1 (0.17.0)
google-apis-core (>= 0.11.0, < 2.a)
google-apis-playcustomapp_v1 (0.13.0)
google-apis-core (>= 0.11.0, < 2.a)
google-apis-storage_v1 (0.19.0)
google-apis-core (>= 0.9.0, < 2.a)
google-apis-iamcredentials_v1 (0.12.0)
google-apis-core (>= 0.6, < 2.a)
google-apis-playcustomapp_v1 (0.9.0)
google-apis-core (>= 0.6, < 2.a)
google-apis-storage_v1 (0.15.0)
google-apis-core (>= 0.5, < 2.a)
google-cloud-core (1.6.0)
google-cloud-env (~> 1.0)
google-cloud-errors (~> 1.0)
google-cloud-env (1.6.0)
faraday (>= 0.17.3, < 3.0)
google-cloud-errors (1.3.1)
google-cloud-storage (1.44.0)
google-cloud-errors (1.2.0)
google-cloud-storage (1.36.2)
addressable (~> 2.8)
digest-crc (~> 0.4)
google-apis-iamcredentials_v1 (~> 0.1)
google-apis-storage_v1 (~> 0.19.0)
google-apis-storage_v1 (~> 0.1)
google-cloud-core (~> 1.6)
googleauth (>= 0.16.2, < 2.a)
mini_mime (~> 1.0)
googleauth (1.5.2)
googleauth (1.2.0)
faraday (>= 0.17.3, < 3.a)
jwt (>= 1.4, < 3.0)
memoist (~> 0.16)
@ -148,11 +148,11 @@ GEM
http-cookie (1.0.5)
domain_name (~> 0.5)
httpclient (2.8.3)
jmespath (1.6.2)
json (2.6.3)
jwt (2.7.0)
jmespath (1.6.1)
json (2.6.2)
jwt (2.4.1)
memoist (0.16.2)
mini_magick (4.12.0)
mini_magick (4.11.0)
mini_mime (1.1.2)
multi_json (1.15.0)
multipart-post (2.0.0)
@ -160,8 +160,8 @@ GEM
naturally (2.2.1)
optparse (0.1.1)
os (1.1.4)
plist (3.7.0)
public_suffix (5.0.1)
plist (3.6.0)
public_suffix (4.0.7)
rake (13.0.6)
representable (3.2.0)
declarative (< 0.1.0)
@ -178,7 +178,7 @@ GEM
faraday (>= 0.17.5, < 3.a)
jwt (>= 1.5, < 3.0)
multi_json (~> 1.10)
simctl (1.6.10)
simctl (1.6.8)
CFPropertyList
naturally
terminal-notifier (2.0.0)
@ -193,9 +193,8 @@ GEM
unf (0.1.4)
unf_ext
unf_ext (0.0.8.2)
unf_ext (0.0.8.2-x64-mingw32)
unicode-display_width (1.8.0)
webrick (1.8.1)
webrick (1.7.0)
word_wrap (1.0.0)
xcodeproj (1.22.0)
CFPropertyList (>= 2.3.3, < 4.0)
@ -217,4 +216,4 @@ DEPENDENCIES
fastlane
BUNDLED WITH
2.4.10
2.3.11

55
android/app/_BUCK Normal file
View File

@ -0,0 +1,55 @@
# To learn about Buck see [Docs](https://buckbuild.com/).
# To run your application with Buck:
# - install Buck
# - `npm start` - to start the packager
# - `cd android`
# - `keytool -genkey -v -keystore keystores/debug.keystore -storepass android -alias androiddebugkey -keypass android -dname "CN=Android Debug,O=Android,C=US"`
# - `./gradlew :app:copyDownloadableDepsToLibs` - make all Gradle compile dependencies available to Buck
# - `buck install -r android/app` - compile, install and run application
#
load(":build_defs.bzl", "create_aar_targets", "create_jar_targets")
lib_deps = []
create_aar_targets(glob(["libs/*.aar"]))
create_jar_targets(glob(["libs/*.jar"]))
android_library(
name = "all-libs",
exported_deps = lib_deps,
)
android_library(
name = "app-code",
srcs = glob([
"src/main/java/**/*.java",
]),
deps = [
":all-libs",
":build_config",
":res",
],
)
android_build_config(
name = "build_config",
package = "chat.rocket.reactnative",
)
android_resource(
name = "res",
package = "chat.rocket.reactnative",
res = "src/main/res",
)
android_binary(
name = "app",
keystore = "//android/keystores:debug",
manifest = "src/main/AndroidManifest.xml",
package_type = "debug",
deps = [
":app-code",
],
)

View File

@ -3,7 +3,6 @@ def isFoss = taskRequests.contains("foss")
apply plugin: "com.android.application"
apply plugin: 'kotlin-android'
apply plugin: "com.facebook.react"
if (!isFoss) {
apply plugin: 'com.google.firebase.crashlytics'
@ -13,88 +12,126 @@ if (!isFoss) {
import com.android.build.OutputFile
/**
* This is the configuration block to customize your React Native Android app.
* By default you don't need to apply any configuration, just uncomment the lines you need.
* The react.gradle file registers a task for each build variant (e.g. bundleDebugJsAndAssets
* and bundleReleaseJsAndAssets).
* These basically call `react-native bundle` with the correct arguments during the Android build
* cycle. By default, bundleDebugJsAndAssets is skipped, as in debug/dev mode we prefer to load the
* bundle directly from the development server. Below you can see all the possible configurations
* and their defaults. If you decide to add a configuration block, make sure to add it before the
* `apply from: "../../node_modules/react-native/react.gradle"` line.
*
* project.ext.react = [
* // the name of the generated asset file containing your JS bundle
* bundleAssetName: "index.android.bundle",
*
* // the entry file for bundle generation. If none specified and
* // "index.android.js" exists, it will be used. Otherwise "index.tsx" is
* // default. Can be overridden with ENTRY_FILE environment variable.
* entryFile: "index.android.js",
*
* // https://facebook.github.io/react-native/docs/performance#enable-the-ram-format
* bundleCommand: "ram-bundle",
*
* // whether to bundle JS and assets in debug mode
* bundleInDebug: false,
*
* // whether to bundle JS and assets in release mode
* bundleInRelease: true,
*
* // whether to bundle JS and assets in another build variant (if configured).
* // See http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Variants
* // The configuration property can be in the following formats
* // 'bundleIn${productFlavor}${buildType}'
* // 'bundleIn${buildType}'
* // bundleInFreeDebug: true,
* // bundleInPaidRelease: true,
* // bundleInBeta: true,
*
* // whether to disable dev mode in custom build variants (by default only disabled in release)
* // for example: to disable dev mode in the staging build type (if configured)
* devDisabledInStaging: true,
* // The configuration property can be in the following formats
* // 'devDisabledIn${productFlavor}${buildType}'
* // 'devDisabledIn${buildType}'
*
* // the root of your project, i.e. where "package.json" lives
* root: "../../",
*
* // where to put the JS bundle asset in debug mode
* jsBundleDirDebug: "$buildDir/intermediates/assets/debug",
*
* // where to put the JS bundle asset in release mode
* jsBundleDirRelease: "$buildDir/intermediates/assets/release",
*
* // where to put drawable resources / React Native assets, e.g. the ones you use via
* // require('./image.png')), in debug mode
* resourcesDirDebug: "$buildDir/intermediates/res/merged/debug",
*
* // where to put drawable resources / React Native assets, e.g. the ones you use via
* // require('./image.png')), in release mode
* resourcesDirRelease: "$buildDir/intermediates/res/merged/release",
*
* // by default the gradle tasks are skipped if none of the JS files or assets change; this means
* // that we don't look at files in android/ or ios/ to determine whether the tasks are up to
* // date; if you have any other folders that you want to ignore for performance reasons (gradle
* // indexes the entire tree), add them here. Alternatively, if you have JS files in android/
* // for example, you might want to remove it from here.
* inputExcludes: ["android/**", "ios/**"],
*
* // override which node gets called and with what additional arguments
* nodeExecutableAndArgs: ["node"],
*
* // supply additional arguments to the packager
* extraPackagerArgs: []
* ]
*/
react {
/* Folders */
// The root of your project, i.e. where "package.json" lives. Default is '..'
// root = file("../")
// The folder where the react-native NPM package is. Default is ../node_modules/react-native
// reactNativeDir = file("../node_modules/react-native")
// The folder where the react-native Codegen package is. Default is ../node_modules/react-native-codegen
// codegenDir = file("../node_modules/react-native-codegen")
// The cli.js file which is the React Native CLI entrypoint. Default is ../node_modules/react-native/cli.js
// cliFile = file("../node_modules/react-native/cli.js")
/* Variants */
// The list of variants to that are debuggable. For those we're going to
// skip the bundling of the JS bundle and the assets. By default is just 'debug'.
// If you add flavors like lite, prod, etc. you'll have to list your debuggableVariants.
debuggableVariants = ["experimentalPlayDebug", "officialPlayDebug", "experimentalFossDebug", "officialFossDebug"]
/* Bundling */
// A list containing the node command and its flags. Default is just 'node'.
// nodeExecutableAndArgs = ["node"]
//
// The command to run when bundling. By default is 'bundle'
// bundleCommand = "ram-bundle"
//
// The path to the CLI configuration file. Default is empty.
// bundleConfig = file(../rn-cli.config.js)
//
// The name of the generated asset file containing your JS bundle
// bundleAssetName = "MyApplication.android.bundle"
//
// The entry file for bundle generation. Default is 'index.android.js' or 'index.js'
// entryFile = file("../js/MyApplication.android.js")
//
// A list of extra flags to pass to the 'bundle' commands.
// See https://github.com/react-native-community/cli/blob/main/docs/commands.md#bundle
// extraPackagerArgs = []
/* Hermes Commands */
// The hermes compiler command to run. By default it is 'hermesc'
// hermesCommand = "$rootDir/my-custom-hermesc/bin/hermesc"
//
// The list of flags to pass to the Hermes compiler. By default is "-O", "-output-source-map"
// hermesFlags = ["-O", "-output-source-map"]
}
project.ext.react = [
bundleAssetName: "app.bundle",
iconFontNames: [ 'custom.ttf' ],
enableHermes: true, // clean and rebuild if changing
]
// project.ext.react = [
// bundleAssetName: "app.bundle",
// iconFontNames: [ 'custom.ttf' ],
// enableHermes: true, // clean and rebuild if changing
// ]
apply from: "../../node_modules/react-native/react.gradle"
/**
* Set this to true to create four separate APKs instead of one,
* one for each native architecture. This is useful if you don't
* use App Bundles (https://developer.android.com/guide/app-bundle/)
* and want to have separate APKs to upload to the Play Store.
* Set this to true to create two separate APKs instead of one:
* - An APK that only works on ARM devices
* - An APK that only works on x86 devices
* The advantage is the size of the APK is reduced by about 4MB.
* Upload all the APKs to the Play Store and people will download
* the correct one based on the CPU architecture of their device.
*/
def enableSeparateBuildPerCPUArchitecture = false
/**
* Set this to true to Run Proguard on Release builds to minify the Java bytecode.
* Run Proguard to shrink the Java bytecode in release builds.
*/
def enableProguardInReleaseBuilds = false
/**
* The preferred build flavor of JavaScriptCore (JSC)
* The preferred build flavor of JavaScriptCore.
*
* For example, to use the international variant, you can use:
* `def jscFlavor = 'org.webkit:android-jsc-intl:+'`
*
* The international variant includes ICU i18n library and necessary data
* allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that
* give correct results when using with locales other than en-US. Note that
* give correct results when using with locales other than en-US. Note that
* this variant is about 6MiB larger per architecture than default.
*/
def jscFlavor = 'org.webkit:android-jsc:+'
/**
* Whether to enable the Hermes VM.
*
* This should be set on project.ext.react and mirrored here. If it is not set
* on project.ext.react, JavaScript will not be compiled to Hermes Bytecode
* and the benefits of using Hermes will therefore be sharply reduced.
*/
def enableHermes = project.ext.react.get("enableHermes", false);
/**
* Private function to get the list of Native Architectures you want to build.
* This reads the value from reactNativeArchitectures in your gradle.properties
* file and works together with the --active-arch-only flag of react-native run-android.
* Architectures to build native code for.
*/
def reactNativeArchitectures() {
def value = project.getProperties().get("reactNativeArchitectures")
@ -105,8 +142,6 @@ android {
ndkVersion rootProject.ext.ndkVersion
compileSdkVersion rootProject.ext.compileSdkVersion
// Can't set this, since it causes issues to Official flavor
// namespace APPLICATION_ID
defaultConfig {
applicationId APPLICATION_ID
minSdkVersion rootProject.ext.minSdkVersion
@ -121,16 +156,78 @@ android {
resValue "string", "rn_config_reader_custom_package", "chat.rocket.reactnative"
testBuildType System.getProperty('testBuildType', 'debug')
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
}
splits {
abi {
reset()
enable enableSeparateBuildPerCPUArchitecture
universalApk false // If true, also generate a universal APK
include (*reactNativeArchitectures())
buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()
if (isNewArchitectureEnabled()) {
// We configure the NDK build only if you decide to opt-in for the New Architecture.
externalNativeBuild {
ndkBuild {
arguments "APP_PLATFORM=android-21",
"APP_STL=c++_shared",
"NDK_TOOLCHAIN_VERSION=clang",
"GENERATED_SRC_DIR=$buildDir/generated/source",
"PROJECT_BUILD_DIR=$buildDir",
"REACT_ANDROID_DIR=$rootDir/../node_modules/react-native/ReactAndroid",
"REACT_ANDROID_BUILD_DIR=$rootDir/../node_modules/react-native/ReactAndroid/build"
cFlags "-Wall", "-Werror", "-fexceptions", "-frtti", "-DWITH_INSPECTOR=1"
cppFlags "-std=c++17"
// Make sure this target name is the same you specify inside the
// src/main/jni/Android.mk file for the `LOCAL_MODULE` variable.
targets "rndiffapp_appmodules"
// Fix for windows limit on number of character in file paths and in command lines
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
arguments "NDK_APP_SHORT_COMMANDS=true"
}
}
}
if (!enableSeparateBuildPerCPUArchitecture) {
ndk {
abiFilters (*reactNativeArchitectures())
}
}
}
}
if (isNewArchitectureEnabled()) {
// We configure the NDK build only if you decide to opt-in for the New Architecture.
externalNativeBuild {
ndkBuild {
path "$projectDir/src/main/jni/Android.mk"
}
}
def reactAndroidProjectDir = project(':ReactAndroid').projectDir
def packageReactNdkDebugLibs = tasks.register("packageReactNdkDebugLibs", Copy) {
dependsOn(":ReactAndroid:packageReactNdkDebugLibsForBuck")
from("$reactAndroidProjectDir/src/main/jni/prebuilt/lib")
into("$buildDir/react-ndk/exported")
}
def packageReactNdkReleaseLibs = tasks.register("packageReactNdkReleaseLibs", Copy) {
dependsOn(":ReactAndroid:packageReactNdkReleaseLibsForBuck")
from("$reactAndroidProjectDir/src/main/jni/prebuilt/lib")
into("$buildDir/react-ndk/exported")
}
afterEvaluate {
// If you wish to add a custom TurboModule or component locally,
// you should uncomment this line.
// preBuild.dependsOn("generateCodegenArtifactsFromSchema")
preDebugBuild.dependsOn(packageReactNdkDebugLibs)
preReleaseBuild.dependsOn(packageReactNdkReleaseLibs)
// Due to a bug inside AGP, we have to explicitly set a dependency
// between configureNdkBuild* tasks and the preBuild tasks.
// This can be removed once this is solved: https://issuetracker.google.com/issues/207403732
configureNdkBuildRelease.dependsOn(preReleaseBuild)
configureNdkBuildDebug.dependsOn(preDebugBuild)
reactNativeArchitectures().each { architecture ->
tasks.findByName("configureNdkBuildDebug[${architecture}]")?.configure {
dependsOn("preDebugBuild")
}
tasks.findByName("configureNdkBuildRelease[${architecture}]")?.configure {
dependsOn("preReleaseBuild")
}
}
}
}
signingConfigs {
release {
if (project.hasProperty('KEYSTORE')) {
@ -141,6 +238,14 @@ android {
}
}
}
splits {
abi {
reset()
enable enableSeparateBuildPerCPUArchitecture
universalApk false // If true, also generate a universal APK
include (*reactNativeArchitectures())
}
}
buildTypes {
release {
minifyEnabled enableProguardInReleaseBuilds
@ -157,6 +262,18 @@ android {
}
}
// packagingOptions {
// pickFirst '**/armeabi-v7a/libc++_shared.so'
// pickFirst '**/x86/libc++_shared.so'
// pickFirst '**/arm64-v8a/libc++_shared.so'
// pickFirst '**/x86_64/libc++_shared.so'
// }
// FIXME: Remove when we update RN
packagingOptions {
pickFirst '**/*.so'
}
// applicationVariants are e.g. debug, release
flavorDimensions "app", "type"
@ -225,47 +342,74 @@ android {
}
dependencies {
// The version of react-native is set by the React Native Gradle Plugin
implementation("com.facebook.react:react-android")
implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.0.0")
debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}")
debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") {
exclude group:'com.squareup.okhttp3', module:'okhttp'
}
debugImplementation("com.facebook.flipper:flipper-fresco-plugin:${FLIPPER_VERSION}")
if (hermesEnabled.toBoolean()) {
implementation("com.facebook.react:hermes-android")
} else {
implementation jscFlavor
}
implementation project(':@react-native-community_viewpager')
implementation "androidx.core:core-splashscreen:1.0.0"
playImplementation project(':react-native-notifications')
playImplementation 'com.google.firebase:firebase-core:16.0.0'
playImplementation project(':@react-native-firebase_app')
playImplementation project(':@react-native-firebase_analytics')
playImplementation project(':@react-native-firebase_crashlytics')
implementation fileTree(dir: "libs", include: ["*.jar"])
//noinspection GradleDynamicVersion
implementation "com.facebook.react:react-native:+" // From node_modules
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0"
debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}") {
exclude group:'com.facebook.fbjni'
}
debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") {
exclude group:'com.facebook.flipper'
exclude group:'com.squareup.okhttp3', module:'okhttp'
}
debugImplementation("com.facebook.flipper:flipper-fresco-plugin:${FLIPPER_VERSION}") {
exclude group:'com.facebook.flipper'
}
if (enableHermes) {
def hermesPath = "../../node_modules/hermes-engine/android/";
debugImplementation files(hermesPath + "hermes-debug.aar")
releaseImplementation files(hermesPath + "hermes-release.aar")
} else {
implementation jscFlavor
}
implementation "com.google.code.gson:gson:2.8.9"
implementation "com.github.bumptech.glide:glide:4.9.0"
annotationProcessor "com.github.bumptech.glide:compiler:4.9.0"
implementation "com.tencent:mmkv-static:1.2.10"
androidTestImplementation('com.wix:detox:+')
androidTestImplementation 'androidx.test:core:1.4.0'
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'com.facebook.soloader:soloader:0.10.4'
}
if (isNewArchitectureEnabled()) {
// If new architecture is enabled, we let you build RN from source
// Otherwise we fallback to a prebuilt .aar bundled in the NPM package.
// This will be applied to all the imported transtitive dependency.
configurations.all {
resolutionStrategy.dependencySubstitution {
substitute(module("com.facebook.react:react-native"))
.using(project(":ReactAndroid")).because("On New Architecture we're building React Native from source")
}
}
}
// Run this once to be able to run the application with BUCK
// puts all compile dependencies into folder libs for BUCK to use
task copyDownloadableDepsToLibs(type: Copy) {
from configurations.implementation
into 'libs'
}
apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)
if (!isFoss) {
apply plugin: 'com.google.gms.google-services'
}
bugsnag {
uploadReactNativeMappings = false
}
def isNewArchitectureEnabled() {
// To opt-in for the New Architecture, you can either:
// - Set `newArchEnabled` to true inside the `gradle.properties` file
// - Invoke gradle with `-newArchEnabled=true`
// - Set an environment variable `ORG_GRADLE_PROJECT_newArchEnabled=true`
return project.hasProperty("newArchEnabled") && project.newArchEnabled == "true"
}

View File

@ -0,0 +1,19 @@
"""Helper definitions to glob .aar and .jar targets"""
def create_aar_targets(aarfiles):
for aarfile in aarfiles:
name = "aars__" + aarfile[aarfile.rindex("/") + 1:aarfile.rindex(".aar")]
lib_deps.append(":" + name)
android_prebuilt_aar(
name = name,
aar = aarfile,
)
def create_jar_targets(jarfiles):
for jarfile in jarfiles:
name = "jars__" + jarfile[jarfile.rindex("/") + 1:jarfile.rindex(".jar")]
lib_deps.append(":" + name)
prebuilt_jar(
name = name,
binary_jar = jarfile,
)

View File

@ -1,3 +1,9 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* <p>This source code is licensed under the MIT license found in the LICENSE file in the root
* directory of this source tree.
*/
package chat.rocket.reactnative;
import android.content.Context;
import com.facebook.flipper.android.AndroidFlipperClient;
@ -18,11 +24,6 @@ import com.facebook.react.bridge.ReactContext;
import com.facebook.react.modules.network.NetworkingModule;
import com.facebook.react.modules.network.CustomClientBuilder;
import okhttp3.OkHttpClient;
/**
* Class responsible of loading Flipper inside your React Native application. This is the debug
* flavor of it. Here you can add your own plugins and customize the Flipper setup.
*/
public class ReactNativeFlipper {
public static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) {
if (FlipperUtils.shouldEnableFlipper(context)) {

View File

@ -0,0 +1,24 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="731.4286"
android:viewportHeight="731.4286">
<group android:translateX="109.71429"
android:translateY="109.71429">
<group>
<clip-path android:pathData="M0,0h512v512h-512z M 0,0"/>
<path
android:pathData="M404.999,208.068C396.342,194.624 384.207,182.722 368.953,172.683C339.479,153.318 300.753,142.65 259.908,142.65C246.261,142.65 232.816,143.837 219.765,146.187C211.667,138.391 202.2,131.378 192.173,125.836C154.971,107.29 122.187,114.196 105.623,120.152C100.181,122.11 98.502,128.993 102.527,133.146C114.209,145.202 133.536,169.029 128.785,190.696C110.315,209.551 100.3,232.287 100.3,255.959C100.3,280.083 110.315,302.818 128.785,321.674C133.536,343.341 114.209,367.18 102.527,379.236C98.514,383.377 100.181,390.259 105.623,392.217C122.187,398.174 154.971,405.092 192.185,386.545C202.212,381.004 211.679,373.991 219.777,366.195C232.828,368.544 246.273,369.731 259.92,369.731C300.777,369.731 339.503,359.075 368.965,339.71C384.219,329.671 396.354,317.782 405.011,304.325C414.657,289.35 419.539,273.225 419.539,256.422C419.527,239.169 414.645,223.055 404.999,208.068ZM258.241,341.787C240.58,341.787 223.742,339.508 208.392,335.391L197.174,346.177C191.077,352.039 183.932,357.343 176.478,361.52C166.606,366.349 156.853,368.995 147.207,369.79C147.755,368.806 148.255,367.809 148.791,366.812C160.032,346.165 163.069,327.607 157.889,311.148C139.502,296.707 128.475,278.22 128.475,258.083C128.475,211.865 186.576,174.392 258.241,174.392C329.905,174.392 388.018,211.865 388.018,258.083C388.018,304.314 329.917,341.787 258.241,341.787Z"
android:fillColor="#ffffff"/>
<path
android:pathData="M196.162,238.837C185.6,238.837 177.038,247.333 177.038,257.811C177.038,268.288 185.6,276.784 196.162,276.784C206.725,276.784 215.287,268.288 215.287,257.811C215.287,247.333 206.725,238.837 196.162,238.837Z"
android:fillColor="#ffffff"/>
<path
android:pathData="M257.717,238.837C247.154,238.837 238.592,247.333 238.592,257.811C238.592,268.288 247.154,276.784 257.717,276.784C268.279,276.784 276.842,268.288 276.842,257.811C276.842,247.333 268.279,238.837 257.717,238.837Z"
android:fillColor="#ffffff"/>
<path
android:pathData="M319.282,238.837C308.72,238.837 300.158,247.333 300.158,257.811C300.158,268.288 308.72,276.784 319.282,276.784C329.845,276.784 338.407,268.288 338.407,257.811C338.407,247.333 329.845,238.837 319.282,238.837Z"
android:fillColor="#ffffff"/>
</group>
</group>
</vector>

View File

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background"/>
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
<background android:drawable="@drawable/ic_launcher_background"/>
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
<monochrome android:drawable="@drawable/ic_launcher_monochrome"/>
</adaptive-icon>

View File

@ -2,4 +2,5 @@
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background"/>
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
</adaptive-icon>
<monochrome android:drawable="@drawable/ic_launcher_monochrome"/>
</adaptive-icon>

View File

@ -6,10 +6,9 @@ import android.os.Bundle;
import com.facebook.react.ReactActivity;
import com.facebook.react.ReactActivityDelegate;
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint;
import com.facebook.react.defaults.DefaultReactActivityDelegate;
import com.facebook.react.ReactRootView;
import com.zoontek.rnbootsplash.RNBootSplash;
import expo.modules.ReactActivityDelegateWrapper;
public class MainActivity extends ReactActivity {
@ -44,20 +43,26 @@ public class MainActivity extends ReactActivity {
this.sendBroadcast(intent);
}
/**
* Returns the instance of the {@link ReactActivityDelegate}. Here we use a util class {@link
* DefaultReactActivityDelegate} which allows you to easily enable Fabric and Concurrent React
* (aka React 18) with two boolean flags.
/**
* Returns the instance of the {@link ReactActivityDelegate}. There the RootView is created and
* you can specify the rendered you wish to use (Fabric or the older renderer).
*/
@Override
protected ReactActivityDelegate createReactActivityDelegate() {
return new DefaultReactActivityDelegate(
this,
getMainComponentName(),
return new ReactActivityDelegateWrapper(this, new MainActivityDelegate(this, getMainComponentName()));
}
public static class MainActivityDelegate extends ReactActivityDelegate {
public MainActivityDelegate(ReactActivity activity, String mainComponentName) {
super(activity, mainComponentName);
}
@Override
protected ReactRootView createRootView() {
ReactRootView reactRootView = new ReactRootView(getContext());
// If you opted-in for the New Architecture, we enable the Fabric Renderer.
DefaultNewArchitectureEntryPoint.getFabricEnabled(), // fabricEnabled
// If you opted-in for the New Architecture, we enable Concurrent React (i.e. React 18).
DefaultNewArchitectureEntryPoint.getConcurrentReactEnabled() // concurrentRootEnabled
);
reactRootView.setIsFabric(BuildConfig.IS_NEW_ARCHITECTURE_ENABLED);
return reactRootView;
}
}
}

View File

@ -8,70 +8,115 @@ import com.facebook.react.PackageList;
import com.facebook.react.ReactApplication;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint;
import com.facebook.react.defaults.DefaultReactNativeHost;
import com.facebook.react.config.ReactFeatureFlags;
import com.facebook.react.ReactInstanceManager;
import com.facebook.soloader.SoLoader;
import com.reactnativecommunity.viewpager.RNCViewPagerPackage;
import com.facebook.react.bridge.JSIModulePackage;
import com.swmansion.reanimated.ReanimatedJSIModulePackage;
import android.content.Context;
import android.content.res.Configuration;
import expo.modules.ApplicationLifecycleDispatcher;
import expo.modules.ReactNativeHostWrapper;
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
import java.util.List;
import chat.rocket.reactnative.newarchitecture.MainApplicationReactNativeHost;
import chat.rocket.reactnative.networking.SSLPinningPackage;
public class MainApplication extends Application implements ReactApplication {
private final ReactNativeHost mReactNativeHost =
new DefaultReactNativeHost(this) {
@Override
public boolean getUseDeveloperSupport() {
return BuildConfig.DEBUG;
}
private final ReactNativeHost mReactNativeHost = new ReactNativeHostWrapper(this, new ReactNativeHost(this) {
@Override
public boolean getUseDeveloperSupport() {
return BuildConfig.DEBUG;
}
@Override
protected List<ReactPackage> getPackages() {
@SuppressWarnings("UnnecessaryLocalVariable")
List<ReactPackage> packages = new PackageList(this).getPackages();
packages.add(new RNCViewPagerPackage());
packages.add(new SSLPinningPackage());
List<ReactPackage> additionalModules = new AdditionalModules().getAdditionalModules(MainApplication.this);
packages.addAll(additionalModules);
return packages;
}
@Override
protected List<ReactPackage> getPackages() {
@SuppressWarnings("UnnecessaryLocalVariable")
List<ReactPackage> packages = new PackageList(this).getPackages();
packages.add(new RNCViewPagerPackage());
packages.add(new SSLPinningPackage());
List<ReactPackage> additionalModules = new AdditionalModules().getAdditionalModules(MainApplication.this);
packages.addAll(additionalModules);
return packages;
}
@Override
protected String getJSMainModuleName() {
return "index";
}
@Override
protected String getJSMainModuleName() {
return "index";
}
@Override
protected boolean isNewArchEnabled() {
return BuildConfig.IS_NEW_ARCHITECTURE_ENABLED;
}
@Override
protected JSIModulePackage getJSIModulePackage() {
return new ReanimatedJSIModulePackage();
}
@Override
protected Boolean isHermesEnabled() {
return BuildConfig.IS_HERMES_ENABLED;
}
};
@Override
protected @Nullable String getBundleAssetName() {
return "app.bundle";
}
});
private final ReactNativeHost mNewArchitectureNativeHost =
new ReactNativeHostWrapper(this, new MainApplicationReactNativeHost(this));
@Override
public ReactNativeHost getReactNativeHost() {
return mReactNativeHost;
if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
return mNewArchitectureNativeHost;
} else {
return mReactNativeHost;
}
}
@Override
public void onCreate() {
super.onCreate();
// If you opted-in for the New Architecture, we enable the TurboModule system
ReactFeatureFlags.useTurboModules = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED;
SoLoader.init(this, /* native exopackage */ false);
if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
// If you opted-in for the New Architecture, we load the native entry point for this app.
DefaultNewArchitectureEntryPoint.load();
initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
ApplicationLifecycleDispatcher.onApplicationCreate(this);
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
ApplicationLifecycleDispatcher.onConfigurationChanged(this, newConfig);
}
/**
* Loads Flipper in React Native templates. Call this in the onCreate method with something like
* initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
*
* @param context
* @param reactInstanceManager
*/
private static void initializeFlipper(
Context context, ReactInstanceManager reactInstanceManager) {
if (BuildConfig.DEBUG) {
try {
/*
We use reflection here to pick up the class that initializes Flipper,
since Flipper library is not available in release mode
*/
Class<?> aClass = Class.forName("chat.rocket.reactnative.ReactNativeFlipper");
aClass
.getMethod("initializeFlipper", Context.class, ReactInstanceManager.class)
.invoke(null, context, reactInstanceManager);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
ReactNativeFlipper.initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
}
}

View File

@ -0,0 +1,116 @@
package chat.rocket.reactnative.newarchitecture;
import android.app.Application;
import androidx.annotation.NonNull;
import com.facebook.react.PackageList;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.react.ReactPackageTurboModuleManagerDelegate;
import com.facebook.react.bridge.JSIModulePackage;
import com.facebook.react.bridge.JSIModuleProvider;
import com.facebook.react.bridge.JSIModuleSpec;
import com.facebook.react.bridge.JSIModuleType;
import com.facebook.react.bridge.JavaScriptContextHolder;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.UIManager;
import com.facebook.react.fabric.ComponentFactory;
import com.facebook.react.fabric.CoreComponentsRegistry;
import com.facebook.react.fabric.EmptyReactNativeConfig;
import com.facebook.react.fabric.FabricJSIModuleProvider;
import com.facebook.react.uimanager.ViewManagerRegistry;
import chat.rocket.reactnative.BuildConfig;
import chat.rocket.reactnative.newarchitecture.components.MainComponentsRegistry;
import chat.rocket.reactnative.newarchitecture.modules.MainApplicationTurboModuleManagerDelegate;
import java.util.ArrayList;
import java.util.List;
/**
* A {@link ReactNativeHost} that helps you load everything needed for the New Architecture, both
* TurboModule delegates and the Fabric Renderer.
*
* <p>Please note that this class is used ONLY if you opt-in for the New Architecture (see the
* `newArchEnabled` property). Is ignored otherwise.
*/
public class MainApplicationReactNativeHost extends ReactNativeHost {
public MainApplicationReactNativeHost(Application application) {
super(application);
}
@Override
public boolean getUseDeveloperSupport() {
return BuildConfig.DEBUG;
}
@Override
protected List<ReactPackage> getPackages() {
List<ReactPackage> packages = new PackageList(this).getPackages();
// Packages that cannot be autolinked yet can be added manually here, for example:
// packages.add(new MyReactNativePackage());
// TurboModules must also be loaded here providing a valid TurboReactPackage implementation:
// packages.add(new TurboReactPackage() { ... });
// If you have custom Fabric Components, their ViewManagers should also be loaded here
// inside a ReactPackage.
return packages;
}
@Override
protected String getJSMainModuleName() {
return "index";
}
@NonNull
@Override
protected ReactPackageTurboModuleManagerDelegate.Builder
getReactPackageTurboModuleManagerDelegateBuilder() {
// Here we provide the ReactPackageTurboModuleManagerDelegate Builder. This is necessary
// for the new architecture and to use TurboModules correctly.
return new MainApplicationTurboModuleManagerDelegate.Builder();
}
@Override
protected JSIModulePackage getJSIModulePackage() {
return new JSIModulePackage() {
@Override
public List<JSIModuleSpec> getJSIModules(
final ReactApplicationContext reactApplicationContext,
final JavaScriptContextHolder jsContext) {
final List<JSIModuleSpec> specs = new ArrayList<>();
// Here we provide a new JSIModuleSpec that will be responsible of providing the
// custom Fabric Components.
specs.add(
new JSIModuleSpec() {
@Override
public JSIModuleType getJSIModuleType() {
return JSIModuleType.UIManager;
}
@Override
public JSIModuleProvider<UIManager> getJSIModuleProvider() {
final ComponentFactory componentFactory = new ComponentFactory();
CoreComponentsRegistry.register(componentFactory);
// Here we register a Components Registry.
// The one that is generated with the template contains no components
// and just provides you the one from React Native core.
MainComponentsRegistry.register(componentFactory);
final ReactInstanceManager reactInstanceManager = getReactInstanceManager();
ViewManagerRegistry viewManagerRegistry =
new ViewManagerRegistry(
reactInstanceManager.getOrCreateViewManagers(reactApplicationContext));
return new FabricJSIModuleProvider(
reactApplicationContext,
componentFactory,
new EmptyReactNativeConfig(),
viewManagerRegistry);
}
});
return specs;
}
};
}
}

View File

@ -0,0 +1,36 @@
package chat.rocket.reactnative.newarchitecture.components;
import com.facebook.jni.HybridData;
import com.facebook.proguard.annotations.DoNotStrip;
import com.facebook.react.fabric.ComponentFactory;
import com.facebook.soloader.SoLoader;
/**
* Class responsible to load the custom Fabric Components. This class has native methods and needs a
* corresponding C++ implementation/header file to work correctly (already placed inside the jni/
* folder for you).
*
* <p>Please note that this class is used ONLY if you opt-in for the New Architecture (see the
* `newArchEnabled` property). Is ignored otherwise.
*/
@DoNotStrip
public class MainComponentsRegistry {
static {
SoLoader.loadLibrary("fabricjni");
}
@DoNotStrip private final HybridData mHybridData;
@DoNotStrip
private native HybridData initHybrid(ComponentFactory componentFactory);
@DoNotStrip
private MainComponentsRegistry(ComponentFactory componentFactory) {
mHybridData = initHybrid(componentFactory);
}
@DoNotStrip
public static MainComponentsRegistry register(ComponentFactory componentFactory) {
return new MainComponentsRegistry(componentFactory);
}
}

View File

@ -0,0 +1,48 @@
package chat.rocket.reactnative.newarchitecture.modules;
import com.facebook.jni.HybridData;
import com.facebook.react.ReactPackage;
import com.facebook.react.ReactPackageTurboModuleManagerDelegate;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.soloader.SoLoader;
import java.util.List;
/**
* Class responsible to load the TurboModules. This class has native methods and needs a
* corresponding C++ implementation/header file to work correctly (already placed inside the jni/
* folder for you).
*
* <p>Please note that this class is used ONLY if you opt-in for the New Architecture (see the
* `newArchEnabled` property). Is ignored otherwise.
*/
public class MainApplicationTurboModuleManagerDelegate
extends ReactPackageTurboModuleManagerDelegate {
private static volatile boolean sIsSoLibraryLoaded;
protected MainApplicationTurboModuleManagerDelegate(
ReactApplicationContext reactApplicationContext, List<ReactPackage> packages) {
super(reactApplicationContext, packages);
}
protected native HybridData initHybrid();
native boolean canCreateTurboModule(String moduleName);
public static class Builder extends ReactPackageTurboModuleManagerDelegate.Builder {
protected MainApplicationTurboModuleManagerDelegate build(
ReactApplicationContext context, List<ReactPackage> packages) {
return new MainApplicationTurboModuleManagerDelegate(context, packages);
}
}
@Override
protected synchronized void maybeLoadOtherSoLibraries() {
if (!sIsSoLibraryLoaded) {
// If you change the name of your application .so file in the Android.mk file,
// make sure you update the name here as well.
SoLoader.loadLibrary("rocketchat_appmodules");
sIsSoLibraryLoaded = true;
}
}
}

View File

@ -0,0 +1,49 @@
THIS_DIR := $(call my-dir)
include $(REACT_ANDROID_DIR)/Android-prebuilt.mk
# If you wish to add a custom TurboModule or Fabric component in your app you
# will have to include the following autogenerated makefile.
# include $(GENERATED_SRC_DIR)/codegen/jni/Android.mk
include $(CLEAR_VARS)
LOCAL_PATH := $(THIS_DIR)
# You can customize the name of your application .so file here.
LOCAL_MODULE := rocketchat_appmodules
LOCAL_C_INCLUDES := $(LOCAL_PATH)
LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/*.cpp)
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)
# If you wish to add a custom TurboModule or Fabric component in your app you
# will have to uncomment those lines to include the generated source
# files from the codegen (placed in $(GENERATED_SRC_DIR)/codegen/jni)
#
# LOCAL_C_INCLUDES += $(GENERATED_SRC_DIR)/codegen/jni
# LOCAL_SRC_FILES += $(wildcard $(GENERATED_SRC_DIR)/codegen/jni/*.cpp)
# LOCAL_EXPORT_C_INCLUDES += $(GENERATED_SRC_DIR)/codegen/jni
# Here you should add any native library you wish to depend on.
LOCAL_SHARED_LIBRARIES := \
libfabricjni \
libfbjni \
libfolly_futures \
libfolly_json \
libglog \
libjsi \
libreact_codegen_rncore \
libreact_debug \
libreact_nativemodule_core \
libreact_render_componentregistry \
libreact_render_core \
libreact_render_debug \
libreact_render_graphics \
librrc_view \
libruntimeexecutor \
libturbomodulejsijni \
libyoga
LOCAL_CFLAGS := -DLOG_TAG=\"ReactNative\" -fexceptions -frtti -std=c++17 -Wall
include $(BUILD_SHARED_LIBRARY)

View File

@ -0,0 +1,24 @@
#include "MainApplicationModuleProvider.h"
#include <rncore.h>
namespace facebook {
namespace react {
std::shared_ptr<TurboModule> MainApplicationModuleProvider(
const std::string moduleName,
const JavaTurboModule::InitParams &params) {
// Here you can provide your own module provider for TurboModules coming from
// either your application or from external libraries. The approach to follow
// is similar to the following (for a library called `samplelibrary`:
//
// auto module = samplelibrary_ModuleProvider(moduleName, params);
// if (module != nullptr) {
// return module;
// }
// return rncore_ModuleProvider(moduleName, params);
return rncore_ModuleProvider(moduleName, params);
}
} // namespace react
} // namespace facebook

View File

@ -0,0 +1,16 @@
#pragma once
#include <memory>
#include <string>
#include <ReactCommon/JavaTurboModule.h>
namespace facebook {
namespace react {
std::shared_ptr<TurboModule> MainApplicationModuleProvider(
const std::string moduleName,
const JavaTurboModule::InitParams &params);
} // namespace react
} // namespace facebook

View File

@ -0,0 +1,45 @@
#include "MainApplicationTurboModuleManagerDelegate.h"
#include "MainApplicationModuleProvider.h"
namespace facebook {
namespace react {
jni::local_ref<MainApplicationTurboModuleManagerDelegate::jhybriddata>
MainApplicationTurboModuleManagerDelegate::initHybrid(
jni::alias_ref<jhybridobject>) {
return makeCxxInstance();
}
void MainApplicationTurboModuleManagerDelegate::registerNatives() {
registerHybrid({
makeNativeMethod(
"initHybrid", MainApplicationTurboModuleManagerDelegate::initHybrid),
makeNativeMethod(
"canCreateTurboModule",
MainApplicationTurboModuleManagerDelegate::canCreateTurboModule),
});
}
std::shared_ptr<TurboModule>
MainApplicationTurboModuleManagerDelegate::getTurboModule(
const std::string name,
const std::shared_ptr<CallInvoker> jsInvoker) {
// Not implemented yet: provide pure-C++ NativeModules here.
return nullptr;
}
std::shared_ptr<TurboModule>
MainApplicationTurboModuleManagerDelegate::getTurboModule(
const std::string name,
const JavaTurboModule::InitParams &params) {
return MainApplicationModuleProvider(name, params);
}
bool MainApplicationTurboModuleManagerDelegate::canCreateTurboModule(
std::string name) {
return getTurboModule(name, nullptr) != nullptr ||
getTurboModule(name, {.moduleName = name}) != nullptr;
}
} // namespace react
} // namespace facebook

View File

@ -0,0 +1,38 @@
#include <memory>
#include <string>
#include <ReactCommon/TurboModuleManagerDelegate.h>
#include <fbjni/fbjni.h>
namespace facebook {
namespace react {
class MainApplicationTurboModuleManagerDelegate
: public jni::HybridClass<
MainApplicationTurboModuleManagerDelegate,
TurboModuleManagerDelegate> {
public:
// Adapt it to the package you used for your Java class.
static constexpr auto kJavaDescriptor =
"Lchat/rocket/reactnative/newarchitecture/modules/MainApplicationTurboModuleManagerDelegate;";
static jni::local_ref<jhybriddata> initHybrid(jni::alias_ref<jhybridobject>);
static void registerNatives();
std::shared_ptr<TurboModule> getTurboModule(
const std::string name,
const std::shared_ptr<CallInvoker> jsInvoker) override;
std::shared_ptr<TurboModule> getTurboModule(
const std::string name,
const JavaTurboModule::InitParams &params) override;
/**
* Test-only method. Allows user to verify whether a TurboModule can be
* created by instances of this class.
*/
bool canCreateTurboModule(std::string name);
};
} // namespace react
} // namespace facebook

View File

@ -0,0 +1,61 @@
#include "MainComponentsRegistry.h"
#include <CoreComponentsRegistry.h>
#include <fbjni/fbjni.h>
#include <react/renderer/componentregistry/ComponentDescriptorProviderRegistry.h>
#include <react/renderer/components/rncore/ComponentDescriptors.h>
namespace facebook {
namespace react {
MainComponentsRegistry::MainComponentsRegistry(ComponentFactory *delegate) {}
std::shared_ptr<ComponentDescriptorProviderRegistry const>
MainComponentsRegistry::sharedProviderRegistry() {
auto providerRegistry = CoreComponentsRegistry::sharedProviderRegistry();
// Custom Fabric Components go here. You can register custom
// components coming from your App or from 3rd party libraries here.
//
// providerRegistry->add(concreteComponentDescriptorProvider<
// AocViewerComponentDescriptor>());
return providerRegistry;
}
jni::local_ref<MainComponentsRegistry::jhybriddata>
MainComponentsRegistry::initHybrid(
jni::alias_ref<jclass>,
ComponentFactory *delegate) {
auto instance = makeCxxInstance(delegate);
auto buildRegistryFunction =
[](EventDispatcher::Weak const &eventDispatcher,
ContextContainer::Shared const &contextContainer)
-> ComponentDescriptorRegistry::Shared {
auto registry = MainComponentsRegistry::sharedProviderRegistry()
->createComponentDescriptorRegistry(
{eventDispatcher, contextContainer});
auto mutableRegistry =
std::const_pointer_cast<ComponentDescriptorRegistry>(registry);
mutableRegistry->setFallbackComponentDescriptor(
std::make_shared<UnimplementedNativeViewComponentDescriptor>(
ComponentDescriptorParameters{
eventDispatcher, contextContainer, nullptr}));
return registry;
};
delegate->buildRegistryFunction = buildRegistryFunction;
return instance;
}
void MainComponentsRegistry::registerNatives() {
registerHybrid({
makeNativeMethod("initHybrid", MainComponentsRegistry::initHybrid),
});
}
} // namespace react
} // namespace facebook

View File

@ -0,0 +1,32 @@
#pragma once
#include <ComponentFactory.h>
#include <fbjni/fbjni.h>
#include <react/renderer/componentregistry/ComponentDescriptorProviderRegistry.h>
#include <react/renderer/componentregistry/ComponentDescriptorRegistry.h>
namespace facebook {
namespace react {
class MainComponentsRegistry
: public facebook::jni::HybridClass<MainComponentsRegistry> {
public:
// Adapt it to the package you used for your Java class.
constexpr static auto kJavaDescriptor =
"Lchat/rocket/reactnative/newarchitecture/components/MainComponentsRegistry;";
static void registerNatives();
MainComponentsRegistry(ComponentFactory *delegate);
private:
static std::shared_ptr<ComponentDescriptorProviderRegistry const>
sharedProviderRegistry();
static jni::local_ref<jhybriddata> initHybrid(
jni::alias_ref<jclass>,
ComponentFactory *delegate);
};
} // namespace react
} // namespace facebook

View File

@ -0,0 +1,11 @@
#include <fbjni/fbjni.h>
#include "MainApplicationTurboModuleManagerDelegate.h"
#include "MainComponentsRegistry.h"
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *) {
return facebook::jni::initialize(vm, [] {
facebook::react::MainApplicationTurboModuleManagerDelegate::
registerNatives();
facebook::react::MainComponentsRegistry::registerNatives();
});
}

View File

@ -0,0 +1,24 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="731.4286"
android:viewportHeight="731.4286">
<group android:translateX="109.71429"
android:translateY="109.71429">
<group>
<clip-path android:pathData="M0,0h512v512h-512z M 0,0"/>
<path
android:pathData="M404.999,208.068C396.342,194.624 384.207,182.722 368.953,172.683C339.479,153.318 300.753,142.65 259.908,142.65C246.261,142.65 232.816,143.837 219.765,146.187C211.667,138.391 202.2,131.378 192.173,125.836C154.971,107.29 122.187,114.196 105.623,120.152C100.181,122.11 98.502,128.993 102.527,133.146C114.209,145.202 133.536,169.029 128.785,190.696C110.315,209.551 100.3,232.287 100.3,255.959C100.3,280.083 110.315,302.818 128.785,321.674C133.536,343.341 114.209,367.18 102.527,379.236C98.514,383.377 100.181,390.259 105.623,392.217C122.187,398.174 154.971,405.092 192.185,386.545C202.212,381.004 211.679,373.991 219.777,366.195C232.828,368.544 246.273,369.731 259.92,369.731C300.777,369.731 339.503,359.075 368.965,339.71C384.219,329.671 396.354,317.782 405.011,304.325C414.657,289.35 419.539,273.225 419.539,256.422C419.527,239.169 414.645,223.055 404.999,208.068ZM258.241,341.787C240.58,341.787 223.742,339.508 208.392,335.391L197.174,346.177C191.077,352.039 183.932,357.343 176.478,361.52C166.606,366.349 156.853,368.995 147.207,369.79C147.755,368.806 148.255,367.809 148.791,366.812C160.032,346.165 163.069,327.607 157.889,311.148C139.502,296.707 128.475,278.22 128.475,258.083C128.475,211.865 186.576,174.392 258.241,174.392C329.905,174.392 388.018,211.865 388.018,258.083C388.018,304.314 329.917,341.787 258.241,341.787Z"
android:fillColor="#ffffff"/>
<path
android:pathData="M196.162,238.837C185.6,238.837 177.038,247.333 177.038,257.811C177.038,268.288 185.6,276.784 196.162,276.784C206.725,276.784 215.287,268.288 215.287,257.811C215.287,247.333 206.725,238.837 196.162,238.837Z"
android:fillColor="#ffffff"/>
<path
android:pathData="M257.717,238.837C247.154,238.837 238.592,247.333 238.592,257.811C238.592,268.288 247.154,276.784 257.717,276.784C268.279,276.784 276.842,268.288 276.842,257.811C276.842,247.333 268.279,238.837 257.717,238.837Z"
android:fillColor="#ffffff"/>
<path
android:pathData="M319.282,238.837C308.72,238.837 300.158,247.333 300.158,257.811C300.158,268.288 308.72,276.784 319.282,276.784C329.845,276.784 338.407,268.288 338.407,257.811C338.407,247.333 329.845,238.837 319.282,238.837Z"
android:fillColor="#ffffff"/>
</group>
</group>
</vector>

View File

@ -2,4 +2,5 @@
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background"/>
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
<monochrome android:drawable="@drawable/ic_launcher_monochrome"/>
</adaptive-icon>

View File

@ -2,4 +2,5 @@
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background"/>
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
</adaptive-icon>
<monochrome android:drawable="@drawable/ic_launcher_monochrome"/>
</adaptive-icon>

View File

@ -34,6 +34,8 @@ public class Ejson {
String senderName;
String msg;
String tmid;
private MMKV mmkv;
private String TOKEN_KEY = "reactnativemeteor_usertoken-";

View File

@ -1,7 +1,6 @@
package chat.rocket.reactnative;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.util.Base64;
import android.util.Log;
@ -81,7 +80,7 @@ class Encryption {
dbName += "-experimental";
}
dbName += ".db";
Database database = new Database(dbName, reactContext, SQLiteDatabase.CREATE_IF_NECESSARY);
Database database = new Database(dbName, reactContext);
String[] query = {ejson.rid};
Cursor cursor = database.rawQuery("select * from subscriptions where id == ? limit 1", query);

View File

@ -123,7 +123,9 @@ public class ReplyBroadcast extends BroadcastReceiver {
if (msg != message) {
msgMap.put("t", "e2e");
}
msgMap.put("tmid", null);
if(ejson.tmid != null) {
msgMap.put("tmid", ejson.tmid);
}
Map m = new HashMap();
m.put("message", msgMap);

View File

@ -1,12 +0,0 @@
package chat.rocket.reactnative;
import android.content.Context;
import com.facebook.react.ReactInstanceManager;
/**
* Class responsible of loading Flipper inside your React Native application. This is the release
* flavor of it so it's empty as we don't want to load Flipper.
*/
public class ReactNativeFlipper {
public static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) {
// Do nothing as we don't want to initialize Flipper on Release.
}
}

View File

@ -1,10 +1,11 @@
import org.apache.tools.ant.taskdefs.condition.Os
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
def taskRequests = getGradle().getStartParameter().getTaskRequests().toString().toLowerCase()
def isPlay = !taskRequests.contains("foss")
ext {
// TODO: target 33
buildToolsVersion = "33.0.0"
minSdkVersion = 23
compileSdkVersion = 33
@ -38,20 +39,75 @@ buildscript {
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.9.0'
classpath 'com.bugsnag:bugsnag-android-gradle-plugin:7.+'
}
classpath("com.android.tools.build:gradle:7.3.1")
classpath("com.android.tools.build:gradle:7.0.4")
classpath("com.facebook.react:react-native-gradle-plugin")
classpath("de.undercouch:gradle-download-task:4.1.2")
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
allprojects {
repositories {
mavenLocal()
maven {
// All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
url("$rootDir/../node_modules/react-native/android")
}
maven {
// Android JSC is installed from npm
url("$rootDir/../node_modules/jsc-android/dist")
}
maven {
url "$rootDir/../node_modules/detox/Detox-android"
}
maven {
// expo-camera bundles a custom com.google.android:cameraview
url "$rootDir/../node_modules/expo-camera/android/maven"
}
mavenCentral {
content {
excludeGroup "com.facebook.react"
}
}
google()
maven { url 'https://maven.google.com' }
maven { url 'https://www.jitpack.io' }
// https://stackoverflow.com/a/74333788/5447468
// TODO: remove once we update RN
exclusiveContent {
// We get React Native's Android binaries exclusively through npm,
// from a local Maven repo inside node_modules/react-native/.
// (The use of exclusiveContent prevents looking elsewhere like Maven Central
// and potentially getting a wrong version.)
filter {
includeGroup "com.facebook.react"
}
forRepository {
maven {
// NOTE: if you are in a monorepo, you may have "$rootDir/../../../node_modules/react-native/android"
url "$rootDir/../node_modules/react-native/android"
}
}
}
}
}
subprojects { subproject ->
afterEvaluate {
if (!project.name.equalsIgnoreCase("app") && project.hasProperty("android")) {
android {
compileSdkVersion 31
buildToolsVersion "31.0.0"
defaultConfig {
minSdkVersion 23
targetSdkVersion 31
}
}
}
}
}

View File

@ -37,10 +37,6 @@ reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64
# are providing them.
newArchEnabled=false
# Use this property to enable or disable the Hermes JS engine.
# If set to false, you will be using JSC instead.
hermesEnabled=true
# Application ID
APPLICATION_ID=chat.rocket.reactnative

View File

@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

View File

@ -11,13 +11,9 @@ apply from: file("../node_modules/@react-native-community/cli-platform-android/n
include ':app'
includeBuild('../node_modules/react-native-gradle-plugin')
includeBuild('../node_modules/react-native') {
dependencySubstitution {
substitute(module("com.facebook.react:react-android")).using(project(":ReactAndroid"))
substitute(module("com.facebook.react:react-native")).using(project(":ReactAndroid"))
substitute(module("com.facebook.react:hermes-android")).using(project(":ReactAndroid:hermes-engine"))
substitute(module("com.facebook.react:hermes-engine")).using(project(":ReactAndroid:hermes-engine"))
}
if (settings.hasProperty("newArchEnabled") && settings.newArchEnabled == "true") {
include(":ReactAndroid")
project(":ReactAndroid").projectDir = file('../node_modules/react-native/ReactAndroid')
}
apply from: new File(["node", "--print", "require.resolve('expo/package.json')"].execute(null, rootDir).text.trim(), "../scripts/autolinking.gradle")

View File

@ -3,15 +3,17 @@ import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import { connect } from 'react-redux';
import { SetUsernameStackParamList, StackParamList } from './definitions/navigationTypes';
import Navigation from './lib/navigation/appNavigation';
import { defaultHeader, getActiveRouteName, navigationTheme } from './lib/methods/helpers/navigation';
import { RootEnum } from './definitions';
// Stacks
import AuthLoadingView from './views/AuthLoadingView';
// SetUsername Stack
import SetUsernameView from './views/SetUsernameView';
import OutsideStack from './stacks/OutsideStack';
import InsideStack from './stacks/InsideStack';
import MasterDetailStack from './stacks/MasterDetailStack';
import { SetUsernameStackParamList, StackParamList } from './stacks/types';
import { ThemeContext } from './theme';
import { setCurrentScreen } from './lib/methods/helpers/log';

View File

@ -85,6 +85,7 @@ export const ENCRYPTION = createRequestTypes('ENCRYPTION', ['INIT', 'STOP', 'DEC
export const PERMISSIONS = createRequestTypes('PERMISSIONS', ['SET', 'UPDATE']);
export const ROLES = createRequestTypes('ROLES', ['SET', 'UPDATE', 'REMOVE']);
export const USERS_ROLES = createRequestTypes('USERS_ROLES', ['SET']);
export const VIDEO_CONF = createRequestTypes('VIDEO_CONF', [
'HANDLE_INCOMING_WEBSOCKET_MESSAGES',
'SET',

13
app/actions/usersRoles.ts Normal file
View File

@ -0,0 +1,13 @@
import { Action } from 'redux';
import { TUsersRoles } from '../reducers/usersRoles';
import { USERS_ROLES } from './actionsTypes';
export type TActionUsersRoles = Action & { usersRoles: TUsersRoles };
export function setUsersRoles(usersRoles: TUsersRoles): Action & { usersRoles: TUsersRoles } {
return {
type: USERS_ROLES.SET,
usersRoles
};
}

201
app/commands.ts Normal file
View File

@ -0,0 +1,201 @@
/* eslint-disable no-bitwise */
import { NativeSyntheticEvent } from 'react-native';
import KeyCommands, { constants, KeyCommand } from 'react-native-keycommands';
import I18n from './i18n';
const KEY_TYPING = '\t';
const KEY_PREFERENCES = 'p';
const KEY_SEARCH = 'f';
const KEY_PREVIOUS_ROOM = '[';
const KEY_NEXT_ROOM = ']';
const KEY_NEW_ROOM = __DEV__ ? 'e' : 'n';
const KEY_ROOM_ACTIONS = __DEV__ ? 'b' : 'i';
const KEY_UPLOAD = 'u';
const KEY_REPLY = ';';
const KEY_SERVER_SELECTION = __DEV__ ? 'o' : '`';
const KEY_ADD_SERVER = __DEV__ ? 'l' : 'n';
const KEY_SEND_MESSAGE = '\r';
const KEY_SELECT = '123456789';
const keyCommands = [
{
// Focus messageBox
input: KEY_TYPING,
modifierFlags: 0,
discoverabilityTitle: I18n.t('Type_message')
},
{
// Send message on textInput to current room
input: KEY_SEND_MESSAGE,
modifierFlags: 0,
discoverabilityTitle: I18n.t('Send')
},
{
// Open Preferences Modal
input: KEY_PREFERENCES,
modifierFlags: constants.keyModifierCommand,
discoverabilityTitle: I18n.t('Preferences')
},
{
// Focus Room Search
input: KEY_SEARCH,
modifierFlags: constants.keyModifierCommand | constants.keyModifierAlternate,
discoverabilityTitle: I18n.t('Room_search')
},
{
// Select a room by order using 1-9
input: '1...9',
modifierFlags: constants.keyModifierCommand,
discoverabilityTitle: I18n.t('Room_selection')
},
{
// Change room to next on Rooms List
input: KEY_NEXT_ROOM,
modifierFlags: constants.keyModifierCommand,
discoverabilityTitle: I18n.t('Next_room')
},
{
// Change room to previous on Rooms List
input: KEY_PREVIOUS_ROOM,
modifierFlags: constants.keyModifierCommand,
discoverabilityTitle: I18n.t('Previous_room')
},
{
// Open New Room Modal
input: KEY_NEW_ROOM,
modifierFlags: constants.keyModifierCommand,
discoverabilityTitle: I18n.t('New_room')
},
{
// Open Room Actions
input: KEY_ROOM_ACTIONS,
modifierFlags: constants.keyModifierCommand,
discoverabilityTitle: I18n.t('Room_actions')
},
{
// Upload a file to room
input: KEY_UPLOAD,
modifierFlags: constants.keyModifierCommand,
discoverabilityTitle: I18n.t('Upload_room')
},
{
// Search Messages on current room
input: KEY_SEARCH,
modifierFlags: constants.keyModifierCommand,
discoverabilityTitle: I18n.t('Search_messages')
},
{
// Scroll messages on current room
input: '↑ ↓',
modifierFlags: constants.keyModifierAlternate,
discoverabilityTitle: I18n.t('Scroll_messages')
},
{
// Scroll up messages on current room
input: constants.keyInputUpArrow,
modifierFlags: constants.keyModifierAlternate
},
{
// Scroll down messages on current room
input: constants.keyInputDownArrow,
modifierFlags: constants.keyModifierAlternate
},
{
// Reply latest message with Quote
input: KEY_REPLY,
modifierFlags: constants.keyModifierCommand,
discoverabilityTitle: I18n.t('Reply_latest')
},
{
// Open server dropdown
input: KEY_SERVER_SELECTION,
modifierFlags: constants.keyModifierCommand | constants.keyModifierAlternate,
discoverabilityTitle: I18n.t('Server_selection')
},
{
// Select a server by order using 1-9
input: '1...9',
modifierFlags: constants.keyModifierCommand | constants.keyModifierAlternate,
discoverabilityTitle: I18n.t('Server_selection_numbers')
},
{
// Navigate to add new server
input: KEY_ADD_SERVER,
modifierFlags: constants.keyModifierCommand | constants.keyModifierAlternate,
discoverabilityTitle: I18n.t('Add_server')
},
// Refers to select rooms on list
...[1, 2, 3, 4, 5, 6, 7, 8, 9].map(value => ({
input: `${value}`,
modifierFlags: constants.keyModifierCommand
})),
// Refers to select servers on list
...[1, 2, 3, 4, 5, 6, 7, 8, 9].map(value => ({
input: `${value}`,
modifierFlags: constants.keyModifierCommand | constants.keyModifierAlternate
}))
];
export const setKeyCommands = (): void => KeyCommands.setKeyCommands(keyCommands);
export const deleteKeyCommands = (): void => KeyCommands.deleteKeyCommands(keyCommands);
export const KEY_COMMAND = 'KEY_COMMAND';
export interface IKeyCommandEvent extends NativeSyntheticEvent<typeof KeyCommand> {
input: number & string;
modifierFlags: string | number;
}
export const commandHandle = (event: IKeyCommandEvent, key: string | string[], flags: string[] = []): boolean => {
const { input, modifierFlags } = event;
let _flags = 0;
if (flags.includes('command') && flags.includes('alternate')) {
_flags = constants.keyModifierCommand | constants.keyModifierAlternate;
} else if (flags.includes('command')) {
_flags = constants.keyModifierCommand;
} else if (flags.includes('alternate')) {
_flags = constants.keyModifierAlternate;
}
return key.includes(input) && modifierFlags === _flags;
};
export const handleCommandTyping = (event: IKeyCommandEvent): boolean => commandHandle(event, KEY_TYPING);
export const handleCommandSubmit = (event: IKeyCommandEvent): boolean => commandHandle(event, KEY_SEND_MESSAGE);
export const handleCommandShowUpload = (event: IKeyCommandEvent): boolean => commandHandle(event, KEY_UPLOAD, ['command']);
export const handleCommandScroll = (event: IKeyCommandEvent): boolean =>
commandHandle(event, [constants.keyInputUpArrow, constants.keyInputDownArrow], ['alternate']);
export const handleCommandRoomActions = (event: IKeyCommandEvent): boolean => commandHandle(event, KEY_ROOM_ACTIONS, ['command']);
export const handleCommandSearchMessages = (event: IKeyCommandEvent): boolean => commandHandle(event, KEY_SEARCH, ['command']);
export const handleCommandReplyLatest = (event: IKeyCommandEvent): boolean => commandHandle(event, KEY_REPLY, ['command']);
export const handleCommandSelectServer = (event: IKeyCommandEvent): boolean =>
commandHandle(event, KEY_SELECT, ['command', 'alternate']);
export const handleCommandShowPreferences = (event: IKeyCommandEvent): boolean =>
commandHandle(event, KEY_PREFERENCES, ['command']);
export const handleCommandSearching = (event: IKeyCommandEvent): boolean =>
commandHandle(event, KEY_SEARCH, ['command', 'alternate']);
export const handleCommandSelectRoom = (event: IKeyCommandEvent): boolean => commandHandle(event, KEY_SELECT, ['command']);
export const handleCommandPreviousRoom = (event: IKeyCommandEvent): boolean =>
commandHandle(event, KEY_PREVIOUS_ROOM, ['command']);
export const handleCommandNextRoom = (event: IKeyCommandEvent): boolean => commandHandle(event, KEY_NEXT_ROOM, ['command']);
export const handleCommandShowNewMessage = (event: IKeyCommandEvent): boolean => commandHandle(event, KEY_NEW_ROOM, ['command']);
export const handleCommandAddNewServer = (event: IKeyCommandEvent): boolean =>
commandHandle(event, KEY_ADD_SERVER, ['command', 'alternate']);
export const handleCommandOpenServerDropdown = (event: IKeyCommandEvent): boolean =>
commandHandle(event, KEY_SERVER_SELECTION, ['command', 'alternate']);

View File

@ -4,7 +4,7 @@ import React, { forwardRef, isValidElement, useEffect, useImperativeHandle, useR
import { Keyboard } from 'react-native';
import { Easing } from 'react-native-reanimated';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import BottomSheet, { BottomSheetBackdrop, BottomSheetBackdropProps } from '@gorhom/bottom-sheet';
import BottomSheet, { BottomSheetBackdrop } from '@gorhom/bottom-sheet';
import { useDimensions, useOrientation } from '../../dimensions';
import { useTheme } from '../../theme';
@ -107,7 +107,7 @@ const ActionSheet = React.memo(
};
const renderBackdrop = useCallback(
(props: BottomSheetBackdropProps) => (
props => (
<BottomSheetBackdrop
{...props}
appearsOnIndex={0}

File diff suppressed because one or more lines are too long

View File

@ -75,7 +75,6 @@ const EmojiPicker = ({
parentWidth={parentWidth}
/>
) : (
// @ts-ignore
<ScrollableTabView
renderTabBar={() => <TabBar />}
contentProps={{

View File

@ -13,6 +13,7 @@ export interface IHeaderButtonItem extends Omit<ICustomIcon, 'name' | 'size' | '
testID?: string;
badge?(): void;
color?: string;
disabled?: boolean;
}
export const BUTTON_HIT_SLOP = {

View File

@ -21,4 +21,4 @@ export function ImageComponent({
Component = FastImage;
}
return Component;
};
}

View File

@ -322,7 +322,7 @@ const MessageActions = React.memo(
const db = database.active;
await db.write(async () => {
await message.update(m => {
m.autoTranslate = !m.autoTranslate;
m.autoTranslate = m.autoTranslate !== null ? !m.autoTranslate : false;
m._updatedAt = new Date();
});
});
@ -479,7 +479,7 @@ const MessageActions = React.memo(
// Toggle Auto-translate
if (room.autoTranslate && message.u && message.u._id !== user.id) {
options.push({
title: I18n.t(message.autoTranslate ? 'View_Original' : 'Translate'),
title: I18n.t(message.autoTranslate !== false ? 'View_Original' : 'Translate'),
icon: 'language',
onPress: () => handleToggleTranslation(message)
});

View File

@ -31,7 +31,7 @@ const MentionItemContent = React.memo(({ trackingType, item }: IMessageBoxMentio
return (
<>
<MentionEmoji item={item} />
<Text style={[styles.mentionText, { color: themes[theme].titleText }]}>:{item.name ?? item}:</Text>
<Text style={[styles.mentionText, { color: themes[theme].titleText }]}>:{item.name || item}:</Text>
</>
);
case MENTIONS_TRACKING_TYPE_COMMANDS:
@ -57,7 +57,7 @@ const MentionItemContent = React.memo(({ trackingType, item }: IMessageBoxMentio
return (
<>
<Avatar style={styles.avatar} text={item.username || item.name} size={30} type={item.t} />
<Text style={[styles.mentionText, { color: themes[theme].titleText }]}>{item.username ?? item.name ?? item}</Text>
<Text style={[styles.mentionText, { color: themes[theme].titleText }]}>{item.username || item.name || item}</Text>
</>
);
}

View File

@ -24,19 +24,19 @@ const RECORDING_EXTENSION = '.m4a';
const RECORDING_SETTINGS = {
android: {
extension: RECORDING_EXTENSION,
outputFormat: Audio.AndroidOutputFormat.MPEG_4,
audioEncoder: Audio.AndroidAudioEncoder.AAC,
sampleRate: Audio.RecordingOptionsPresets.LOW_QUALITY.android.sampleRate,
numberOfChannels: Audio.RecordingOptionsPresets.LOW_QUALITY.android.numberOfChannels,
bitRate: Audio.RecordingOptionsPresets.LOW_QUALITY.android.bitRate
outputFormat: Audio.RECORDING_OPTION_ANDROID_OUTPUT_FORMAT_MPEG_4,
audioEncoder: Audio.RECORDING_OPTION_ANDROID_AUDIO_ENCODER_AAC,
sampleRate: Audio.RECORDING_OPTIONS_PRESET_LOW_QUALITY.android.sampleRate,
numberOfChannels: Audio.RECORDING_OPTIONS_PRESET_LOW_QUALITY.android.numberOfChannels,
bitRate: Audio.RECORDING_OPTIONS_PRESET_LOW_QUALITY.android.bitRate
},
ios: {
extension: RECORDING_EXTENSION,
audioQuality: Audio.IOSAudioQuality.MIN,
sampleRate: Audio.RecordingOptionsPresets.LOW_QUALITY.ios.sampleRate,
numberOfChannels: Audio.RecordingOptionsPresets.LOW_QUALITY.ios.numberOfChannels,
bitRate: Audio.RecordingOptionsPresets.LOW_QUALITY.ios.bitRate,
outputFormat: Audio.IOSOutputFormat.MPEG4AAC
audioQuality: Audio.RECORDING_OPTION_IOS_AUDIO_QUALITY_MIN,
sampleRate: Audio.RECORDING_OPTIONS_PRESET_LOW_QUALITY.ios.sampleRate,
numberOfChannels: Audio.RECORDING_OPTIONS_PRESET_LOW_QUALITY.ios.numberOfChannels,
bitRate: Audio.RECORDING_OPTIONS_PRESET_LOW_QUALITY.ios.bitRate,
outputFormat: Audio.RECORDING_OPTION_IOS_OUTPUT_FORMAT_MPEG4AAC
},
web: {}
};

View File

@ -1,5 +1,5 @@
import React, { Component } from 'react';
import { Alert, NativeModules, Text, View, BackHandler } from 'react-native';
import { Alert, Keyboard, NativeModules, Text, View, BackHandler } from 'react-native';
import { connect } from 'react-redux';
import { KeyboardAccessoryView } from 'react-native-ui-lib/keyboard';
import ImagePicker, { Image, ImageOrVideo, Options } from 'react-native-image-crop-picker';
@ -21,6 +21,8 @@ import { themes, emojis } from '../../lib/constants';
import LeftButtons from './LeftButtons';
import RightButtons from './RightButtons';
import { canUploadFile } from '../../lib/methods/helpers/media';
import EventEmiter from '../../lib/methods/helpers/events';
import { KEY_COMMAND, handleCommandShowUpload, handleCommandSubmit, handleCommandTyping } from '../../commands';
import getMentionRegexp from './getMentionRegexp';
import Mentions from './Mentions';
import MessageboxContext from './Context';
@ -138,6 +140,8 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
private selection: { start: number; end: number };
private focused: boolean;
private imagePickerConfig: Options;
private libraryPickerConfig: Options;
@ -188,6 +192,7 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
};
this.text = '';
this.selection = { start: 0, end: 0 };
this.focused = false;
const libPickerLabels = {
cropperChooseText: I18n.t('Choose'),
@ -263,6 +268,10 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
this.setShowSend(true);
}
if (isTablet) {
EventEmiter.addEventListener(KEY_COMMAND, this.handleCommands);
}
if (usedCannedResponse) {
this.onChangeText(usedCannedResponse);
}
@ -437,6 +446,9 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
if (this.unsubscribeBlur) {
this.unsubscribeBlur();
}
if (isTablet) {
EventEmiter.removeListener(KEY_COMMAND, this.handleCommands);
}
BackHandler.removeEventListener('hardwareBackPress', this.handleBackPress);
}
@ -966,7 +978,7 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
const { showEmojiKeyboard } = this.state;
this.closeEmoji();
setTimeout(() => action && action(params), showEmojiKeyboard && isIOS ? TIMEOUT_CLOSE_EMOJI : undefined);
setTimeout(() => action && action(params), showEmojiKeyboard && isIOS ? TIMEOUT_CLOSE_EMOJI : null);
};
submit = async () => {
@ -1101,6 +1113,21 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
});
};
handleCommands = ({ event }: { event: any }) => {
if (handleCommandTyping(event)) {
if (this.focused) {
Keyboard.dismiss();
} else {
this.component.focus();
}
this.focused = !this.focused;
} else if (handleCommandSubmit(event)) {
this.submit();
} else if (handleCommandShowUpload(event)) {
this.showMessageBoxActions();
}
};
onPressSendToChannel = () => this.setState(({ tshow }) => ({ tshow: !tshow }));
renderSendToChannel = () => {

View File

@ -21,7 +21,6 @@ const ReactionsList = ({ reactions, getCustomEmoji }: IReactionsListProps): Reac
const allTabLabel = { emoji: I18n.t('All'), usernames: [], names: [], _id: 'All' };
return (
<View style={styles.container} testID='reactionsList'>
{/* @ts-ignore */}
<ScrollableTabView renderTabBar={() => <ReactionsTabBar getCustomEmoji={getCustomEmoji} />}>
<AllTab tabLabel={allTabLabel} reactions={sortedReactions} getCustomEmoji={getCustomEmoji} />
{sortedReactions?.map(reaction => (

View File

@ -17,7 +17,7 @@ const SearchBox = ({ onChangeText, onSubmitEditing, testID }: TextInputProps): J
const { colors } = useTheme();
const internalOnChangeText = useCallback((value: string) => {
const internalOnChangeText = useCallback(value => {
setText(value);
onChangeText?.(value);
}, []);

View File

@ -1,8 +1,7 @@
import React, { useEffect } from 'react';
import React from 'react';
import { StatusBar as StatusBarRN } from 'react-native';
import { useTheme } from '../theme';
import { isAndroid } from '../lib/methods/helpers';
const supportedStyles = {
'light-content': 'light-content',
@ -14,23 +13,15 @@ interface IStatusBar {
backgroundColor?: string;
}
const StatusBar = React.memo(({ barStyle, backgroundColor }: IStatusBar) => {
const StatusBar = ({ barStyle, backgroundColor }: IStatusBar) => {
const { theme, colors } = useTheme();
useEffect(() => {
if (!barStyle) {
barStyle = 'light-content';
if (theme === 'light') {
barStyle = 'dark-content';
}
if (!barStyle) {
barStyle = 'light-content';
if (theme === 'light') {
barStyle = 'dark-content';
}
if (isAndroid) {
StatusBarRN.setBackgroundColor(backgroundColor ?? colors.headerBackground);
}
StatusBarRN.setBarStyle(barStyle, true);
}, [theme, barStyle, backgroundColor]);
return <StatusBarRN />;
});
}
return <StatusBarRN backgroundColor={backgroundColor ?? colors.headerBackground} barStyle={barStyle} animated />;
};
export default StatusBar;

View File

@ -46,7 +46,6 @@ const Toast = (): React.ReactElement => {
ref={getToastRef}
// @ts-ignore
position='center'
// @ts-ignore
style={[styles.toast, { backgroundColor: colors.toastBackground }]}
textStyle={[styles.text, { color: colors.buttonText }]}
opacity={0.9}

View File

@ -93,7 +93,6 @@ export const DatePicker = ({ element, language, action, context, loading, value,
mode='date'
display={isAndroid ? 'default' : 'inline'}
value={currentDate}
// @ts-ignore
onChange={onChange}
textColor={themes[theme].titleText}
/>

View File

@ -1,6 +1,6 @@
import React from 'react';
import { Text, View } from 'react-native';
import Touchable, { PlatformTouchableProps } from 'react-native-platform-touchable';
import Touchable from 'react-native-platform-touchable';
import { CustomIcon } from '../../CustomIcon';
import ActivityIndicator from '../../ActivityIndicator';
@ -9,9 +9,9 @@ import { useTheme } from '../../../theme';
interface IInput {
children?: JSX.Element;
onPress: PlatformTouchableProps['onPress'];
onPress: () => void;
inputStyle?: object;
disabled?: PlatformTouchableProps['disabled'];
disabled?: boolean | null;
placeholder?: string;
loading?: boolean;
innerInputStyle?: object;

View File

@ -36,7 +36,7 @@ interface IMultiSelect {
onClose?: () => void;
inputStyle?: TextStyle;
value?: any[];
disabled?: boolean;
disabled?: boolean | null;
innerInputStyle?: object;
}

View File

@ -71,7 +71,6 @@ export const Select = ({ options = [], placeholder, onChange, loading, disabled,
);
return (
// @ts-ignore lib types issues. We need to fork it and maintain or find another lib
<RNPickerSelect
items={items}
placeholder={placeholderObject}
@ -88,6 +87,8 @@ export const Select = ({ options = [], placeholder, onChange, loading, disabled,
}}
Icon={Icon}
textInputProps={{
// style property was Omitted in lib, but can be used normally
// @ts-ignore
style: { ...styles.pickerText, color: selected ? themes[theme].titleText : themes[theme].auxiliaryText }
}}
/>

View File

@ -7,7 +7,7 @@ import { CustomIcon, TIconsName } from '../../../CustomIcon';
import useStyle from './styles';
type VideoConfMessageIconProps = {
variant: 'ended' | 'incoming' | 'outgoing';
variant: 'ended' | 'incoming' | 'outgoing' | 'issue';
children: React.ReactElement | React.ReactElement[];
};
@ -33,6 +33,12 @@ export const VideoConferenceBaseContainer = ({ variant, children }: VideoConfMes
color: colors.conferenceCallOngoingPhoneIcon,
backgroundColor: colors.conferenceCallOngoingPhoneBackground,
label: i18n.t('Call_ongoing')
},
issue: {
icon: 'phone-issue',
color: colors.statusFontOnWarning,
backgroundColor: colors.statusBackgroundWarning,
label: i18n.t('Call_issue')
}
};
@ -45,7 +51,7 @@ export const VideoConferenceBaseContainer = ({ variant, children }: VideoConfMes
backgroundColor: iconStyle[variant].backgroundColor
}}
>
<CustomIcon name={iconStyle[variant].icon} size={variant === 'incoming' ? 16 : 24} color={iconStyle[variant].color} />
<CustomIcon name={iconStyle[variant].icon} size={24} color={iconStyle[variant].color} />
</View>
<Text style={style.infoContainerText}>{iconStyle[variant].label}</Text>
</View>

View File

@ -0,0 +1,18 @@
import React from 'react';
import { Text } from 'react-native';
import i18n from '../../../../i18n';
import useStyle from './styles';
import { VideoConferenceBaseContainer } from './VideoConferenceBaseContainer';
const VideoConferenceIssue = React.memo(() => {
const style = useStyle();
return (
<VideoConferenceBaseContainer variant='issue'>
<Text style={style.callBack}>{i18n.t('Waiting_for_server_connection')}</Text>
</VideoConferenceBaseContainer>
);
});
export default VideoConferenceIssue;

View File

@ -5,9 +5,10 @@ import VideoConferenceDirect from './components/VideoConferenceDirect';
import VideoConferenceEnded from './components/VideoConferenceEnded';
import VideoConferenceOutgoing from './components/VideoConferenceOutgoing';
import VideoConferenceSkeletonLoading from './components/VideoConferenceSkeletonLoading';
import VideoConferenceIssue from './components/VideoConferenceIssue';
export default function VideoConferenceBlock({ callId, blockId }: { callId: string; blockId: string }): React.ReactElement {
const { result } = useEndpointData('video-conference.info', { callId });
const { result, error } = useEndpointData('video-conference.info', { callId });
if (result?.success) {
const { users, type, status, createdBy, rid } = result;
@ -19,5 +20,7 @@ export default function VideoConferenceBlock({ callId, blockId }: { callId: stri
return <VideoConferenceOutgoing blockId={blockId} users={users} />;
}
if (result?.error || error) return <VideoConferenceIssue />;
return <VideoConferenceSkeletonLoading />;
}

View File

@ -2,8 +2,10 @@ import React from 'react';
import { KaTeX as KaTeXProps } from '@rocket.chat/message-parser';
// eslint-disable-next-line import/no-unresolved
import MathView, { MathText } from 'react-native-math-view';
import Katex from 'react-native-katex';
import { useTheme } from '../../../theme';
import { DEFAULT_MESSAGE_HEIGHT } from '../../message/utils';
interface IKaTeXProps {
value: KaTeXProps['value'];
@ -11,7 +13,13 @@ interface IKaTeXProps {
export const KaTeX = ({ value }: IKaTeXProps): React.ReactElement | null => {
const { colors } = useTheme();
return <MathView math={value} style={{ color: colors.bodyText }} />;
return (
<MathView
math={value}
style={{ color: colors.bodyText }}
renderError={() => <Katex expression={value} style={{ flex: 1, height: DEFAULT_MESSAGE_HEIGHT }} />}
/>
);
};
export const InlineKaTeX = ({ value }: IKaTeXProps): React.ReactElement | null => {

View File

@ -8,8 +8,11 @@ export const previewFormatText = (msg: string) => {
let m = formatText(msg);
m = formatHyperlink(m);
m = shortnameToUnicode(m);
// Removes sequential empty spaces before to use removeMarkdown,
// because with some edge cases the library takes a long time to finish the process
m = m.replace(/\s+/g, ' ');
m = removeMarkdown(m);
// Removes sequential empty spaces
// Removes sequential empty spaces to remove leading empty space on quotes at the rooms list view
m = m.replace(/\s+/g, ' ');
m = m.replace(/\n+/g, ' ');
return m;

View File

@ -12,6 +12,7 @@ import { IAttachment, TGetCustomEmoji } from '../../definitions';
import CollapsibleQuote from './Components/CollapsibleQuote';
import openLink from '../../lib/methods/helpers/openLink';
import Markdown from '../markdown';
import { getMessageFromAttachment } from './utils';
export type TElement = {
type: string;
@ -54,11 +55,14 @@ const AttachedActions = ({ attachment, getCustomEmoji }: { attachment: IAttachme
const Attachments: React.FC<IMessageAttachments> = React.memo(
({ attachments, timeFormat, showAttachment, style, getCustomEmoji, isReply, author }: IMessageAttachments) => {
const { translateLanguage } = useContext(MessageContext);
if (!attachments || attachments.length === 0) {
return null;
}
const attachmentsElements = attachments.map((file: IAttachment, index: number) => {
const msg = getMessageFromAttachment(file, translateLanguage);
if (file && file.image_url) {
return (
<Image
@ -69,6 +73,7 @@ const Attachments: React.FC<IMessageAttachments> = React.memo(
style={style}
isReply={isReply}
author={author}
msg={msg}
/>
);
}
@ -82,6 +87,7 @@ const Attachments: React.FC<IMessageAttachments> = React.memo(
isReply={isReply}
style={style}
author={author}
msg={msg}
/>
);
}
@ -95,6 +101,7 @@ const Attachments: React.FC<IMessageAttachments> = React.memo(
getCustomEmoji={getCustomEmoji}
style={style}
isReply={isReply}
msg={msg}
/>
);
}
@ -108,7 +115,9 @@ const Attachments: React.FC<IMessageAttachments> = React.memo(
);
}
return <Reply key={index} index={index} attachment={file} timeFormat={timeFormat} getCustomEmoji={getCustomEmoji} />;
return (
<Reply key={index} index={index} attachment={file} timeFormat={timeFormat} getCustomEmoji={getCustomEmoji} msg={msg} />
);
});
return <>{attachmentsElements}</>;
},

View File

@ -1,7 +1,7 @@
import React, { useContext, useEffect, useRef, useState } from 'react';
import { StyleProp, TextStyle, View } from 'react-native';
import { AVPlaybackStatus } from 'expo-av';
import { activateKeepAwakeAsync, deactivateKeepAwake } from 'expo-keep-awake';
import { activateKeepAwake, deactivateKeepAwake } from 'expo-keep-awake';
import { useSharedValue } from 'react-native-reanimated';
import Markdown from '../../../markdown';
@ -23,9 +23,10 @@ interface IMessageAudioProps {
style?: StyleProp<TextStyle>[];
getCustomEmoji: TGetCustomEmoji;
author?: IUserMessage;
msg?: string;
}
const MessageAudio = ({ file, getCustomEmoji, author, isReply, style }: IMessageAudioProps) => {
const MessageAudio = ({ file, getCustomEmoji, author, isReply, style, msg }: IMessageAudioProps) => {
const [loading, setLoading] = useState(true);
const [paused, setPaused] = useState(true);
const [cached, setCached] = useState(false);
@ -195,7 +196,7 @@ const MessageAudio = ({ file, getCustomEmoji, author, isReply, style }: IMessage
if (paused) {
deactivateKeepAwake();
} else {
activateKeepAwakeAsync();
activateKeepAwake();
}
}, [paused]);
@ -204,13 +205,12 @@ const MessageAudio = ({ file, getCustomEmoji, author, isReply, style }: IMessage
}
return (
<>
<Markdown msg={file.description} style={[isReply && style]} username={user.username} getCustomEmoji={getCustomEmoji} />
<Markdown msg={msg} style={[isReply && style]} username={user.username} getCustomEmoji={getCustomEmoji} />
<View
style={[
styles.audioContainer,
{ backgroundColor: colors.audioComponentBackground, borderColor: colors.audioBorderColor }
]}
>
]}>
<PlayButton disabled={isReply} loading={loading} paused={paused} cached={cached} onPress={onPress} />
<Slider currentTime={currentTime} duration={duration} loaded={!isReply && cached} onChangeTime={setPosition} />
<AudioRate onChange={onChangeRate} loaded={!isReply && cached} rate={rate} />

View File

@ -1,19 +1,18 @@
import React, { useContext, useEffect, useState } from 'react';
import { StyleProp, TextStyle, View } from 'react-native';
import FastImage from 'react-native-fast-image';
import { dequal } from 'dequal';
import Touchable from './Touchable';
import Markdown from '../markdown';
import styles from './styles';
import MessageContext from './Context';
import { TGetCustomEmoji } from '../../definitions/IEmoji';
import { IAttachment, IUserMessage } from '../../definitions';
import { useTheme } from '../../theme';
import { formatAttachmentUrl } from '../../lib/methods/helpers/formatAttachmentUrl';
import { cancelDownload, downloadMediaFile, isDownloadActive, getMediaCache } from '../../lib/methods/handleMediaDownload';
import { TGetCustomEmoji } from '../../definitions/IEmoji';
import { fetchAutoDownloadEnabled } from '../../lib/methods/autoDownloadPreference';
import { cancelDownload, downloadMediaFile, getMediaCache, isDownloadActive } from '../../lib/methods/handleMediaDownload';
import { formatAttachmentUrl } from '../../lib/methods/helpers/formatAttachmentUrl';
import { useTheme } from '../../theme';
import Markdown from '../markdown';
import BlurComponent from './Components/BlurComponent';
import MessageContext from './Context';
import Touchable from './Touchable';
import styles from './styles';
interface IMessageButton {
children: React.ReactElement;
@ -29,6 +28,7 @@ interface IMessageImage {
isReply?: boolean;
getCustomEmoji?: TGetCustomEmoji;
author?: IUserMessage;
msg?: string;
}
const Button = React.memo(({ children, onPress, disabled }: IMessageButton) => {
@ -61,124 +61,124 @@ export const MessageImage = React.memo(({ imgUri, cached, loading }: { imgUri: s
);
});
const ImageContainer = React.memo(
({ file, imageUrl, showAttachment, getCustomEmoji, style, isReply, author }: IMessageImage) => {
const [imageCached, setImageCached] = useState(file);
const [cached, setCached] = useState(false);
const [loading, setLoading] = useState(true);
const { theme } = useTheme();
const { baseUrl, user } = useContext(MessageContext);
const getUrl = (link?: string) => imageUrl || formatAttachmentUrl(link, user.id, user.token, baseUrl);
const img = getUrl(file.image_url);
// The param file.title_link is the one that point to image with best quality, however we still need to test the imageUrl
// And we cannot be certain whether the file.title_link actually exists.
const imgUrlToCache = getUrl(imageCached.title_link || imageCached.image_url);
const ImageContainer = ({
file,
imageUrl,
showAttachment,
getCustomEmoji,
style,
isReply,
author,
msg
}: IMessageImage): React.ReactElement | null => {
const [imageCached, setImageCached] = useState(file);
const [cached, setCached] = useState(false);
const [loading, setLoading] = useState(true);
const { theme } = useTheme();
const { baseUrl, user } = useContext(MessageContext);
const getUrl = (link?: string) => imageUrl || formatAttachmentUrl(link, user.id, user.token, baseUrl);
const img = getUrl(file.image_url);
// The param file.title_link is the one that point to image with best quality, however we still need to test the imageUrl
// And we cannot be certain whether the file.title_link actually exists.
const imgUrlToCache = getUrl(imageCached.title_link || imageCached.image_url);
useEffect(() => {
const handleCache = async () => {
if (img) {
const cachedImageResult = await getMediaCache({
type: 'image',
mimeType: imageCached.image_type,
urlToCache: imgUrlToCache
});
if (cachedImageResult?.exists) {
setImageCached(prev => ({
...prev,
title_link: cachedImageResult?.uri
}));
setLoading(false);
setCached(true);
return;
}
if (isReply) {
setLoading(false);
return;
}
if (isDownloadActive(imgUrlToCache)) {
return;
}
setLoading(false);
await handleAutoDownload();
}
};
handleCache();
}, []);
if (!img) {
return null;
}
const handleAutoDownload = async () => {
const isCurrentUserAuthor = author?._id === user.id;
const isAutoDownloadEnabled = fetchAutoDownloadEnabled('imagesPreferenceDownload');
if (isAutoDownloadEnabled || isCurrentUserAuthor) {
await handleDownload();
}
};
const handleDownload = async () => {
try {
setLoading(true);
const imageUri = await downloadMediaFile({
downloadUrl: imgUrlToCache,
useEffect(() => {
const handleCache = async () => {
if (img) {
const cachedImageResult = await getMediaCache({
type: 'image',
mimeType: imageCached.image_type
mimeType: imageCached.image_type,
urlToCache: imgUrlToCache
});
setImageCached(prev => ({
...prev,
title_link: imageUri
}));
setCached(true);
} catch (e) {
setCached(false);
} finally {
if (cachedImageResult?.exists) {
setImageCached(prev => ({
...prev,
title_link: cachedImageResult?.uri
}));
setLoading(false);
setCached(true);
return;
}
if (isReply) {
setLoading(false);
return;
}
if (isDownloadActive(imgUrlToCache)) {
return;
}
setLoading(false);
await handleAutoDownload();
}
};
handleCache();
}, []);
const onPress = () => {
if (loading && isDownloadActive(imgUrlToCache)) {
cancelDownload(imgUrlToCache);
setLoading(false);
setCached(false);
return;
}
if (!cached && !loading) {
handleDownload();
return;
}
if (!showAttachment) {
return;
}
showAttachment(imageCached);
};
if (!img) {
return null;
}
if (imageCached.description) {
return (
<View>
<Markdown
msg={imageCached.description}
style={[isReply && style]}
username={user.username}
getCustomEmoji={getCustomEmoji}
theme={theme}
/>
<Button disabled={isReply} onPress={onPress}>
<MessageImage imgUri={img} cached={cached} loading={loading} />
</Button>
</View>
);
const handleAutoDownload = async () => {
const isCurrentUserAuthor = author?._id === user.id;
const isAutoDownloadEnabled = fetchAutoDownloadEnabled('imagesPreferenceDownload');
if (isAutoDownloadEnabled || isCurrentUserAuthor) {
await handleDownload();
}
};
const handleDownload = async () => {
try {
setLoading(true);
const imageUri = await downloadMediaFile({
downloadUrl: imgUrlToCache,
type: 'image',
mimeType: imageCached.image_type
});
setImageCached(prev => ({
...prev,
title_link: imageUri
}));
setCached(true);
} catch (e) {
setCached(false);
} finally {
setLoading(false);
}
};
const onPress = () => {
if (loading && isDownloadActive(imgUrlToCache)) {
cancelDownload(imgUrlToCache);
setLoading(false);
setCached(false);
return;
}
if (!cached && !loading) {
handleDownload();
return;
}
if (!showAttachment) {
return;
}
showAttachment(imageCached);
};
if (msg) {
return (
<Button disabled={isReply} onPress={onPress}>
<MessageImage imgUri={img} cached={cached} loading={loading} />
</Button>
<View>
<Markdown msg={msg} style={[isReply && style]} username={user.username} getCustomEmoji={getCustomEmoji} theme={theme} />
<Button disabled={isReply} onPress={onPress}>
<MessageImage imgUri={img} cached={cached} loading={loading} />
</Button>
</View>
);
},
(prevProps, nextProps) => dequal(prevProps.file, nextProps.file)
);
}
return (
<Button disabled={isReply} onPress={onPress}>
<MessageImage imgUri={img} cached={cached} loading={loading} />
</Button>
);
};
ImageContainer.displayName = 'MessageImageContainer';
MessageImage.displayName = 'MessageImage';

View File

@ -91,6 +91,7 @@ interface IMessageReply {
timeFormat?: string;
index: number;
getCustomEmoji: TGetCustomEmoji;
msg?: string;
}
const Title = React.memo(
@ -197,7 +198,7 @@ const Fields = React.memo(
);
const Reply = React.memo(
({ attachment, timeFormat, index, getCustomEmoji }: IMessageReply) => {
({ attachment, timeFormat, index, getCustomEmoji, msg }: IMessageReply) => {
const [loading, setLoading] = useState(false);
const { theme } = useTheme();
const { baseUrl, user, jumpToMessage } = useContext(MessageContext);
@ -238,7 +239,7 @@ const Reply = React.memo(
style={[
styles.button,
index > 0 && styles.marginTop,
attachment.description && styles.marginBottom,
msg && styles.marginBottom,
{
borderColor
}
@ -271,7 +272,7 @@ const Reply = React.memo(
) : null}
</View>
</Touchable>
<Markdown msg={attachment.description} username={user.username} getCustomEmoji={getCustomEmoji} theme={theme} />
<Markdown msg={msg} username={user.username} getCustomEmoji={getCustomEmoji} theme={theme} />
</>
);
},

View File

@ -14,6 +14,7 @@ import EventEmitter from '../../lib/methods/helpers/events';
import I18n from '../../i18n';
import MessageContext from './Context';
import { IUrl } from '../../definitions';
import { DEFAULT_MESSAGE_HEIGHT } from './utils';
const styles = StyleSheet.create({
button: {
@ -45,7 +46,7 @@ const styles = StyleSheet.create({
},
image: {
width: '100%',
height: 150,
height: DEFAULT_MESSAGE_HEIGHT,
borderTopLeftRadius: 4,
borderTopRightRadius: 4
},

View File

@ -1,26 +1,26 @@
import React, { useContext, useEffect, useState } from 'react';
import { StyleProp, StyleSheet, TextStyle, View, Text } from 'react-native';
import { dequal } from 'dequal';
import { StyleProp, StyleSheet, Text, TextStyle, View } from 'react-native';
import FastImage from 'react-native-fast-image';
import messageStyles from './styles';
import Touchable from './Touchable';
import Markdown from '../markdown';
import { isIOS } from '../../lib/methods/helpers';
import { themes } from '../../lib/constants';
import MessageContext from './Context';
import { fileDownload } from './helpers/fileDownload';
import EventEmitter from '../../lib/methods/helpers/events';
import { LISTENER } from '../Toast';
import I18n from '../../i18n';
import { IAttachment } from '../../definitions/IAttachment';
import { TGetCustomEmoji } from '../../definitions/IEmoji';
import { useTheme } from '../../theme';
import { formatAttachmentUrl } from '../../lib/methods/helpers/formatAttachmentUrl';
import { cancelDownload, downloadMediaFile, isDownloadActive, getMediaCache } from '../../lib/methods/handleMediaDownload';
import I18n from '../../i18n';
import { themes } from '../../lib/constants';
import { fetchAutoDownloadEnabled } from '../../lib/methods/autoDownloadPreference';
import { cancelDownload, downloadMediaFile, getMediaCache, isDownloadActive } from '../../lib/methods/handleMediaDownload';
import { isIOS } from '../../lib/methods/helpers';
import EventEmitter from '../../lib/methods/helpers/events';
import { formatAttachmentUrl } from '../../lib/methods/helpers/formatAttachmentUrl';
import { useTheme } from '../../theme';
import sharedStyles from '../../views/Styles';
import { LISTENER } from '../Toast';
import Markdown from '../markdown';
import BlurComponent from './Components/BlurComponent';
import MessageContext from './Context';
import Touchable from './Touchable';
import { fileDownload } from './helpers/fileDownload';
import messageStyles from './styles';
import { DEFAULT_MESSAGE_HEIGHT } from './utils';
const SUPPORTED_TYPES = ['video/quicktime', 'video/mp4', ...(isIOS ? [] : ['video/3gp', 'video/mkv'])];
const isTypeSupported = (type: string) => SUPPORTED_TYPES.indexOf(type) !== -1;
@ -29,7 +29,7 @@ const styles = StyleSheet.create({
button: {
flex: 1,
borderRadius: 4,
height: 150,
height: DEFAULT_MESSAGE_HEIGHT,
marginBottom: 6,
alignItems: 'center',
justifyContent: 'center'
@ -56,6 +56,7 @@ interface IMessageVideo {
getCustomEmoji: TGetCustomEmoji;
style?: StyleProp<TextStyle>[];
isReply?: boolean;
msg?: string;
}
const CancelIndicator = () => {
@ -81,139 +82,130 @@ const Thumbnail = ({ loading, thumbnailUrl, cached }: { loading: boolean; thumbn
</>
);
const Video = React.memo(
({ file, showAttachment, getCustomEmoji, style, isReply }: IMessageVideo) => {
const [videoCached, setVideoCached] = useState(file);
const [loading, setLoading] = useState(true);
const [cached, setCached] = useState(false);
const { baseUrl, user } = useContext(MessageContext);
const { theme } = useTheme();
const video = formatAttachmentUrl(file.video_url, user.id, user.token, baseUrl);
const Video = ({ file, showAttachment, getCustomEmoji, style, isReply, msg }: IMessageVideo): React.ReactElement | null => {
const [videoCached, setVideoCached] = useState(file);
const [loading, setLoading] = useState(true);
const [cached, setCached] = useState(false);
const { baseUrl, user } = useContext(MessageContext);
const { theme } = useTheme();
const video = formatAttachmentUrl(file.video_url, user.id, user.token, baseUrl);
useEffect(() => {
const handleVideoSearchAndDownload = async () => {
if (video) {
const cachedVideoResult = await getMediaCache({
type: 'video',
mimeType: file.video_type,
urlToCache: video
});
const downloadActive = isDownloadActive(video);
if (cachedVideoResult?.exists) {
setVideoCached(prev => ({
...prev,
video_url: cachedVideoResult?.uri
}));
setLoading(false);
setCached(true);
if (downloadActive) {
cancelDownload(video);
}
return;
}
if (isReply) {
setLoading(false);
return;
}
await handleAutoDownload();
}
};
handleVideoSearchAndDownload();
}, []);
if (!baseUrl) {
return null;
}
const handleAutoDownload = async () => {
const isAutoDownloadEnabled = fetchAutoDownloadEnabled('videoPreferenceDownload');
if (isAutoDownloadEnabled && file.video_type && isTypeSupported(file.video_type)) {
await handleDownload();
return;
}
setLoading(false);
};
const handleDownload = async () => {
setLoading(true);
try {
const videoUri = await downloadMediaFile({
downloadUrl: video,
useEffect(() => {
const handleVideoSearchAndDownload = async () => {
if (video) {
const cachedVideoResult = await getMediaCache({
type: 'video',
mimeType: file.video_type
mimeType: file.video_type,
urlToCache: video
});
setVideoCached(prev => ({
...prev,
video_url: videoUri
}));
setCached(true);
} catch {
setCached(false);
} finally {
setLoading(false);
const downloadActive = isDownloadActive(video);
if (cachedVideoResult?.exists) {
setVideoCached(prev => ({
...prev,
video_url: cachedVideoResult?.uri
}));
setLoading(false);
setCached(true);
if (downloadActive) {
cancelDownload(video);
}
return;
}
if (isReply) {
setLoading(false);
return;
}
await handleAutoDownload();
}
};
handleVideoSearchAndDownload();
}, []);
const onPress = async () => {
if (file.video_type && cached && isTypeSupported(file.video_type) && showAttachment) {
showAttachment(videoCached);
return;
}
if (!loading && !cached && file.video_type && isTypeSupported(file.video_type)) {
handleDownload();
return;
}
if (loading && !cached) {
handleCancelDownload();
return;
}
if (!isIOS && file.video_url) {
await downloadVideoToGallery(video);
return;
}
EventEmitter.emit(LISTENER, { message: I18n.t('Unsupported_format') });
};
if (!baseUrl) {
return null;
}
const handleCancelDownload = () => {
if (loading) {
cancelDownload(video);
setLoading(false);
}
};
const handleAutoDownload = async () => {
const isAutoDownloadEnabled = fetchAutoDownloadEnabled('videoPreferenceDownload');
if (isAutoDownloadEnabled && file.video_type && isTypeSupported(file.video_type)) {
await handleDownload();
return;
}
setLoading(false);
};
const downloadVideoToGallery = async (uri: string) => {
setLoading(true);
const fileDownloaded = await fileDownload(uri, file);
const handleDownload = async () => {
setLoading(true);
try {
const videoUri = await downloadMediaFile({
downloadUrl: video,
type: 'video',
mimeType: file.video_type
});
setVideoCached(prev => ({
...prev,
video_url: videoUri
}));
setCached(true);
} catch {
setCached(false);
} finally {
setLoading(false);
}
};
if (fileDownloaded) {
EventEmitter.emit(LISTENER, { message: I18n.t('saved_to_gallery') });
return;
}
EventEmitter.emit(LISTENER, { message: I18n.t('error-save-video') });
};
const onPress = async () => {
if (file.video_type && cached && isTypeSupported(file.video_type) && showAttachment) {
showAttachment(videoCached);
return;
}
if (!loading && !cached && file.video_type && isTypeSupported(file.video_type)) {
handleDownload();
return;
}
if (loading && !cached) {
handleCancelDownload();
return;
}
if (!isIOS && file.video_url) {
await downloadVideoToGallery(video);
return;
}
EventEmitter.emit(LISTENER, { message: I18n.t('Unsupported_format') });
};
return (
<>
<Markdown
msg={file.description}
username={user.username}
getCustomEmoji={getCustomEmoji}
style={[isReply && style]}
theme={theme}
/>
<Touchable
disabled={isReply}
onPress={onPress}
style={[styles.button, messageStyles.mustWrapBlur, { backgroundColor: themes[theme].videoBackground }]}
background={Touchable.Ripple(themes[theme].bannerBackground)}
>
<Thumbnail loading={loading} cached={cached} />
</Touchable>
</>
);
},
(prevProps, nextProps) => dequal(prevProps.file, nextProps.file)
);
const handleCancelDownload = () => {
if (loading) {
cancelDownload(video);
setLoading(false);
}
};
const downloadVideoToGallery = async (uri: string) => {
setLoading(true);
const fileDownloaded = await fileDownload(uri, file);
setLoading(false);
if (fileDownloaded) {
EventEmitter.emit(LISTENER, { message: I18n.t('saved_to_gallery') });
return;
}
EventEmitter.emit(LISTENER, { message: I18n.t('error-save-video') });
};
return (
<>
<Markdown msg={msg} username={user.username} getCustomEmoji={getCustomEmoji} style={[isReply && style]} theme={theme} />
<Touchable
disabled={isReply}
onPress={onPress}
style={[styles.button, messageStyles.mustWrapBlur, { backgroundColor: themes[theme].videoBackground }]}
background={Touchable.Ripple(themes[theme].bannerBackground)}
>
<Thumbnail loading={loading} cached={cached} />
</Touchable>
</>
);
};
export default Video;

View File

@ -95,7 +95,8 @@ class MessageContainer extends React.Component<IMessageContainerProps, IMessageC
shouldComponentUpdate(nextProps: IMessageContainerProps, nextState: IMessageContainerState) {
const { isManualUnignored } = this.state;
const { threadBadgeColor, isIgnored, highlighted, previousItem } = this.props;
const { threadBadgeColor, isIgnored, highlighted, previousItem, autoTranslateRoom, autoTranslateLanguage } = this.props;
if (nextProps.highlighted !== highlighted) {
return true;
}
@ -111,6 +112,12 @@ class MessageContainer extends React.Component<IMessageContainerProps, IMessageC
if (nextProps.previousItem?._id !== previousItem?._id) {
return true;
}
if (nextProps.autoTranslateRoom !== autoTranslateRoom) {
return true;
}
if (nextProps.autoTranslateRoom !== autoTranslateRoom || nextProps.autoTranslateLanguage !== autoTranslateLanguage) {
return true;
}
return false;
}
@ -382,14 +389,17 @@ class MessageContainer extends React.Component<IMessageContainerProps, IMessageC
let message = msg;
let isTranslated = false;
const otherUserMessage = u.username !== user.username;
// "autoTranslateRoom" and "autoTranslateLanguage" are properties from the subscription
// "autoTranslateMessage" is a toggle between "View Original" and "Translate" state
if (autoTranslateRoom && autoTranslateMessage && autoTranslateLanguage) {
if (autoTranslateRoom && autoTranslateMessage && autoTranslateLanguage && otherUserMessage) {
const messageTranslated = getMessageTranslation(item, autoTranslateLanguage);
isTranslated = !!messageTranslated;
message = messageTranslated || message;
}
const canTranslateMessage = autoTranslateRoom && autoTranslateLanguage && autoTranslateMessage !== false && otherUserMessage;
return (
<MessageContext.Provider
value={{
@ -409,7 +419,8 @@ class MessageContainer extends React.Component<IMessageContainerProps, IMessageC
jumpToMessage,
threadBadgeColor,
toggleFollowThread,
replies
replies,
translateLanguage: canTranslateMessage ? autoTranslateLanguage : undefined
}}
>
{/* @ts-ignore*/}

View File

@ -1,8 +1,11 @@
/* eslint-disable complexity */
import { IAttachment } from '../../definitions';
import { MessageTypesValues, TMessageModel } from '../../definitions/IMessage';
import I18n from '../../i18n';
import { DISCUSSION } from './constants';
export const DEFAULT_MESSAGE_HEIGHT = 150;
export const formatMessageCount = (count?: number, type?: string): string | null => {
const discussion = type === DISCUSSION;
let text = discussion ? I18n.t('No_messages_yet') : null;
@ -194,3 +197,14 @@ export const getMessageTranslation = (message: TMessageModel, autoTranslateLangu
}
return null;
};
export const getMessageFromAttachment = (attachment: IAttachment, translateLanguage?: string): string | undefined => {
let msg = attachment.description;
if (translateLanguage) {
const translatedMessage = attachment.translations?.[translateLanguage];
if (translatedMessage) {
msg = translatedMessage;
}
}
return msg;
};

View File

@ -1,4 +1,5 @@
import { IUser } from './IUser';
import { IAttachmentTranslations } from './IMessage';
export interface IAttachment {
ts?: string | Date;
@ -29,6 +30,7 @@ export interface IAttachment {
thumb_url?: string;
collapsed?: boolean;
audio_type?: string;
translations?: IAttachmentTranslations;
}
export interface IServerAttachment {

View File

@ -0,0 +1,6 @@
export interface ICommand {
event: {
input: string;
modifierFlags: number;
};
}

View File

@ -41,7 +41,7 @@ export interface IEditedBy {
export type TOnLinkPress = (link: string) => void;
export interface ITranslations {
export interface IMessageTranslations {
_id: string;
language: string;
value: string;
@ -136,7 +136,7 @@ export interface IMessage extends IMessageFromServer {
replies?: string[];
unread?: boolean;
autoTranslate?: boolean;
translations?: ITranslations[];
translations?: IMessageTranslations[];
tmsg?: string;
blocks?: any;
e2e?: E2EType;
@ -243,3 +243,7 @@ export type MessageTypesValues =
| 'message_pinned'
| 'message_snippeted'
| 'jitsi_call_started';
export interface IAttachmentTranslations {
[k: string]: string;
}

View File

@ -40,6 +40,6 @@ export interface IBaseScreen<T extends Record<string, object | undefined>, S ext
dispatch: Dispatch;
isMasterDetail: boolean;
// TODO: remove after migrating all Class components
theme?: TSupportedThemes;
theme: TSupportedThemes;
colors: TColors;
}

View File

@ -1,5 +1,12 @@
import { NavigatorScreenParams } from '@react-navigation/core';
import { StackNavigationOptions } from '@react-navigation/stack';
import { TSubscriptionModel } from './ISubscription';
import { TServerModel } from './IServer';
import { IAttachment } from './IAttachment';
import { MasterDetailInsideStackParamList } from '../stacks/MasterDetailStack/types';
import { OutsideParamList, InsideStackParamList } from '../stacks/types';
interface INavigationProps {
route?: any;
navigation?: any;
@ -9,3 +16,41 @@ interface INavigationProps {
export type TNavigationOptions = {
navigationOptions?(props: INavigationProps): StackNavigationOptions;
};
export type SetUsernameStackParamList = {
SetUsernameView: {
title: string;
};
};
export type StackParamList = {
AuthLoading: undefined;
OutsideStack: NavigatorScreenParams<OutsideParamList>;
InsideStack: NavigatorScreenParams<InsideStackParamList>;
MasterDetailStack: NavigatorScreenParams<MasterDetailInsideStackParamList>;
SetUsernameStack: NavigatorScreenParams<SetUsernameStackParamList>;
};
export type ShareInsideStackParamList = {
ShareListView: undefined;
ShareView: {
attachments: IAttachment[];
isShareView?: boolean;
isShareExtension: boolean;
serverInfo: TServerModel;
text: string;
room: TSubscriptionModel;
thread?: any; // TODO: Change
};
SelectServerView: undefined;
};
export type ShareOutsideStackParamList = {
WithoutServersView: undefined;
};
export type ShareAppStackParamList = {
AuthLoading?: undefined;
OutsideStack?: NavigatorScreenParams<ShareOutsideStackParamList>;
InsideStack?: NavigatorScreenParams<ShareInsideStackParamList>;
};

View File

@ -36,6 +36,8 @@ import { IInquiry } from '../../ee/omnichannel/reducers/inquiry';
import { IPermissionsState } from '../../reducers/permissions';
import { IEnterpriseModules } from '../../reducers/enterpriseModules';
import { IVideoConf } from '../../reducers/videoConf';
import { TActionUsersRoles } from '../../actions/usersRoles';
import { TUsersRoles } from '../../reducers/usersRoles';
export interface IApplicationState {
settings: TSettingsState;
@ -60,6 +62,7 @@ export interface IApplicationState {
permissions: IPermissionsState;
roles: IRoles;
videoConf: IVideoConf;
usersRoles: TUsersRoles;
}
export type TApplicationActions = TActionActiveUsers &
@ -79,4 +82,5 @@ export type TApplicationActions = TActionActiveUsers &
TActionInquiry &
TActionPermissions &
TActionEnterpriseModules &
TActionVideoConf;
TActionVideoConf &
TActionUsersRoles;

View File

@ -6,6 +6,7 @@ declare module 'react-native-image-progress';
declare module 'react-native-ui-lib/keyboard';
declare module '@rocket.chat/sdk';
declare module 'react-native-config-reader';
declare module 'react-native-keycommands';
declare module 'react-native-mime-types';
declare module 'react-native-restart';
declare module 'rn-root-view';

View File

@ -689,12 +689,14 @@
"Also_send_thread_message_to_channel_behavior": "Also send thread message to channel",
"Accounts_Default_User_Preferences_alsoSendThreadToChannel_Description": "Allow users to select the 'Also send to channel' behavior",
"Waiting_for_answer": "Waiting for answer",
"Waiting_for_server_connection": "Waiting for server connection",
"Call_ended": "Call ended",
"Call_was_not_answered": "Call was not answered",
"Call_rejected": "Call rejected",
"Call_back": "Call Back",
"Call_again": "Call Again",
"Call_ongoing": "Call Ongoing",
"Call_issue": "Call issue",
"Joined": "Joined",
"Calling": "Calling",
"Start_a_call": "Start a call",

View File

@ -689,11 +689,13 @@
"Also_send_thread_message_to_channel_behavior": "Também enviar mensagem do tópico para o canal",
"Accounts_Default_User_Preferences_alsoSendThreadToChannel_Description": "Permitir que os usuários selecionem o comportamento Também enviar para o canal",
"Waiting_for_answer": "Esperando por resposta",
"Waiting_for_server_connection": "Aguardando conexão com o servidor",
"Call_ended": "Chamada finalizada",
"Call_was_not_answered": "A chamada não foi atendida",
"Call_back": "Ligue de volta",
"Call_again": "Ligue novamente",
"Call_ongoing": "Chamada em andamento",
"Call_issue": "Chamada com problemas",
"Joined": "Ingressou",
"Calling": "Chamando",
"Start_a_call": "Inicie uma chamada",

View File

@ -1,5 +1,6 @@
import React from 'react';
import { Dimensions, Linking, EmitterSubscription } from 'react-native';
import { Dimensions, Linking } from 'react-native';
import { KeyCommandsEmitter } from 'react-native-keycommands';
import { initialWindowMetrics, SafeAreaProvider } from 'react-native-safe-area-context';
import RNScreens from 'react-native-screens';
import { Provider } from 'react-redux';
@ -8,11 +9,13 @@ import { GestureHandlerRootView } from 'react-native-gesture-handler';
import { appInit, appInitLocalSettings, setMasterDetail as setMasterDetailAction } from './actions/app';
import { deepLinkingOpen } from './actions/deepLinking';
import AppContainer from './AppContainer';
import { KEY_COMMAND } from './commands';
import { ActionSheetProvider } from './containers/ActionSheet';
import InAppNotification from './containers/InAppNotification';
import Toast from './containers/Toast';
import TwoFactor from './containers/TwoFactor';
import Loading from './containers/Loading';
import { ICommand } from './definitions/ICommand';
import { IThemePreference } from './definitions/ITheme';
import { DimensionsContext } from './dimensions';
import { colors, isFDroidBuild, MIN_WIDTH_MASTER_DETAIL_LAYOUT, themes } from './lib/constants';
@ -23,6 +26,7 @@ import store from './lib/store';
import { initStore } from './lib/store/auxStore';
import { ThemeContext, TSupportedThemes } from './theme';
import { debounce, isTablet } from './lib/methods/helpers';
import EventEmitter from './lib/methods/helpers/events';
import { toggleAnalyticsEventsReport, toggleCrashErrorsReport } from './lib/methods/helpers/log';
import {
getTheme,
@ -79,7 +83,8 @@ const parseDeepLinking = (url: string) => {
export default class Root extends React.Component<{}, IState> {
private listenerTimeout!: any;
private dimensionsListener?: EmitterSubscription;
private onKeyCommands: any;
constructor(props: any) {
super(props);
@ -101,7 +106,6 @@ export default class Root extends React.Component<{}, IState> {
this.initTablet();
}
setNativeTheme(theme);
subscribeTheme(theme, this.state.theme, this.setTheme);
}
componentDidMount() {
@ -113,16 +117,18 @@ export default class Root extends React.Component<{}, IState> {
}
});
}, 5000);
this.dimensionsListener = Dimensions.addEventListener('change', this.onDimensionsChange);
Dimensions.addEventListener('change', this.onDimensionsChange);
}
componentWillUnmount() {
clearTimeout(this.listenerTimeout);
if (this.dimensionsListener) {
this.dimensionsListener.remove();
}
Dimensions.removeEventListener('change', this.onDimensionsChange);
unsubscribeTheme();
if (this.onKeyCommands && this.onKeyCommands.remove) {
this.onKeyCommands.remove();
}
}
init = async () => {
@ -175,9 +181,9 @@ export default class Root extends React.Component<{}, IState> {
this.setState(
prevState => newThemeState(prevState, newTheme as IThemePreference),
() => {
const { themePreferences, theme } = this.state;
const { themePreferences } = this.state;
// subscribe to Appearance changes
subscribeTheme(themePreferences, theme, this.setTheme);
subscribeTheme(themePreferences, this.setTheme);
}
);
};
@ -189,6 +195,9 @@ export default class Root extends React.Component<{}, IState> {
initTablet = () => {
const { width } = this.state;
this.setMasterDetail(width);
this.onKeyCommands = KeyCommandsEmitter.addListener('onKeyCommand', (command: ICommand) => {
EventEmitter.emit(KEY_COMMAND, { event: command });
});
};
initCrashReport = () => {

View File

@ -99,6 +99,8 @@ export const colors = {
gray300: '#5f656e',
gray100: '#CBCED1',
n900: '#1F2329',
statusBackgroundWarning: '#FFECAD',
statusFontOnWarning: '#B88D00',
overlayColor: '#1F2329B2',
audioPlayerPrimary: '#156FF5',
audioPlayerSecondary: '#CBCED1',
@ -183,6 +185,8 @@ export const colors = {
gray300: '#5f656e',
gray100: '#CBCED1',
n900: '#FFFFFF',
statusBackgroundWarning: '#FFECAD',
statusFontOnWarning: '#B88D00',
overlayColor: '#1F2329B2',
audioPlayerPrimary: '#3976D1',
audioPlayerSecondary: '#404754',
@ -267,6 +271,8 @@ export const colors = {
gray300: '#5f656e',
gray100: '#CBCED1',
n900: '#FFFFFF',
statusBackgroundWarning: '#FFECAD',
statusFontOnWarning: '#B88D00',
overlayColor: '#1F2329B2',
audioPlayerPrimary: '#3976D1',
audioPlayerSecondary: '#404754',

Some files were not shown because too many files have changed in this diff Show More