[RELEASE] Merge beta into master (#1082)
* Bump version to 1.16.0 (#1014) * [IMPROVEMENT] Share credentials with Rocket.Chat.iOS (#982) * ✨ Create user table * ✨ Introduce user table * 🔥 Remove unused table * ➕ Add userdefaults to storage data * 💚 Fix android build * ✨ Get credentials from iOS native client * 🔥 Remove unused code * ⏪ Revert sign xcode * 🐛 Fix first login-logout * 🎨 Use constants to UserDefaults Keys * 🐛 Fix clear server-user-info on logout * 🐛 Fix filter null value * 🚑 Remove user object in logout * ✨ Fix get servers from native-client * 🚑 Fix error on change server * [FIX] Don't run UserDefaults credentials on Android (#1015) * 🐛 Fix native credentials (android) * Fix migration loop * [IMPROVEMENT] Hide frequently used emoji tab when empty (#792) * [IMPROVEMENT] Bigger emoji in emoji only messages (#793) * issue #725: bigger emoji in emoji only message * issue-725/add storybook for Message/Emoji * issue-725: update storybook/Message jest snapshot * comment storybook import * allow spaces and line breaks in emoji only message * merge develop * revert unnecessary spacing * [FIX] Empty message if contains only a link (#787) * Fix empty message if contains only a link * 🐛 Fix empty space * [IMPROVEMENT] Refactor empty space regex on quote (#1017) * 🎨 Improve regex to empty space on quote * 🎨 Improve on regex to empty space on quote * [NEW] Custom fields on signup (#1013) * added custom feilds on registration * added flag as leftIcon and removed lable * added try and catch * typo * [CHORE] Renew provisioning profiles (#1020) * [NEW] Auto-translate (#1012) * Update realm * View original and translate working * Read AutoTranslate_Enabled setting * RocketChat.canAutoTranslate() * AutoTranslateView * Save language * Auto-translate switch * Translate message * [IMPROVEMENT] Use haptics rather than vibration (#1016) * Install expo-haptics * Use expo-haptics rather than RN's Vibration module * [IMPROVEMENT] Use Rest API for file upload (#1005) * removed rn-fetch-blob and use native XMLHttpRequest instead * removed unnessary changes * fix android bug * fix android bug * added tmid support * fix bug * fixed isssue with cacel model * fix problems with audio * done requested changes * fix bug with android * [CHORE] [CI] [TESTS] update detox to make ci pass (#1026) * feat: update detox to 12.11.3 to make CI pass * ci: comment all jobs but leave e2e-test job * commit to rerun IC e2e-test job * ci: uncomment all CI jobs * [NEW] Room swipe actions: mark as read/unread, hide, fav (#976) * added unread and fav feature * changed the layout * fix jest * done requested changes * added requested changes * [FIX] Android build (#1027) * [FIX] Android build * CircleCI error * [FIX] iOS share credentials build (#1028) * [FIX] iOS share credentials build * Use `hasMigration` as a string * [CI] Restore cache on CI (#1029) * feat: add fastlane save\restore cache config; comment not needed jobs; * install fastlane using 'bundle install' * install fastlane using 'sudo bundle install' * uncomment ios build commands * run set up google services in ios folder * add working_directory: ios to ios-build steps * remove 'cd ios' from Fastlane build step * add save\restore cache for npm modules * group save_cache steps * cache fastlane in ios-testflight job * uncomment previously commented jobs\steps * fix: add missing colon * use key for caching: node-modules-{{ checksum ".circleci/config.yml" }}-{{ checksum "yarn.lock" }} * add names for save\restore steps * ci: add `default` step with `working_directory: ~/repo` to ios-build job * return back caching npm: `node-v1-{{ checksum "package.json" }}-{{ arch }}` * fix: add missing curly braces * save\restore cache in e2e-test job; remove {{arch}} from cache names * add names to restore_cache steps in android-build job * add names to save_cache steps in android-build job * add names to all save\restore steps; change checksum package.json to yarn.lock * change `npm` to `NPM` in steps naming * remove {{ checksum circle ci }} from android-build job and fix naming of steps * [FIX] Rooms swipes (#1034) * Regression: on press style feedback * Action button styles * Fix animations * Styles changed * Update subscription without having to wait for socket * Calculate width on RoomsListView instead * [FIX] Decrease bigger emoji size to 30 (#1031) * [FIX] Append server URL on avatar if necessary (#1038) * Comment removeClippedSubviews * Comment width animation * Remove redux from RoomItem * Fix wrong re-render comparison * Remove listener * Raise minDeltaX * memo actions * Spring with native driver * Refactor functions * Fix props issues * Remove RoomItem.height * Long swipe * Refactor animations * this.rowTranslation -> this.transX * Moved state to this * Bump version to 1.16.1 (#1045) * [FIX] Set UserDefaults AppGroup on notification tap (#1047) * [FIX] Auto-translate messages as they arrive * Fix favorite button * [FIX] Swipe animations (#1044) * Comment removeClippedSubviews * Comment width animation * Remove redux from RoomItem * Fix wrong re-render comparison * Remove listener * Raise minDeltaX * memo actions * Spring with native driver * Refactor functions * Fix props issues * Remove RoomItem.height * Long swipe * Refactor animations * this.rowTranslation -> this.transX * Moved state to this * Fix favorite button * [FIX] Auto-translate messages as they arrive (#1049) * Comment removeClippedSubviews * Comment width animation * Remove redux from RoomItem * Fix wrong re-render comparison * Remove listener * Raise minDeltaX * memo actions * Spring with native driver * Refactor functions * Fix props issues * Remove RoomItem.height * Long swipe * Refactor animations * this.rowTranslation -> this.transX * Moved state to this * [FIX] Auto-translate messages as they arrive * [i18n] Add missing de translations (#1040) * [CHORE] Switch to react-native-localize (#1043) * Bump version to 1.17.0 (#1057) * Load views as needed (#1056) * [IMPROVEMENT] Change "resend" icon position (#1048) * [NEW] Video support (#801) * [NEW] File upload (#882) * [NEW] Share extension (#942) * [FIX] Share extension CI build (#1060) * Change bundleID * Provisioning * get provisioning profile * [IMPROVEMENT] Reusable toast (#1065) * [FIX] Moment locales (#1066) * [FIX] Share Extension issues (#1064) * [FIX] Empty white list enables all media types upload (#1077) * Merge branch 'master' into develop (#1079) * [FIX] Empty white list enables all media types upload (#1080) * Create utils to media (canUpload) * Fix variable name * [CHORE] Update README (#1081)
This commit is contained in:
parent
8ea6f1647e
commit
2d58a8b983
54
README.md
54
README.md
|
@ -1,13 +1,11 @@
|
||||||
# Rocket.Chat React Native Mobile
|
# Rocket.Chat React Native Mobile
|
||||||
|
|
||||||
[![Greenkeeper badge](https://badges.greenkeeper.io/RocketChat/Rocket.Chat.ReactNative.svg)](https://greenkeeper.io/)
|
|
||||||
[![Build Status](https://img.shields.io/travis/RocketChat/Rocket.Chat.ReactNative/master.svg)](https://travis-ci.org/RocketChat/Rocket.Chat.ReactNative)
|
|
||||||
[![Project Dependencies](https://david-dm.org/RocketChat/Rocket.Chat.ReactNative.svg)](https://david-dm.org/RocketChat/Rocket.Chat.ReactNative)
|
[![Project Dependencies](https://david-dm.org/RocketChat/Rocket.Chat.ReactNative.svg)](https://david-dm.org/RocketChat/Rocket.Chat.ReactNative)
|
||||||
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/bb15e2392a71473ea59d3f634f35c54e)](https://www.codacy.com/app/RocketChat/Rocket.Chat.ReactNative?utm_source=github.com&utm_medium=referral&utm_content=RocketChat/Rocket.Chat.ReactNative&utm_campaign=badger)
|
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/bb15e2392a71473ea59d3f634f35c54e)](https://www.codacy.com/app/RocketChat/Rocket.Chat.ReactNative?utm_source=github.com&utm_medium=referral&utm_content=RocketChat/Rocket.Chat.ReactNative&utm_campaign=badger)
|
||||||
[![codecov](https://codecov.io/gh/RocketChat/Rocket.Chat.ReactNative/branch/master/graph/badge.svg)](https://codecov.io/gh/RocketChat/Rocket.Chat.ReactNative)
|
[![codecov](https://codecov.io/gh/RocketChat/Rocket.Chat.ReactNative/branch/master/graph/badge.svg)](https://codecov.io/gh/RocketChat/Rocket.Chat.ReactNative)
|
||||||
[![CodeFactor](https://www.codefactor.io/repository/github/rocketchat/rocket.chat.reactnative/badge)](https://www.codefactor.io/repository/github/rocketchat/rocket.chat.reactnative)
|
[![CodeFactor](https://www.codefactor.io/repository/github/rocketchat/rocket.chat.reactnative/badge)](https://www.codefactor.io/repository/github/rocketchat/rocket.chat.reactnative)
|
||||||
|
|
||||||
**Supported Server Versions:** 0.66.0+
|
**Supported Server Versions:** 0.70.0+
|
||||||
|
|
||||||
## Download
|
## Download
|
||||||
<a href="https://play.google.com/store/apps/details?id=chat.rocket.reactnative">
|
<a href="https://play.google.com/store/apps/details?id=chat.rocket.reactnative">
|
||||||
|
@ -59,55 +57,53 @@ If you don't need multiple servers, there is a branch `single-server` just for t
|
||||||
Readme will guide you on how to config.
|
Readme will guide you on how to config.
|
||||||
|
|
||||||
## Current priorities
|
## Current priorities
|
||||||
1) [NEW] Jitsi integration ([#711][i711])
|
1) Jitsi integration
|
||||||
2) [NEW] Federation ([#706][i706])
|
2) Notification Preferences
|
||||||
3) [NEW] Record video ([#712][i712])
|
3) Two-way authentication
|
||||||
4) [NEW] Slash Commands ([#405][i405])
|
4) Authentication via SAML
|
||||||
5) [NEW] Share extension ([#391][i391])
|
5) Authentication via Custom OAuth
|
||||||
|
6) Authentication via CAS
|
||||||
[i711]: https://github.com/RocketChat/Rocket.Chat.ReactNative/issues/711
|
7) Bugsnag
|
||||||
[i706]: https://github.com/RocketChat/Rocket.Chat.ReactNative/issues/706
|
8) Optional Analytics
|
||||||
[i707]: https://github.com/RocketChat/Rocket.Chat.ReactNative/issues/707
|
9) Typescript
|
||||||
[i712]: https://github.com/RocketChat/Rocket.Chat.ReactNative/issues/712
|
10) Prettier
|
||||||
[i708]: https://github.com/RocketChat/Rocket.Chat.ReactNative/issues/708
|
|
||||||
[i391]: https://github.com/RocketChat/Rocket.Chat.ReactNative/issues/391
|
|
||||||
[i405]: https://github.com/RocketChat/Rocket.Chat.ReactNative/issues/405
|
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
| Feature | Status |
|
| Feature | Status |
|
||||||
|--------------------------------------------------------------- |-------- |
|
|--------------------------------------------------------------- |-------- |
|
||||||
| Jitsi Integration | ❌ |
|
| Jitsi Integration | ❌ |
|
||||||
| Federation (Directory) | ❌ |
|
| Federation (Directory) | ✅ |
|
||||||
| Threads | ✅ |
|
| Discussions | ❌ |
|
||||||
|
| Threads | ✅ |
|
||||||
| Record Audio | ✅ |
|
| Record Audio | ✅ |
|
||||||
| Record Video | ❌ |
|
| Record Video | ✅ |
|
||||||
| Commands | ❌ |
|
| Commands | ✅ |
|
||||||
| Draft message per room | ✅ |
|
| Draft message per room | ✅ |
|
||||||
| Share Extension | ❌ |
|
| Share Extension | ✅ |
|
||||||
| Notifications Preferences | ✅ |
|
| Notifications Preferences | ✅ |
|
||||||
| Edited status | ✅ |
|
| Edited status | ✅ |
|
||||||
| Upload video | ❌ |
|
| Upload video | ✅ |
|
||||||
| Grouped messages | ✅ |
|
| Grouped messages | ✅ |
|
||||||
| Mark room as read | ❌ |
|
| Mark room as read | ✅ |
|
||||||
| Mark room as unread | ❌ |
|
| Mark room as unread | ✅ |
|
||||||
| Tablet Support | ❌ |
|
| Tablet Support | ❌ |
|
||||||
| Read receipt | ❌ |
|
| Read receipt | ✅ |
|
||||||
| Broadbast Channel | ✅ |
|
| Broadbast Channel | ✅ |
|
||||||
| Authentication via SAML | ❌ |
|
| Authentication via SAML | ❌ |
|
||||||
| Authentication via CAS | ❌ |
|
| Authentication via CAS | ❌ |
|
||||||
| Custom Fields on Signup | ❌ |
|
| Custom Fields on Signup | ✅ |
|
||||||
| Report message | ❌ |
|
| Report message | ✅ |
|
||||||
| Theming | ❌ |
|
| Theming | ❌ |
|
||||||
| Settings -> Review the App | ❌ |
|
| Settings -> Review the App | ❌ |
|
||||||
| Settings -> Default Browser | ❌ |
|
| Settings -> Default Browser | ❌ |
|
||||||
| Admin panel | ✅ |
|
| Admin panel | ✅ |
|
||||||
| Reply message from notification | ❌ |
|
| Reply message from notification | ❌ |
|
||||||
| Unread counter banner on message list | ✅ |
|
| Unread counter banner on message list | ✅ |
|
||||||
| E2E | ❌ |
|
| E2E Encryption | ❌ |
|
||||||
| Join a Protected Room | ❌ |
|
| Join a Protected Room | ❌ |
|
||||||
| Optional Analytics | ❌ |
|
| Optional Analytics | ❌ |
|
||||||
| Settings -> About us | ❌ |
|
| Settings -> About us | ❌ |
|
||||||
| Settings -> Contact us | ❌ |
|
| Settings -> Contact us | ✅ |
|
||||||
| Settings -> Update App Icon | ❌ |
|
| Settings -> Update App Icon | ❌ |
|
||||||
| Settings -> Share | ❌ |
|
| Settings -> Share | ❌ |
|
||||||
| Accessibility (Medium) | ❌ |
|
| Accessibility (Medium) | ❌ |
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
export const initialConstants = null;
|
||||||
|
export const findBestAvailableLanguage = () => null;
|
|
@ -0,0 +1,3 @@
|
||||||
|
export default {
|
||||||
|
realmPath: ''
|
||||||
|
};
|
File diff suppressed because it is too large
Load Diff
|
@ -110,7 +110,7 @@ android {
|
||||||
minSdkVersion rootProject.ext.minSdkVersion
|
minSdkVersion rootProject.ext.minSdkVersion
|
||||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||||
versionCode VERSIONCODE as Integer
|
versionCode VERSIONCODE as Integer
|
||||||
versionName "1.16.1"
|
versionName "1.17.0"
|
||||||
vectorDrawables.useSupportLibrary = true
|
vectorDrawables.useSupportLibrary = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,6 +174,9 @@ android {
|
||||||
dependencies {
|
dependencies {
|
||||||
addUnimodulesDependencies()
|
addUnimodulesDependencies()
|
||||||
implementation "org.webkit:android-jsc:r241213"
|
implementation "org.webkit:android-jsc:r241213"
|
||||||
|
implementation project(':rn-extensions-share')
|
||||||
|
implementation project(':rn-fetch-blob')
|
||||||
|
implementation project(':react-native-document-picker')
|
||||||
implementation project(':react-native-firebase')
|
implementation project(':react-native-firebase')
|
||||||
implementation project(':react-native-webview')
|
implementation project(':react-native-webview')
|
||||||
implementation project(':react-native-orientation-locker')
|
implementation project(':react-native-orientation-locker')
|
||||||
|
@ -185,7 +188,7 @@ dependencies {
|
||||||
})
|
})
|
||||||
implementation project(':react-native-gesture-handler')
|
implementation project(':react-native-gesture-handler')
|
||||||
implementation project(':react-native-image-crop-picker')
|
implementation project(':react-native-image-crop-picker')
|
||||||
implementation project(':react-native-i18n')
|
implementation project(':react-native-localize')
|
||||||
implementation project(':react-native-audio')
|
implementation project(':react-native-audio')
|
||||||
implementation project(":reactnativekeyboardinput")
|
implementation project(":reactnativekeyboardinput")
|
||||||
implementation project(':react-native-video')
|
implementation project(':react-native-video')
|
||||||
|
|
|
@ -5,8 +5,10 @@
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
<uses-permission android:name="android.permission.CAMERA" />
|
<uses-permission android:name="android.permission.CAMERA" />
|
||||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||||
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||||
<uses-permission android:name="android.permission.RECORD_AUDIO" />
|
<uses-permission android:name="android.permission.RECORD_AUDIO" />
|
||||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||||
|
<uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" />
|
||||||
<uses-permission-sdk-23 android:name="android.permission.VIBRATE"/>
|
<uses-permission-sdk-23 android:name="android.permission.VIBRATE"/>
|
||||||
|
|
||||||
<application
|
<application
|
||||||
|
@ -25,6 +27,7 @@
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
|
<action android:name="android.intent.action.DOWNLOAD_COMPLETE"/>
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
<intent-filter android:label="@string/app_name">
|
<intent-filter android:label="@string/app_name">
|
||||||
<action android:name="android.intent.action.VIEW" />
|
<action android:name="android.intent.action.VIEW" />
|
||||||
|
@ -36,6 +39,19 @@
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
|
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
|
||||||
|
<activity
|
||||||
|
android:noHistory="true"
|
||||||
|
android:name=".share.ShareActivity"
|
||||||
|
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
|
||||||
|
android:label="@string/share_extension_name"
|
||||||
|
android:screenOrientation="portrait"
|
||||||
|
android:theme="@style/AppTheme" >
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.SEND" />
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
<data android:mimeType="*/*" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|
|
@ -3,6 +3,7 @@ package chat.rocket.reactnative;
|
||||||
import android.app.Application;
|
import android.app.Application;
|
||||||
|
|
||||||
import com.facebook.react.ReactApplication;
|
import com.facebook.react.ReactApplication;
|
||||||
|
import io.github.elyx0.reactnativedocumentpicker.DocumentPickerPackage;
|
||||||
import io.invertase.firebase.RNFirebasePackage;
|
import io.invertase.firebase.RNFirebasePackage;
|
||||||
import io.invertase.firebase.fabric.crashlytics.RNFirebaseCrashlyticsPackage;
|
import io.invertase.firebase.fabric.crashlytics.RNFirebaseCrashlyticsPackage;
|
||||||
import io.invertase.firebase.analytics.RNFirebaseAnalyticsPackage;
|
import io.invertase.firebase.analytics.RNFirebaseAnalyticsPackage;
|
||||||
|
@ -15,7 +16,7 @@ import com.facebook.react.ReactPackage;
|
||||||
import com.facebook.react.shell.MainReactPackage;
|
import com.facebook.react.shell.MainReactPackage;
|
||||||
import com.facebook.soloader.SoLoader;
|
import com.facebook.soloader.SoLoader;
|
||||||
|
|
||||||
import com.AlexanderZaytsev.RNI18n.RNI18nPackage;
|
import com.reactcommunity.rnlocalize.RNLocalizePackage;
|
||||||
import com.reactnative.ivpusic.imagepicker.PickerPackage;
|
import com.reactnative.ivpusic.imagepicker.PickerPackage;
|
||||||
import com.brentvatne.react.ReactVideoPackage;
|
import com.brentvatne.react.ReactVideoPackage;
|
||||||
import com.dylanvann.fastimage.FastImageViewPackage;
|
import com.dylanvann.fastimage.FastImageViewPackage;
|
||||||
|
@ -33,6 +34,8 @@ import com.learnium.RNDeviceInfo.RNDeviceInfo;
|
||||||
import com.actionsheet.ActionSheetPackage;
|
import com.actionsheet.ActionSheetPackage;
|
||||||
import io.realm.react.RealmReactPackage;
|
import io.realm.react.RealmReactPackage;
|
||||||
import com.swmansion.rnscreens.RNScreensPackage;
|
import com.swmansion.rnscreens.RNScreensPackage;
|
||||||
|
import chat.rocket.SharePackage;
|
||||||
|
import com.RNFetchBlob.RNFetchBlobPackage;
|
||||||
|
|
||||||
import chat.rocket.reactnative.generated.BasePackageList;
|
import chat.rocket.reactnative.generated.BasePackageList;
|
||||||
|
|
||||||
|
@ -60,6 +63,7 @@ public class MainApplication extends Application implements ReactApplication, IN
|
||||||
protected List<ReactPackage> getPackages() {
|
protected List<ReactPackage> getPackages() {
|
||||||
return Arrays.<ReactPackage>asList(
|
return Arrays.<ReactPackage>asList(
|
||||||
new MainReactPackage(),
|
new MainReactPackage(),
|
||||||
|
new DocumentPickerPackage(),
|
||||||
new RNFirebasePackage(),
|
new RNFirebasePackage(),
|
||||||
new RNFirebaseCrashlyticsPackage(),
|
new RNFirebaseCrashlyticsPackage(),
|
||||||
new RNFirebaseAnalyticsPackage(),
|
new RNFirebaseAnalyticsPackage(),
|
||||||
|
@ -67,6 +71,8 @@ public class MainApplication extends Application implements ReactApplication, IN
|
||||||
new RNCWebViewPackage(),
|
new RNCWebViewPackage(),
|
||||||
new OrientationPackage(),
|
new OrientationPackage(),
|
||||||
new SplashScreenReactPackage(),
|
new SplashScreenReactPackage(),
|
||||||
|
new SharePackage(),
|
||||||
|
new RNFetchBlobPackage(),
|
||||||
new RNGestureHandlerPackage(),
|
new RNGestureHandlerPackage(),
|
||||||
new RNScreensPackage(),
|
new RNScreensPackage(),
|
||||||
new ActionSheetPackage(),
|
new ActionSheetPackage(),
|
||||||
|
@ -78,7 +84,7 @@ public class MainApplication extends Application implements ReactApplication, IN
|
||||||
new ReactNativeAudioPackage(),
|
new ReactNativeAudioPackage(),
|
||||||
new KeyboardInputPackage(MainApplication.this),
|
new KeyboardInputPackage(MainApplication.this),
|
||||||
new FastImageViewPackage(),
|
new FastImageViewPackage(),
|
||||||
new RNI18nPackage(),
|
new RNLocalizePackage(),
|
||||||
new RNNotificationsPackage(MainApplication.this),
|
new RNNotificationsPackage(MainApplication.this),
|
||||||
new ModuleRegistryAdapter(mModuleRegistryProvider)
|
new ModuleRegistryAdapter(mModuleRegistryProvider)
|
||||||
);
|
);
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
package chat.rocket.reactnative.share;
|
||||||
|
|
||||||
|
import com.facebook.react.ReactActivity;
|
||||||
|
import com.facebook.react.ReactActivityDelegate;
|
||||||
|
import com.facebook.react.ReactRootView;
|
||||||
|
import com.swmansion.gesturehandler.react.RNGestureHandlerEnabledRootView;
|
||||||
|
|
||||||
|
public class ShareActivity extends ReactActivity {
|
||||||
|
@Override
|
||||||
|
protected String getMainComponentName() {
|
||||||
|
return "ShareRocketChatRN";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ReactActivityDelegate createReactActivityDelegate() {
|
||||||
|
return new ReactActivityDelegate(this, getMainComponentName()) {
|
||||||
|
@Override
|
||||||
|
protected ReactRootView createRootView() {
|
||||||
|
return new RNGestureHandlerEnabledRootView(ShareActivity.this);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
package chat.rocket.reactnative.share;
|
||||||
|
|
||||||
|
import chat.rocket.reactnative.BuildConfig;
|
||||||
|
|
||||||
|
import chat.rocket.SharePackage;
|
||||||
|
|
||||||
|
import android.app.Application;
|
||||||
|
|
||||||
|
import com.facebook.react.shell.MainReactPackage;
|
||||||
|
import com.facebook.react.ReactNativeHost;
|
||||||
|
import com.facebook.react.ReactApplication;
|
||||||
|
import com.facebook.react.ReactPackage;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
|
public class ShareApplication extends Application implements ReactApplication {
|
||||||
|
private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
|
||||||
|
@Override
|
||||||
|
public boolean getUseDeveloperSupport() {
|
||||||
|
return BuildConfig.DEBUG;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<ReactPackage> getPackages() {
|
||||||
|
return Arrays.<ReactPackage>asList(
|
||||||
|
new MainReactPackage(),
|
||||||
|
new SharePackage()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ReactNativeHost getReactNativeHost() {
|
||||||
|
return mReactNativeHost;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
<resources>
|
<resources>
|
||||||
<string name="app_name">Rocket.Chat Experimental</string>
|
<string name="app_name">Rocket.Chat Experimental</string>
|
||||||
|
<string name="share_extension_name">Rocket.Chat Experimental</string>
|
||||||
<string name="no_browser_found">No Browser Found</string>
|
<string name="no_browser_found">No Browser Found</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -2,4 +2,19 @@
|
||||||
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
|
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
|
||||||
<item name="android:colorEdgeEffect">#aaaaaa</item>
|
<item name="android:colorEdgeEffect">#aaaaaa</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<style name="Share.Window" parent="android:Theme">
|
||||||
|
<item name="android:windowEnterAnimation">@null</item>
|
||||||
|
<item name="android:windowExitAnimation">@null</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="Theme.Share.Transparent" parent="android:Theme">
|
||||||
|
<item name="android:windowIsTranslucent">true</item>
|
||||||
|
<item name="android:windowBackground">@color/primary_dark</item>
|
||||||
|
<item name="android:windowContentOverlay">@null</item>
|
||||||
|
<item name="android:windowNoTitle">true</item>
|
||||||
|
<item name="android:windowIsFloating">true</item>
|
||||||
|
<item name="android:backgroundDimEnabled">true</item>
|
||||||
|
<item name="android:windowAnimationStyle">@style/Share.Window</item>
|
||||||
|
</style>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -2,6 +2,8 @@ apply from: '../node_modules/react-native-unimodules/gradle.groovy'
|
||||||
includeUnimodulesProjects()
|
includeUnimodulesProjects()
|
||||||
|
|
||||||
rootProject.name = 'RocketChatRN'
|
rootProject.name = 'RocketChatRN'
|
||||||
|
include ':react-native-document-picker'
|
||||||
|
project(':react-native-document-picker').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-document-picker/android')
|
||||||
include ':react-native-firebase'
|
include ':react-native-firebase'
|
||||||
project(':react-native-firebase').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-firebase/android')
|
project(':react-native-firebase').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-firebase/android')
|
||||||
include ':react-native-webview'
|
include ':react-native-webview'
|
||||||
|
@ -20,8 +22,8 @@ include ':react-native-gesture-handler'
|
||||||
project(':react-native-gesture-handler').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-gesture-handler/android')
|
project(':react-native-gesture-handler').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-gesture-handler/android')
|
||||||
include ':react-native-image-crop-picker'
|
include ':react-native-image-crop-picker'
|
||||||
project(':react-native-image-crop-picker').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-image-crop-picker/android')
|
project(':react-native-image-crop-picker').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-image-crop-picker/android')
|
||||||
include ':react-native-i18n'
|
include ':react-native-localize'
|
||||||
project(':react-native-i18n').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-i18n/android')
|
project(':react-native-localize').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-localize/android')
|
||||||
include ':react-native-fast-image'
|
include ':react-native-fast-image'
|
||||||
project(':react-native-fast-image').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-fast-image/android')
|
project(':react-native-fast-image').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-fast-image/android')
|
||||||
include ':react-native-audio'
|
include ':react-native-audio'
|
||||||
|
@ -36,4 +38,8 @@ include ':realm'
|
||||||
project(':realm').projectDir = new File(rootProject.projectDir, '../node_modules/realm/android')
|
project(':realm').projectDir = new File(rootProject.projectDir, '../node_modules/realm/android')
|
||||||
include ':reactnativenotifications'
|
include ':reactnativenotifications'
|
||||||
project(':reactnativenotifications').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-notifications/android')
|
project(':reactnativenotifications').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-notifications/android')
|
||||||
include ':app'
|
include ':rn-fetch-blob'
|
||||||
|
project(':rn-fetch-blob').projectDir = new File(rootProject.projectDir, '../node_modules/rn-fetch-blob/android')
|
||||||
|
include ':app', ':rn-extensions-share'
|
||||||
|
project(':rn-extensions-share').projectDir = new File(rootProject.projectDir, '../node_modules/rn-extensions-share/android')
|
||||||
|
|
||||||
|
|
1
app.json
1
app.json
|
@ -1,4 +1,5 @@
|
||||||
{
|
{
|
||||||
"name": "RocketChatRN",
|
"name": "RocketChatRN",
|
||||||
|
"share": "ShareRocketChatRN",
|
||||||
"displayName": "RocketChatRN"
|
"displayName": "RocketChatRN"
|
||||||
}
|
}
|
|
@ -14,6 +14,11 @@ export const LOGIN = createRequestTypes('LOGIN', [
|
||||||
'SET_SERVICES',
|
'SET_SERVICES',
|
||||||
'SET_PREFERENCE'
|
'SET_PREFERENCE'
|
||||||
]);
|
]);
|
||||||
|
export const SHARE = createRequestTypes('SHARE', [
|
||||||
|
'SELECT_SERVER',
|
||||||
|
'SET_USER',
|
||||||
|
'SET_SERVER_INFO'
|
||||||
|
]);
|
||||||
export const USER = createRequestTypes('USER', ['SET']);
|
export const USER = createRequestTypes('USER', ['SET']);
|
||||||
export const ROOMS = createRequestTypes('ROOMS', [
|
export const ROOMS = createRequestTypes('ROOMS', [
|
||||||
...defaultTypes,
|
...defaultTypes,
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
import { SHARE } from './actionsTypes';
|
||||||
|
|
||||||
|
export function shareSelectServer(server) {
|
||||||
|
return {
|
||||||
|
type: SHARE.SELECT_SERVER,
|
||||||
|
server
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function shareSetUser(user) {
|
||||||
|
return {
|
||||||
|
type: SHARE.SET_USER,
|
||||||
|
user
|
||||||
|
};
|
||||||
|
}
|
|
@ -68,6 +68,12 @@ export default {
|
||||||
Threads_enabled: {
|
Threads_enabled: {
|
||||||
type: null
|
type: null
|
||||||
},
|
},
|
||||||
|
FileUpload_MediaTypeWhiteList: {
|
||||||
|
type: 'valueAsString'
|
||||||
|
},
|
||||||
|
FileUpload_MaxFileSize: {
|
||||||
|
type: 'valueAsNumber'
|
||||||
|
},
|
||||||
API_Gitlab_URL: {
|
API_Gitlab_URL: {
|
||||||
type: 'valueAsString'
|
type: 'valueAsString'
|
||||||
},
|
},
|
||||||
|
|
|
@ -5,6 +5,7 @@ import HeaderButtons, { HeaderButton, Item } from 'react-navigation-header-butto
|
||||||
import { CustomIcon } from '../lib/Icons';
|
import { CustomIcon } from '../lib/Icons';
|
||||||
import { isIOS } from '../utils/deviceInfo';
|
import { isIOS } from '../utils/deviceInfo';
|
||||||
import { COLOR_PRIMARY, COLOR_WHITE } from '../constants/colors';
|
import { COLOR_PRIMARY, COLOR_WHITE } from '../constants/colors';
|
||||||
|
import I18n from '../i18n';
|
||||||
|
|
||||||
const color = isIOS ? COLOR_PRIMARY : COLOR_WHITE;
|
const color = isIOS ? COLOR_PRIMARY : COLOR_WHITE;
|
||||||
export const headerIconSize = 23;
|
export const headerIconSize = 23;
|
||||||
|
@ -32,6 +33,15 @@ export const CloseModalButton = React.memo(({ navigation, testID }) => (
|
||||||
</CustomHeaderButtons>
|
</CustomHeaderButtons>
|
||||||
));
|
));
|
||||||
|
|
||||||
|
export const CloseShareExtensionButton = React.memo(({ onPress, testID }) => (
|
||||||
|
<CustomHeaderButtons left>
|
||||||
|
{isIOS
|
||||||
|
? <Item title={I18n.t('Cancel')} onPress={onPress} testID={testID} />
|
||||||
|
: <Item title='close' iconName='cross' onPress={onPress} testID={testID} />
|
||||||
|
}
|
||||||
|
</CustomHeaderButtons>
|
||||||
|
));
|
||||||
|
|
||||||
export const MoreButton = React.memo(({ onPress, testID }) => (
|
export const MoreButton = React.memo(({ onPress, testID }) => (
|
||||||
<CustomHeaderButtons>
|
<CustomHeaderButtons>
|
||||||
<Item title='more' iconName='menu' onPress={onPress} testID={testID} />
|
<Item title='more' iconName='menu' onPress={onPress} testID={testID} />
|
||||||
|
@ -50,6 +60,10 @@ CloseModalButton.propTypes = {
|
||||||
navigation: PropTypes.object.isRequired,
|
navigation: PropTypes.object.isRequired,
|
||||||
testID: PropTypes.string.isRequired
|
testID: PropTypes.string.isRequired
|
||||||
};
|
};
|
||||||
|
CloseShareExtensionButton.propTypes = {
|
||||||
|
onPress: PropTypes.func.isRequired,
|
||||||
|
testID: PropTypes.string.isRequired
|
||||||
|
};
|
||||||
MoreButton.propTypes = {
|
MoreButton.propTypes = {
|
||||||
onPress: PropTypes.func.isRequired,
|
onPress: PropTypes.func.isRequired,
|
||||||
testID: PropTypes.string.isRequired
|
testID: PropTypes.string.isRequired
|
||||||
|
|
|
@ -21,6 +21,8 @@ import I18n from '../i18n';
|
||||||
import log from '../utils/log';
|
import log from '../utils/log';
|
||||||
import Navigation from '../lib/Navigation';
|
import Navigation from '../lib/Navigation';
|
||||||
import { getMessageTranslation } from './message/utils';
|
import { getMessageTranslation } from './message/utils';
|
||||||
|
import { LISTENER } from './Toast';
|
||||||
|
import EventEmitter from '../utils/events';
|
||||||
|
|
||||||
@connect(
|
@connect(
|
||||||
state => ({
|
state => ({
|
||||||
|
@ -48,7 +50,6 @@ export default class MessageActions extends React.Component {
|
||||||
actionsHide: PropTypes.func.isRequired,
|
actionsHide: PropTypes.func.isRequired,
|
||||||
room: PropTypes.object.isRequired,
|
room: PropTypes.object.isRequired,
|
||||||
actionMessage: PropTypes.object,
|
actionMessage: PropTypes.object,
|
||||||
toast: PropTypes.element,
|
|
||||||
user: PropTypes.object,
|
user: PropTypes.object,
|
||||||
deleteRequest: PropTypes.func.isRequired,
|
deleteRequest: PropTypes.func.isRequired,
|
||||||
editInit: PropTypes.func.isRequired,
|
editInit: PropTypes.func.isRequired,
|
||||||
|
@ -275,9 +276,9 @@ export default class MessageActions extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
handleCopy = async() => {
|
handleCopy = async() => {
|
||||||
const { actionMessage, toast } = this.props;
|
const { actionMessage } = this.props;
|
||||||
await Clipboard.setString(actionMessage.msg);
|
await Clipboard.setString(actionMessage.msg);
|
||||||
toast.show(I18n.t('Copied_to_clipboard'));
|
EventEmitter.emit(LISTENER, { message: I18n.t('Copied_to_clipboard') });
|
||||||
}
|
}
|
||||||
|
|
||||||
handleShare = async() => {
|
handleShare = async() => {
|
||||||
|
@ -294,10 +295,10 @@ export default class MessageActions extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
handlePermalink = async() => {
|
handlePermalink = async() => {
|
||||||
const { actionMessage, toast } = this.props;
|
const { actionMessage } = this.props;
|
||||||
const permalink = await this.getPermalink(actionMessage);
|
const permalink = await this.getPermalink(actionMessage);
|
||||||
Clipboard.setString(permalink);
|
Clipboard.setString(permalink);
|
||||||
toast.show(I18n.t('Permalink_copied_to_clipboard'));
|
EventEmitter.emit(LISTENER, { message: I18n.t('Permalink_copied_to_clipboard') });
|
||||||
}
|
}
|
||||||
|
|
||||||
handlePin = () => {
|
handlePin = () => {
|
||||||
|
|
|
@ -2,6 +2,7 @@ import React, { Component } from 'react';
|
||||||
import {
|
import {
|
||||||
View, Text, StyleSheet, Image, ScrollView, TouchableHighlight
|
View, Text, StyleSheet, Image, ScrollView, TouchableHighlight
|
||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import Modal from 'react-native-modal';
|
import Modal from 'react-native-modal';
|
||||||
import { responsive } from 'react-native-responsive-ui';
|
import { responsive } from 'react-native-responsive-ui';
|
||||||
|
@ -12,7 +13,11 @@ import Button from '../Button';
|
||||||
import I18n from '../../i18n';
|
import I18n from '../../i18n';
|
||||||
import sharedStyles from '../../views/Styles';
|
import sharedStyles from '../../views/Styles';
|
||||||
import { isIOS } from '../../utils/deviceInfo';
|
import { isIOS } from '../../utils/deviceInfo';
|
||||||
import { COLOR_PRIMARY, COLOR_BACKGROUND_CONTAINER, COLOR_WHITE } from '../../constants/colors';
|
import { canUploadFile } from '../../utils/media';
|
||||||
|
import {
|
||||||
|
COLOR_PRIMARY, COLOR_BACKGROUND_CONTAINER, COLOR_WHITE, COLOR_DANGER
|
||||||
|
} from '../../constants/colors';
|
||||||
|
import { CustomIcon } from '../../lib/Icons';
|
||||||
|
|
||||||
const cancelButtonColor = COLOR_BACKGROUND_CONTAINER;
|
const cancelButtonColor = COLOR_BACKGROUND_CONTAINER;
|
||||||
|
|
||||||
|
@ -63,18 +68,56 @@ const styles = StyleSheet.create({
|
||||||
androidButtonText: {
|
androidButtonText: {
|
||||||
fontSize: 18,
|
fontSize: 18,
|
||||||
textAlign: 'center'
|
textAlign: 'center'
|
||||||
|
},
|
||||||
|
fileIcon: {
|
||||||
|
color: COLOR_PRIMARY,
|
||||||
|
margin: 20,
|
||||||
|
flex: 1,
|
||||||
|
textAlign: 'center'
|
||||||
|
},
|
||||||
|
errorIcon: {
|
||||||
|
color: COLOR_DANGER
|
||||||
|
},
|
||||||
|
fileMime: {
|
||||||
|
...sharedStyles.textColorTitle,
|
||||||
|
...sharedStyles.textBold,
|
||||||
|
textAlign: 'center',
|
||||||
|
fontSize: 20,
|
||||||
|
marginBottom: 20
|
||||||
|
},
|
||||||
|
errorContainer: {
|
||||||
|
margin: 20,
|
||||||
|
flex: 1,
|
||||||
|
textAlign: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center'
|
||||||
|
},
|
||||||
|
video: {
|
||||||
|
flex: 1,
|
||||||
|
borderRadius: 4,
|
||||||
|
height: 150,
|
||||||
|
backgroundColor: '#1f2329',
|
||||||
|
marginBottom: 6,
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center'
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
@responsive
|
@responsive
|
||||||
|
@connect(state => ({
|
||||||
|
FileUpload_MediaTypeWhiteList: state.settings.FileUpload_MediaTypeWhiteList,
|
||||||
|
FileUpload_MaxFileSize: state.settings.FileUpload_MaxFileSize
|
||||||
|
}))
|
||||||
export default class UploadModal extends Component {
|
export default class UploadModal extends Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
isVisible: PropTypes.bool,
|
isVisible: PropTypes.bool,
|
||||||
file: PropTypes.object,
|
file: PropTypes.object,
|
||||||
close: PropTypes.func,
|
close: PropTypes.func,
|
||||||
submit: PropTypes.func,
|
submit: PropTypes.func,
|
||||||
window: PropTypes.object
|
window: PropTypes.object,
|
||||||
|
FileUpload_MediaTypeWhiteList: PropTypes.string,
|
||||||
|
FileUpload_MaxFileSize: PropTypes.number
|
||||||
}
|
}
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
|
@ -116,12 +159,79 @@ export default class UploadModal extends Component {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
canUploadFile = () => {
|
||||||
|
const { FileUpload_MediaTypeWhiteList, FileUpload_MaxFileSize, file } = this.props;
|
||||||
|
if (!(file && file.path)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (file.size > FileUpload_MaxFileSize) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// if white list is empty, all media types are enabled
|
||||||
|
if (!FileUpload_MediaTypeWhiteList) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
const allowedMime = FileUpload_MediaTypeWhiteList.split(',');
|
||||||
|
if (allowedMime.includes(file.mime)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
const wildCardGlob = '/*';
|
||||||
|
const wildCards = allowedMime.filter(item => item.indexOf(wildCardGlob) > 0);
|
||||||
|
if (wildCards.includes(file.mime.replace(/(\/.*)$/, wildCardGlob))) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
submit = () => {
|
submit = () => {
|
||||||
const { file, submit } = this.props;
|
const { file, submit } = this.props;
|
||||||
const { name, description } = this.state;
|
const { name, description } = this.state;
|
||||||
submit({ ...file, name, description });
|
submit({ ...file, name, description });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderError = () => {
|
||||||
|
const { file, FileUpload_MaxFileSize, close } = this.props;
|
||||||
|
const { window: { width } } = this.props;
|
||||||
|
const errorMessage = (FileUpload_MaxFileSize < file.size)
|
||||||
|
? 'error-file-too-large'
|
||||||
|
: 'error-invalid-file-type';
|
||||||
|
return (
|
||||||
|
<View style={[styles.container, { width: width - 32 }]}>
|
||||||
|
<View style={styles.titleContainer}>
|
||||||
|
<Text style={styles.title}>{I18n.t(errorMessage)}</Text>
|
||||||
|
</View>
|
||||||
|
<View style={styles.errorContainer}>
|
||||||
|
<CustomIcon name='circle-cross' size={120} style={styles.errorIcon} />
|
||||||
|
</View>
|
||||||
|
<Text style={styles.fileMime}>{ file.mime }</Text>
|
||||||
|
<View style={styles.buttonContainer}>
|
||||||
|
{
|
||||||
|
(isIOS)
|
||||||
|
? (
|
||||||
|
<Button
|
||||||
|
title={I18n.t('Cancel')}
|
||||||
|
type='secondary'
|
||||||
|
backgroundColor={cancelButtonColor}
|
||||||
|
style={styles.button}
|
||||||
|
onPress={close}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
: (
|
||||||
|
<TouchableHighlight
|
||||||
|
onPress={close}
|
||||||
|
style={[styles.androidButton, { backgroundColor: cancelButtonColor }]}
|
||||||
|
underlayColor={cancelButtonColor}
|
||||||
|
activeOpacity={0.5}
|
||||||
|
>
|
||||||
|
<Text style={[styles.androidButtonText, { ...sharedStyles.textBold, color: COLOR_PRIMARY }]}>{I18n.t('Cancel')}</Text>
|
||||||
|
</TouchableHighlight>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
renderButtons = () => {
|
renderButtons = () => {
|
||||||
const { close } = this.props;
|
const { close } = this.props;
|
||||||
if (isIOS) {
|
if (isIOS) {
|
||||||
|
@ -166,9 +276,27 @@ export default class UploadModal extends Component {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderPreview() {
|
||||||
|
const { file } = this.props;
|
||||||
|
if (file.mime && file.mime.match(/image/)) {
|
||||||
|
return (<Image source={{ isStatic: true, uri: file.path }} style={styles.image} />);
|
||||||
|
}
|
||||||
|
if (file.mime && file.mime.match(/video/)) {
|
||||||
|
return (
|
||||||
|
<View style={styles.video}>
|
||||||
|
<CustomIcon name='play' size={72} color={COLOR_WHITE} />
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return (<CustomIcon name='file-generic' size={72} style={styles.fileIcon} />);
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { window: { width }, isVisible, close } = this.props;
|
const {
|
||||||
const { name, description, file } = this.state;
|
window: { width }, isVisible, close, file, FileUpload_MediaTypeWhiteList, FileUpload_MaxFileSize
|
||||||
|
} = this.props;
|
||||||
|
const { name, description } = this.state;
|
||||||
|
const showError = !canUploadFile(file, { FileUpload_MediaTypeWhiteList, FileUpload_MaxFileSize });
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
isVisible={isVisible}
|
isVisible={isVisible}
|
||||||
|
@ -181,26 +309,29 @@ export default class UploadModal extends Component {
|
||||||
hideModalContentWhileAnimating
|
hideModalContentWhileAnimating
|
||||||
avoidKeyboard
|
avoidKeyboard
|
||||||
>
|
>
|
||||||
<View style={[styles.container, { width: width - 32 }]}>
|
{(showError) ? this.renderError()
|
||||||
<View style={styles.titleContainer}>
|
: (
|
||||||
<Text style={styles.title}>{I18n.t('Upload_file_question_mark')}</Text>
|
<View style={[styles.container, { width: width - 32 }]}>
|
||||||
</View>
|
<View style={styles.titleContainer}>
|
||||||
|
<Text style={styles.title}>{I18n.t('Upload_file_question_mark')}</Text>
|
||||||
|
</View>
|
||||||
|
|
||||||
<ScrollView style={styles.scrollView}>
|
<ScrollView style={styles.scrollView}>
|
||||||
<Image source={{ isStatic: true, uri: file.path }} style={styles.image} />
|
{this.renderPreview()}
|
||||||
<TextInput
|
<TextInput
|
||||||
placeholder={I18n.t('File_name')}
|
placeholder={I18n.t('File_name')}
|
||||||
value={name}
|
value={name}
|
||||||
onChangeText={value => this.setState({ name: value })}
|
onChangeText={value => this.setState({ name: value })}
|
||||||
/>
|
/>
|
||||||
<TextInput
|
<TextInput
|
||||||
placeholder={I18n.t('File_description')}
|
placeholder={I18n.t('File_description')}
|
||||||
value={description}
|
value={description}
|
||||||
onChangeText={value => this.setState({ description: value })}
|
onChangeText={value => this.setState({ description: value })}
|
||||||
/>
|
/>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
{this.renderButtons()}
|
{this.renderButtons()}
|
||||||
</View>
|
</View>
|
||||||
|
)}
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ import { emojify } from 'react-emojione';
|
||||||
import { KeyboardAccessoryView } from 'react-native-keyboard-input';
|
import { KeyboardAccessoryView } from 'react-native-keyboard-input';
|
||||||
import ImagePicker from 'react-native-image-crop-picker';
|
import ImagePicker from 'react-native-image-crop-picker';
|
||||||
import equal from 'deep-equal';
|
import equal from 'deep-equal';
|
||||||
|
import DocumentPicker from 'react-native-document-picker';
|
||||||
import ActionSheet from 'react-native-action-sheet';
|
import ActionSheet from 'react-native-action-sheet';
|
||||||
|
|
||||||
import { userTyping as userTypingAction } from '../../actions/room';
|
import { userTyping as userTypingAction } from '../../actions/room';
|
||||||
|
@ -46,21 +47,22 @@ const onlyUnique = function onlyUnique(value, index, self) {
|
||||||
const imagePickerConfig = {
|
const imagePickerConfig = {
|
||||||
cropping: true,
|
cropping: true,
|
||||||
compressImageQuality: 0.8,
|
compressImageQuality: 0.8,
|
||||||
avoidEmptySpaceAroundImage: false,
|
avoidEmptySpaceAroundImage: false
|
||||||
cropperChooseText: I18n.t('Choose'),
|
};
|
||||||
cropperCancelText: I18n.t('Cancel')
|
|
||||||
|
const libraryPickerConfig = {
|
||||||
|
mediaType: 'any'
|
||||||
|
};
|
||||||
|
|
||||||
|
const videoPickerConfig = {
|
||||||
|
mediaType: 'video'
|
||||||
};
|
};
|
||||||
|
|
||||||
const fileOptions = [I18n.t('Cancel')];
|
|
||||||
const FILE_CANCEL_INDEX = 0;
|
const FILE_CANCEL_INDEX = 0;
|
||||||
|
|
||||||
// Photo
|
|
||||||
fileOptions.push(I18n.t('Take_a_photo'));
|
|
||||||
const FILE_PHOTO_INDEX = 1;
|
const FILE_PHOTO_INDEX = 1;
|
||||||
|
const FILE_VIDEO_INDEX = 2;
|
||||||
// Library
|
const FILE_LIBRARY_INDEX = 3;
|
||||||
fileOptions.push(I18n.t('Choose_from_library'));
|
const FILE_DOCUMENT_INDEX = 4;
|
||||||
const FILE_LIBRARY_INDEX = 2;
|
|
||||||
|
|
||||||
class MessageBox extends Component {
|
class MessageBox extends Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
@ -107,6 +109,30 @@ class MessageBox extends Component {
|
||||||
this.customEmojis = [];
|
this.customEmojis = [];
|
||||||
this.onEmojiSelected = this.onEmojiSelected.bind(this);
|
this.onEmojiSelected = this.onEmojiSelected.bind(this);
|
||||||
this.text = '';
|
this.text = '';
|
||||||
|
this.fileOptions = [
|
||||||
|
I18n.t('Cancel'),
|
||||||
|
I18n.t('Take_a_photo'),
|
||||||
|
I18n.t('Take_a_video'),
|
||||||
|
I18n.t('Choose_from_library'),
|
||||||
|
I18n.t('Choose_file')
|
||||||
|
];
|
||||||
|
const libPickerLabels = {
|
||||||
|
cropperChooseText: I18n.t('Choose'),
|
||||||
|
cropperCancelText: I18n.t('Cancel'),
|
||||||
|
loadingLabelText: I18n.t('Processing')
|
||||||
|
};
|
||||||
|
this.imagePickerConfig = {
|
||||||
|
...imagePickerConfig,
|
||||||
|
...libPickerLabels
|
||||||
|
};
|
||||||
|
this.libraryPickerConfig = {
|
||||||
|
...libraryPickerConfig,
|
||||||
|
...libPickerLabels
|
||||||
|
};
|
||||||
|
this.videoPickerConfig = {
|
||||||
|
...videoPickerConfig,
|
||||||
|
...libPickerLabels
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
@ -462,9 +488,10 @@ class MessageBox extends Component {
|
||||||
this.setShowSend(false);
|
this.setShowSend(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
sendImageMessage = async(file) => {
|
sendMediaMessage = async(file) => {
|
||||||
const { rid, tmid } = this.props;
|
const {
|
||||||
|
rid, tmid, baseUrl: server, user
|
||||||
|
} = this.props;
|
||||||
this.setState({ file: { isVisible: false } });
|
this.setState({ file: { isVisible: false } });
|
||||||
const fileInfo = {
|
const fileInfo = {
|
||||||
name: file.name,
|
name: file.name,
|
||||||
|
@ -475,37 +502,65 @@ class MessageBox extends Component {
|
||||||
path: file.path
|
path: file.path
|
||||||
};
|
};
|
||||||
try {
|
try {
|
||||||
await RocketChat.sendFileMessage(rid, fileInfo, tmid);
|
await RocketChat.sendFileMessage(rid, fileInfo, tmid, server, user);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
log('err_send_image', e);
|
log('err_send_media_message', e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
takePhoto = async() => {
|
takePhoto = async() => {
|
||||||
try {
|
try {
|
||||||
const image = await ImagePicker.openCamera(imagePickerConfig);
|
const image = await ImagePicker.openCamera(this.imagePickerConfig);
|
||||||
this.showUploadModal(image);
|
this.showUploadModal(image);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
log('err_take_photo', e);
|
log('err_take_photo', e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
takeVideo = async() => {
|
||||||
|
try {
|
||||||
|
const video = await ImagePicker.openCamera(this.videoPickerConfig);
|
||||||
|
this.showUploadModal(video);
|
||||||
|
} catch (e) {
|
||||||
|
log('err_take_video', e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
chooseFromLibrary = async() => {
|
chooseFromLibrary = async() => {
|
||||||
try {
|
try {
|
||||||
const image = await ImagePicker.openPicker(imagePickerConfig);
|
const image = await ImagePicker.openPicker(this.libraryPickerConfig);
|
||||||
this.showUploadModal(image);
|
this.showUploadModal(image);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
log('err_choose_from_library', e);
|
log('err_choose_from_library', e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
chooseFile = async() => {
|
||||||
|
try {
|
||||||
|
const res = await DocumentPicker.pick({
|
||||||
|
type: [DocumentPicker.types.allFiles]
|
||||||
|
});
|
||||||
|
this.showUploadModal({
|
||||||
|
filename: res.name,
|
||||||
|
size: res.size,
|
||||||
|
mime: res.type,
|
||||||
|
path: res.uri
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
if (!DocumentPicker.isCancel(error)) {
|
||||||
|
log('chooseFile', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
showUploadModal = (file) => {
|
showUploadModal = (file) => {
|
||||||
this.setState({ file: { ...file, isVisible: true } });
|
this.setState({ file: { ...file, isVisible: true } });
|
||||||
}
|
}
|
||||||
|
|
||||||
showFileActions = () => {
|
showFileActions = () => {
|
||||||
ActionSheet.showActionSheetWithOptions({
|
ActionSheet.showActionSheetWithOptions({
|
||||||
options: fileOptions,
|
options: this.fileOptions,
|
||||||
cancelButtonIndex: FILE_CANCEL_INDEX
|
cancelButtonIndex: FILE_CANCEL_INDEX
|
||||||
}, (actionIndex) => {
|
}, (actionIndex) => {
|
||||||
this.handleFileActionPress(actionIndex);
|
this.handleFileActionPress(actionIndex);
|
||||||
|
@ -517,9 +572,15 @@ class MessageBox extends Component {
|
||||||
case FILE_PHOTO_INDEX:
|
case FILE_PHOTO_INDEX:
|
||||||
this.takePhoto();
|
this.takePhoto();
|
||||||
break;
|
break;
|
||||||
|
case FILE_VIDEO_INDEX:
|
||||||
|
this.takeVideo();
|
||||||
|
break;
|
||||||
case FILE_LIBRARY_INDEX:
|
case FILE_LIBRARY_INDEX:
|
||||||
this.chooseFromLibrary();
|
this.chooseFromLibrary();
|
||||||
break;
|
break;
|
||||||
|
case FILE_DOCUMENT_INDEX:
|
||||||
|
this.chooseFile();
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -543,14 +604,16 @@ class MessageBox extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
finishAudioMessage = async(fileInfo) => {
|
finishAudioMessage = async(fileInfo) => {
|
||||||
const { rid, tmid } = this.props;
|
const {
|
||||||
|
rid, tmid, baseUrl: server, user
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
recording: false
|
recording: false
|
||||||
});
|
});
|
||||||
if (fileInfo) {
|
if (fileInfo) {
|
||||||
try {
|
try {
|
||||||
await RocketChat.sendFileMessage(rid, fileInfo, tmid);
|
await RocketChat.sendFileMessage(rid, fileInfo, tmid, server, user);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e && e.error === 'error-file-too-large') {
|
if (e && e.error === 'error-file-too-large') {
|
||||||
return Alert.alert(I18n.t(e.error));
|
return Alert.alert(I18n.t(e.error));
|
||||||
|
@ -895,7 +958,7 @@ class MessageBox extends Component {
|
||||||
isVisible={(file && file.isVisible)}
|
isVisible={(file && file.isVisible)}
|
||||||
file={file}
|
file={file}
|
||||||
close={() => this.setState({ file: {} })}
|
close={() => this.setState({ file: {} })}
|
||||||
submit={this.sendImageMessage}
|
submit={this.sendMediaMessage}
|
||||||
/>
|
/>
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
|
|
|
@ -7,8 +7,12 @@ import { COLOR_TEXT_DESCRIPTION } from '../constants/colors';
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
style: {
|
style: {
|
||||||
marginRight: 7,
|
marginRight: 7,
|
||||||
marginTop: 3,
|
marginTop: 3
|
||||||
tintColor: COLOR_TEXT_DESCRIPTION,
|
},
|
||||||
|
imageColor: {
|
||||||
|
tintColor: COLOR_TEXT_DESCRIPTION
|
||||||
|
},
|
||||||
|
iconColor: {
|
||||||
color: COLOR_TEXT_DESCRIPTION
|
color: COLOR_TEXT_DESCRIPTION
|
||||||
},
|
},
|
||||||
discussion: {
|
discussion: {
|
||||||
|
@ -23,13 +27,15 @@ const RoomTypeIcon = React.memo(({ type, size, style }) => {
|
||||||
|
|
||||||
if (type === 'discussion') {
|
if (type === 'discussion') {
|
||||||
// FIXME: These are temporary only. We should have all room icons on <Customicon />, but our design team is still working on this.
|
// FIXME: These are temporary only. We should have all room icons on <Customicon />, but our design team is still working on this.
|
||||||
return <CustomIcon name='chat' size={13} style={[styles.style, styles.discussion]} />;
|
return <CustomIcon name='chat' size={13} style={[styles.style, styles.iconColor, styles.discussion]} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type === 'c') {
|
if (type === 'c') {
|
||||||
return <Image source={{ uri: 'hashtag' }} style={[styles.style, style, { width: size, height: size }]} />;
|
return <Image source={{ uri: 'hashtag' }} style={[styles.style, styles.imageColor, style, { width: size, height: size }]} />;
|
||||||
|
} if (type === 'd') {
|
||||||
|
return <CustomIcon name='at' size={13} style={[styles.style, styles.iconColor, styles.discussion]} />;
|
||||||
}
|
}
|
||||||
return <Image source={{ uri: 'lock' }} style={[styles.style, style, { width: size, height: size }]} />;
|
return <Image source={{ uri: 'lock' }} style={[styles.style, styles.imageColor, style, { width: size, height: size }]} />;
|
||||||
});
|
});
|
||||||
|
|
||||||
RoomTypeIcon.propTypes = {
|
RoomTypeIcon.propTypes = {
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { View, StyleSheet, TextInput } from 'react-native';
|
import {
|
||||||
|
View, StyleSheet, TextInput, Text
|
||||||
|
} from 'react-native';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
import Touchable from 'react-native-platform-touchable';
|
||||||
|
|
||||||
import I18n from '../i18n';
|
import I18n from '../i18n';
|
||||||
import { isIOS } from '../utils/deviceInfo';
|
import { isIOS } from '../utils/deviceInfo';
|
||||||
|
@ -9,7 +12,10 @@ import sharedStyles from '../views/Styles';
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
backgroundColor: isIOS ? '#F7F8FA' : '#54585E'
|
backgroundColor: isIOS ? '#F7F8FA' : '#54585E',
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center',
|
||||||
|
flex: 1
|
||||||
},
|
},
|
||||||
searchBox: {
|
searchBox: {
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
|
@ -21,7 +27,8 @@ const styles = StyleSheet.create({
|
||||||
height: 36,
|
height: 36,
|
||||||
margin: 16,
|
margin: 16,
|
||||||
marginVertical: 10,
|
marginVertical: 10,
|
||||||
paddingHorizontal: 10
|
paddingHorizontal: 10,
|
||||||
|
flex: 1
|
||||||
},
|
},
|
||||||
input: {
|
input: {
|
||||||
color: '#8E8E93',
|
color: '#8E8E93',
|
||||||
|
@ -31,10 +38,26 @@ const styles = StyleSheet.create({
|
||||||
paddingTop: 0,
|
paddingTop: 0,
|
||||||
paddingBottom: 0,
|
paddingBottom: 0,
|
||||||
...sharedStyles.textRegular
|
...sharedStyles.textRegular
|
||||||
|
},
|
||||||
|
cancel: {
|
||||||
|
marginRight: 10
|
||||||
|
},
|
||||||
|
cancelText: {
|
||||||
|
...sharedStyles.textRegular,
|
||||||
|
...sharedStyles.textColorHeaderBack,
|
||||||
|
fontSize: 17
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const SearchBox = ({ onChangeText, onSubmitEditing, testID }) => (
|
const CancelButton = onCancelPress => (
|
||||||
|
<Touchable onPress={onCancelPress} style={styles.cancel}>
|
||||||
|
<Text style={styles.cancelText}>{I18n.t('Cancel')}</Text>
|
||||||
|
</Touchable>
|
||||||
|
);
|
||||||
|
|
||||||
|
const SearchBox = ({
|
||||||
|
onChangeText, onSubmitEditing, testID, hasCancel, onCancelPress, ...props
|
||||||
|
}) => (
|
||||||
<View style={styles.container}>
|
<View style={styles.container}>
|
||||||
<View style={styles.searchBox}>
|
<View style={styles.searchBox}>
|
||||||
<CustomIcon name='magnifier' size={14} color='#8E8E93' />
|
<CustomIcon name='magnifier' size={14} color='#8E8E93' />
|
||||||
|
@ -50,14 +73,18 @@ const SearchBox = ({ onChangeText, onSubmitEditing, testID }) => (
|
||||||
underlineColorAndroid='transparent'
|
underlineColorAndroid='transparent'
|
||||||
onChangeText={onChangeText}
|
onChangeText={onChangeText}
|
||||||
onSubmitEditing={onSubmitEditing}
|
onSubmitEditing={onSubmitEditing}
|
||||||
|
{...props}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
|
{ hasCancel ? CancelButton(onCancelPress) : null }
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
|
|
||||||
SearchBox.propTypes = {
|
SearchBox.propTypes = {
|
||||||
onChangeText: PropTypes.func.isRequired,
|
onChangeText: PropTypes.func.isRequired,
|
||||||
onSubmitEditing: PropTypes.func,
|
onSubmitEditing: PropTypes.func,
|
||||||
|
hasCancel: PropTypes.bool,
|
||||||
|
onCancelPress: PropTypes.func,
|
||||||
testID: PropTypes.string
|
testID: PropTypes.string
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { StyleSheet } from 'react-native';
|
||||||
|
import EasyToast from 'react-native-easy-toast';
|
||||||
|
|
||||||
|
import { COLOR_TOAST, COLOR_WHITE } from '../constants/colors';
|
||||||
|
import sharedStyles from '../views/Styles';
|
||||||
|
import EventEmitter from '../utils/events';
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
toast: {
|
||||||
|
backgroundColor: COLOR_TOAST,
|
||||||
|
maxWidth: 300,
|
||||||
|
padding: 10
|
||||||
|
},
|
||||||
|
text: {
|
||||||
|
...sharedStyles.textRegular,
|
||||||
|
color: COLOR_WHITE,
|
||||||
|
fontSize: 14,
|
||||||
|
textAlign: 'center'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export const LISTENER = 'Toast';
|
||||||
|
|
||||||
|
export default class Toast extends React.Component {
|
||||||
|
componentDidMount() {
|
||||||
|
EventEmitter.addEventListener(LISTENER, this.showToast);
|
||||||
|
}
|
||||||
|
|
||||||
|
shouldComponentUpdate() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
EventEmitter.removeListener(LISTENER);
|
||||||
|
}
|
||||||
|
|
||||||
|
showToast = ({ message }) => {
|
||||||
|
this.toast.show(message, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<EasyToast
|
||||||
|
ref={toast => this.toast = toast}
|
||||||
|
position='center'
|
||||||
|
style={styles.toast}
|
||||||
|
textStyle={styles.text}
|
||||||
|
opacity={0.9}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Text } from 'react-native';
|
import { Text, View } from 'react-native';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
import I18n from '../../i18n';
|
import I18n from '../../i18n';
|
||||||
|
@ -12,26 +12,35 @@ const Content = React.memo((props) => {
|
||||||
return <Text style={styles.textInfo}>{getInfoMessage({ ...props })}</Text>;
|
return <Text style={styles.textInfo}>{getInfoMessage({ ...props })}</Text>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let content = null;
|
||||||
|
|
||||||
if (props.tmid && !props.msg) {
|
if (props.tmid && !props.msg) {
|
||||||
return <Text style={styles.text}>{I18n.t('Sent_an_attachment')}</Text>;
|
content = <Text style={styles.text}>{I18n.t('Sent_an_attachment')}</Text>;
|
||||||
|
} else {
|
||||||
|
content = (
|
||||||
|
<Markdown
|
||||||
|
msg={props.msg}
|
||||||
|
baseUrl={props.baseUrl}
|
||||||
|
username={props.user.username}
|
||||||
|
isEdited={props.isEdited}
|
||||||
|
mentions={props.mentions}
|
||||||
|
channels={props.channels}
|
||||||
|
numberOfLines={props.tmid ? 1 : 0}
|
||||||
|
getCustomEmoji={props.getCustomEmoji}
|
||||||
|
useMarkdown={props.useMarkdown}
|
||||||
|
/>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Markdown
|
<View style={props.isTemp && styles.temp}>
|
||||||
msg={props.msg}
|
{content}
|
||||||
baseUrl={props.baseUrl}
|
</View>
|
||||||
username={props.user.username}
|
|
||||||
isEdited={props.isEdited}
|
|
||||||
mentions={props.mentions}
|
|
||||||
channels={props.channels}
|
|
||||||
numberOfLines={props.tmid ? 1 : 0}
|
|
||||||
getCustomEmoji={props.getCustomEmoji}
|
|
||||||
useMarkdown={props.useMarkdown}
|
|
||||||
/>
|
|
||||||
);
|
);
|
||||||
}, (prevProps, nextProps) => prevProps.msg === nextProps.msg);
|
}, (prevProps, nextProps) => prevProps.isTemp === nextProps.isTemp && prevProps.msg === nextProps.msg);
|
||||||
|
|
||||||
Content.propTypes = {
|
Content.propTypes = {
|
||||||
|
isTemp: PropTypes.bool,
|
||||||
isInfo: PropTypes.bool,
|
isInfo: PropTypes.bool,
|
||||||
isEdited: PropTypes.bool,
|
isEdited: PropTypes.bool,
|
||||||
useMarkdown: PropTypes.bool,
|
useMarkdown: PropTypes.bool,
|
||||||
|
|
|
@ -4,7 +4,6 @@ import { View } from 'react-native';
|
||||||
import Touchable from 'react-native-platform-touchable';
|
import Touchable from 'react-native-platform-touchable';
|
||||||
|
|
||||||
import User from './User';
|
import User from './User';
|
||||||
import MessageError from './MessageError';
|
|
||||||
import styles from './styles';
|
import styles from './styles';
|
||||||
import sharedStyles from '../../views/Styles';
|
import sharedStyles from '../../views/Styles';
|
||||||
import RepliedThread from './RepliedThread';
|
import RepliedThread from './RepliedThread';
|
||||||
|
@ -45,7 +44,7 @@ const Message = React.memo((props) => {
|
||||||
if (props.isThreadReply || props.isThreadSequential || props.isInfo) {
|
if (props.isThreadReply || props.isThreadSequential || props.isInfo) {
|
||||||
const thread = props.isThreadReply ? <RepliedThread isTemp={props.isTemp} {...props} /> : null;
|
const thread = props.isThreadReply ? <RepliedThread isTemp={props.isTemp} {...props} /> : null;
|
||||||
return (
|
return (
|
||||||
<View style={[styles.container, props.style, props.isTemp && styles.temp]}>
|
<View style={[styles.container, props.style]}>
|
||||||
{thread}
|
{thread}
|
||||||
<View style={[styles.flex, sharedStyles.alignItemsCenter]}>
|
<View style={[styles.flex, sharedStyles.alignItemsCenter]}>
|
||||||
<MessageAvatar small {...props} />
|
<MessageAvatar small {...props} />
|
||||||
|
@ -62,7 +61,7 @@ const Message = React.memo((props) => {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<View style={[styles.container, props.style, props.isTemp && styles.temp]}>
|
<View style={[styles.container, props.style]}>
|
||||||
<View style={styles.flex}>
|
<View style={styles.flex}>
|
||||||
<MessageAvatar {...props} />
|
<MessageAvatar {...props} />
|
||||||
<View
|
<View
|
||||||
|
@ -86,8 +85,7 @@ Message.displayName = 'Message';
|
||||||
const MessageTouchable = React.memo((props) => {
|
const MessageTouchable = React.memo((props) => {
|
||||||
if (props.hasError) {
|
if (props.hasError) {
|
||||||
return (
|
return (
|
||||||
<View style={styles.root}>
|
<View>
|
||||||
<MessageError {...props} />
|
|
||||||
<Message {...props} />
|
<Message {...props} />
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
|
|
|
@ -5,14 +5,15 @@ import PropTypes from 'prop-types';
|
||||||
import { CustomIcon } from '../../lib/Icons';
|
import { CustomIcon } from '../../lib/Icons';
|
||||||
import { COLOR_DANGER } from '../../constants/colors';
|
import { COLOR_DANGER } from '../../constants/colors';
|
||||||
import styles from './styles';
|
import styles from './styles';
|
||||||
|
import { BUTTON_HIT_SLOP } from './utils';
|
||||||
|
|
||||||
const MessageError = React.memo(({ hasError, onErrorPress }) => {
|
const MessageError = React.memo(({ hasError, onErrorPress }) => {
|
||||||
if (!hasError) {
|
if (!hasError) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<Touchable onPress={onErrorPress} style={styles.errorButton}>
|
<Touchable onPress={onErrorPress} style={styles.errorButton} hitSlop={BUTTON_HIT_SLOP}>
|
||||||
<CustomIcon name='circle-cross' color={COLOR_DANGER} size={20} />
|
<CustomIcon name='warning' color={COLOR_DANGER} size={18} />
|
||||||
</Touchable>
|
</Touchable>
|
||||||
);
|
);
|
||||||
}, (prevProps, nextProps) => prevProps.hasError === nextProps.hasError);
|
}, (prevProps, nextProps) => prevProps.hasError === nextProps.hasError);
|
||||||
|
|
|
@ -3,6 +3,7 @@ import PropTypes from 'prop-types';
|
||||||
import { View, Text, StyleSheet } from 'react-native';
|
import { View, Text, StyleSheet } from 'react-native';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
|
|
||||||
|
import MessageError from './MessageError';
|
||||||
import sharedStyles from '../../views/Styles';
|
import sharedStyles from '../../views/Styles';
|
||||||
import messageStyles from './styles';
|
import messageStyles from './styles';
|
||||||
|
|
||||||
|
@ -31,9 +32,9 @@ const styles = StyleSheet.create({
|
||||||
});
|
});
|
||||||
|
|
||||||
const User = React.memo(({
|
const User = React.memo(({
|
||||||
isHeader, useRealName, author, alias, ts, timeFormat
|
isHeader, useRealName, author, alias, ts, timeFormat, hasError, ...props
|
||||||
}) => {
|
}) => {
|
||||||
if (isHeader) {
|
if (isHeader || hasError) {
|
||||||
const username = (useRealName && author.name) || author.username;
|
const username = (useRealName && author.name) || author.username;
|
||||||
const aliasUsername = alias ? (<Text style={styles.alias}> @{username}</Text>) : null;
|
const aliasUsername = alias ? (<Text style={styles.alias}> @{username}</Text>) : null;
|
||||||
const time = moment(ts).format(timeFormat);
|
const time = moment(ts).format(timeFormat);
|
||||||
|
@ -47,6 +48,7 @@ const User = React.memo(({
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
<Text style={messageStyles.time}>{time}</Text>
|
<Text style={messageStyles.time}>{time}</Text>
|
||||||
|
{ hasError && <MessageError hasError={hasError} {...props} /> }
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -55,6 +57,7 @@ const User = React.memo(({
|
||||||
|
|
||||||
User.propTypes = {
|
User.propTypes = {
|
||||||
isHeader: PropTypes.bool,
|
isHeader: PropTypes.bool,
|
||||||
|
hasError: PropTypes.bool,
|
||||||
useRealName: PropTypes.bool,
|
useRealName: PropTypes.bool,
|
||||||
author: PropTypes.object,
|
author: PropTypes.object,
|
||||||
alias: PropTypes.string,
|
alias: PropTypes.string,
|
||||||
|
|
|
@ -128,6 +128,9 @@ export default class MessageContainer extends React.Component {
|
||||||
const {
|
const {
|
||||||
item, previousItem, broadcast, Message_GroupingPeriod
|
item, previousItem, broadcast, Message_GroupingPeriod
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
if (this.hasError || (previousItem && previousItem.status === messagesStatus.ERROR)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
if (previousItem && (
|
if (previousItem && (
|
||||||
(previousItem.ts.toDateString() === item.ts.toDateString())
|
(previousItem.ts.toDateString() === item.ts.toDateString())
|
||||||
&& (previousItem.u.username === item.u.username)
|
&& (previousItem.u.username === item.u.username)
|
||||||
|
|
|
@ -114,7 +114,7 @@ export default StyleSheet.create({
|
||||||
color: COLOR_PRIMARY
|
color: COLOR_PRIMARY
|
||||||
},
|
},
|
||||||
errorButton: {
|
errorButton: {
|
||||||
paddingHorizontal: 15,
|
paddingLeft: 10,
|
||||||
paddingVertical: 5
|
paddingVertical: 5
|
||||||
},
|
},
|
||||||
buttonContainer: {
|
buttonContainer: {
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
import I18n from 'react-native-i18n';
|
import i18n from 'i18n-js';
|
||||||
|
import { I18nManager } from 'react-native';
|
||||||
|
import * as RNLocalize from 'react-native-localize';
|
||||||
|
|
||||||
import en from './locales/en';
|
import en from './locales/en';
|
||||||
import ru from './locales/ru';
|
import ru from './locales/ru';
|
||||||
import fr from './locales/fr';
|
import fr from './locales/fr';
|
||||||
|
@ -7,11 +10,22 @@ import ptBR from './locales/pt-BR';
|
||||||
import zhCN from './locales/zh-CN';
|
import zhCN from './locales/zh-CN';
|
||||||
import ptPT from './locales/pt-PT';
|
import ptPT from './locales/pt-PT';
|
||||||
|
|
||||||
I18n.fallbacks = true;
|
i18n.translations = {
|
||||||
I18n.defaultLocale = 'en';
|
en,
|
||||||
|
ru,
|
||||||
I18n.translations = {
|
'pt-BR': ptBR,
|
||||||
en, ru, 'pt-BR': ptBR, 'zh-CN': zhCN, fr, de, 'pt-PT': ptPT
|
'zh-CN': zhCN,
|
||||||
|
fr,
|
||||||
|
de,
|
||||||
|
'pt-PT': ptPT
|
||||||
};
|
};
|
||||||
|
i18n.fallbacks = true;
|
||||||
|
|
||||||
export default I18n;
|
const defaultLanguage = { languageTag: 'en', isRTL: false };
|
||||||
|
const availableLanguages = Object.keys(i18n.translations);
|
||||||
|
const { languageTag, isRTL } = RNLocalize.findBestAvailableLanguage(availableLanguages) || defaultLanguage;
|
||||||
|
|
||||||
|
I18nManager.forceRTL(isRTL);
|
||||||
|
i18n.locale = languageTag;
|
||||||
|
|
||||||
|
export default i18n;
|
||||||
|
|
|
@ -99,6 +99,7 @@ export default {
|
||||||
Are_you_sure_question_mark: 'Sind Sie sicher?',
|
Are_you_sure_question_mark: 'Sind Sie sicher?',
|
||||||
Are_you_sure_you_want_to_leave_the_room: 'Möchten Sie den Raum wirklich verlassen {{room}}?',
|
Are_you_sure_you_want_to_leave_the_room: 'Möchten Sie den Raum wirklich verlassen {{room}}?',
|
||||||
Authenticating: 'Authentifizierung',
|
Authenticating: 'Authentifizierung',
|
||||||
|
Auto_Translate: 'Automatische Übersetzung',
|
||||||
Avatar_changed_successfully: 'Avatar erfolgreich geändert!',
|
Avatar_changed_successfully: 'Avatar erfolgreich geändert!',
|
||||||
Avatar_Url: 'Avatar-URL',
|
Avatar_Url: 'Avatar-URL',
|
||||||
Away: 'Abwesend',
|
Away: 'Abwesend',
|
||||||
|
@ -155,11 +156,13 @@ export default {
|
||||||
Email_or_password_field_is_empty: 'Das E-Mail- oder Passwortfeld ist leer',
|
Email_or_password_field_is_empty: 'Das E-Mail- oder Passwortfeld ist leer',
|
||||||
Email: 'Email',
|
Email: 'Email',
|
||||||
email: 'Email',
|
email: 'Email',
|
||||||
|
Enable_Auto_Translate: 'Automatische Übersetzung aktivieren',
|
||||||
Enable_markdown: 'Markdown aktivieren',
|
Enable_markdown: 'Markdown aktivieren',
|
||||||
Enable_notifications: 'Benachrichtigungen aktivieren',
|
Enable_notifications: 'Benachrichtigungen aktivieren',
|
||||||
Everyone_can_access_this_channel: 'Jeder kann auf diesen Kanal zugreifen',
|
Everyone_can_access_this_channel: 'Jeder kann auf diesen Kanal zugreifen',
|
||||||
erasing_room: 'lösche Raum',
|
erasing_room: 'lösche Raum',
|
||||||
Error_uploading: 'Fehler beim Hochladen',
|
Error_uploading: 'Fehler beim Hochladen',
|
||||||
|
Favorite: 'Favorisieren',
|
||||||
Favorites: 'Favoriten',
|
Favorites: 'Favoriten',
|
||||||
Files: 'Dateien',
|
Files: 'Dateien',
|
||||||
File_description: 'Dateibeschreibung',
|
File_description: 'Dateibeschreibung',
|
||||||
|
@ -173,6 +176,7 @@ export default {
|
||||||
Forgot_Password: 'Passwort vergessen',
|
Forgot_Password: 'Passwort vergessen',
|
||||||
Group_by_favorites: 'Nach Favoriten gruppieren',
|
Group_by_favorites: 'Nach Favoriten gruppieren',
|
||||||
Group_by_type: 'Gruppieren nach Typ',
|
Group_by_type: 'Gruppieren nach Typ',
|
||||||
|
Hide: 'Ausblenden',
|
||||||
Has_joined_the_channel: 'Ist dem Kanal beigetreten',
|
Has_joined_the_channel: 'Ist dem Kanal beigetreten',
|
||||||
Has_joined_the_conversation: 'Hat sich dem Gespräch angeschlossen',
|
Has_joined_the_conversation: 'Hat sich dem Gespräch angeschlossen',
|
||||||
Has_left_the_channel: 'Hat den Kanal verlassen',
|
Has_left_the_channel: 'Hat den Kanal verlassen',
|
||||||
|
@ -266,6 +270,7 @@ export default {
|
||||||
Reactions_are_disabled: 'Reaktionen sind deaktiviert',
|
Reactions_are_disabled: 'Reaktionen sind deaktiviert',
|
||||||
Reactions_are_enabled: 'Reaktionen sind aktiviert',
|
Reactions_are_enabled: 'Reaktionen sind aktiviert',
|
||||||
Reactions: 'Reaktionen',
|
Reactions: 'Reaktionen',
|
||||||
|
Read: 'Gelesen',
|
||||||
Read_Only_Channel: 'Nur-Lese-Kanal',
|
Read_Only_Channel: 'Nur-Lese-Kanal',
|
||||||
Read_Only: 'Schreibgeschützt',
|
Read_Only: 'Schreibgeschützt',
|
||||||
Read_Receipt: 'Lesebestätigung',
|
Read_Receipt: 'Lesebestätigung',
|
||||||
|
@ -343,12 +348,14 @@ export default {
|
||||||
Timezone: 'Zeitzone',
|
Timezone: 'Zeitzone',
|
||||||
topic: 'Thema',
|
topic: 'Thema',
|
||||||
Topic: 'Thema',
|
Topic: 'Thema',
|
||||||
|
Translate: 'Übersetzen',
|
||||||
Try_again: 'Versuchen Sie es nochmal',
|
Try_again: 'Versuchen Sie es nochmal',
|
||||||
Two_Factor_Authentication: 'Zwei-Faktor-Authentifizierung',
|
Two_Factor_Authentication: 'Zwei-Faktor-Authentifizierung',
|
||||||
Type_the_channel_name_here: 'Geben Sie hier den Kanalnamen ein',
|
Type_the_channel_name_here: 'Geben Sie hier den Kanalnamen ein',
|
||||||
unarchive: 'wiederherstellen',
|
unarchive: 'wiederherstellen',
|
||||||
UNARCHIVE: 'WIEDERHERSTELLEN',
|
UNARCHIVE: 'WIEDERHERSTELLEN',
|
||||||
Unblock_user: 'Nutzer entblockieren',
|
Unblock_user: 'Nutzer entblockieren',
|
||||||
|
Unfavorite: 'Nicht mehr favorisieren',
|
||||||
Unfollowed_thread: 'Thread nicht mehr folgen',
|
Unfollowed_thread: 'Thread nicht mehr folgen',
|
||||||
Unmute: 'Stummschaltung aufheben',
|
Unmute: 'Stummschaltung aufheben',
|
||||||
unmuted: 'Stummschaltung aufgehoben',
|
unmuted: 'Stummschaltung aufgehoben',
|
||||||
|
@ -374,6 +381,7 @@ export default {
|
||||||
Username_or_email: 'Benutzername oder E-Mail-Adresse',
|
Username_or_email: 'Benutzername oder E-Mail-Adresse',
|
||||||
Validating: 'Validierung',
|
Validating: 'Validierung',
|
||||||
Video_call: 'Videoanruf',
|
Video_call: 'Videoanruf',
|
||||||
|
View_Original: 'Original anzeigen',
|
||||||
Voice_call: 'Sprachanruf',
|
Voice_call: 'Sprachanruf',
|
||||||
Welcome: 'Herzlich willkommen',
|
Welcome: 'Herzlich willkommen',
|
||||||
Welcome_to_RocketChat: 'Willkommen bei Rocket.Chat',
|
Welcome_to_RocketChat: 'Willkommen bei Rocket.Chat',
|
||||||
|
|
|
@ -103,6 +103,7 @@ export default {
|
||||||
Avatar_changed_successfully: 'Avatar changed successfully!',
|
Avatar_changed_successfully: 'Avatar changed successfully!',
|
||||||
Avatar_Url: 'Avatar URL',
|
Avatar_Url: 'Avatar URL',
|
||||||
Away: 'Away',
|
Away: 'Away',
|
||||||
|
Back: 'Back',
|
||||||
Block_user: 'Block user',
|
Block_user: 'Block user',
|
||||||
Broadcast_channel_Description: 'Only authorized users can write new messages, but the other users will be able to reply',
|
Broadcast_channel_Description: 'Only authorized users can write new messages, but the other users will be able to reply',
|
||||||
Broadcast_Channel: 'Broadcast Channel',
|
Broadcast_Channel: 'Broadcast Channel',
|
||||||
|
@ -120,6 +121,7 @@ export default {
|
||||||
Close_emoji_selector: 'Close emoji selector',
|
Close_emoji_selector: 'Close emoji selector',
|
||||||
Choose: 'Choose',
|
Choose: 'Choose',
|
||||||
Choose_from_library: 'Choose from library',
|
Choose_from_library: 'Choose from library',
|
||||||
|
Choose_file: 'Choose file',
|
||||||
Code: 'Code',
|
Code: 'Code',
|
||||||
Collaborative: 'Collaborative',
|
Collaborative: 'Collaborative',
|
||||||
Confirm: 'Confirm',
|
Confirm: 'Confirm',
|
||||||
|
@ -262,6 +264,7 @@ export default {
|
||||||
Private_Channel: 'Private Channel',
|
Private_Channel: 'Private Channel',
|
||||||
Private_Groups: 'Private Groups',
|
Private_Groups: 'Private Groups',
|
||||||
Private: 'Private',
|
Private: 'Private',
|
||||||
|
Processing: 'Processing...',
|
||||||
Profile_saved_successfully: 'Profile saved successfully!',
|
Profile_saved_successfully: 'Profile saved successfully!',
|
||||||
Profile: 'Profile',
|
Profile: 'Profile',
|
||||||
Public_Channel: 'Public Channel',
|
Public_Channel: 'Public Channel',
|
||||||
|
@ -308,11 +311,13 @@ export default {
|
||||||
Search_global_users: 'Search for global users',
|
Search_global_users: 'Search for global users',
|
||||||
Search_global_users_description: 'If you turn-on, you can search for any user from others companies or servers.',
|
Search_global_users_description: 'If you turn-on, you can search for any user from others companies or servers.',
|
||||||
Select_Avatar: 'Select Avatar',
|
Select_Avatar: 'Select Avatar',
|
||||||
|
Select_Server: 'Select Server',
|
||||||
Select_Users: 'Select Users',
|
Select_Users: 'Select Users',
|
||||||
Send: 'Send',
|
Send: 'Send',
|
||||||
Send_audio_message: 'Send audio message',
|
Send_audio_message: 'Send audio message',
|
||||||
Send_crash_report: 'Send crash report',
|
Send_crash_report: 'Send crash report',
|
||||||
Send_message: 'Send message',
|
Send_message: 'Send message',
|
||||||
|
Send_to: 'Send to...',
|
||||||
Sent_an_attachment: 'Sent an attachment',
|
Sent_an_attachment: 'Sent an attachment',
|
||||||
Server: 'Server',
|
Server: 'Server',
|
||||||
Servers: 'Servers',
|
Servers: 'Servers',
|
||||||
|
@ -335,6 +340,7 @@ export default {
|
||||||
Started_discussion: 'Started a discussion:',
|
Started_discussion: 'Started a discussion:',
|
||||||
Submit: 'Submit',
|
Submit: 'Submit',
|
||||||
Take_a_photo: 'Take a photo',
|
Take_a_photo: 'Take a photo',
|
||||||
|
Take_a_video: 'Take a video',
|
||||||
tap_to_change_status: 'tap to change status',
|
tap_to_change_status: 'tap to change status',
|
||||||
Tap_to_view_servers_list: 'Tap to view servers list',
|
Tap_to_view_servers_list: 'Tap to view servers list',
|
||||||
Terms_of_Service: ' Terms of Service ',
|
Terms_of_Service: ' Terms of Service ',
|
||||||
|
@ -346,6 +352,7 @@ export default {
|
||||||
Thread: 'Thread',
|
Thread: 'Thread',
|
||||||
Threads: 'Threads',
|
Threads: 'Threads',
|
||||||
Timezone: 'Timezone',
|
Timezone: 'Timezone',
|
||||||
|
To: 'To',
|
||||||
topic: 'topic',
|
topic: 'topic',
|
||||||
Topic: 'Topic',
|
Topic: 'Topic',
|
||||||
Translate: 'Translate',
|
Translate: 'Translate',
|
||||||
|
@ -386,6 +393,7 @@ export default {
|
||||||
Welcome: 'Welcome',
|
Welcome: 'Welcome',
|
||||||
Welcome_to_RocketChat: 'Welcome to Rocket.Chat',
|
Welcome_to_RocketChat: 'Welcome to Rocket.Chat',
|
||||||
Whats_your_2fa: 'What\'s your 2FA code?',
|
Whats_your_2fa: 'What\'s your 2FA code?',
|
||||||
|
Without_Servers: 'Without Servers',
|
||||||
Yes_action_it: 'Yes, {{action}} it!',
|
Yes_action_it: 'Yes, {{action}} it!',
|
||||||
Yesterday: 'Yesterday',
|
Yesterday: 'Yesterday',
|
||||||
You_are_in_preview_mode: 'You are in preview mode',
|
You_are_in_preview_mode: 'You are in preview mode',
|
||||||
|
@ -395,6 +403,7 @@ export default {
|
||||||
you_were_mentioned: 'you were mentioned',
|
you_were_mentioned: 'you were mentioned',
|
||||||
you: 'you',
|
you: 'you',
|
||||||
You: 'You',
|
You: 'You',
|
||||||
|
You_need_to_access_at_least_one_RocketChat_server_to_share_something: 'You need to access at least one Rocket.Chat server to share something.',
|
||||||
Version_no: 'Version: {{version}}',
|
Version_no: 'Version: {{version}}',
|
||||||
You_will_not_be_able_to_recover_this_message: 'You will not be able to recover this message!',
|
You_will_not_be_able_to_recover_this_message: 'You will not be able to recover this message!',
|
||||||
Change_Language: 'Change Language',
|
Change_Language: 'Change Language',
|
||||||
|
|
|
@ -108,6 +108,7 @@ export default {
|
||||||
Avatar_changed_successfully: 'Avatar alterado com sucesso!',
|
Avatar_changed_successfully: 'Avatar alterado com sucesso!',
|
||||||
Avatar_Url: 'Avatar URL',
|
Avatar_Url: 'Avatar URL',
|
||||||
Away: 'Ausente',
|
Away: 'Ausente',
|
||||||
|
Back: 'Voltar',
|
||||||
Block_user: 'Bloquear usuário',
|
Block_user: 'Bloquear usuário',
|
||||||
Broadcast_channel_Description: 'Somente usuários autorizados podem escrever novas mensagens, mas os outros usuários poderão responder',
|
Broadcast_channel_Description: 'Somente usuários autorizados podem escrever novas mensagens, mas os outros usuários poderão responder',
|
||||||
Broadcast_Channel: 'Canal de Transmissão',
|
Broadcast_Channel: 'Canal de Transmissão',
|
||||||
|
@ -125,6 +126,7 @@ export default {
|
||||||
Close_emoji_selector: 'Fechar seletor de emojis',
|
Close_emoji_selector: 'Fechar seletor de emojis',
|
||||||
Choose: 'Escolher',
|
Choose: 'Escolher',
|
||||||
Choose_from_library: 'Escolha da biblioteca',
|
Choose_from_library: 'Escolha da biblioteca',
|
||||||
|
Choose_file: 'Enviar arquivo',
|
||||||
Code: 'Código',
|
Code: 'Código',
|
||||||
Collaborative: 'Colaborativo',
|
Collaborative: 'Colaborativo',
|
||||||
Confirm: 'Confirmar',
|
Confirm: 'Confirmar',
|
||||||
|
@ -255,6 +257,7 @@ export default {
|
||||||
Private_Channel: 'Canal Privado',
|
Private_Channel: 'Canal Privado',
|
||||||
Private_Groups: 'Grupo Privado',
|
Private_Groups: 'Grupo Privado',
|
||||||
Private: 'Privado',
|
Private: 'Privado',
|
||||||
|
Processing: 'Processando...',
|
||||||
Profile_saved_successfully: 'Perfil salvo com sucesso!',
|
Profile_saved_successfully: 'Perfil salvo com sucesso!',
|
||||||
Profile: 'Perfil',
|
Profile: 'Perfil',
|
||||||
Public_Channel: 'Canal Público',
|
Public_Channel: 'Canal Público',
|
||||||
|
@ -299,10 +302,12 @@ export default {
|
||||||
Search_global_users: 'Busca por usuários globais',
|
Search_global_users: 'Busca por usuários globais',
|
||||||
Search_global_users_description: 'Caso ativado, busca por usuários de outras empresas ou servidores.',
|
Search_global_users_description: 'Caso ativado, busca por usuários de outras empresas ou servidores.',
|
||||||
Select_Avatar: 'Selecionar Avatar',
|
Select_Avatar: 'Selecionar Avatar',
|
||||||
|
Select_Server: 'Selecionar Servidor',
|
||||||
Select_Users: 'Selecionar Usuários',
|
Select_Users: 'Selecionar Usuários',
|
||||||
Send: 'Enviar',
|
Send: 'Enviar',
|
||||||
Send_audio_message: 'Enviar mensagem de áudio',
|
Send_audio_message: 'Enviar mensagem de áudio',
|
||||||
Send_message: 'Enviar mensagem',
|
Send_message: 'Enviar mensagem',
|
||||||
|
Send_to: 'Enviar para...',
|
||||||
Sent_an_attachment: 'Enviou um anexo',
|
Sent_an_attachment: 'Enviou um anexo',
|
||||||
Server: 'Servidor',
|
Server: 'Servidor',
|
||||||
Set_username_subtitle: 'O usuário é utilizado para permitir que você seja mencionado em mensagens',
|
Set_username_subtitle: 'O usuário é utilizado para permitir que você seja mencionado em mensagens',
|
||||||
|
@ -322,6 +327,7 @@ export default {
|
||||||
Started_discussion: 'Iniciou uma discussão:',
|
Started_discussion: 'Iniciou uma discussão:',
|
||||||
Submit: 'Enviar',
|
Submit: 'Enviar',
|
||||||
Take_a_photo: 'Tirar uma foto',
|
Take_a_photo: 'Tirar uma foto',
|
||||||
|
Take_a_video: 'Gravar um vídeo',
|
||||||
Terms_of_Service: ' Termos de Serviço ',
|
Terms_of_Service: ' Termos de Serviço ',
|
||||||
The_URL_is_invalid: 'A URL fornecida é inválida ou não acessível. Por favor tente novamente, mas com uma url diferente.',
|
The_URL_is_invalid: 'A URL fornecida é inválida ou não acessível. Por favor tente novamente, mas com uma url diferente.',
|
||||||
There_was_an_error_while_action: 'Aconteceu um erro {{action}}!',
|
There_was_an_error_while_action: 'Aconteceu um erro {{action}}!',
|
||||||
|
@ -330,6 +336,7 @@ export default {
|
||||||
Thread: 'Tópico',
|
Thread: 'Tópico',
|
||||||
Threads: 'Tópicos',
|
Threads: 'Tópicos',
|
||||||
Timezone: 'Fuso horário',
|
Timezone: 'Fuso horário',
|
||||||
|
To: 'Para',
|
||||||
topic: 'tópico',
|
topic: 'tópico',
|
||||||
Topic: 'Tópico',
|
Topic: 'Tópico',
|
||||||
Try_again: 'Tentar novamente',
|
Try_again: 'Tentar novamente',
|
||||||
|
@ -366,6 +373,7 @@ export default {
|
||||||
Welcome: 'Bem vindo',
|
Welcome: 'Bem vindo',
|
||||||
Welcome_to_RocketChat: 'Bem vindo ao Rocket.Chat',
|
Welcome_to_RocketChat: 'Bem vindo ao Rocket.Chat',
|
||||||
Whats_your_2fa: 'Qual seu código de autenticação?',
|
Whats_your_2fa: 'Qual seu código de autenticação?',
|
||||||
|
Without_Servers: 'Sem Servidores',
|
||||||
Yes_action_it: 'Sim, {{action}}!',
|
Yes_action_it: 'Sim, {{action}}!',
|
||||||
Yesterday: 'Ontem',
|
Yesterday: 'Ontem',
|
||||||
You_are_in_preview_mode: 'Está é uma prévia do canal',
|
You_are_in_preview_mode: 'Está é uma prévia do canal',
|
||||||
|
@ -375,5 +383,6 @@ export default {
|
||||||
you_were_mentioned: 'você foi mencionado',
|
you_were_mentioned: 'você foi mencionado',
|
||||||
you: 'você',
|
you: 'você',
|
||||||
You: 'Você',
|
You: 'Você',
|
||||||
|
You_need_to_access_at_least_one_RocketChat_server_to_share_something: 'Você precisa acessar ao menos um servidor Rocket.Chat para compartilhar.',
|
||||||
You_will_not_be_able_to_recover_this_message: 'Você não será capaz de recuperar essa mensagem!'
|
You_will_not_be_able_to_recover_this_message: 'Você não será capaz de recuperar essa mensagem!'
|
||||||
};
|
};
|
||||||
|
|
185
app/index.js
185
app/index.js
|
@ -5,47 +5,18 @@ import {
|
||||||
import { Provider } from 'react-redux';
|
import { Provider } from 'react-redux';
|
||||||
import { useScreens } from 'react-native-screens'; // eslint-disable-line import/no-unresolved
|
import { useScreens } from 'react-native-screens'; // eslint-disable-line import/no-unresolved
|
||||||
import { Linking } from 'react-native';
|
import { Linking } from 'react-native';
|
||||||
import firebase from 'react-native-firebase';
|
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
import { appInit } from './actions';
|
import { appInit } from './actions';
|
||||||
import { deepLinkingOpen } from './actions/deepLinking';
|
import { deepLinkingOpen } from './actions/deepLinking';
|
||||||
import OnboardingView from './views/OnboardingView';
|
|
||||||
import NewServerView from './views/NewServerView';
|
|
||||||
import LoginSignupView from './views/LoginSignupView';
|
|
||||||
import AuthLoadingView from './views/AuthLoadingView';
|
|
||||||
import RoomsListView from './views/RoomsListView';
|
|
||||||
import RoomView from './views/RoomView';
|
|
||||||
import NewMessageView from './views/NewMessageView';
|
|
||||||
import DirectoryView from './views/DirectoryView';
|
|
||||||
import LoginView from './views/LoginView';
|
|
||||||
import Navigation from './lib/Navigation';
|
import Navigation from './lib/Navigation';
|
||||||
import Sidebar from './views/SidebarView';
|
import Sidebar from './views/SidebarView';
|
||||||
import ProfileView from './views/ProfileView';
|
|
||||||
import SettingsView from './views/SettingsView';
|
|
||||||
import LanguageView from './views/LanguageView';
|
|
||||||
import AdminPanelView from './views/AdminPanelView';
|
|
||||||
import RoomActionsView from './views/RoomActionsView';
|
|
||||||
import RoomInfoView from './views/RoomInfoView';
|
|
||||||
import RoomInfoEditView from './views/RoomInfoEditView';
|
|
||||||
import RoomMembersView from './views/RoomMembersView';
|
|
||||||
import SearchMessagesView from './views/SearchMessagesView';
|
|
||||||
import ReadReceiptsView from './views/ReadReceiptView';
|
|
||||||
import ThreadMessagesView from './views/ThreadMessagesView';
|
|
||||||
import MessagesView from './views/MessagesView';
|
|
||||||
import AutoTranslateView from './views/AutoTranslateView';
|
|
||||||
import SelectedUsersView from './views/SelectedUsersView';
|
|
||||||
import CreateChannelView from './views/CreateChannelView';
|
|
||||||
import LegalView from './views/LegalView';
|
|
||||||
import ForgotPasswordView from './views/ForgotPasswordView';
|
|
||||||
import RegisterView from './views/RegisterView';
|
|
||||||
import OAuthView from './views/OAuthView';
|
|
||||||
import SetUsernameView from './views/SetUsernameView';
|
|
||||||
import { HEADER_BACKGROUND, HEADER_TITLE, HEADER_BACK } from './constants/colors';
|
|
||||||
import parseQuery from './lib/methods/helpers/parseQuery';
|
import parseQuery from './lib/methods/helpers/parseQuery';
|
||||||
import { initializePushNotifications, onNotification } from './notifications/push';
|
import { initializePushNotifications, onNotification } from './notifications/push';
|
||||||
import store from './lib/createStore';
|
import store from './lib/createStore';
|
||||||
import NotificationBadge from './notifications/inApp';
|
import NotificationBadge from './notifications/inApp';
|
||||||
|
import { defaultHeader, onNavigationStateChange } from './utils/navigation';
|
||||||
|
import Toast from './containers/Toast';
|
||||||
|
|
||||||
useScreens();
|
useScreens();
|
||||||
|
|
||||||
|
@ -63,35 +34,38 @@ const parseDeepLinking = (url) => {
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
const defaultHeader = {
|
|
||||||
headerStyle: {
|
|
||||||
backgroundColor: HEADER_BACKGROUND
|
|
||||||
},
|
|
||||||
headerTitleStyle: {
|
|
||||||
color: HEADER_TITLE
|
|
||||||
},
|
|
||||||
headerBackTitle: null,
|
|
||||||
headerTintColor: HEADER_BACK
|
|
||||||
};
|
|
||||||
|
|
||||||
// Outside
|
// Outside
|
||||||
const OutsideStack = createStackNavigator({
|
const OutsideStack = createStackNavigator({
|
||||||
OnboardingView: {
|
OnboardingView: {
|
||||||
screen: OnboardingView,
|
getScreen: () => require('./views/OnboardingView').default,
|
||||||
header: null
|
header: null
|
||||||
},
|
},
|
||||||
NewServerView,
|
NewServerView: {
|
||||||
LoginSignupView,
|
getScreen: () => require('./views/NewServerView').default
|
||||||
LoginView,
|
},
|
||||||
ForgotPasswordView,
|
LoginSignupView: {
|
||||||
RegisterView,
|
getScreen: () => require('./views/LoginSignupView').default
|
||||||
LegalView
|
},
|
||||||
|
LoginView: {
|
||||||
|
getScreen: () => require('./views/LoginView').default
|
||||||
|
},
|
||||||
|
ForgotPasswordView: {
|
||||||
|
getScreen: () => require('./views/ForgotPasswordView').default
|
||||||
|
},
|
||||||
|
RegisterView: {
|
||||||
|
getScreen: () => require('./views/RegisterView').default
|
||||||
|
},
|
||||||
|
LegalView: {
|
||||||
|
getScreen: () => require('./views/LegalView').default
|
||||||
|
}
|
||||||
}, {
|
}, {
|
||||||
defaultNavigationOptions: defaultHeader
|
defaultNavigationOptions: defaultHeader
|
||||||
});
|
});
|
||||||
|
|
||||||
const OAuthStack = createStackNavigator({
|
const OAuthStack = createStackNavigator({
|
||||||
OAuthView
|
OAuthView: {
|
||||||
|
getScreen: () => require('./views/OAuthView').default
|
||||||
|
}
|
||||||
}, {
|
}, {
|
||||||
defaultNavigationOptions: defaultHeader
|
defaultNavigationOptions: defaultHeader
|
||||||
});
|
});
|
||||||
|
@ -107,19 +81,45 @@ const OutsideStackModal = createStackNavigator({
|
||||||
|
|
||||||
// Inside
|
// Inside
|
||||||
const ChatsStack = createStackNavigator({
|
const ChatsStack = createStackNavigator({
|
||||||
RoomsListView,
|
RoomsListView: {
|
||||||
RoomView,
|
getScreen: () => require('./views/RoomsListView').default
|
||||||
RoomActionsView,
|
},
|
||||||
RoomInfoView,
|
RoomView: {
|
||||||
RoomInfoEditView,
|
getScreen: () => require('./views/RoomView').default
|
||||||
RoomMembersView,
|
},
|
||||||
SearchMessagesView,
|
RoomActionsView: {
|
||||||
SelectedUsersView,
|
getScreen: () => require('./views/RoomActionsView').default
|
||||||
ThreadMessagesView,
|
},
|
||||||
MessagesView,
|
RoomInfoView: {
|
||||||
AutoTranslateView,
|
getScreen: () => require('./views/RoomInfoView').default
|
||||||
ReadReceiptsView,
|
},
|
||||||
DirectoryView
|
RoomInfoEditView: {
|
||||||
|
getScreen: () => require('./views/RoomInfoEditView').default
|
||||||
|
},
|
||||||
|
RoomMembersView: {
|
||||||
|
getScreen: () => require('./views/RoomMembersView').default
|
||||||
|
},
|
||||||
|
SearchMessagesView: {
|
||||||
|
getScreen: () => require('./views/SearchMessagesView').default
|
||||||
|
},
|
||||||
|
SelectedUsersView: {
|
||||||
|
getScreen: () => require('./views/SelectedUsersView').default
|
||||||
|
},
|
||||||
|
ThreadMessagesView: {
|
||||||
|
getScreen: () => require('./views/ThreadMessagesView').default
|
||||||
|
},
|
||||||
|
MessagesView: {
|
||||||
|
getScreen: () => require('./views/MessagesView').default
|
||||||
|
},
|
||||||
|
AutoTranslateView: {
|
||||||
|
getScreen: () => require('./views/AutoTranslateView').default
|
||||||
|
},
|
||||||
|
ReadReceiptsView: {
|
||||||
|
getScreen: () => require('./views/ReadReceiptView').default
|
||||||
|
},
|
||||||
|
DirectoryView: {
|
||||||
|
getScreen: () => require('./views/DirectoryView').default
|
||||||
|
}
|
||||||
}, {
|
}, {
|
||||||
defaultNavigationOptions: defaultHeader
|
defaultNavigationOptions: defaultHeader
|
||||||
});
|
});
|
||||||
|
@ -135,7 +135,9 @@ ChatsStack.navigationOptions = ({ navigation }) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const ProfileStack = createStackNavigator({
|
const ProfileStack = createStackNavigator({
|
||||||
ProfileView
|
ProfileView: {
|
||||||
|
getScreen: () => require('./views/ProfileView').default
|
||||||
|
}
|
||||||
}, {
|
}, {
|
||||||
defaultNavigationOptions: defaultHeader
|
defaultNavigationOptions: defaultHeader
|
||||||
});
|
});
|
||||||
|
@ -151,14 +153,20 @@ ProfileStack.navigationOptions = ({ navigation }) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const SettingsStack = createStackNavigator({
|
const SettingsStack = createStackNavigator({
|
||||||
SettingsView,
|
SettingsView: {
|
||||||
LanguageView
|
getScreen: () => require('./views/SettingsView').default
|
||||||
|
},
|
||||||
|
LanguageView: {
|
||||||
|
getScreen: () => require('./views/LanguageView').default
|
||||||
|
}
|
||||||
}, {
|
}, {
|
||||||
defaultNavigationOptions: defaultHeader
|
defaultNavigationOptions: defaultHeader
|
||||||
});
|
});
|
||||||
|
|
||||||
const AdminPanelStack = createStackNavigator({
|
const AdminPanelStack = createStackNavigator({
|
||||||
AdminPanelView
|
AdminPanelView: {
|
||||||
|
getScreen: () => require('./views/AdminPanelView').default
|
||||||
|
}
|
||||||
}, {
|
}, {
|
||||||
defaultNavigationOptions: defaultHeader
|
defaultNavigationOptions: defaultHeader
|
||||||
});
|
});
|
||||||
|
@ -183,9 +191,15 @@ const ChatsDrawer = createDrawerNavigator({
|
||||||
});
|
});
|
||||||
|
|
||||||
const NewMessageStack = createStackNavigator({
|
const NewMessageStack = createStackNavigator({
|
||||||
NewMessageView,
|
NewMessageView: {
|
||||||
SelectedUsersViewCreateChannel: SelectedUsersView,
|
getScreen: () => require('./views/NewMessageView').default
|
||||||
CreateChannelView
|
},
|
||||||
|
SelectedUsersViewCreateChannel: {
|
||||||
|
getScreen: () => require('./views/SelectedUsersView').default
|
||||||
|
},
|
||||||
|
CreateChannelView: {
|
||||||
|
getScreen: () => require('./views/CreateChannelView').default
|
||||||
|
}
|
||||||
}, {
|
}, {
|
||||||
defaultNavigationOptions: defaultHeader
|
defaultNavigationOptions: defaultHeader
|
||||||
});
|
});
|
||||||
|
@ -200,7 +214,9 @@ const InsideStackModal = createStackNavigator({
|
||||||
});
|
});
|
||||||
|
|
||||||
const SetUsernameStack = createStackNavigator({
|
const SetUsernameStack = createStackNavigator({
|
||||||
SetUsernameView
|
SetUsernameView: {
|
||||||
|
getScreen: () => require('./views/SetUsernameView').default
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
class CustomInsideStack extends React.Component {
|
class CustomInsideStack extends React.Component {
|
||||||
|
@ -216,6 +232,7 @@ class CustomInsideStack extends React.Component {
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<InsideStackModal navigation={navigation} />
|
<InsideStackModal navigation={navigation} />
|
||||||
<NotificationBadge navigation={navigation} />
|
<NotificationBadge navigation={navigation} />
|
||||||
|
<Toast />
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -225,7 +242,9 @@ const App = createAppContainer(createSwitchNavigator(
|
||||||
{
|
{
|
||||||
OutsideStack: OutsideStackModal,
|
OutsideStack: OutsideStackModal,
|
||||||
InsideStack: CustomInsideStack,
|
InsideStack: CustomInsideStack,
|
||||||
AuthLoading: AuthLoadingView,
|
AuthLoading: {
|
||||||
|
getScreen: () => require('./views/AuthLoadingView').default
|
||||||
|
},
|
||||||
SetUsernameStack
|
SetUsernameStack
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -233,28 +252,6 @@ const App = createAppContainer(createSwitchNavigator(
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
|
|
||||||
// gets the current screen from navigation state
|
|
||||||
const getActiveRouteName = (navigationState) => {
|
|
||||||
if (!navigationState) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
const route = navigationState.routes[navigationState.index];
|
|
||||||
// dive into nested navigators
|
|
||||||
if (route.routes) {
|
|
||||||
return getActiveRouteName(route);
|
|
||||||
}
|
|
||||||
return route.routeName;
|
|
||||||
};
|
|
||||||
|
|
||||||
const onNavigationStateChange = (prevState, currentState) => {
|
|
||||||
const currentScreen = getActiveRouteName(currentState);
|
|
||||||
const prevScreen = getActiveRouteName(prevState);
|
|
||||||
|
|
||||||
if (prevScreen !== currentScreen) {
|
|
||||||
firebase.analytics().setCurrentScreen(currentScreen);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export default class Root extends React.Component {
|
export default class Root extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
import { NavigationActions } from 'react-navigation';
|
||||||
|
|
||||||
|
let _shareNavigator;
|
||||||
|
|
||||||
|
function setTopLevelNavigator(navigatorRef) {
|
||||||
|
_shareNavigator = navigatorRef;
|
||||||
|
}
|
||||||
|
|
||||||
|
function navigate(routeName, params) {
|
||||||
|
_shareNavigator.dispatch(
|
||||||
|
NavigationActions.navigate({
|
||||||
|
routeName,
|
||||||
|
params
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
navigate,
|
||||||
|
setTopLevelNavigator
|
||||||
|
};
|
|
@ -40,6 +40,15 @@ export default async function() {
|
||||||
if (setting._id === 'Site_Name') {
|
if (setting._id === 'Site_Name') {
|
||||||
updateServer.call(this, { name: setting.valueAsString });
|
updateServer.call(this, { name: setting.valueAsString });
|
||||||
}
|
}
|
||||||
|
if (setting._id === 'UI_Use_Real_Name') {
|
||||||
|
updateServer.call(this, { useRealName: setting.valueAsBoolean });
|
||||||
|
}
|
||||||
|
if (setting._id === 'FileUpload_MediaTypeWhiteList') {
|
||||||
|
updateServer.call(this, { FileUpload_MediaTypeWhiteList: setting.valueAsString });
|
||||||
|
}
|
||||||
|
if (setting._id === 'FileUpload_MaxFileSize') {
|
||||||
|
updateServer.call(this, { FileUpload_MaxFileSize: setting.valueAsNumber });
|
||||||
|
}
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import reduxStore from '../createStore';
|
|
||||||
import database from '../realm';
|
import database from '../realm';
|
||||||
import log from '../../utils/log';
|
import log from '../../utils/log';
|
||||||
|
|
||||||
|
@ -23,11 +22,12 @@ export function cancelUpload(path) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function sendFileMessage(rid, fileInfo, tmid) {
|
export function sendFileMessage(rid, fileInfo, tmid, server, user) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
try {
|
try {
|
||||||
const { FileUpload_MaxFileSize, Site_Url } = reduxStore.getState().settings;
|
const { serversDB } = database.databases;
|
||||||
const { id, token } = reduxStore.getState().login.user;
|
const { FileUpload_MaxFileSize, id: Site_Url } = serversDB.objectForPrimaryKey('servers', server);
|
||||||
|
const { id, token } = user;
|
||||||
|
|
||||||
// -1 maxFileSize means there is no limit
|
// -1 maxFileSize means there is no limit
|
||||||
if (FileUpload_MaxFileSize > -1 && fileInfo.size > FileUpload_MaxFileSize) {
|
if (FileUpload_MaxFileSize > -1 && fileInfo.size > FileUpload_MaxFileSize) {
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
import messagesStatus from '../../constants/messagesStatus';
|
import messagesStatus from '../../constants/messagesStatus';
|
||||||
import buildMessage from './helpers/buildMessage';
|
import buildMessage from './helpers/buildMessage';
|
||||||
import database from '../realm';
|
import database from '../realm';
|
||||||
import reduxStore from '../createStore';
|
|
||||||
import log from '../../utils/log';
|
import log from '../../utils/log';
|
||||||
import random from '../../utils/random';
|
import random from '../../utils/random';
|
||||||
|
|
||||||
export const getMessage = (rid, msg = '', tmid) => {
|
export const getMessage = (rid, msg = '', tmid, user) => {
|
||||||
const _id = random(17);
|
const _id = random(17);
|
||||||
|
const { id, username } = user;
|
||||||
const message = {
|
const message = {
|
||||||
_id,
|
_id,
|
||||||
rid,
|
rid,
|
||||||
|
@ -16,8 +16,8 @@ export const getMessage = (rid, msg = '', tmid) => {
|
||||||
_updatedAt: new Date(),
|
_updatedAt: new Date(),
|
||||||
status: messagesStatus.TEMP,
|
status: messagesStatus.TEMP,
|
||||||
u: {
|
u: {
|
||||||
_id: reduxStore.getState().login.user.id || '1',
|
_id: id || '1',
|
||||||
username: reduxStore.getState().login.user.username
|
username
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
try {
|
try {
|
||||||
|
@ -43,9 +43,9 @@ export async function sendMessageCall(message) {
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default async function(rid, msg, tmid) {
|
export default async function(rid, msg, tmid, user) {
|
||||||
try {
|
try {
|
||||||
const message = getMessage(rid, msg, tmid);
|
const message = getMessage(rid, msg, tmid, user);
|
||||||
const [room] = database.objects('subscriptions').filtered('rid == $0', rid);
|
const [room] = database.objects('subscriptions').filtered('rid == $0', rid);
|
||||||
|
|
||||||
if (room) {
|
if (room) {
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import Realm from 'realm';
|
import Realm from 'realm';
|
||||||
|
import RNRealmPath from 'react-native-realm-path';
|
||||||
|
|
||||||
// import { AsyncStorage } from 'react-native';
|
// import { AsyncStorage } from 'react-native';
|
||||||
// Realm.clearTestState();
|
// Realm.clearTestState();
|
||||||
|
@ -25,6 +26,9 @@ const serversSchema = {
|
||||||
id: 'string',
|
id: 'string',
|
||||||
name: { type: 'string', optional: true },
|
name: { type: 'string', optional: true },
|
||||||
iconURL: { type: 'string', optional: true },
|
iconURL: { type: 'string', optional: true },
|
||||||
|
useRealName: { type: 'bool', optional: true },
|
||||||
|
FileUpload_MediaTypeWhiteList: { type: 'string', optional: true },
|
||||||
|
FileUpload_MaxFileSize: { type: 'int', optional: true },
|
||||||
roomsUpdatedAt: { type: 'date', optional: true },
|
roomsUpdatedAt: { type: 'date', optional: true },
|
||||||
version: 'string?'
|
version: 'string?'
|
||||||
}
|
}
|
||||||
|
@ -408,12 +412,12 @@ const inMemorySchema = [usersTypingSchema, activeUsersSchema];
|
||||||
class DB {
|
class DB {
|
||||||
databases = {
|
databases = {
|
||||||
serversDB: new Realm({
|
serversDB: new Realm({
|
||||||
path: 'default.realm',
|
path: `${ RNRealmPath.realmPath }default.realm`,
|
||||||
schema: [
|
schema: [
|
||||||
userSchema,
|
userSchema,
|
||||||
serversSchema
|
serversSchema
|
||||||
],
|
],
|
||||||
schemaVersion: 9,
|
schemaVersion: 10,
|
||||||
migration: (oldRealm, newRealm) => {
|
migration: (oldRealm, newRealm) => {
|
||||||
if (oldRealm.schemaVersion >= 1 && newRealm.schemaVersion <= 9) {
|
if (oldRealm.schemaVersion >= 1 && newRealm.schemaVersion <= 9) {
|
||||||
const newServers = newRealm.objects('servers');
|
const newServers = newRealm.objects('servers');
|
||||||
|
@ -426,7 +430,7 @@ class DB {
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
inMemoryDB: new Realm({
|
inMemoryDB: new Realm({
|
||||||
path: 'memory.realm',
|
path: `${ RNRealmPath.realmPath }memory.realm`,
|
||||||
schema: inMemorySchema,
|
schema: inMemorySchema,
|
||||||
schemaVersion: 2,
|
schemaVersion: 2,
|
||||||
inMemory: true
|
inMemory: true
|
||||||
|
@ -468,7 +472,7 @@ class DB {
|
||||||
setActiveDB(database = '') {
|
setActiveDB(database = '') {
|
||||||
const path = database.replace(/(^\w+:|^)\/\//, '');
|
const path = database.replace(/(^\w+:|^)\/\//, '');
|
||||||
return this.databases.activeDB = new Realm({
|
return this.databases.activeDB = new Realm({
|
||||||
path: `${ path }.realm`,
|
path: `${ RNRealmPath.realmPath }${ path }.realm`,
|
||||||
schema,
|
schema,
|
||||||
schemaVersion: 13,
|
schemaVersion: 13,
|
||||||
migration: (oldRealm, newRealm) => {
|
migration: (oldRealm, newRealm) => {
|
||||||
|
|
|
@ -14,6 +14,9 @@ import {
|
||||||
setUser, setLoginServices, loginRequest, loginFailure, logout
|
setUser, setLoginServices, loginRequest, loginFailure, logout
|
||||||
} from '../actions/login';
|
} from '../actions/login';
|
||||||
import { disconnect, connectSuccess, connectRequest } from '../actions/connect';
|
import { disconnect, connectSuccess, connectRequest } from '../actions/connect';
|
||||||
|
import {
|
||||||
|
shareSelectServer, shareSetUser
|
||||||
|
} from '../actions/share';
|
||||||
|
|
||||||
import subscribeRooms from './methods/subscriptions/rooms';
|
import subscribeRooms from './methods/subscriptions/rooms';
|
||||||
import subscribeRoom from './methods/subscriptions/room';
|
import subscribeRoom from './methods/subscriptions/room';
|
||||||
|
@ -217,6 +220,35 @@ const RocketChat = {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
async shareExtensionInit(server) {
|
||||||
|
database.setActiveDB(server);
|
||||||
|
|
||||||
|
if (this.sdk) {
|
||||||
|
this.sdk.disconnect();
|
||||||
|
this.sdk = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use useSsl: false only if server url starts with http://
|
||||||
|
const useSsl = !/http:\/\//.test(server);
|
||||||
|
|
||||||
|
this.sdk = new RocketchatClient({ host: server, protocol: 'ddp', useSsl });
|
||||||
|
|
||||||
|
// set Server
|
||||||
|
const { serversDB } = database.databases;
|
||||||
|
reduxStore.dispatch(shareSelectServer(server));
|
||||||
|
|
||||||
|
// set User info
|
||||||
|
const userId = await RNUserDefaults.get(`${ RocketChat.TOKEN_KEY }-${ server }`);
|
||||||
|
const user = userId && serversDB.objectForPrimaryKey('user', userId);
|
||||||
|
reduxStore.dispatch(shareSetUser({
|
||||||
|
id: user.id,
|
||||||
|
token: user.token,
|
||||||
|
username: user.username
|
||||||
|
}));
|
||||||
|
|
||||||
|
await RocketChat.login({ resume: user.token });
|
||||||
|
},
|
||||||
|
|
||||||
register(credentials) {
|
register(credentials) {
|
||||||
// RC 0.50.0
|
// RC 0.50.0
|
||||||
return this.sdk.post('users.register', credentials, false);
|
return this.sdk.post('users.register', credentials, false);
|
||||||
|
@ -730,14 +762,14 @@ const RocketChat = {
|
||||||
return JSON.parse(useMarkdown);
|
return JSON.parse(useMarkdown);
|
||||||
},
|
},
|
||||||
async getSortPreferences() {
|
async getSortPreferences() {
|
||||||
const prefs = await AsyncStorage.getItem(SORT_PREFS_KEY);
|
const prefs = await RNUserDefaults.objectForKey(SORT_PREFS_KEY);
|
||||||
return JSON.parse(prefs);
|
return prefs;
|
||||||
},
|
},
|
||||||
async saveSortPreference(param) {
|
async saveSortPreference(param) {
|
||||||
try {
|
try {
|
||||||
let prefs = await RocketChat.getSortPreferences();
|
let prefs = await RocketChat.getSortPreferences();
|
||||||
prefs = { ...prefs, ...param };
|
prefs = { ...prefs, ...param };
|
||||||
return await AsyncStorage.setItem(SORT_PREFS_KEY, JSON.stringify(prefs));
|
return await RNUserDefaults.setObjectForKey(SORT_PREFS_KEY, prefs);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.warn(error);
|
console.warn(error);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,9 @@ import PropTypes from 'prop-types';
|
||||||
import Avatar from '../../containers/Avatar';
|
import Avatar from '../../containers/Avatar';
|
||||||
import Touch from '../../utils/touch';
|
import Touch from '../../utils/touch';
|
||||||
import RoomTypeIcon from '../../containers/RoomTypeIcon';
|
import RoomTypeIcon from '../../containers/RoomTypeIcon';
|
||||||
import styles from './styles';
|
import styles, { ROW_HEIGHT } from './styles';
|
||||||
|
|
||||||
|
export { ROW_HEIGHT };
|
||||||
|
|
||||||
const DirectoryItemLabel = React.memo(({ text }) => {
|
const DirectoryItemLabel = React.memo(({ text }) => {
|
||||||
if (!text) {
|
if (!text) {
|
||||||
|
@ -30,10 +32,10 @@ const DirectoryItem = ({
|
||||||
/>
|
/>
|
||||||
<View style={styles.directoryItemTextContainer}>
|
<View style={styles.directoryItemTextContainer}>
|
||||||
<View style={styles.directoryItemTextTitle}>
|
<View style={styles.directoryItemTextTitle}>
|
||||||
<RoomTypeIcon type='c' />
|
<RoomTypeIcon type={type} />
|
||||||
<Text style={styles.directoryItemName} numberOfLines={1}>{title}</Text>
|
<Text style={styles.directoryItemName} numberOfLines={1}>{title}</Text>
|
||||||
</View>
|
</View>
|
||||||
<Text style={styles.directoryItemUsername} numberOfLines={1}>{description}</Text>
|
{ description ? <Text style={styles.directoryItemUsername} numberOfLines={1}>{description}</Text> : null }
|
||||||
</View>
|
</View>
|
||||||
<DirectoryItemLabel text={rightLabel} />
|
<DirectoryItemLabel text={rightLabel} />
|
||||||
</View>
|
</View>
|
|
@ -0,0 +1,49 @@
|
||||||
|
import { StyleSheet } from 'react-native';
|
||||||
|
|
||||||
|
import { COLOR_WHITE } from '../../constants/colors';
|
||||||
|
import sharedStyles from '../../views/Styles';
|
||||||
|
|
||||||
|
export const ROW_HEIGHT = 54;
|
||||||
|
|
||||||
|
export default StyleSheet.create({
|
||||||
|
directoryItemButton: {
|
||||||
|
height: ROW_HEIGHT,
|
||||||
|
backgroundColor: COLOR_WHITE
|
||||||
|
},
|
||||||
|
directoryItemContainer: {
|
||||||
|
flex: 1,
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
paddingHorizontal: 15
|
||||||
|
},
|
||||||
|
directoryItemAvatar: {
|
||||||
|
marginRight: 12
|
||||||
|
},
|
||||||
|
directoryItemTextTitle: {
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center'
|
||||||
|
},
|
||||||
|
directoryItemTextContainer: {
|
||||||
|
flex: 1,
|
||||||
|
flexDirection: 'column',
|
||||||
|
justifyContent: 'center'
|
||||||
|
},
|
||||||
|
directoryItemName: {
|
||||||
|
flex: 1,
|
||||||
|
fontSize: 17,
|
||||||
|
...sharedStyles.textMedium,
|
||||||
|
...sharedStyles.textColorNormal
|
||||||
|
},
|
||||||
|
directoryItemUsername: {
|
||||||
|
fontSize: 14,
|
||||||
|
...sharedStyles.textRegular,
|
||||||
|
...sharedStyles.textColorDescription
|
||||||
|
},
|
||||||
|
directoryItemLabel: {
|
||||||
|
fontSize: 14,
|
||||||
|
paddingLeft: 10,
|
||||||
|
...sharedStyles.textRegular,
|
||||||
|
...sharedStyles.textColorDescription
|
||||||
|
}
|
||||||
|
});
|
|
@ -1,5 +1,4 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import moment from 'moment';
|
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { View, Text, Animated } from 'react-native';
|
import { View, Text, Animated } from 'react-native';
|
||||||
import { RectButton, PanGestureHandler, State } from 'react-native-gesture-handler';
|
import { RectButton, PanGestureHandler, State } from 'react-native-gesture-handler';
|
||||||
|
@ -12,6 +11,7 @@ import styles, {
|
||||||
import UnreadBadge from './UnreadBadge';
|
import UnreadBadge from './UnreadBadge';
|
||||||
import TypeIcon from './TypeIcon';
|
import TypeIcon from './TypeIcon';
|
||||||
import LastMessage from './LastMessage';
|
import LastMessage from './LastMessage';
|
||||||
|
import { capitalize, formatDate } from '../../utils/room';
|
||||||
import { LeftActions, RightActions } from './Actions';
|
import { LeftActions, RightActions } from './Actions';
|
||||||
|
|
||||||
export { ROW_HEIGHT };
|
export { ROW_HEIGHT };
|
||||||
|
@ -203,19 +203,12 @@ export default class RoomItem extends React.Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
formatDate = date => moment(date).calendar(null, {
|
|
||||||
lastDay: `[${ I18n.t('Yesterday') }]`,
|
|
||||||
sameDay: 'h:mm A',
|
|
||||||
lastWeek: 'dddd',
|
|
||||||
sameElse: 'MMM D'
|
|
||||||
})
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
unread, userMentions, name, _updatedAt, alert, testID, type, avatarSize, baseUrl, userId, username, token, id, prid, showLastMessage, lastMessage, isRead, width, favorite
|
unread, userMentions, name, _updatedAt, alert, testID, type, avatarSize, baseUrl, userId, username, token, id, prid, showLastMessage, lastMessage, isRead, width, favorite
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
const date = this.formatDate(_updatedAt);
|
const date = formatDate(_updatedAt);
|
||||||
|
|
||||||
let accessibilityLabel = name;
|
let accessibilityLabel = name;
|
||||||
if (unread === 1) {
|
if (unread === 1) {
|
||||||
|
@ -275,7 +268,7 @@ export default class RoomItem extends React.Component {
|
||||||
<View style={styles.titleContainer}>
|
<View style={styles.titleContainer}>
|
||||||
<TypeIcon type={type} id={id} prid={prid} />
|
<TypeIcon type={type} id={id} prid={prid} />
|
||||||
<Text style={[styles.title, alert && styles.alert]} ellipsizeMode='tail' numberOfLines={1}>{ name }</Text>
|
<Text style={[styles.title, alert && styles.alert]} ellipsizeMode='tail' numberOfLines={1}>{ name }</Text>
|
||||||
{_updatedAt ? <Text style={[styles.date, alert && styles.updateAlert]} ellipsizeMode='tail' numberOfLines={1}>{ date }</Text> : null}
|
{_updatedAt ? <Text style={[styles.date, alert && styles.updateAlert]} ellipsizeMode='tail' numberOfLines={1}>{ capitalize(date) }</Text> : null}
|
||||||
</View>
|
</View>
|
||||||
<View style={styles.row}>
|
<View style={styles.row}>
|
||||||
<LastMessage lastMessage={lastMessage} type={type} showLastMessage={showLastMessage} username={username} alert={alert} />
|
<LastMessage lastMessage={lastMessage} type={type} showLastMessage={showLastMessage} username={username} alert={alert} />
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { View, Text } from 'react-native';
|
||||||
|
import FastImage from 'react-native-fast-image';
|
||||||
|
import { RectButton } from 'react-native-gesture-handler';
|
||||||
|
|
||||||
|
import log from '../../utils/log';
|
||||||
|
import Check from '../../containers/Check';
|
||||||
|
import styles, { ROW_HEIGHT } from './styles';
|
||||||
|
|
||||||
|
export { ROW_HEIGHT };
|
||||||
|
|
||||||
|
const ServerItem = React.memo(({
|
||||||
|
server, item, onPress, hasCheck
|
||||||
|
}) => (
|
||||||
|
<RectButton onPress={onPress} style={styles.serverItem} testID={`rooms-list-header-server-${ item.id }`}>
|
||||||
|
<View style={styles.serverItemContainer}>
|
||||||
|
{item.iconURL
|
||||||
|
? (
|
||||||
|
<FastImage
|
||||||
|
source={{
|
||||||
|
uri: item.iconURL,
|
||||||
|
priority: FastImage.priority.high
|
||||||
|
}}
|
||||||
|
defaultSource={{ uri: 'logo' }}
|
||||||
|
style={styles.serverIcon}
|
||||||
|
onError={() => log('err_loading_server_icon')}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
: (
|
||||||
|
<FastImage
|
||||||
|
source={{ uri: 'logo' }}
|
||||||
|
style={styles.serverIcon}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
<View style={styles.serverTextContainer}>
|
||||||
|
<Text style={styles.serverName}>{item.name || item.id}</Text>
|
||||||
|
<Text style={styles.serverUrl}>{item.id}</Text>
|
||||||
|
</View>
|
||||||
|
{item.id === server && hasCheck ? <Check /> : null}
|
||||||
|
</View>
|
||||||
|
</RectButton>
|
||||||
|
));
|
||||||
|
|
||||||
|
ServerItem.propTypes = {
|
||||||
|
onPress: PropTypes.func.isRequired,
|
||||||
|
item: PropTypes.object.isRequired,
|
||||||
|
hasCheck: PropTypes.bool,
|
||||||
|
server: PropTypes.string
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ServerItem;
|
|
@ -0,0 +1,39 @@
|
||||||
|
import { StyleSheet } from 'react-native';
|
||||||
|
|
||||||
|
import sharedStyles from '../../views/Styles';
|
||||||
|
import { COLOR_WHITE } from '../../constants/colors';
|
||||||
|
|
||||||
|
export const ROW_HEIGHT = 56;
|
||||||
|
|
||||||
|
export default StyleSheet.create({
|
||||||
|
serverItem: {
|
||||||
|
height: ROW_HEIGHT,
|
||||||
|
backgroundColor: COLOR_WHITE,
|
||||||
|
justifyContent: 'center'
|
||||||
|
},
|
||||||
|
serverItemContainer: {
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center'
|
||||||
|
},
|
||||||
|
serverIcon: {
|
||||||
|
width: 44,
|
||||||
|
height: 44,
|
||||||
|
marginHorizontal: 15,
|
||||||
|
borderRadius: 4
|
||||||
|
},
|
||||||
|
serverTextContainer: {
|
||||||
|
flex: 1,
|
||||||
|
flexDirection: 'column',
|
||||||
|
justifyContent: 'center'
|
||||||
|
},
|
||||||
|
serverName: {
|
||||||
|
fontSize: 18,
|
||||||
|
...sharedStyles.textColorNormal,
|
||||||
|
...sharedStyles.textSemibold
|
||||||
|
},
|
||||||
|
serverUrl: {
|
||||||
|
fontSize: 15,
|
||||||
|
...sharedStyles.textColorDescription,
|
||||||
|
...sharedStyles.textRegular
|
||||||
|
}
|
||||||
|
});
|
|
@ -11,6 +11,7 @@ import app from './app';
|
||||||
import sortPreferences from './sortPreferences';
|
import sortPreferences from './sortPreferences';
|
||||||
import notification from './notification';
|
import notification from './notification';
|
||||||
import markdown from './markdown';
|
import markdown from './markdown';
|
||||||
|
import share from './share';
|
||||||
|
|
||||||
export default combineReducers({
|
export default combineReducers({
|
||||||
settings,
|
settings,
|
||||||
|
@ -24,5 +25,6 @@ export default combineReducers({
|
||||||
rooms,
|
rooms,
|
||||||
sortPreferences,
|
sortPreferences,
|
||||||
notification,
|
notification,
|
||||||
markdown
|
markdown,
|
||||||
|
share
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
import { SHARE } from '../actions/actionsTypes';
|
||||||
|
|
||||||
|
const initialState = {
|
||||||
|
user: {},
|
||||||
|
server: ''
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function share(state = initialState, action) {
|
||||||
|
switch (action.type) {
|
||||||
|
case SHARE.SELECT_SERVER:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
server: action.server
|
||||||
|
};
|
||||||
|
case SHARE.SET_USER:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
user: action.user
|
||||||
|
};
|
||||||
|
default:
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,12 +2,15 @@ import {
|
||||||
put, call, takeLatest, select, take, fork, cancel
|
put, call, takeLatest, select, take, fork, cancel
|
||||||
} from 'redux-saga/effects';
|
} from 'redux-saga/effects';
|
||||||
import RNUserDefaults from 'rn-user-defaults';
|
import RNUserDefaults from 'rn-user-defaults';
|
||||||
|
import moment from 'moment';
|
||||||
|
import 'moment/min/locales';
|
||||||
|
|
||||||
import * as types from '../actions/actionsTypes';
|
import * as types from '../actions/actionsTypes';
|
||||||
import { appStart } from '../actions';
|
import { appStart } from '../actions';
|
||||||
import { serverFinishAdd, selectServerRequest } from '../actions/server';
|
import { serverFinishAdd, selectServerRequest } from '../actions/server';
|
||||||
import { loginFailure, loginSuccess, setUser } from '../actions/login';
|
import { loginFailure, loginSuccess, setUser } from '../actions/login';
|
||||||
import { roomsRequest } from '../actions/rooms';
|
import { roomsRequest } from '../actions/rooms';
|
||||||
|
import { toMomentLocale } from '../utils/moment';
|
||||||
import RocketChat from '../lib/rocketchat';
|
import RocketChat from '../lib/rocketchat';
|
||||||
import log from '../utils/log';
|
import log from '../utils/log';
|
||||||
import I18n from '../i18n';
|
import I18n from '../i18n';
|
||||||
|
@ -72,6 +75,7 @@ const handleLoginSuccess = function* handleLoginSuccess({ user }) {
|
||||||
yield fork(fetchUserPresence);
|
yield fork(fetchUserPresence);
|
||||||
|
|
||||||
I18n.locale = user.language;
|
I18n.locale = user.language;
|
||||||
|
moment.locale(toMomentLocale(user.language));
|
||||||
|
|
||||||
const { serversDB } = database.databases;
|
const { serversDB } = database.databases;
|
||||||
serversDB.write(() => {
|
serversDB.write(() => {
|
||||||
|
@ -132,6 +136,7 @@ const handleLogout = function* handleLogout() {
|
||||||
const handleSetUser = function handleSetUser({ user }) {
|
const handleSetUser = function handleSetUser({ user }) {
|
||||||
if (user && user.language) {
|
if (user && user.language) {
|
||||||
I18n.locale = user.language;
|
I18n.locale = user.language;
|
||||||
|
moment.locale(toMomentLocale(user.language));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,98 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { View } from 'react-native';
|
||||||
|
import { createAppContainer, createStackNavigator, createSwitchNavigator } from 'react-navigation';
|
||||||
|
import { Provider } from 'react-redux';
|
||||||
|
import RNUserDefaults from 'rn-user-defaults';
|
||||||
|
|
||||||
|
import Navigation from './lib/ShareNavigation';
|
||||||
|
import store from './lib/createStore';
|
||||||
|
import sharedStyles from './views/Styles';
|
||||||
|
import { isNotch, isIOS } from './utils/deviceInfo';
|
||||||
|
import { defaultHeader, onNavigationStateChange } from './utils/navigation';
|
||||||
|
import RocketChat from './lib/rocketchat';
|
||||||
|
|
||||||
|
const InsideNavigator = createStackNavigator({
|
||||||
|
ShareListView: {
|
||||||
|
getScreen: () => require('./views/ShareListView').default
|
||||||
|
},
|
||||||
|
ShareView: {
|
||||||
|
getScreen: () => require('./views/ShareView').default
|
||||||
|
},
|
||||||
|
SelectServerView: {
|
||||||
|
getScreen: () => require('./views/SelectServerView').default
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
initialRouteName: 'ShareListView',
|
||||||
|
defaultNavigationOptions: defaultHeader
|
||||||
|
});
|
||||||
|
|
||||||
|
const OutsideNavigator = createStackNavigator({
|
||||||
|
WithoutServersView: {
|
||||||
|
getScreen: () => require('./views/WithoutServersView').default
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
initialRouteName: 'WithoutServersView',
|
||||||
|
defaultNavigationOptions: defaultHeader
|
||||||
|
});
|
||||||
|
|
||||||
|
const AppContainer = createAppContainer(createSwitchNavigator({
|
||||||
|
OutsideStack: OutsideNavigator,
|
||||||
|
InsideStack: InsideNavigator,
|
||||||
|
AuthLoading: {
|
||||||
|
getScreen: () => require('./views/AuthLoadingView').default
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
initialRouteName: 'AuthLoading'
|
||||||
|
}));
|
||||||
|
|
||||||
|
class Root extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
isLandscape: false
|
||||||
|
};
|
||||||
|
this.init();
|
||||||
|
}
|
||||||
|
|
||||||
|
init = async() => {
|
||||||
|
if (isIOS) {
|
||||||
|
await RNUserDefaults.setName('group.ios.chat.rocket');
|
||||||
|
}
|
||||||
|
const currentServer = await RNUserDefaults.get('currentServer');
|
||||||
|
const token = await RNUserDefaults.get(RocketChat.TOKEN_KEY);
|
||||||
|
|
||||||
|
if (currentServer && token) {
|
||||||
|
await Navigation.navigate('InsideStack');
|
||||||
|
await RocketChat.shareExtensionInit(currentServer);
|
||||||
|
} else {
|
||||||
|
await Navigation.navigate('OutsideStack');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handleLayout = (event) => {
|
||||||
|
const { width, height } = event.nativeEvent.layout;
|
||||||
|
this.setState({ isLandscape: width > height });
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { isLandscape } = this.state;
|
||||||
|
return (
|
||||||
|
<View
|
||||||
|
style={[sharedStyles.container, isLandscape && isNotch ? sharedStyles.notchLandscapeContainer : {}]}
|
||||||
|
onLayout={this.handleLayout}
|
||||||
|
>
|
||||||
|
<Provider store={store}>
|
||||||
|
<AppContainer
|
||||||
|
ref={(navigatorRef) => {
|
||||||
|
Navigation.setTopLevelNavigator(navigatorRef);
|
||||||
|
}}
|
||||||
|
onNavigationStateChange={onNavigationStateChange}
|
||||||
|
/>
|
||||||
|
</Provider>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Root;
|
|
@ -1,32 +1,3 @@
|
||||||
import React from 'react';
|
import { Alert } from 'react-native';
|
||||||
import { Alert, StyleSheet } from 'react-native';
|
|
||||||
import EasyToast from 'react-native-easy-toast';
|
|
||||||
|
|
||||||
import { COLOR_TOAST, COLOR_WHITE } from '../constants/colors';
|
|
||||||
import { isNotch } from './deviceInfo';
|
|
||||||
import sharedStyles from '../views/Styles';
|
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
|
||||||
toast: {
|
|
||||||
backgroundColor: COLOR_TOAST
|
|
||||||
},
|
|
||||||
text: {
|
|
||||||
...sharedStyles.textRegular,
|
|
||||||
color: COLOR_WHITE,
|
|
||||||
fontSize: 14
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const positionValue = isNotch ? 230 : 200;
|
|
||||||
|
|
||||||
export const Toast = React.forwardRef((props, ref) => (
|
|
||||||
<EasyToast
|
|
||||||
{...props}
|
|
||||||
ref={ref}
|
|
||||||
positionValue={positionValue}
|
|
||||||
style={styles.toast}
|
|
||||||
textStyle={styles.text}
|
|
||||||
opacity={0.8}
|
|
||||||
/>
|
|
||||||
));
|
|
||||||
export const showErrorAlert = (message, title, onPress = () => {}) => Alert.alert(title, message, [{ text: 'OK', onPress }], { cancelable: true });
|
export const showErrorAlert = (message, title, onPress = () => {}) => Alert.alert(title, message, [{ text: 'OK', onPress }], { cancelable: true });
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
export const canUploadFile = (file, serverInfo) => {
|
||||||
|
const { FileUpload_MediaTypeWhiteList, FileUpload_MaxFileSize } = serverInfo;
|
||||||
|
if (!(file && file.path)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (file.size > FileUpload_MaxFileSize) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// if white list is empty, all media types are enabled
|
||||||
|
if (!FileUpload_MediaTypeWhiteList) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
const allowedMime = FileUpload_MediaTypeWhiteList.split(',');
|
||||||
|
if (allowedMime.includes(file.mime)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
const wildCardGlob = '/*';
|
||||||
|
const wildCards = allowedMime.filter(item => item.indexOf(wildCardGlob) > 0);
|
||||||
|
if (wildCards.includes(file.mime.replace(/(\/.*)$/, wildCardGlob))) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
|
@ -0,0 +1,11 @@
|
||||||
|
const localeKeys = {
|
||||||
|
en: 'en',
|
||||||
|
ru: 'ru',
|
||||||
|
'pt-BR': 'pt-br',
|
||||||
|
'zh-CN': 'zh-cn',
|
||||||
|
fr: 'fr',
|
||||||
|
de: 'de',
|
||||||
|
'pt-PT': 'pt'
|
||||||
|
};
|
||||||
|
|
||||||
|
export const toMomentLocale = locale => localeKeys[locale];
|
|
@ -0,0 +1,36 @@
|
||||||
|
import firebase from 'react-native-firebase';
|
||||||
|
|
||||||
|
import { HEADER_BACKGROUND, HEADER_TITLE, HEADER_BACK } from '../constants/colors';
|
||||||
|
|
||||||
|
export const defaultHeader = {
|
||||||
|
headerStyle: {
|
||||||
|
backgroundColor: HEADER_BACKGROUND
|
||||||
|
},
|
||||||
|
headerTitleStyle: {
|
||||||
|
color: HEADER_TITLE
|
||||||
|
},
|
||||||
|
headerBackTitle: null,
|
||||||
|
headerTintColor: HEADER_BACK
|
||||||
|
};
|
||||||
|
|
||||||
|
// gets the current screen from navigation state
|
||||||
|
export const getActiveRouteName = (navigationState) => {
|
||||||
|
if (!navigationState) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const route = navigationState.routes[navigationState.index];
|
||||||
|
// dive into nested navigators
|
||||||
|
if (route.routes) {
|
||||||
|
return getActiveRouteName(route);
|
||||||
|
}
|
||||||
|
return route.routeName;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const onNavigationStateChange = (prevState, currentState) => {
|
||||||
|
const currentScreen = getActiveRouteName(currentState);
|
||||||
|
const prevScreen = getActiveRouteName(prevState);
|
||||||
|
|
||||||
|
if (prevScreen !== currentScreen) {
|
||||||
|
firebase.analytics().setCurrentScreen(currentScreen);
|
||||||
|
}
|
||||||
|
};
|
|
@ -0,0 +1,36 @@
|
||||||
|
import moment from 'moment';
|
||||||
|
|
||||||
|
import I18n from '../i18n';
|
||||||
|
|
||||||
|
export const isOwner = room => room && room.roles && room.roles.length && !!room.roles.find(role => role === 'owner');
|
||||||
|
|
||||||
|
export const isMuted = (room, user) => room && room.muted && room.muted.find && !!room.muted.find(m => m === user.username);
|
||||||
|
|
||||||
|
export const isReadOnly = (room, user) => {
|
||||||
|
if (isOwner(room)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return (room && room.ro) || isMuted(room, user);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const isBlocked = (room) => {
|
||||||
|
if (room) {
|
||||||
|
const { t, blocked, blocker } = room;
|
||||||
|
if (t === 'd' && (blocked || blocker)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const capitalize = (s) => {
|
||||||
|
if (typeof s !== 'string') { return ''; }
|
||||||
|
return s.charAt(0).toUpperCase() + s.slice(1);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const formatDate = date => moment(date).calendar(null, {
|
||||||
|
lastDay: `[${ I18n.t('Yesterday') }]`,
|
||||||
|
sameDay: 'LT',
|
||||||
|
lastWeek: 'dddd',
|
||||||
|
sameElse: 'MMM D'
|
||||||
|
});
|
|
@ -7,7 +7,7 @@ import { connect } from 'react-redux';
|
||||||
import { SafeAreaView } from 'react-navigation';
|
import { SafeAreaView } from 'react-navigation';
|
||||||
|
|
||||||
import RocketChat from '../../lib/rocketchat';
|
import RocketChat from '../../lib/rocketchat';
|
||||||
import DirectoryItem from './DirectoryItem';
|
import DirectoryItem from '../../presentation/DirectoryItem';
|
||||||
import sharedStyles from '../Styles';
|
import sharedStyles from '../Styles';
|
||||||
import I18n from '../../i18n';
|
import I18n from '../../i18n';
|
||||||
import Touch from '../../utils/touch';
|
import Touch from '../../utils/touch';
|
||||||
|
|
|
@ -98,46 +98,6 @@ export default StyleSheet.create({
|
||||||
marginHorizontal: 15,
|
marginHorizontal: 15,
|
||||||
flex: 1
|
flex: 1
|
||||||
},
|
},
|
||||||
directoryItemButton: {
|
|
||||||
height: 54,
|
|
||||||
backgroundColor: COLOR_WHITE
|
|
||||||
},
|
|
||||||
directoryItemContainer: {
|
|
||||||
flex: 1,
|
|
||||||
flexDirection: 'row',
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'center',
|
|
||||||
paddingHorizontal: 15
|
|
||||||
},
|
|
||||||
directoryItemAvatar: {
|
|
||||||
marginRight: 12
|
|
||||||
},
|
|
||||||
directoryItemTextTitle: {
|
|
||||||
flexDirection: 'row',
|
|
||||||
alignItems: 'center'
|
|
||||||
},
|
|
||||||
directoryItemTextContainer: {
|
|
||||||
flex: 1,
|
|
||||||
flexDirection: 'column',
|
|
||||||
justifyContent: 'center'
|
|
||||||
},
|
|
||||||
directoryItemName: {
|
|
||||||
flex: 1,
|
|
||||||
fontSize: 17,
|
|
||||||
...sharedStyles.textMedium,
|
|
||||||
...sharedStyles.textColorNormal
|
|
||||||
},
|
|
||||||
directoryItemUsername: {
|
|
||||||
fontSize: 14,
|
|
||||||
...sharedStyles.textRegular,
|
|
||||||
...sharedStyles.textColorDescription
|
|
||||||
},
|
|
||||||
directoryItemLabel: {
|
|
||||||
fontSize: 14,
|
|
||||||
paddingLeft: 10,
|
|
||||||
...sharedStyles.textRegular,
|
|
||||||
...sharedStyles.textColorDescription
|
|
||||||
},
|
|
||||||
inverted: {
|
inverted: {
|
||||||
transform: [{ scaleY: -1 }]
|
transform: [{ scaleY: -1 }]
|
||||||
},
|
},
|
||||||
|
|
|
@ -13,7 +13,9 @@ import KeyboardView from '../../presentation/KeyboardView';
|
||||||
import sharedStyles from '../Styles';
|
import sharedStyles from '../Styles';
|
||||||
import styles from './styles';
|
import styles from './styles';
|
||||||
import scrollPersistTaps from '../../utils/scrollPersistTaps';
|
import scrollPersistTaps from '../../utils/scrollPersistTaps';
|
||||||
import { showErrorAlert, Toast } from '../../utils/info';
|
import { showErrorAlert } from '../../utils/info';
|
||||||
|
import { LISTENER } from '../../containers/Toast';
|
||||||
|
import EventEmitter from '../../utils/events';
|
||||||
import RocketChat from '../../lib/rocketchat';
|
import RocketChat from '../../lib/rocketchat';
|
||||||
import RCTextInput from '../../containers/TextInput';
|
import RCTextInput from '../../containers/TextInput';
|
||||||
import log from '../../utils/log';
|
import log from '../../utils/log';
|
||||||
|
@ -222,7 +224,7 @@ export default class ProfileView extends React.Component {
|
||||||
setUser({ ...params });
|
setUser({ ...params });
|
||||||
}
|
}
|
||||||
this.setState({ saving: false, showPasswordAlert: false });
|
this.setState({ saving: false, showPasswordAlert: false });
|
||||||
this.toast.show(I18n.t('Profile_saved_successfully'));
|
EventEmitter.emit(LISTENER, { message: I18n.t('Profile_saved_successfully') });
|
||||||
this.init();
|
this.init();
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -235,7 +237,7 @@ export default class ProfileView extends React.Component {
|
||||||
try {
|
try {
|
||||||
const { user } = this.props;
|
const { user } = this.props;
|
||||||
await RocketChat.resetAvatar(user.id);
|
await RocketChat.resetAvatar(user.id);
|
||||||
this.toast.show(I18n.t('Avatar_changed_successfully'));
|
EventEmitter.emit(LISTENER, { message: I18n.t('Avatar_changed_successfully') });
|
||||||
this.init();
|
this.init();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.handleError(e, 'resetAvatar', 'changing_avatar');
|
this.handleError(e, 'resetAvatar', 'changing_avatar');
|
||||||
|
@ -386,7 +388,6 @@ export default class ProfileView extends React.Component {
|
||||||
keyboardVerticalOffset={128}
|
keyboardVerticalOffset={128}
|
||||||
>
|
>
|
||||||
<StatusBar />
|
<StatusBar />
|
||||||
<Toast ref={toast => this.toast = toast} />
|
|
||||||
<ScrollView
|
<ScrollView
|
||||||
contentContainerStyle={sharedStyles.containerScrollView}
|
contentContainerStyle={sharedStyles.containerScrollView}
|
||||||
testID='profile-view-list'
|
testID='profile-view-list'
|
||||||
|
|
|
@ -12,7 +12,9 @@ import KeyboardView from '../../presentation/KeyboardView';
|
||||||
import sharedStyles from '../Styles';
|
import sharedStyles from '../Styles';
|
||||||
import styles from './styles';
|
import styles from './styles';
|
||||||
import scrollPersistTaps from '../../utils/scrollPersistTaps';
|
import scrollPersistTaps from '../../utils/scrollPersistTaps';
|
||||||
import { showErrorAlert, Toast } from '../../utils/info';
|
import { showErrorAlert } from '../../utils/info';
|
||||||
|
import { LISTENER } from '../../containers/Toast';
|
||||||
|
import EventEmitter from '../../utils/events';
|
||||||
import database, { safeAddListener } from '../../lib/realm';
|
import database, { safeAddListener } from '../../lib/realm';
|
||||||
import RocketChat from '../../lib/rocketchat';
|
import RocketChat from '../../lib/rocketchat';
|
||||||
import RCTextInput from '../../containers/TextInput';
|
import RCTextInput from '../../containers/TextInput';
|
||||||
|
@ -215,7 +217,7 @@ export default class RoomInfoEditView extends React.Component {
|
||||||
if (error) {
|
if (error) {
|
||||||
showErrorAlert(I18n.t('There_was_an_error_while_action', { action: I18n.t('saving_settings') }));
|
showErrorAlert(I18n.t('There_was_an_error_while_action', { action: I18n.t('saving_settings') }));
|
||||||
} else {
|
} else {
|
||||||
this.toast.show(I18n.t('Settings_succesfully_changed'));
|
EventEmitter.emit(LISTENER, { message: I18n.t('Settings_succesfully_changed') });
|
||||||
}
|
}
|
||||||
}, 100);
|
}, 100);
|
||||||
}
|
}
|
||||||
|
@ -428,7 +430,6 @@ export default class RoomInfoEditView extends React.Component {
|
||||||
<Text style={[sharedStyles.button_inverted, styles.colorDanger]} accessibilityTraits='button'>{I18n.t('DELETE')}</Text>
|
<Text style={[sharedStyles.button_inverted, styles.colorDanger]} accessibilityTraits='button'>{I18n.t('DELETE')}</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
<Loading visible={saving} />
|
<Loading visible={saving} />
|
||||||
<Toast ref={toast => this.toast = toast} />
|
|
||||||
</SafeAreaView>
|
</SafeAreaView>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
</KeyboardView>
|
</KeyboardView>
|
||||||
|
|
|
@ -12,7 +12,8 @@ import UserItem from '../../presentation/UserItem';
|
||||||
import scrollPersistTaps from '../../utils/scrollPersistTaps';
|
import scrollPersistTaps from '../../utils/scrollPersistTaps';
|
||||||
import RocketChat from '../../lib/rocketchat';
|
import RocketChat from '../../lib/rocketchat';
|
||||||
import database, { safeAddListener } from '../../lib/realm';
|
import database, { safeAddListener } from '../../lib/realm';
|
||||||
import { Toast } from '../../utils/info';
|
import { LISTENER } from '../../containers/Toast';
|
||||||
|
import EventEmitter from '../../utils/events';
|
||||||
import log from '../../utils/log';
|
import log from '../../utils/log';
|
||||||
import I18n from '../../i18n';
|
import I18n from '../../i18n';
|
||||||
import SearchBox from '../../containers/SearchBox';
|
import SearchBox from '../../containers/SearchBox';
|
||||||
|
@ -232,7 +233,7 @@ export default class RoomMembersView extends React.Component {
|
||||||
const { rid, userLongPressed } = this.state;
|
const { rid, userLongPressed } = this.state;
|
||||||
try {
|
try {
|
||||||
await RocketChat.toggleMuteUserInRoom(rid, userLongPressed.username, !userLongPressed.muted);
|
await RocketChat.toggleMuteUserInRoom(rid, userLongPressed.username, !userLongPressed.muted);
|
||||||
this.toast.show(I18n.t('User_has_been_key', { key: userLongPressed.muted ? I18n.t('unmuted') : I18n.t('muted') }));
|
EventEmitter.emit(LISTENER, { message: I18n.t('User_has_been_key', { key: userLongPressed.muted ? I18n.t('unmuted') : I18n.t('muted') }) });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
log('err_handle_mute', e);
|
log('err_handle_mute', e);
|
||||||
}
|
}
|
||||||
|
@ -299,7 +300,6 @@ export default class RoomMembersView extends React.Component {
|
||||||
windowSize={10}
|
windowSize={10}
|
||||||
{...scrollPersistTaps}
|
{...scrollPersistTaps}
|
||||||
/>
|
/>
|
||||||
<Toast ref={toast => this.toast = toast} />
|
|
||||||
</SafeAreaView>
|
</SafeAreaView>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,7 +64,13 @@ const styles = StyleSheet.create({
|
||||||
export default class UploadProgress extends Component {
|
export default class UploadProgress extends Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
window: PropTypes.object,
|
window: PropTypes.object,
|
||||||
rid: PropTypes.string
|
rid: PropTypes.string,
|
||||||
|
user: PropTypes.shape({
|
||||||
|
id: PropTypes.string.isRequired,
|
||||||
|
username: PropTypes.string.isRequired,
|
||||||
|
token: PropTypes.string.isRequired
|
||||||
|
}),
|
||||||
|
baseUrl: PropTypes.string.isRequired
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
|
@ -124,13 +130,13 @@ export default class UploadProgress extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
tryAgain = async(item) => {
|
tryAgain = async(item) => {
|
||||||
const { rid } = this.props;
|
const { rid, baseUrl: server, user } = this.props;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
database.write(() => {
|
database.write(() => {
|
||||||
item.error = false;
|
item.error = false;
|
||||||
});
|
});
|
||||||
await RocketChat.sendFileMessage(rid, item);
|
await RocketChat.sendFileMessage(rid, item, undefined, server, user);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
log('err_upload_progress_try_again', e);
|
log('err_upload_progress_try_again', e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,7 +41,8 @@ import debounce from '../../utils/debounce';
|
||||||
import buildMessage from '../../lib/methods/helpers/buildMessage';
|
import buildMessage from '../../lib/methods/helpers/buildMessage';
|
||||||
import FileModal from '../../containers/FileModal';
|
import FileModal from '../../containers/FileModal';
|
||||||
import ReactionsModal from '../../containers/ReactionsModal';
|
import ReactionsModal from '../../containers/ReactionsModal';
|
||||||
import { Toast } from '../../utils/info';
|
import { LISTENER } from '../../containers/Toast';
|
||||||
|
import { isReadOnly, isBlocked } from '../../utils/room';
|
||||||
|
|
||||||
@connect(state => ({
|
@connect(state => ({
|
||||||
user: {
|
user: {
|
||||||
|
@ -409,8 +410,9 @@ export default class RoomView extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
sendMessage = (message, tmid) => {
|
sendMessage = (message, tmid) => {
|
||||||
|
const { user } = this.props;
|
||||||
LayoutAnimation.easeInEaseOut();
|
LayoutAnimation.easeInEaseOut();
|
||||||
RocketChat.sendMessage(this.rid, message, this.tmid || tmid).then(() => {
|
RocketChat.sendMessage(this.rid, message, this.tmid || tmid, user).then(() => {
|
||||||
this.setLastOpen(null);
|
this.setLastOpen(null);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -455,37 +457,6 @@ export default class RoomView extends React.Component {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
isOwner = () => {
|
|
||||||
const { room } = this.state;
|
|
||||||
return room && room.roles && room.roles.length && !!room.roles.find(role => role === 'owner');
|
|
||||||
}
|
|
||||||
|
|
||||||
isMuted = () => {
|
|
||||||
const { room } = this.state;
|
|
||||||
const { user } = this.props;
|
|
||||||
return room && room.muted && room.muted.find && !!room.muted.find(m => m === user.username);
|
|
||||||
}
|
|
||||||
|
|
||||||
isReadOnly = () => {
|
|
||||||
const { room } = this.state;
|
|
||||||
if (this.isOwner()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return (room && room.ro) || this.isMuted();
|
|
||||||
}
|
|
||||||
|
|
||||||
isBlocked = () => {
|
|
||||||
const { room } = this.state;
|
|
||||||
|
|
||||||
if (room) {
|
|
||||||
const { t, blocked, blocker } = room;
|
|
||||||
if (t === 'd' && (blocked || blocker)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// eslint-disable-next-line react/sort-comp
|
// eslint-disable-next-line react/sort-comp
|
||||||
fetchThreadName = async(tmid) => {
|
fetchThreadName = async(tmid) => {
|
||||||
try {
|
try {
|
||||||
|
@ -502,7 +473,7 @@ export default class RoomView extends React.Component {
|
||||||
toggleFollowThread = async(isFollowingThread) => {
|
toggleFollowThread = async(isFollowingThread) => {
|
||||||
try {
|
try {
|
||||||
await RocketChat.toggleFollowMessage(this.tmid, !isFollowingThread);
|
await RocketChat.toggleFollowMessage(this.tmid, !isFollowingThread);
|
||||||
this.toast.show(isFollowingThread ? 'Unfollowed thread' : 'Following thread');
|
EventEmitter.emit(LISTENER, { message: isFollowingThread ? 'Unfollowed thread' : 'Following thread' });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
log('err_toggle_follow_thread', e);
|
log('err_toggle_follow_thread', e);
|
||||||
}
|
}
|
||||||
|
@ -576,7 +547,7 @@ export default class RoomView extends React.Component {
|
||||||
|
|
||||||
renderFooter = () => {
|
renderFooter = () => {
|
||||||
const { joined, room } = this.state;
|
const { joined, room } = this.state;
|
||||||
const { navigation } = this.props;
|
const { navigation, user } = this.props;
|
||||||
|
|
||||||
if (!joined && !this.tmid) {
|
if (!joined && !this.tmid) {
|
||||||
return (
|
return (
|
||||||
|
@ -593,14 +564,14 @@ export default class RoomView extends React.Component {
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (this.isReadOnly()) {
|
if (isReadOnly(room, user)) {
|
||||||
return (
|
return (
|
||||||
<View style={styles.readOnly}>
|
<View style={styles.readOnly}>
|
||||||
<Text style={styles.previewMode}>{I18n.t('This_room_is_read_only')}</Text>
|
<Text style={styles.previewMode}>{I18n.t('This_room_is_read_only')}</Text>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (this.isBlocked()) {
|
if (isBlocked(room)) {
|
||||||
return (
|
return (
|
||||||
<View style={styles.readOnly}>
|
<View style={styles.readOnly}>
|
||||||
<Text style={styles.previewMode}>{I18n.t('This_room_is_blocked')}</Text>
|
<Text style={styles.previewMode}>{I18n.t('This_room_is_blocked')}</Text>
|
||||||
|
@ -630,7 +601,7 @@ export default class RoomView extends React.Component {
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
{room._id && showActions
|
{room._id && showActions
|
||||||
? <MessageActions room={room} tmid={this.tmid} user={user} toast={this.toast} />
|
? <MessageActions room={room} tmid={this.tmid} user={user} />
|
||||||
: null
|
: null
|
||||||
}
|
}
|
||||||
{showErrorActions ? <MessageErrorActions /> : null}
|
{showErrorActions ? <MessageErrorActions /> : null}
|
||||||
|
@ -653,7 +624,7 @@ export default class RoomView extends React.Component {
|
||||||
{this.renderFooter()}
|
{this.renderFooter()}
|
||||||
{this.renderActions()}
|
{this.renderActions()}
|
||||||
<ReactionPicker onEmojiSelected={this.onReactionPress} />
|
<ReactionPicker onEmojiSelected={this.onReactionPress} />
|
||||||
<UploadProgress rid={this.rid} />
|
<UploadProgress rid={this.rid} user={user} baseUrl={baseUrl} />
|
||||||
<FileModal
|
<FileModal
|
||||||
attachment={selectedAttachment}
|
attachment={selectedAttachment}
|
||||||
isVisible={photoModalVisible}
|
isVisible={photoModalVisible}
|
||||||
|
@ -668,7 +639,6 @@ export default class RoomView extends React.Component {
|
||||||
user={user}
|
user={user}
|
||||||
baseUrl={baseUrl}
|
baseUrl={baseUrl}
|
||||||
/>
|
/>
|
||||||
<Toast ref={toast => this.toast = toast} />
|
|
||||||
</SafeAreaView>
|
</SafeAreaView>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,108 @@
|
||||||
|
import React from 'react';
|
||||||
|
import {
|
||||||
|
FlatList, StyleSheet, View
|
||||||
|
} from 'react-native';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import { SafeAreaView } from 'react-navigation';
|
||||||
|
|
||||||
|
import I18n from '../i18n';
|
||||||
|
import database from '../lib/realm';
|
||||||
|
import StatusBar from '../containers/StatusBar';
|
||||||
|
import { COLOR_BACKGROUND_CONTAINER } from '../constants/colors';
|
||||||
|
import Navigation from '../lib/ShareNavigation';
|
||||||
|
import ServerItem, { ROW_HEIGHT } from '../presentation/ServerItem';
|
||||||
|
import sharedStyles from './Styles';
|
||||||
|
import RocketChat from '../lib/rocketchat';
|
||||||
|
|
||||||
|
const getItemLayout = (data, index) => ({ length: ROW_HEIGHT, offset: ROW_HEIGHT * index, index });
|
||||||
|
const keyExtractor = item => item.id;
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
flex: 1,
|
||||||
|
backgroundColor: COLOR_BACKGROUND_CONTAINER
|
||||||
|
},
|
||||||
|
list: {
|
||||||
|
marginVertical: 32,
|
||||||
|
...sharedStyles.separatorVertical
|
||||||
|
},
|
||||||
|
separator: {
|
||||||
|
...sharedStyles.separatorBottom,
|
||||||
|
marginLeft: 48
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
@connect(({ share }) => ({
|
||||||
|
server: share.server
|
||||||
|
}))
|
||||||
|
export default class SelectServerView extends React.Component {
|
||||||
|
static navigationOptions = () => ({
|
||||||
|
title: I18n.t('Select_Server')
|
||||||
|
})
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
server: PropTypes.string
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
const { serversDB } = database.databases;
|
||||||
|
const servers = serversDB.objects('servers');
|
||||||
|
const filteredServers = servers.filter(server => server.roomsUpdatedAt);
|
||||||
|
this.state = {
|
||||||
|
servers: filteredServers
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
select = async(server) => {
|
||||||
|
const {
|
||||||
|
server: currentServer
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
|
Navigation.navigate('ShareListView');
|
||||||
|
if (currentServer !== server) {
|
||||||
|
await RocketChat.shareExtensionInit(server);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
renderItem = ({ item }) => {
|
||||||
|
const { server } = this.props;
|
||||||
|
return (
|
||||||
|
<ServerItem
|
||||||
|
server={server}
|
||||||
|
onPress={() => this.select(item.id)}
|
||||||
|
item={item}
|
||||||
|
hasCheck
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderSeparator = () => <View style={styles.separator} />;
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { servers } = this.state;
|
||||||
|
return (
|
||||||
|
<SafeAreaView
|
||||||
|
style={styles.container}
|
||||||
|
forceInset={{ bottom: 'never' }}
|
||||||
|
>
|
||||||
|
<StatusBar />
|
||||||
|
<View style={styles.list}>
|
||||||
|
<FlatList
|
||||||
|
data={servers}
|
||||||
|
keyExtractor={keyExtractor}
|
||||||
|
renderItem={this.renderItem}
|
||||||
|
getItemLayout={getItemLayout}
|
||||||
|
ItemSeparatorComponent={this.renderSeparator}
|
||||||
|
enableEmptySections
|
||||||
|
removeClippedSubviews
|
||||||
|
keyboardShouldPersistTaps='always'
|
||||||
|
windowSize={7}
|
||||||
|
bounces={false}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
</SafeAreaView>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
import React from 'react';
|
||||||
|
import {
|
||||||
|
View, StyleSheet, Text, TextInput
|
||||||
|
} from 'react-native';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
import I18n from '../../../i18n';
|
||||||
|
import { COLOR_WHITE, HEADER_TITLE } from '../../../constants/colors';
|
||||||
|
import sharedStyles from '../../Styles';
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
flex: 1,
|
||||||
|
justifyContent: 'center'
|
||||||
|
},
|
||||||
|
search: {
|
||||||
|
fontSize: 20,
|
||||||
|
color: COLOR_WHITE,
|
||||||
|
...sharedStyles.textRegular,
|
||||||
|
marginHorizontal: 14
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
fontSize: 20,
|
||||||
|
...sharedStyles.textBold,
|
||||||
|
color: HEADER_TITLE,
|
||||||
|
marginHorizontal: 16
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const Header = React.memo(({ searching, onChangeSearchText }) => {
|
||||||
|
if (searching) {
|
||||||
|
return (
|
||||||
|
<View style={styles.container}>
|
||||||
|
<TextInput
|
||||||
|
style={styles.search}
|
||||||
|
placeholder={I18n.t('Search')}
|
||||||
|
placeholderTextColor='rgba(255, 255, 255, 0.5)'
|
||||||
|
onChangeText={onChangeSearchText}
|
||||||
|
autoFocus
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return <Text style={styles.title}>{I18n.t('Send_to')}</Text>;
|
||||||
|
});
|
||||||
|
|
||||||
|
Header.propTypes = {
|
||||||
|
searching: PropTypes.bool,
|
||||||
|
onChangeSearchText: PropTypes.func
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Header;
|
|
@ -0,0 +1,76 @@
|
||||||
|
import React, { useState } from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import {
|
||||||
|
Keyboard, LayoutAnimation, View, StyleSheet
|
||||||
|
} from 'react-native';
|
||||||
|
import ShareExtension from 'rn-extensions-share';
|
||||||
|
|
||||||
|
import SearchBox from '../../../containers/SearchBox';
|
||||||
|
import { CloseShareExtensionButton } from '../../../containers/HeaderButton';
|
||||||
|
import { HEADER_BACKGROUND } from '../../../constants/colors';
|
||||||
|
|
||||||
|
import sharedStyles from '../../Styles';
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
backgroundColor: HEADER_BACKGROUND,
|
||||||
|
flexDirection: 'row',
|
||||||
|
...sharedStyles.separatorBottom
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const Header = React.memo(({
|
||||||
|
searching, onChangeSearchText, initSearch, cancelSearch
|
||||||
|
}) => {
|
||||||
|
const [text, setText] = useState('');
|
||||||
|
|
||||||
|
const onChangeText = (searchText) => {
|
||||||
|
onChangeSearchText(searchText);
|
||||||
|
setText(searchText);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onCancelPress = () => {
|
||||||
|
Keyboard.dismiss();
|
||||||
|
onChangeText('');
|
||||||
|
cancelSearch();
|
||||||
|
LayoutAnimation.easeInEaseOut();
|
||||||
|
};
|
||||||
|
|
||||||
|
const onFocus = () => {
|
||||||
|
initSearch();
|
||||||
|
LayoutAnimation.easeInEaseOut();
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={styles.container}>
|
||||||
|
{
|
||||||
|
!searching
|
||||||
|
? (
|
||||||
|
<CloseShareExtensionButton
|
||||||
|
onPress={ShareExtension.close}
|
||||||
|
testID='share-extension-close'
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
: null
|
||||||
|
}
|
||||||
|
<SearchBox
|
||||||
|
value={text}
|
||||||
|
hasCancel={searching}
|
||||||
|
onFocus={onFocus}
|
||||||
|
onCancelPress={onCancelPress}
|
||||||
|
onChangeText={onChangeText}
|
||||||
|
testID='rooms-list-view-search'
|
||||||
|
key='rooms-list-view-search'
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
Header.propTypes = {
|
||||||
|
searching: PropTypes.bool,
|
||||||
|
onChangeSearchText: PropTypes.func,
|
||||||
|
initSearch: PropTypes.func,
|
||||||
|
cancelSearch: PropTypes.func
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Header;
|
|
@ -0,0 +1,30 @@
|
||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
import Header from './Header';
|
||||||
|
|
||||||
|
const ShareListHeader = React.memo(({
|
||||||
|
searching, initSearch, cancelSearch, search
|
||||||
|
}) => {
|
||||||
|
const onSearchChangeText = (text) => {
|
||||||
|
search(text.trim());
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Header
|
||||||
|
searching={searching}
|
||||||
|
initSearch={initSearch}
|
||||||
|
cancelSearch={cancelSearch}
|
||||||
|
onChangeSearchText={onSearchChangeText}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
ShareListHeader.propTypes = {
|
||||||
|
searching: PropTypes.bool,
|
||||||
|
initSearch: PropTypes.func,
|
||||||
|
cancelSearch: PropTypes.func,
|
||||||
|
search: PropTypes.func
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ShareListHeader;
|
|
@ -0,0 +1,417 @@
|
||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import {
|
||||||
|
View, Text, LayoutAnimation, FlatList, ActivityIndicator, Keyboard, BackHandler
|
||||||
|
} from 'react-native';
|
||||||
|
import { SafeAreaView } from 'react-navigation';
|
||||||
|
import ShareExtension from 'rn-extensions-share';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import RNFetchBlob from 'rn-fetch-blob';
|
||||||
|
import * as mime from 'react-native-mime-types';
|
||||||
|
import { isEqual } from 'lodash';
|
||||||
|
|
||||||
|
import Navigation from '../../lib/ShareNavigation';
|
||||||
|
import database from '../../lib/realm';
|
||||||
|
import { isIOS, isAndroid } from '../../utils/deviceInfo';
|
||||||
|
import I18n from '../../i18n';
|
||||||
|
import { CustomIcon } from '../../lib/Icons';
|
||||||
|
import log from '../../utils/log';
|
||||||
|
import { canUploadFile } from '../../utils/media';
|
||||||
|
import DirectoryItem, { ROW_HEIGHT } from '../../presentation/DirectoryItem';
|
||||||
|
import ServerItem from '../../presentation/ServerItem';
|
||||||
|
import { CloseShareExtensionButton, CustomHeaderButtons, Item } from '../../containers/HeaderButton';
|
||||||
|
import ShareListHeader from './Header';
|
||||||
|
|
||||||
|
import styles from './styles';
|
||||||
|
import StatusBar from '../../containers/StatusBar';
|
||||||
|
|
||||||
|
const LIMIT = 50;
|
||||||
|
const getItemLayout = (data, index) => ({ length: ROW_HEIGHT, offset: ROW_HEIGHT * index, index });
|
||||||
|
const keyExtractor = item => item.rid;
|
||||||
|
|
||||||
|
@connect(({ share }) => ({
|
||||||
|
userId: share.user && share.user.id,
|
||||||
|
token: share.user && share.user.token,
|
||||||
|
server: share.server,
|
||||||
|
baseUrl: share ? share.server : ''
|
||||||
|
}))
|
||||||
|
/** @extends React.Component */
|
||||||
|
export default class ShareListView extends React.Component {
|
||||||
|
static navigationOptions = ({ navigation }) => {
|
||||||
|
const searching = navigation.getParam('searching');
|
||||||
|
const initSearch = navigation.getParam('initSearch', () => {});
|
||||||
|
const cancelSearch = navigation.getParam('cancelSearch', () => {});
|
||||||
|
const search = navigation.getParam('search', () => {});
|
||||||
|
|
||||||
|
if (isIOS) {
|
||||||
|
return {
|
||||||
|
headerTitle: (
|
||||||
|
<ShareListHeader
|
||||||
|
searching={searching}
|
||||||
|
initSearch={initSearch}
|
||||||
|
cancelSearch={cancelSearch}
|
||||||
|
search={search}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
headerBackTitle: null,
|
||||||
|
headerLeft: searching
|
||||||
|
? (
|
||||||
|
<CustomHeaderButtons left>
|
||||||
|
<Item title='cancel' iconName='cross' onPress={cancelSearch} />
|
||||||
|
</CustomHeaderButtons>
|
||||||
|
)
|
||||||
|
: (
|
||||||
|
<CloseShareExtensionButton
|
||||||
|
onPress={ShareExtension.close}
|
||||||
|
testID='share-extension-close'
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
headerTitle: <ShareListHeader searching={searching} search={search} />,
|
||||||
|
headerRight: (
|
||||||
|
searching
|
||||||
|
? null
|
||||||
|
: (
|
||||||
|
<CustomHeaderButtons>
|
||||||
|
{isAndroid ? <Item title='search' iconName='magnifier' onPress={initSearch} /> : null}
|
||||||
|
</CustomHeaderButtons>
|
||||||
|
)
|
||||||
|
)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
navigation: PropTypes.object,
|
||||||
|
server: PropTypes.string,
|
||||||
|
baseUrl: PropTypes.string,
|
||||||
|
token: PropTypes.string,
|
||||||
|
userId: PropTypes.string
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.data = [];
|
||||||
|
this.state = {
|
||||||
|
showError: false,
|
||||||
|
searching: false,
|
||||||
|
searchText: '',
|
||||||
|
value: '',
|
||||||
|
isMedia: false,
|
||||||
|
mediaLoading: false,
|
||||||
|
fileInfo: null,
|
||||||
|
searchResults: [],
|
||||||
|
chats: [],
|
||||||
|
servers: [],
|
||||||
|
loading: true,
|
||||||
|
serverInfo: null
|
||||||
|
};
|
||||||
|
this.didFocusListener = props.navigation.addListener('didFocus', () => BackHandler.addEventListener('hardwareBackPress', this.handleBackPress));
|
||||||
|
this.willBlurListener = props.navigation.addListener('willBlur', () => BackHandler.addEventListener('hardwareBackPress', this.handleBackPress));
|
||||||
|
}
|
||||||
|
|
||||||
|
async componentDidMount() {
|
||||||
|
const { navigation, server } = this.props;
|
||||||
|
navigation.setParams({
|
||||||
|
initSearch: this.initSearch,
|
||||||
|
cancelSearch: this.cancelSearch,
|
||||||
|
search: this.search
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
const { value, type } = await ShareExtension.data();
|
||||||
|
let fileInfo = null;
|
||||||
|
const isMedia = (type === 'media');
|
||||||
|
if (isMedia) {
|
||||||
|
this.setState({ mediaLoading: true });
|
||||||
|
const data = await RNFetchBlob.fs.stat(this.uriToPath(value));
|
||||||
|
fileInfo = {
|
||||||
|
name: data.filename,
|
||||||
|
description: '',
|
||||||
|
size: data.size,
|
||||||
|
mime: mime.lookup(data.path),
|
||||||
|
store: 'Uploads',
|
||||||
|
path: isIOS ? data.path : `file://${ data.path }`
|
||||||
|
};
|
||||||
|
}
|
||||||
|
this.setState({
|
||||||
|
value, fileInfo, isMedia, mediaLoading: false
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
log('err_process_media_share_extension', e);
|
||||||
|
this.setState({ mediaLoading: false });
|
||||||
|
}
|
||||||
|
|
||||||
|
this.getSubscriptions(server);
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillReceiveProps(nextProps) {
|
||||||
|
const { server } = this.props;
|
||||||
|
if (nextProps.server !== server) {
|
||||||
|
this.getSubscriptions(nextProps.server);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
shouldComponentUpdate(nextProps, nextState) {
|
||||||
|
const { searching } = this.state;
|
||||||
|
if (nextState.searching !== searching) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { isMedia } = this.state;
|
||||||
|
if (nextState.isMedia !== isMedia) {
|
||||||
|
this.getSubscriptions(nextProps.server, nextState.fileInfo);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { server } = this.props;
|
||||||
|
if (server !== nextProps.server) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { searchResults } = this.state;
|
||||||
|
if (!isEqual(nextState.searchResults, searchResults)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line react/sort-comp
|
||||||
|
internalSetState = (...args) => {
|
||||||
|
const { navigation } = this.props;
|
||||||
|
if (isIOS && navigation.isFocused()) {
|
||||||
|
LayoutAnimation.easeInEaseOut();
|
||||||
|
}
|
||||||
|
this.setState(...args);
|
||||||
|
}
|
||||||
|
|
||||||
|
getSubscriptions = (server, fileInfo) => {
|
||||||
|
const { fileInfo: fileData } = this.state;
|
||||||
|
const { serversDB } = database.databases;
|
||||||
|
|
||||||
|
if (server) {
|
||||||
|
this.data = database.objects('subscriptions').filtered('archived != true && open == true').sorted('roomUpdatedAt', true);
|
||||||
|
this.servers = serversDB.objects('servers');
|
||||||
|
this.chats = this.data.slice(0, LIMIT);
|
||||||
|
const serverInfo = serversDB.objectForPrimaryKey('servers', server);
|
||||||
|
|
||||||
|
this.internalSetState({
|
||||||
|
chats: this.chats ? this.chats.slice() : [],
|
||||||
|
servers: this.servers ? this.servers.slice() : [],
|
||||||
|
loading: false,
|
||||||
|
showError: !canUploadFile(fileInfo || fileData, serverInfo),
|
||||||
|
serverInfo
|
||||||
|
});
|
||||||
|
this.forceUpdate();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
uriToPath = uri => decodeURIComponent(isIOS ? uri.replace(/^file:\/\//, '') : uri);
|
||||||
|
|
||||||
|
getRoomTitle = (item) => {
|
||||||
|
const { serverInfo } = this.state;
|
||||||
|
const { useRealName } = serverInfo;
|
||||||
|
return ((item.prid || useRealName) && item.fname) || item.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
shareMessage = (item) => {
|
||||||
|
const { value, isMedia, fileInfo } = this.state;
|
||||||
|
const { navigation } = this.props;
|
||||||
|
|
||||||
|
navigation.navigate('ShareView', {
|
||||||
|
rid: item.rid,
|
||||||
|
value,
|
||||||
|
isMedia,
|
||||||
|
fileInfo,
|
||||||
|
name: this.getRoomTitle(item)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
search = (text) => {
|
||||||
|
const result = database.objects('subscriptions').filtered('name CONTAINS[c] $0', text);
|
||||||
|
this.internalSetState({
|
||||||
|
searchResults: result.slice(0, LIMIT),
|
||||||
|
searchText: text
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
initSearch = () => {
|
||||||
|
const { chats } = this.state;
|
||||||
|
const { navigation } = this.props;
|
||||||
|
this.setState({ searching: true, searchResults: chats });
|
||||||
|
navigation.setParams({ searching: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
cancelSearch = () => {
|
||||||
|
const { navigation } = this.props;
|
||||||
|
this.internalSetState({ searching: false, searchResults: [], searchText: '' });
|
||||||
|
navigation.setParams({ searching: false });
|
||||||
|
Keyboard.dismiss();
|
||||||
|
}
|
||||||
|
|
||||||
|
handleBackPress = () => {
|
||||||
|
const { searching } = this.state;
|
||||||
|
if (searching) {
|
||||||
|
this.cancelSearch();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
renderSectionHeader = (header) => {
|
||||||
|
const { searching } = this.state;
|
||||||
|
if (searching) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={styles.headerContainer}>
|
||||||
|
<Text style={styles.headerText}>
|
||||||
|
{I18n.t(header)}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderItem = ({ item }) => {
|
||||||
|
const { userId, token, baseUrl } = this.props;
|
||||||
|
return (
|
||||||
|
<DirectoryItem
|
||||||
|
user={{
|
||||||
|
userId,
|
||||||
|
token
|
||||||
|
}}
|
||||||
|
title={this.getRoomTitle(item)}
|
||||||
|
baseUrl={baseUrl}
|
||||||
|
avatar={this.getRoomTitle(item)}
|
||||||
|
description={
|
||||||
|
item.t === 'c'
|
||||||
|
? (item.topic || item.description)
|
||||||
|
: item.fname
|
||||||
|
}
|
||||||
|
type={item.t}
|
||||||
|
onPress={() => this.shareMessage(item)}
|
||||||
|
testID={`share-extension-item-${ item.name }`}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderSeparator = () => <View style={styles.separator} />;
|
||||||
|
|
||||||
|
renderBorderBottom = () => <View style={styles.borderBottom} />;
|
||||||
|
|
||||||
|
renderSelectServer = () => {
|
||||||
|
const { servers } = this.state;
|
||||||
|
const { server } = this.props;
|
||||||
|
const currentServer = servers.find(serverFiltered => serverFiltered.id === server);
|
||||||
|
return currentServer ? (
|
||||||
|
<React.Fragment>
|
||||||
|
{this.renderSectionHeader('Select_Server')}
|
||||||
|
<View style={styles.bordered}>
|
||||||
|
<ServerItem
|
||||||
|
server={server}
|
||||||
|
onPress={() => Navigation.navigate('SelectServerView')}
|
||||||
|
item={currentServer}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
</React.Fragment>
|
||||||
|
) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
renderEmptyComponent = () => (
|
||||||
|
<View style={[styles.container, styles.emptyContainer]}>
|
||||||
|
<Text style={styles.title}>{I18n.t('No_results_found')}</Text>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
|
||||||
|
renderHeader = () => {
|
||||||
|
const { searching } = this.state;
|
||||||
|
return (
|
||||||
|
<React.Fragment>
|
||||||
|
{ !searching
|
||||||
|
? (
|
||||||
|
<React.Fragment>
|
||||||
|
{this.renderSelectServer()}
|
||||||
|
{this.renderSectionHeader('Chats')}
|
||||||
|
</React.Fragment>
|
||||||
|
)
|
||||||
|
: null
|
||||||
|
}
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderContent = () => {
|
||||||
|
const {
|
||||||
|
chats, mediaLoading, loading, searchResults, searching, searchText
|
||||||
|
} = this.state;
|
||||||
|
|
||||||
|
if (mediaLoading || loading) {
|
||||||
|
return <ActivityIndicator style={styles.loading} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<FlatList
|
||||||
|
data={searching ? searchResults : chats}
|
||||||
|
keyExtractor={keyExtractor}
|
||||||
|
style={styles.flatlist}
|
||||||
|
renderItem={this.renderItem}
|
||||||
|
getItemLayout={getItemLayout}
|
||||||
|
ItemSeparatorComponent={this.renderSeparator}
|
||||||
|
ListHeaderComponent={this.renderHeader}
|
||||||
|
ListFooterComponent={!searching && this.renderBorderBottom}
|
||||||
|
ListHeaderComponentStyle={!searching ? styles.borderBottom : {}}
|
||||||
|
ListEmptyComponent={searching && searchText ? this.renderEmptyComponent : null}
|
||||||
|
enableEmptySections
|
||||||
|
removeClippedSubviews
|
||||||
|
keyboardShouldPersistTaps='always'
|
||||||
|
initialNumToRender={12}
|
||||||
|
windowSize={20}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderError = () => {
|
||||||
|
const {
|
||||||
|
fileInfo: file, loading, searching, serverInfo
|
||||||
|
} = this.state;
|
||||||
|
const { FileUpload_MaxFileSize } = serverInfo;
|
||||||
|
const errorMessage = (FileUpload_MaxFileSize < file.size)
|
||||||
|
? 'error-file-too-large'
|
||||||
|
: 'error-invalid-file-type';
|
||||||
|
|
||||||
|
if (loading) {
|
||||||
|
return <ActivityIndicator style={styles.loading} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={styles.container}>
|
||||||
|
{ !searching
|
||||||
|
? (
|
||||||
|
<React.Fragment>
|
||||||
|
{this.renderSelectServer()}
|
||||||
|
</React.Fragment>
|
||||||
|
)
|
||||||
|
: null
|
||||||
|
}
|
||||||
|
<View style={[styles.container, styles.centered]}>
|
||||||
|
<Text style={styles.title}>{I18n.t(errorMessage)}</Text>
|
||||||
|
<CustomIcon name='circle-cross' size={120} style={styles.errorIcon} />
|
||||||
|
<Text style={styles.fileMime}>{ file.mime }</Text>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { showError } = this.state;
|
||||||
|
return (
|
||||||
|
<SafeAreaView style={styles.container} forceInset={{ bottom: 'never' }}>
|
||||||
|
<StatusBar />
|
||||||
|
{ showError ? this.renderError() : this.renderContent() }
|
||||||
|
</SafeAreaView>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,74 @@
|
||||||
|
import { StyleSheet } from 'react-native';
|
||||||
|
import { isIOS } from '../../utils/deviceInfo';
|
||||||
|
import sharedStyles from '../Styles';
|
||||||
|
|
||||||
|
import {
|
||||||
|
COLOR_BACKGROUND_CONTAINER, COLOR_WHITE, COLOR_DANGER
|
||||||
|
} from '../../constants/colors';
|
||||||
|
|
||||||
|
export default StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
flex: 1,
|
||||||
|
backgroundColor: COLOR_BACKGROUND_CONTAINER
|
||||||
|
},
|
||||||
|
emptyContainer: {
|
||||||
|
padding: 20,
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center'
|
||||||
|
},
|
||||||
|
content: {
|
||||||
|
flex: 1,
|
||||||
|
backgroundColor: isIOS ? COLOR_WHITE : '#E1E5E8',
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center'
|
||||||
|
},
|
||||||
|
centered: {
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center'
|
||||||
|
},
|
||||||
|
flatlist: {
|
||||||
|
marginTop: isIOS ? 6 : 0, // the height of the navigation bar with the searchbar is larger
|
||||||
|
width: '100%',
|
||||||
|
backgroundColor: COLOR_BACKGROUND_CONTAINER
|
||||||
|
},
|
||||||
|
bordered: {
|
||||||
|
...sharedStyles.separatorVertical
|
||||||
|
},
|
||||||
|
borderBottom: {
|
||||||
|
...sharedStyles.separatorBottom
|
||||||
|
},
|
||||||
|
headerContainer: {
|
||||||
|
paddingHorizontal: 15,
|
||||||
|
backgroundColor: COLOR_BACKGROUND_CONTAINER,
|
||||||
|
paddingBottom: 10,
|
||||||
|
paddingTop: 17
|
||||||
|
},
|
||||||
|
headerText: {
|
||||||
|
...sharedStyles.textColorNormal,
|
||||||
|
...sharedStyles.textRegular,
|
||||||
|
fontSize: 17,
|
||||||
|
letterSpacing: 0.27
|
||||||
|
},
|
||||||
|
separator: {
|
||||||
|
...sharedStyles.separatorBottom,
|
||||||
|
marginLeft: 48
|
||||||
|
},
|
||||||
|
loading: {
|
||||||
|
flex: 1
|
||||||
|
},
|
||||||
|
errorIcon: {
|
||||||
|
color: COLOR_DANGER
|
||||||
|
},
|
||||||
|
fileMime: {
|
||||||
|
...sharedStyles.textColorNormal,
|
||||||
|
...sharedStyles.textBold,
|
||||||
|
...sharedStyles.textAlignCenter,
|
||||||
|
fontSize: 20,
|
||||||
|
marginBottom: 20
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
fontSize: 14,
|
||||||
|
...sharedStyles.textColorTitle,
|
||||||
|
...sharedStyles.textBold
|
||||||
|
}
|
||||||
|
});
|
|
@ -0,0 +1,23 @@
|
||||||
|
import React from 'react';
|
||||||
|
import {
|
||||||
|
StyleSheet, ActivityIndicator, View
|
||||||
|
} from 'react-native';
|
||||||
|
import { COLOR_TEXT } from '../../constants/colors';
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
height: '100%',
|
||||||
|
width: '100%',
|
||||||
|
position: 'absolute',
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const Loading = React.memo(() => (
|
||||||
|
<View style={styles.container}>
|
||||||
|
<ActivityIndicator size='large' color={COLOR_TEXT} />
|
||||||
|
</View>
|
||||||
|
));
|
||||||
|
|
||||||
|
export default Loading;
|
|
@ -0,0 +1,245 @@
|
||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import {
|
||||||
|
View, Text, TextInput, Image
|
||||||
|
} from 'react-native';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import ShareExtension from 'rn-extensions-share';
|
||||||
|
|
||||||
|
import {
|
||||||
|
COLOR_TEXT_DESCRIPTION
|
||||||
|
} from '../../constants/colors';
|
||||||
|
import I18n from '../../i18n';
|
||||||
|
import RocketChat from '../../lib/rocketchat';
|
||||||
|
import { CustomIcon } from '../../lib/Icons';
|
||||||
|
import log from '../../utils/log';
|
||||||
|
import styles from './styles';
|
||||||
|
import Loading from './Loading';
|
||||||
|
import database from '../../lib/realm';
|
||||||
|
import { CustomHeaderButtons, Item } from '../../containers/HeaderButton';
|
||||||
|
import { isReadOnly, isBlocked } from '../../utils/room';
|
||||||
|
|
||||||
|
@connect(({ share }) => ({
|
||||||
|
user: {
|
||||||
|
id: share.user && share.user.id,
|
||||||
|
username: share.user && share.user.username,
|
||||||
|
token: share.user && share.user.token
|
||||||
|
},
|
||||||
|
baseUrl: share ? share.server : ''
|
||||||
|
}))
|
||||||
|
export default class ShareView extends React.Component {
|
||||||
|
static navigationOptions = ({ navigation }) => {
|
||||||
|
const canSend = navigation.getParam('canSend', true);
|
||||||
|
|
||||||
|
return ({
|
||||||
|
title: I18n.t('Share'),
|
||||||
|
headerRight:
|
||||||
|
canSend
|
||||||
|
? (
|
||||||
|
<CustomHeaderButtons>
|
||||||
|
<Item
|
||||||
|
title={I18n.t('Send')}
|
||||||
|
onPress={navigation.getParam('sendMessage')}
|
||||||
|
testID='send-message-share-view'
|
||||||
|
buttonStyle={styles.send}
|
||||||
|
/>
|
||||||
|
</CustomHeaderButtons>
|
||||||
|
)
|
||||||
|
: null
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
navigation: PropTypes.object,
|
||||||
|
user: PropTypes.shape({
|
||||||
|
id: PropTypes.string.isRequired,
|
||||||
|
username: PropTypes.string.isRequired,
|
||||||
|
token: PropTypes.string.isRequired
|
||||||
|
}),
|
||||||
|
baseUrl: PropTypes.string.isRequired
|
||||||
|
};
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
const { navigation } = this.props;
|
||||||
|
const rid = navigation.getParam('rid', '');
|
||||||
|
const name = navigation.getParam('name', '');
|
||||||
|
const value = navigation.getParam('value', '');
|
||||||
|
const isMedia = navigation.getParam('isMedia', false);
|
||||||
|
const fileInfo = navigation.getParam('fileInfo', {});
|
||||||
|
|
||||||
|
this.rooms = database.objects('subscriptions').filtered('rid = $0', rid);
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
rid,
|
||||||
|
value,
|
||||||
|
isMedia,
|
||||||
|
name,
|
||||||
|
fileInfo,
|
||||||
|
loading: false,
|
||||||
|
room: this.rooms[0] || { rid },
|
||||||
|
file: {
|
||||||
|
name: fileInfo ? fileInfo.name : '',
|
||||||
|
description: ''
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
const { room } = this.state;
|
||||||
|
const { navigation, user } = this.props;
|
||||||
|
const { username } = user;
|
||||||
|
navigation.setParams({ sendMessage: this._sendMessage, canSend: !(isReadOnly(room, { username }) || isBlocked(room)) });
|
||||||
|
}
|
||||||
|
|
||||||
|
bytesToSize = bytes => `${ (bytes / 1048576).toFixed(2) }MB`;
|
||||||
|
|
||||||
|
_sendMessage = async() => {
|
||||||
|
const { isMedia } = this.state;
|
||||||
|
this.setState({ loading: true });
|
||||||
|
|
||||||
|
if (isMedia) {
|
||||||
|
await this.sendMediaMessage();
|
||||||
|
} else {
|
||||||
|
await this.sendTextMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setState({ loading: false });
|
||||||
|
ShareExtension.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
sendMediaMessage = async() => {
|
||||||
|
const { rid, fileInfo, file } = this.state;
|
||||||
|
const { baseUrl: server, user } = this.props;
|
||||||
|
const { name, description } = file;
|
||||||
|
const fileMessage = { ...fileInfo, name, description };
|
||||||
|
if (fileInfo && rid !== '') {
|
||||||
|
try {
|
||||||
|
await RocketChat.sendFileMessage(rid, fileMessage, undefined, server, user);
|
||||||
|
} catch (e) {
|
||||||
|
log('err_send_media_message', e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sendTextMessage = async() => {
|
||||||
|
const { value, rid } = this.state;
|
||||||
|
const { user } = this.props;
|
||||||
|
if (value !== '' && rid !== '') {
|
||||||
|
try {
|
||||||
|
await RocketChat.sendMessage(rid, value, undefined, user);
|
||||||
|
} catch (error) {
|
||||||
|
log('err_share_extension_send_message', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
renderPreview = () => {
|
||||||
|
const { fileInfo } = this.state;
|
||||||
|
|
||||||
|
const icon = fileInfo.mime.match(/image/)
|
||||||
|
? <Image source={{ isStatic: true, uri: fileInfo.path }} style={styles.mediaImage} />
|
||||||
|
: (
|
||||||
|
<View style={styles.mediaIconContainer}>
|
||||||
|
<CustomIcon name='file-generic' style={styles.mediaIcon} />
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={styles.mediaContent}>
|
||||||
|
{icon}
|
||||||
|
<View style={styles.mediaInfo}>
|
||||||
|
<Text style={styles.mediaText} numberOfLines={1}>{fileInfo.name}</Text>
|
||||||
|
<Text style={styles.mediaText}>{this.bytesToSize(fileInfo.size)}</Text>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
renderMediaContent = () => {
|
||||||
|
const { fileInfo, file } = this.state;
|
||||||
|
return fileInfo ? (
|
||||||
|
<View style={styles.mediaContainer}>
|
||||||
|
{this.renderPreview()}
|
||||||
|
<View style={styles.mediaInputContent}>
|
||||||
|
<TextInput
|
||||||
|
style={[styles.mediaNameInput, styles.input]}
|
||||||
|
placeholder={I18n.t('File_name')}
|
||||||
|
onChangeText={name => this.setState({ file: { ...file, name } })}
|
||||||
|
underlineColorAndroid='transparent'
|
||||||
|
defaultValue={file.name}
|
||||||
|
placeholderTextColor={COLOR_TEXT_DESCRIPTION}
|
||||||
|
/>
|
||||||
|
<TextInput
|
||||||
|
style={[styles.mediaDescriptionInput, styles.input]}
|
||||||
|
placeholder={I18n.t('File_description')}
|
||||||
|
onChangeText={description => this.setState({ file: { ...file, description } })}
|
||||||
|
underlineColorAndroid='transparent'
|
||||||
|
defaultValue={file.description}
|
||||||
|
multiline
|
||||||
|
textAlignVertical='top'
|
||||||
|
placeholderTextColor={COLOR_TEXT_DESCRIPTION}
|
||||||
|
autoFocus
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
) : null;
|
||||||
|
};
|
||||||
|
|
||||||
|
renderInput = () => {
|
||||||
|
const { value } = this.state;
|
||||||
|
return (
|
||||||
|
<TextInput
|
||||||
|
style={[styles.input, styles.textInput]}
|
||||||
|
placeholder=''
|
||||||
|
onChangeText={handleText => this.setState({ value: handleText })}
|
||||||
|
underlineColorAndroid='transparent'
|
||||||
|
defaultValue={value}
|
||||||
|
multiline
|
||||||
|
textAlignVertical='top'
|
||||||
|
placeholderTextColor={COLOR_TEXT_DESCRIPTION}
|
||||||
|
autoFocus
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderError = () => {
|
||||||
|
const { room } = this.state;
|
||||||
|
return (
|
||||||
|
<View style={[styles.container, styles.centered]}>
|
||||||
|
<Text style={styles.title}>
|
||||||
|
{
|
||||||
|
isBlocked(room) ? I18n.t('This_room_is_blocked') : I18n.t('This_room_is_read_only')
|
||||||
|
}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { user } = this.props;
|
||||||
|
const { username } = user;
|
||||||
|
const {
|
||||||
|
name, loading, isMedia, room
|
||||||
|
} = this.state;
|
||||||
|
|
||||||
|
if (isReadOnly(room, { username }) || isBlocked(room)) {
|
||||||
|
return this.renderError();
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={styles.container}>
|
||||||
|
<View style={isMedia ? styles.toContent : styles.toContentText}>
|
||||||
|
<Text style={styles.text} numberOfLines={1}>
|
||||||
|
<Text style={styles.to}>{`${ I18n.t('To') }: `}</Text>
|
||||||
|
<Text style={styles.name}>{`${ name }`}</Text>
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
<View style={styles.content}>
|
||||||
|
{isMedia ? this.renderMediaContent() : this.renderInput()}
|
||||||
|
</View>
|
||||||
|
{ loading ? <Loading /> : null }
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,116 @@
|
||||||
|
import { StyleSheet } from 'react-native';
|
||||||
|
|
||||||
|
import sharedStyles from '../Styles';
|
||||||
|
import {
|
||||||
|
COLOR_BACKGROUND_CONTAINER, COLOR_WHITE
|
||||||
|
} from '../../constants/colors';
|
||||||
|
|
||||||
|
export default StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
flex: 1,
|
||||||
|
backgroundColor: COLOR_BACKGROUND_CONTAINER
|
||||||
|
},
|
||||||
|
centered: {
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center'
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
fontSize: 18,
|
||||||
|
...sharedStyles.textBold,
|
||||||
|
...sharedStyles.textColorNormal,
|
||||||
|
...sharedStyles.textAlignCenter
|
||||||
|
},
|
||||||
|
text: {
|
||||||
|
paddingHorizontal: 16,
|
||||||
|
paddingVertical: 8,
|
||||||
|
...sharedStyles.textColorNormal,
|
||||||
|
...sharedStyles.textRegular
|
||||||
|
},
|
||||||
|
to: {
|
||||||
|
...sharedStyles.textColorDescription,
|
||||||
|
...sharedStyles.textRegular
|
||||||
|
},
|
||||||
|
toContent: {
|
||||||
|
width: '100%',
|
||||||
|
backgroundColor: COLOR_WHITE
|
||||||
|
},
|
||||||
|
toContentText: {
|
||||||
|
width: '100%',
|
||||||
|
backgroundColor: COLOR_BACKGROUND_CONTAINER,
|
||||||
|
...sharedStyles.textColorNormal,
|
||||||
|
...sharedStyles.textRegular
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
...sharedStyles.textRegular,
|
||||||
|
...sharedStyles.textColorTitle
|
||||||
|
},
|
||||||
|
content: {
|
||||||
|
flex: 1,
|
||||||
|
backgroundColor: COLOR_WHITE
|
||||||
|
},
|
||||||
|
mediaContainer: {
|
||||||
|
flex: 1,
|
||||||
|
backgroundColor: COLOR_BACKGROUND_CONTAINER
|
||||||
|
},
|
||||||
|
mediaContent: {
|
||||||
|
flexDirection: 'row',
|
||||||
|
padding: 16,
|
||||||
|
backgroundColor: COLOR_BACKGROUND_CONTAINER,
|
||||||
|
alignItems: 'center'
|
||||||
|
},
|
||||||
|
mediaImage: {
|
||||||
|
height: 64,
|
||||||
|
width: 64
|
||||||
|
},
|
||||||
|
mediaIcon: {
|
||||||
|
fontSize: 64,
|
||||||
|
...sharedStyles.textColorNormal
|
||||||
|
},
|
||||||
|
mediaIconContainer: {
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center'
|
||||||
|
},
|
||||||
|
mediaInfo: {
|
||||||
|
marginLeft: 16,
|
||||||
|
flex: 1
|
||||||
|
},
|
||||||
|
mediaText: {
|
||||||
|
fontSize: 16,
|
||||||
|
...sharedStyles.textColorNormal,
|
||||||
|
...sharedStyles.textRegular
|
||||||
|
},
|
||||||
|
mediaInputContent: {
|
||||||
|
width: '100%',
|
||||||
|
...sharedStyles.separatorVertical,
|
||||||
|
backgroundColor: COLOR_WHITE
|
||||||
|
},
|
||||||
|
input: {
|
||||||
|
fontSize: 16,
|
||||||
|
...sharedStyles.textColorNormal,
|
||||||
|
...sharedStyles.textRegular,
|
||||||
|
backgroundColor: COLOR_WHITE
|
||||||
|
},
|
||||||
|
textInput: {
|
||||||
|
flex: 1,
|
||||||
|
paddingHorizontal: 16
|
||||||
|
},
|
||||||
|
mediaNameInput: {
|
||||||
|
marginLeft: 16,
|
||||||
|
paddingRight: 16,
|
||||||
|
paddingVertical: 8,
|
||||||
|
backgroundColor: COLOR_WHITE,
|
||||||
|
...sharedStyles.separatorBottom
|
||||||
|
},
|
||||||
|
mediaDescriptionInput: {
|
||||||
|
marginLeft: 16,
|
||||||
|
paddingRight: 16,
|
||||||
|
marginVertical: 8,
|
||||||
|
backgroundColor: COLOR_WHITE,
|
||||||
|
height: 100
|
||||||
|
},
|
||||||
|
send: {
|
||||||
|
...sharedStyles.textColorHeaderBack,
|
||||||
|
...sharedStyles.textSemibold,
|
||||||
|
fontSize: 16
|
||||||
|
}
|
||||||
|
});
|
|
@ -1,7 +1,7 @@
|
||||||
import { StyleSheet, Platform } from 'react-native';
|
import { StyleSheet, Platform } from 'react-native';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
COLOR_DANGER, COLOR_BUTTON_PRIMARY, COLOR_SEPARATOR, COLOR_TEXT, COLOR_TEXT_DESCRIPTION, COLOR_TITLE, COLOR_BACKGROUND_CONTAINER, COLOR_WHITE, COLOR_PRIMARY
|
COLOR_DANGER, COLOR_BUTTON_PRIMARY, COLOR_SEPARATOR, COLOR_TEXT, COLOR_TEXT_DESCRIPTION, COLOR_TITLE, COLOR_BACKGROUND_CONTAINER, COLOR_WHITE, COLOR_PRIMARY, HEADER_BACK
|
||||||
} from '../constants/colors';
|
} from '../constants/colors';
|
||||||
|
|
||||||
export default StyleSheet.create({
|
export default StyleSheet.create({
|
||||||
|
@ -72,6 +72,9 @@ export default StyleSheet.create({
|
||||||
textAlignRight: {
|
textAlignRight: {
|
||||||
textAlign: 'right'
|
textAlign: 'right'
|
||||||
},
|
},
|
||||||
|
textAlignCenter: {
|
||||||
|
textAlign: 'center'
|
||||||
|
},
|
||||||
opacity5: {
|
opacity5: {
|
||||||
opacity: 0.5
|
opacity: 0.5
|
||||||
},
|
},
|
||||||
|
@ -176,6 +179,9 @@ export default StyleSheet.create({
|
||||||
textColorDescription: {
|
textColorDescription: {
|
||||||
color: COLOR_TEXT_DESCRIPTION
|
color: COLOR_TEXT_DESCRIPTION
|
||||||
},
|
},
|
||||||
|
textColorHeaderBack: {
|
||||||
|
color: HEADER_BACK
|
||||||
|
},
|
||||||
colorPrimary: {
|
colorPrimary: {
|
||||||
color: COLOR_PRIMARY
|
color: COLOR_PRIMARY
|
||||||
},
|
},
|
||||||
|
@ -192,5 +198,10 @@ export default StyleSheet.create({
|
||||||
borderBottomWidth: StyleSheet.hairlineWidth,
|
borderBottomWidth: StyleSheet.hairlineWidth,
|
||||||
backgroundColor: COLOR_WHITE,
|
backgroundColor: COLOR_WHITE,
|
||||||
marginVertical: 10
|
marginVertical: 10
|
||||||
|
},
|
||||||
|
notchLandscapeContainer: {
|
||||||
|
marginTop: -34,
|
||||||
|
paddingHorizontal: 30,
|
||||||
|
backgroundColor: COLOR_BACKGROUND_CONTAINER
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
import React from 'react';
|
||||||
|
import {
|
||||||
|
StyleSheet, View, Text
|
||||||
|
} from 'react-native';
|
||||||
|
import ShareExtension from 'rn-extensions-share';
|
||||||
|
|
||||||
|
import { CloseShareExtensionButton } from '../containers/HeaderButton';
|
||||||
|
import sharedStyles from './Styles';
|
||||||
|
import I18n from '../i18n';
|
||||||
|
import { COLOR_WHITE } from '../constants/colors';
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
flex: 1,
|
||||||
|
backgroundColor: COLOR_WHITE,
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
padding: 15
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
fontSize: 18,
|
||||||
|
...sharedStyles.textBold,
|
||||||
|
...sharedStyles.textColorNormal
|
||||||
|
},
|
||||||
|
content: {
|
||||||
|
fontSize: 14,
|
||||||
|
...sharedStyles.textAlignCenter,
|
||||||
|
...sharedStyles.textColorNormal,
|
||||||
|
...sharedStyles.textRegular
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default class WithoutServerView extends React.Component {
|
||||||
|
static navigationOptions = () => ({
|
||||||
|
headerLeft: (
|
||||||
|
<CloseShareExtensionButton
|
||||||
|
onPress={ShareExtension.close}
|
||||||
|
testID='share-extension-close'
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<View style={styles.container}>
|
||||||
|
<Text style={styles.title}>{I18n.t('Without_Servers')}</Text>
|
||||||
|
<Text style={styles.content}>{I18n.t('You_need_to_access_at_least_one_RocketChat_server_to_share_something')}</Text>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
6
index.js
6
index.js
|
@ -2,10 +2,10 @@ import 'react-native-console-time-polyfill';
|
||||||
|
|
||||||
import './app/ReactotronConfig';
|
import './app/ReactotronConfig';
|
||||||
import { AppRegistry } from 'react-native';
|
import { AppRegistry } from 'react-native';
|
||||||
import App from './app/index';
|
import { name as appName, share as shareName } from './app.json';
|
||||||
import { name as appName } from './app.json';
|
|
||||||
|
|
||||||
AppRegistry.registerComponent(appName, () => App);
|
AppRegistry.registerComponent(appName, () => require('./app/index').default);
|
||||||
|
AppRegistry.registerComponent(shareName, () => require('./app/share').default);
|
||||||
|
|
||||||
// For storybook, comment everything above and uncomment below
|
// For storybook, comment everything above and uncomment below
|
||||||
// import './storybook';
|
// import './storybook';
|
||||||
|
|
40
ios/Podfile
40
ios/Podfile
|
@ -27,12 +27,14 @@ target 'RocketChatRN' do
|
||||||
|
|
||||||
pod 'RNImageCropPicker', :path => '../node_modules/react-native-image-crop-picker'
|
pod 'RNImageCropPicker', :path => '../node_modules/react-native-image-crop-picker'
|
||||||
pod 'RNDeviceInfo', :path => '../node_modules/react-native-device-info'
|
pod 'RNDeviceInfo', :path => '../node_modules/react-native-device-info'
|
||||||
|
pod 'RNLocalize', :path => '../node_modules/react-native-localize'
|
||||||
|
|
||||||
pod 'RNScreens', :path => '../node_modules/react-native-screens'
|
pod 'RNScreens', :path => '../node_modules/react-native-screens'
|
||||||
|
|
||||||
pod 'react-native-splash-screen', :path => '../node_modules/react-native-splash-screen'
|
pod 'react-native-splash-screen', :path => '../node_modules/react-native-splash-screen'
|
||||||
|
|
||||||
pod 'react-native-orientation-locker', :path => '../node_modules/react-native-orientation-locker'
|
pod 'react-native-orientation-locker', :path => '../node_modules/react-native-orientation-locker'
|
||||||
|
pod 'react-native-realm-path', :path => '../node_modules/react-native-realm-path'
|
||||||
|
|
||||||
pod 'yoga', :path => '../node_modules/react-native/ReactCommon/yoga'
|
pod 'yoga', :path => '../node_modules/react-native/ReactCommon/yoga'
|
||||||
pod 'DoubleConversion', :podspec => '../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec'
|
pod 'DoubleConversion', :podspec => '../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec'
|
||||||
|
@ -45,11 +47,49 @@ target 'RocketChatRN' do
|
||||||
pod 'Crashlytics', '~> 3.12.0'
|
pod 'Crashlytics', '~> 3.12.0'
|
||||||
pod 'GoogleIDFASupport', '~> 3.14.0'
|
pod 'GoogleIDFASupport', '~> 3.14.0'
|
||||||
pod 'Firebase/Performance', '~> 5.20.1'
|
pod 'Firebase/Performance', '~> 5.20.1'
|
||||||
|
pod 'react-native-document-picker', :path => '../node_modules/react-native-document-picker'
|
||||||
|
|
||||||
use_unimodules!
|
use_unimodules!
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
target 'ShareRocketChatRN' do
|
||||||
|
|
||||||
|
rn_path = '../node_modules/react-native'
|
||||||
|
|
||||||
|
pod 'React', path: rn_path, subspecs: [
|
||||||
|
'Core',
|
||||||
|
'RCTActionSheet',
|
||||||
|
'RCTAnimation',
|
||||||
|
# 'RCTGeolocation',
|
||||||
|
'RCTImage',
|
||||||
|
'RCTLinkingIOS',
|
||||||
|
'RCTNetwork',
|
||||||
|
'RCTSettings',
|
||||||
|
'RCTText',
|
||||||
|
'RCTVibration',
|
||||||
|
'RCTWebSocket'
|
||||||
|
]
|
||||||
|
|
||||||
|
pod 'RNDeviceInfo', :path => '../node_modules/react-native-device-info'
|
||||||
|
pod 'RNLocalize', :path => '../node_modules/react-native-localize'
|
||||||
|
|
||||||
|
pod 'react-native-realm-path', :path => '../node_modules/react-native-realm-path'
|
||||||
|
pod 'rn-extensions-share', :path => '../node_modules/rn-extensions-share'
|
||||||
|
|
||||||
|
pod 'yoga', :path => '../node_modules/react-native/ReactCommon/yoga'
|
||||||
|
pod 'DoubleConversion', :podspec => '../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec'
|
||||||
|
pod 'glog', :podspec => '../node_modules/react-native/third-party-podspecs/glog.podspec'
|
||||||
|
pod 'Folly', :podspec => '../node_modules/react-native/third-party-podspecs/Folly.podspec'
|
||||||
|
|
||||||
|
pod 'Firebase/Core', '~> 5.20.1'
|
||||||
|
pod 'Fabric', '~> 1.9.0'
|
||||||
|
pod 'Crashlytics', '~> 3.12.0'
|
||||||
|
pod 'GoogleIDFASupport', '~> 3.14.0'
|
||||||
|
pod 'Firebase/Performance', '~> 5.20.1'
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
post_install do |installer|
|
post_install do |installer|
|
||||||
installer.pods_project.targets.each do |target|
|
installer.pods_project.targets.each do |target|
|
||||||
if target.name == "React"
|
if target.name == "React"
|
||||||
|
|
|
@ -109,8 +109,12 @@ PODS:
|
||||||
- QBImagePickerController (3.4.0)
|
- QBImagePickerController (3.4.0)
|
||||||
- React (0.59.8):
|
- React (0.59.8):
|
||||||
- React/Core (= 0.59.8)
|
- React/Core (= 0.59.8)
|
||||||
|
- react-native-document-picker (3.2.2):
|
||||||
|
- React
|
||||||
- react-native-orientation-locker (1.1.5):
|
- react-native-orientation-locker (1.1.5):
|
||||||
- React
|
- React
|
||||||
|
- react-native-realm-path (1.2.11):
|
||||||
|
- React
|
||||||
- react-native-splash-screen (3.2.0):
|
- react-native-splash-screen (3.2.0):
|
||||||
- React
|
- React
|
||||||
- react-native-webview (5.8.1):
|
- react-native-webview (5.8.1):
|
||||||
|
@ -141,12 +145,16 @@ PODS:
|
||||||
- React/Core
|
- React/Core
|
||||||
- React/fishhook
|
- React/fishhook
|
||||||
- React/RCTBlob
|
- React/RCTBlob
|
||||||
|
- rn-extensions-share (2.3.10):
|
||||||
|
- React
|
||||||
- RNDeviceInfo (1.6.1):
|
- RNDeviceInfo (1.6.1):
|
||||||
- React
|
- React
|
||||||
- RNImageCropPicker (0.21.1):
|
- RNImageCropPicker (0.24.1):
|
||||||
- QBImagePickerController
|
- QBImagePickerController
|
||||||
- React/Core
|
- React/Core
|
||||||
- RSKImageCropper
|
- RSKImageCropper
|
||||||
|
- RNLocalize (1.1.4):
|
||||||
|
- React
|
||||||
- RNScreens (1.0.0-alpha.22):
|
- RNScreens (1.0.0-alpha.22):
|
||||||
- React
|
- React
|
||||||
- RSKImageCropper (2.2.1)
|
- RSKImageCropper (2.2.1)
|
||||||
|
@ -182,7 +190,9 @@ DEPENDENCIES:
|
||||||
- Folly (from `../node_modules/react-native/third-party-podspecs/Folly.podspec`)
|
- Folly (from `../node_modules/react-native/third-party-podspecs/Folly.podspec`)
|
||||||
- glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`)
|
- glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`)
|
||||||
- GoogleIDFASupport (~> 3.14.0)
|
- GoogleIDFASupport (~> 3.14.0)
|
||||||
|
- react-native-document-picker (from `../node_modules/react-native-document-picker`)
|
||||||
- react-native-orientation-locker (from `../node_modules/react-native-orientation-locker`)
|
- react-native-orientation-locker (from `../node_modules/react-native-orientation-locker`)
|
||||||
|
- react-native-realm-path (from `../node_modules/react-native-realm-path`)
|
||||||
- react-native-splash-screen (from `../node_modules/react-native-splash-screen`)
|
- react-native-splash-screen (from `../node_modules/react-native-splash-screen`)
|
||||||
- react-native-webview (from `../node_modules/react-native-webview`)
|
- react-native-webview (from `../node_modules/react-native-webview`)
|
||||||
- React/Core (from `../node_modules/react-native`)
|
- React/Core (from `../node_modules/react-native`)
|
||||||
|
@ -195,8 +205,10 @@ DEPENDENCIES:
|
||||||
- React/RCTText (from `../node_modules/react-native`)
|
- React/RCTText (from `../node_modules/react-native`)
|
||||||
- React/RCTVibration (from `../node_modules/react-native`)
|
- React/RCTVibration (from `../node_modules/react-native`)
|
||||||
- React/RCTWebSocket (from `../node_modules/react-native`)
|
- React/RCTWebSocket (from `../node_modules/react-native`)
|
||||||
|
- rn-extensions-share (from `../node_modules/rn-extensions-share`)
|
||||||
- RNDeviceInfo (from `../node_modules/react-native-device-info`)
|
- RNDeviceInfo (from `../node_modules/react-native-device-info`)
|
||||||
- RNImageCropPicker (from `../node_modules/react-native-image-crop-picker`)
|
- RNImageCropPicker (from `../node_modules/react-native-image-crop-picker`)
|
||||||
|
- RNLocalize (from `../node_modules/react-native-localize`)
|
||||||
- RNScreens (from `../node_modules/react-native-screens`)
|
- RNScreens (from `../node_modules/react-native-screens`)
|
||||||
- UMBarCodeScannerInterface (from `../node_modules/unimodules-barcode-scanner-interface/ios`)
|
- UMBarCodeScannerInterface (from `../node_modules/unimodules-barcode-scanner-interface/ios`)
|
||||||
- UMCameraInterface (from `../node_modules/unimodules-camera-interface/ios`)
|
- UMCameraInterface (from `../node_modules/unimodules-camera-interface/ios`)
|
||||||
|
@ -261,16 +273,24 @@ EXTERNAL SOURCES:
|
||||||
:podspec: "../node_modules/react-native/third-party-podspecs/glog.podspec"
|
:podspec: "../node_modules/react-native/third-party-podspecs/glog.podspec"
|
||||||
React:
|
React:
|
||||||
:path: "../node_modules/react-native"
|
:path: "../node_modules/react-native"
|
||||||
|
react-native-document-picker:
|
||||||
|
:path: "../node_modules/react-native-document-picker"
|
||||||
react-native-orientation-locker:
|
react-native-orientation-locker:
|
||||||
:path: "../node_modules/react-native-orientation-locker"
|
:path: "../node_modules/react-native-orientation-locker"
|
||||||
|
react-native-realm-path:
|
||||||
|
:path: "../node_modules/react-native-realm-path"
|
||||||
react-native-splash-screen:
|
react-native-splash-screen:
|
||||||
:path: "../node_modules/react-native-splash-screen"
|
:path: "../node_modules/react-native-splash-screen"
|
||||||
react-native-webview:
|
react-native-webview:
|
||||||
:path: "../node_modules/react-native-webview"
|
:path: "../node_modules/react-native-webview"
|
||||||
|
rn-extensions-share:
|
||||||
|
:path: "../node_modules/rn-extensions-share"
|
||||||
RNDeviceInfo:
|
RNDeviceInfo:
|
||||||
:path: "../node_modules/react-native-device-info"
|
:path: "../node_modules/react-native-device-info"
|
||||||
RNImageCropPicker:
|
RNImageCropPicker:
|
||||||
:path: "../node_modules/react-native-image-crop-picker"
|
:path: "../node_modules/react-native-image-crop-picker"
|
||||||
|
RNLocalize:
|
||||||
|
:path: "../node_modules/react-native-localize"
|
||||||
RNScreens:
|
RNScreens:
|
||||||
:path: "../node_modules/react-native-screens"
|
:path: "../node_modules/react-native-screens"
|
||||||
UMBarCodeScannerInterface:
|
UMBarCodeScannerInterface:
|
||||||
|
@ -341,11 +361,15 @@ SPEC CHECKSUMS:
|
||||||
Protobuf: 7a877b7f3e5964e3fce995e2eb323dbc6831bb5a
|
Protobuf: 7a877b7f3e5964e3fce995e2eb323dbc6831bb5a
|
||||||
QBImagePickerController: d54cf93db6decf26baf6ed3472f336ef35cae022
|
QBImagePickerController: d54cf93db6decf26baf6ed3472f336ef35cae022
|
||||||
React: 76e6aa2b87d05eb6cccb6926d72685c9a07df152
|
React: 76e6aa2b87d05eb6cccb6926d72685c9a07df152
|
||||||
|
react-native-document-picker: 94a07ce0494c559e2ae9fa86621d6c624d810fec
|
||||||
react-native-orientation-locker: 132a63bab4dddd2a5709f6f7935ad9676b0af7c5
|
react-native-orientation-locker: 132a63bab4dddd2a5709f6f7935ad9676b0af7c5
|
||||||
|
react-native-realm-path: 868473ea0bc4629850f1ec51a70d81055c06d091
|
||||||
react-native-splash-screen: 200d11d188e2e78cea3ad319964f6142b6384865
|
react-native-splash-screen: 200d11d188e2e78cea3ad319964f6142b6384865
|
||||||
react-native-webview: f3e28b48461c78db833f727feec08b13285e7b61
|
react-native-webview: f3e28b48461c78db833f727feec08b13285e7b61
|
||||||
|
rn-extensions-share: 4bfee75806ad54aadeff1dfa535697a6345a50b8
|
||||||
RNDeviceInfo: 958a1ed6f94e04557b865b8ef848cfc83db0ebba
|
RNDeviceInfo: 958a1ed6f94e04557b865b8ef848cfc83db0ebba
|
||||||
RNImageCropPicker: e608efe182652dc8690268cb99cb5a201f2b5ea3
|
RNImageCropPicker: 6134b66a3d5bc13e2895a97c630a4254006902b4
|
||||||
|
RNLocalize: 62a949d2ec5bee0eb8f39a80a48f01e2f4f67080
|
||||||
RNScreens: 720a9e6968beb73e8196239801e887d8401f86ed
|
RNScreens: 720a9e6968beb73e8196239801e887d8401f86ed
|
||||||
RSKImageCropper: 98296ad26b41753f796b6898d015509598f13d97
|
RSKImageCropper: 98296ad26b41753f796b6898d015509598f13d97
|
||||||
UMBarCodeScannerInterface: d5602e23de37f95bb4ee49ee3b2711e128058ae9
|
UMBarCodeScannerInterface: d5602e23de37f95bb4ee49ee3b2711e128058ae9
|
||||||
|
@ -362,6 +386,6 @@ SPEC CHECKSUMS:
|
||||||
UMTaskManagerInterface: 296793ab2a7e181fe5ebe2ba9b40ae208ab4b8fa
|
UMTaskManagerInterface: 296793ab2a7e181fe5ebe2ba9b40ae208ab4b8fa
|
||||||
yoga: 92b2102c3d373d1a790db4ab761d2b0ffc634f64
|
yoga: 92b2102c3d373d1a790db4ab761d2b0ffc634f64
|
||||||
|
|
||||||
PODFILE CHECKSUM: b5e15bac5f306ea636e16393a7a6eb42c017ea99
|
PODFILE CHECKSUM: bfa056aa2707bd200eb8a39ada130c51b702380c
|
||||||
|
|
||||||
COCOAPODS: 1.6.2
|
COCOAPODS: 1.6.2
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
../../../../../node_modules/react-native-localize/ios/RNLocalize.h
|
|
@ -0,0 +1 @@
|
||||||
|
../../../../../node_modules/react-native-document-picker/ios/RNDocumentPicker/RNDocumentPicker.h
|
|
@ -0,0 +1 @@
|
||||||
|
../../../../../node_modules/react-native-realm-path/ios/RNRealmPath.h
|
|
@ -0,0 +1 @@
|
||||||
|
../../../../../node_modules/rn-extensions-share/ios/ReactNativeShareExtension.h
|
|
@ -0,0 +1 @@
|
||||||
|
../../../../../node_modules/react-native-localize/ios/RNLocalize.h
|
|
@ -0,0 +1 @@
|
||||||
|
../../../../../node_modules/react-native-document-picker/ios/RNDocumentPicker/RNDocumentPicker.h
|
|
@ -0,0 +1 @@
|
||||||
|
../../../../../node_modules/react-native-realm-path/ios/RNRealmPath.h
|
|
@ -0,0 +1 @@
|
||||||
|
../../../../../node_modules/rn-extensions-share/ios/ReactNativeShareExtension.h
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "RNImageCropPicker",
|
"name": "RNImageCropPicker",
|
||||||
"version": "0.21.1",
|
"version": "0.24.1",
|
||||||
"summary": "Select single or multiple images, with cropping option",
|
"summary": "Select single or multiple images, with cropping option",
|
||||||
"requires_arc": true,
|
"requires_arc": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
{
|
||||||
|
"name": "RNLocalize",
|
||||||
|
"dependencies": {
|
||||||
|
"React": [
|
||||||
|
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"version": "1.1.4",
|
||||||
|
"license": "MIT",
|
||||||
|
"description": "A toolbox for your React Native app localization.",
|
||||||
|
"summary": "A toolbox for your React Native app localization.",
|
||||||
|
"authors": "Mathieu Acthernoene <zoontek@gmail.com>",
|
||||||
|
"homepage": "https://github.com/react-native-community/react-native-localize",
|
||||||
|
"platforms": {
|
||||||
|
"ios": "9.0"
|
||||||
|
},
|
||||||
|
"source": {
|
||||||
|
"git": "https://github.com/react-native-community/react-native-localize.git",
|
||||||
|
"tag": "1.1.4"
|
||||||
|
},
|
||||||
|
"source_files": "ios/*.{h,m}"
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
{
|
||||||
|
"name": "react-native-document-picker",
|
||||||
|
"version": "3.2.2",
|
||||||
|
"summary": "A react native interface to access Documents from dropbox google drive, iCloud",
|
||||||
|
"license": "MIT",
|
||||||
|
"homepage": "https://github.com/Elyx0/react-native-document-picker#readme",
|
||||||
|
"authors": {
|
||||||
|
"Elyx0": "elyx00@gmail.com"
|
||||||
|
},
|
||||||
|
"source": {
|
||||||
|
"git": "https://github.com/Elyx0/react-native-document-picker"
|
||||||
|
},
|
||||||
|
"source_files": "ios/RNDocumentPicker/*.{h,m}",
|
||||||
|
"platforms": {
|
||||||
|
"ios": "7.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"React": [
|
||||||
|
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
{
|
||||||
|
"name": "react-native-realm-path",
|
||||||
|
"version": "1.2.11",
|
||||||
|
"summary": "A helper to Realm Path on AppGroup iOS.",
|
||||||
|
"license": "MIT",
|
||||||
|
"authors": "Djorkaeff Alexandre",
|
||||||
|
"homepage": "https://github.com/rocketchat/react-native-realm-path",
|
||||||
|
"platforms": {
|
||||||
|
"ios": "10.0"
|
||||||
|
},
|
||||||
|
"source": {
|
||||||
|
"git": "https://github.com/RocketChat/react-native-realm-path.git",
|
||||||
|
"tag": "v1.2.11"
|
||||||
|
},
|
||||||
|
"source_files": "ios/**/*.{h,m}",
|
||||||
|
"dependencies": {
|
||||||
|
"React": [
|
||||||
|
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
{
|
||||||
|
"name": "rn-extensions-share",
|
||||||
|
"version": "2.3.10",
|
||||||
|
"summary": "Share-Extension using react-native for both ios and android",
|
||||||
|
"license": "MIT",
|
||||||
|
"authors": {
|
||||||
|
"name": "Djorkaeff Alexandre",
|
||||||
|
"email": "djorkaeffalexandre@gmail.com",
|
||||||
|
"url": "http://github.com/djorkaeffalexandre"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/RocketChat/rn-extensions-share",
|
||||||
|
"platforms": {
|
||||||
|
"ios": "8.0"
|
||||||
|
},
|
||||||
|
"source": {
|
||||||
|
"git": "https://github.com/RocketChat/rn-extensions-share.git",
|
||||||
|
"tag": "master"
|
||||||
|
},
|
||||||
|
"source_files": "ios/*.{h,m}",
|
||||||
|
"dependencies": {
|
||||||
|
"React": [
|
||||||
|
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
|
@ -109,8 +109,12 @@ PODS:
|
||||||
- QBImagePickerController (3.4.0)
|
- QBImagePickerController (3.4.0)
|
||||||
- React (0.59.8):
|
- React (0.59.8):
|
||||||
- React/Core (= 0.59.8)
|
- React/Core (= 0.59.8)
|
||||||
|
- react-native-document-picker (3.2.2):
|
||||||
|
- React
|
||||||
- react-native-orientation-locker (1.1.5):
|
- react-native-orientation-locker (1.1.5):
|
||||||
- React
|
- React
|
||||||
|
- react-native-realm-path (1.2.11):
|
||||||
|
- React
|
||||||
- react-native-splash-screen (3.2.0):
|
- react-native-splash-screen (3.2.0):
|
||||||
- React
|
- React
|
||||||
- react-native-webview (5.8.1):
|
- react-native-webview (5.8.1):
|
||||||
|
@ -141,12 +145,16 @@ PODS:
|
||||||
- React/Core
|
- React/Core
|
||||||
- React/fishhook
|
- React/fishhook
|
||||||
- React/RCTBlob
|
- React/RCTBlob
|
||||||
|
- rn-extensions-share (2.3.10):
|
||||||
|
- React
|
||||||
- RNDeviceInfo (1.6.1):
|
- RNDeviceInfo (1.6.1):
|
||||||
- React
|
- React
|
||||||
- RNImageCropPicker (0.21.1):
|
- RNImageCropPicker (0.24.1):
|
||||||
- QBImagePickerController
|
- QBImagePickerController
|
||||||
- React/Core
|
- React/Core
|
||||||
- RSKImageCropper
|
- RSKImageCropper
|
||||||
|
- RNLocalize (1.1.4):
|
||||||
|
- React
|
||||||
- RNScreens (1.0.0-alpha.22):
|
- RNScreens (1.0.0-alpha.22):
|
||||||
- React
|
- React
|
||||||
- RSKImageCropper (2.2.1)
|
- RSKImageCropper (2.2.1)
|
||||||
|
@ -182,7 +190,9 @@ DEPENDENCIES:
|
||||||
- Folly (from `../node_modules/react-native/third-party-podspecs/Folly.podspec`)
|
- Folly (from `../node_modules/react-native/third-party-podspecs/Folly.podspec`)
|
||||||
- glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`)
|
- glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`)
|
||||||
- GoogleIDFASupport (~> 3.14.0)
|
- GoogleIDFASupport (~> 3.14.0)
|
||||||
|
- react-native-document-picker (from `../node_modules/react-native-document-picker`)
|
||||||
- react-native-orientation-locker (from `../node_modules/react-native-orientation-locker`)
|
- react-native-orientation-locker (from `../node_modules/react-native-orientation-locker`)
|
||||||
|
- react-native-realm-path (from `../node_modules/react-native-realm-path`)
|
||||||
- react-native-splash-screen (from `../node_modules/react-native-splash-screen`)
|
- react-native-splash-screen (from `../node_modules/react-native-splash-screen`)
|
||||||
- react-native-webview (from `../node_modules/react-native-webview`)
|
- react-native-webview (from `../node_modules/react-native-webview`)
|
||||||
- React/Core (from `../node_modules/react-native`)
|
- React/Core (from `../node_modules/react-native`)
|
||||||
|
@ -195,8 +205,10 @@ DEPENDENCIES:
|
||||||
- React/RCTText (from `../node_modules/react-native`)
|
- React/RCTText (from `../node_modules/react-native`)
|
||||||
- React/RCTVibration (from `../node_modules/react-native`)
|
- React/RCTVibration (from `../node_modules/react-native`)
|
||||||
- React/RCTWebSocket (from `../node_modules/react-native`)
|
- React/RCTWebSocket (from `../node_modules/react-native`)
|
||||||
|
- rn-extensions-share (from `../node_modules/rn-extensions-share`)
|
||||||
- RNDeviceInfo (from `../node_modules/react-native-device-info`)
|
- RNDeviceInfo (from `../node_modules/react-native-device-info`)
|
||||||
- RNImageCropPicker (from `../node_modules/react-native-image-crop-picker`)
|
- RNImageCropPicker (from `../node_modules/react-native-image-crop-picker`)
|
||||||
|
- RNLocalize (from `../node_modules/react-native-localize`)
|
||||||
- RNScreens (from `../node_modules/react-native-screens`)
|
- RNScreens (from `../node_modules/react-native-screens`)
|
||||||
- UMBarCodeScannerInterface (from `../node_modules/unimodules-barcode-scanner-interface/ios`)
|
- UMBarCodeScannerInterface (from `../node_modules/unimodules-barcode-scanner-interface/ios`)
|
||||||
- UMCameraInterface (from `../node_modules/unimodules-camera-interface/ios`)
|
- UMCameraInterface (from `../node_modules/unimodules-camera-interface/ios`)
|
||||||
|
@ -261,16 +273,24 @@ EXTERNAL SOURCES:
|
||||||
:podspec: "../node_modules/react-native/third-party-podspecs/glog.podspec"
|
:podspec: "../node_modules/react-native/third-party-podspecs/glog.podspec"
|
||||||
React:
|
React:
|
||||||
:path: "../node_modules/react-native"
|
:path: "../node_modules/react-native"
|
||||||
|
react-native-document-picker:
|
||||||
|
:path: "../node_modules/react-native-document-picker"
|
||||||
react-native-orientation-locker:
|
react-native-orientation-locker:
|
||||||
:path: "../node_modules/react-native-orientation-locker"
|
:path: "../node_modules/react-native-orientation-locker"
|
||||||
|
react-native-realm-path:
|
||||||
|
:path: "../node_modules/react-native-realm-path"
|
||||||
react-native-splash-screen:
|
react-native-splash-screen:
|
||||||
:path: "../node_modules/react-native-splash-screen"
|
:path: "../node_modules/react-native-splash-screen"
|
||||||
react-native-webview:
|
react-native-webview:
|
||||||
:path: "../node_modules/react-native-webview"
|
:path: "../node_modules/react-native-webview"
|
||||||
|
rn-extensions-share:
|
||||||
|
:path: "../node_modules/rn-extensions-share"
|
||||||
RNDeviceInfo:
|
RNDeviceInfo:
|
||||||
:path: "../node_modules/react-native-device-info"
|
:path: "../node_modules/react-native-device-info"
|
||||||
RNImageCropPicker:
|
RNImageCropPicker:
|
||||||
:path: "../node_modules/react-native-image-crop-picker"
|
:path: "../node_modules/react-native-image-crop-picker"
|
||||||
|
RNLocalize:
|
||||||
|
:path: "../node_modules/react-native-localize"
|
||||||
RNScreens:
|
RNScreens:
|
||||||
:path: "../node_modules/react-native-screens"
|
:path: "../node_modules/react-native-screens"
|
||||||
UMBarCodeScannerInterface:
|
UMBarCodeScannerInterface:
|
||||||
|
@ -341,11 +361,15 @@ SPEC CHECKSUMS:
|
||||||
Protobuf: 7a877b7f3e5964e3fce995e2eb323dbc6831bb5a
|
Protobuf: 7a877b7f3e5964e3fce995e2eb323dbc6831bb5a
|
||||||
QBImagePickerController: d54cf93db6decf26baf6ed3472f336ef35cae022
|
QBImagePickerController: d54cf93db6decf26baf6ed3472f336ef35cae022
|
||||||
React: 76e6aa2b87d05eb6cccb6926d72685c9a07df152
|
React: 76e6aa2b87d05eb6cccb6926d72685c9a07df152
|
||||||
|
react-native-document-picker: 94a07ce0494c559e2ae9fa86621d6c624d810fec
|
||||||
react-native-orientation-locker: 132a63bab4dddd2a5709f6f7935ad9676b0af7c5
|
react-native-orientation-locker: 132a63bab4dddd2a5709f6f7935ad9676b0af7c5
|
||||||
|
react-native-realm-path: 868473ea0bc4629850f1ec51a70d81055c06d091
|
||||||
react-native-splash-screen: 200d11d188e2e78cea3ad319964f6142b6384865
|
react-native-splash-screen: 200d11d188e2e78cea3ad319964f6142b6384865
|
||||||
react-native-webview: f3e28b48461c78db833f727feec08b13285e7b61
|
react-native-webview: f3e28b48461c78db833f727feec08b13285e7b61
|
||||||
|
rn-extensions-share: 4bfee75806ad54aadeff1dfa535697a6345a50b8
|
||||||
RNDeviceInfo: 958a1ed6f94e04557b865b8ef848cfc83db0ebba
|
RNDeviceInfo: 958a1ed6f94e04557b865b8ef848cfc83db0ebba
|
||||||
RNImageCropPicker: e608efe182652dc8690268cb99cb5a201f2b5ea3
|
RNImageCropPicker: 6134b66a3d5bc13e2895a97c630a4254006902b4
|
||||||
|
RNLocalize: 62a949d2ec5bee0eb8f39a80a48f01e2f4f67080
|
||||||
RNScreens: 720a9e6968beb73e8196239801e887d8401f86ed
|
RNScreens: 720a9e6968beb73e8196239801e887d8401f86ed
|
||||||
RSKImageCropper: 98296ad26b41753f796b6898d015509598f13d97
|
RSKImageCropper: 98296ad26b41753f796b6898d015509598f13d97
|
||||||
UMBarCodeScannerInterface: d5602e23de37f95bb4ee49ee3b2711e128058ae9
|
UMBarCodeScannerInterface: d5602e23de37f95bb4ee49ee3b2711e128058ae9
|
||||||
|
@ -362,6 +386,6 @@ SPEC CHECKSUMS:
|
||||||
UMTaskManagerInterface: 296793ab2a7e181fe5ebe2ba9b40ae208ab4b8fa
|
UMTaskManagerInterface: 296793ab2a7e181fe5ebe2ba9b40ae208ab4b8fa
|
||||||
yoga: 92b2102c3d373d1a790db4ab761d2b0ffc634f64
|
yoga: 92b2102c3d373d1a790db4ab761d2b0ffc634f64
|
||||||
|
|
||||||
PODFILE CHECKSUM: b5e15bac5f306ea636e16393a7a6eb42c017ea99
|
PODFILE CHECKSUM: bfa056aa2707bd200eb8a39ada130c51b702380c
|
||||||
|
|
||||||
COCOAPODS: 1.6.2
|
COCOAPODS: 1.6.2
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1568,6 +1568,31 @@ redistribute it freely, subject to the following restrictions:
|
||||||
distribution.
|
distribution.
|
||||||
|
|
||||||
|
|
||||||
|
## react-native-document-picker
|
||||||
|
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2016 Elyx0
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
|
||||||
|
|
||||||
## react-native-orientation-locker
|
## react-native-orientation-locker
|
||||||
|
|
||||||
MIT License
|
MIT License
|
||||||
|
|
|
@ -1739,6 +1739,37 @@ redistribute it freely, subject to the following restrictions:
|
||||||
<key>FooterText</key>
|
<key>FooterText</key>
|
||||||
<string>MIT License
|
<string>MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2016 Elyx0
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
</string>
|
||||||
|
<key>License</key>
|
||||||
|
<string>MIT</string>
|
||||||
|
<key>Title</key>
|
||||||
|
<string>react-native-document-picker</string>
|
||||||
|
<key>Type</key>
|
||||||
|
<string>PSGroupSpecifier</string>
|
||||||
|
</dict>
|
||||||
|
<dict>
|
||||||
|
<key>FooterText</key>
|
||||||
|
<string>MIT License
|
||||||
|
|
||||||
Copyright (c) 2017 Wonday (@wonday.org)
|
Copyright (c) 2017 Wonday (@wonday.org)
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Crashlytics/iOS" "${PODS_ROOT}/Fabric/iOS" "${PODS_ROOT}/FirebaseABTesting/Frameworks" "${PODS_ROOT}/FirebaseAnalytics/Frameworks" "${PODS_ROOT}/FirebasePerformance/Frameworks" "${PODS_ROOT}/FirebaseRemoteConfig/Frameworks" "${PODS_ROOT}/GoogleAppMeasurement/Frameworks"
|
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Crashlytics/iOS" "${PODS_ROOT}/Fabric/iOS" "${PODS_ROOT}/FirebaseABTesting/Frameworks" "${PODS_ROOT}/FirebaseAnalytics/Frameworks" "${PODS_ROOT}/FirebasePerformance/Frameworks" "${PODS_ROOT}/FirebaseRemoteConfig/Frameworks" "${PODS_ROOT}/GoogleAppMeasurement/Frameworks"
|
||||||
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 $(inherited) GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS=1 $(inherited) PB_FIELD_32BIT=1 PB_NO_PACKED_STRUCTS=1 PB_ENABLE_MALLOC=1
|
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 $(inherited) GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS=1 $(inherited) PB_FIELD_32BIT=1 PB_NO_PACKED_STRUCTS=1 PB_ENABLE_MALLOC=1
|
||||||
HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/DoubleConversion" "${PODS_ROOT}/Headers/Public/EXAppLoaderProvider" "${PODS_ROOT}/Headers/Public/EXConstants" "${PODS_ROOT}/Headers/Public/EXFileSystem" "${PODS_ROOT}/Headers/Public/EXHaptics" "${PODS_ROOT}/Headers/Public/EXPermissions" "${PODS_ROOT}/Headers/Public/EXWebBrowser" "${PODS_ROOT}/Headers/Public/Firebase" "${PODS_ROOT}/Headers/Public/FirebaseCore" "${PODS_ROOT}/Headers/Public/FirebaseInstanceID" "${PODS_ROOT}/Headers/Public/GTMSessionFetcher" "${PODS_ROOT}/Headers/Public/GoogleToolboxForMac" "${PODS_ROOT}/Headers/Public/GoogleUtilities" "${PODS_ROOT}/Headers/Public/Protobuf" "${PODS_ROOT}/Headers/Public/QBImagePickerController" "${PODS_ROOT}/Headers/Public/RNDeviceInfo" "${PODS_ROOT}/Headers/Public/RNImageCropPicker" "${PODS_ROOT}/Headers/Public/RNScreens" "${PODS_ROOT}/Headers/Public/RSKImageCropper" "${PODS_ROOT}/Headers/Public/React" "${PODS_ROOT}/Headers/Public/UMBarCodeScannerInterface" "${PODS_ROOT}/Headers/Public/UMCameraInterface" "${PODS_ROOT}/Headers/Public/UMConstantsInterface" "${PODS_ROOT}/Headers/Public/UMCore" "${PODS_ROOT}/Headers/Public/UMFaceDetectorInterface" "${PODS_ROOT}/Headers/Public/UMFileSystemInterface" "${PODS_ROOT}/Headers/Public/UMFontInterface" "${PODS_ROOT}/Headers/Public/UMImageLoaderInterface" "${PODS_ROOT}/Headers/Public/UMPermissionsInterface" "${PODS_ROOT}/Headers/Public/UMReactNativeAdapter" "${PODS_ROOT}/Headers/Public/UMSensorsInterface" "${PODS_ROOT}/Headers/Public/UMTaskManagerInterface" "${PODS_ROOT}/Headers/Public/glog" "${PODS_ROOT}/Headers/Public/nanopb" "${PODS_ROOT}/Headers/Public/react-native-orientation-locker" "${PODS_ROOT}/Headers/Public/react-native-splash-screen" "${PODS_ROOT}/Headers/Public/react-native-webview" "${PODS_ROOT}/Headers/Public/yoga" $(inherited) ${PODS_ROOT}/Firebase/CoreOnly/Sources
|
HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/DoubleConversion" "${PODS_ROOT}/Headers/Public/EXAppLoaderProvider" "${PODS_ROOT}/Headers/Public/EXConstants" "${PODS_ROOT}/Headers/Public/EXFileSystem" "${PODS_ROOT}/Headers/Public/EXHaptics" "${PODS_ROOT}/Headers/Public/EXPermissions" "${PODS_ROOT}/Headers/Public/EXWebBrowser" "${PODS_ROOT}/Headers/Public/Firebase" "${PODS_ROOT}/Headers/Public/FirebaseCore" "${PODS_ROOT}/Headers/Public/FirebaseInstanceID" "${PODS_ROOT}/Headers/Public/GTMSessionFetcher" "${PODS_ROOT}/Headers/Public/GoogleToolboxForMac" "${PODS_ROOT}/Headers/Public/GoogleUtilities" "${PODS_ROOT}/Headers/Public/Protobuf" "${PODS_ROOT}/Headers/Public/QBImagePickerController" "${PODS_ROOT}/Headers/Public/RNDeviceInfo" "${PODS_ROOT}/Headers/Public/RNImageCropPicker" "${PODS_ROOT}/Headers/Public/RNLocalize" "${PODS_ROOT}/Headers/Public/RNScreens" "${PODS_ROOT}/Headers/Public/RSKImageCropper" "${PODS_ROOT}/Headers/Public/React" "${PODS_ROOT}/Headers/Public/UMBarCodeScannerInterface" "${PODS_ROOT}/Headers/Public/UMCameraInterface" "${PODS_ROOT}/Headers/Public/UMConstantsInterface" "${PODS_ROOT}/Headers/Public/UMCore" "${PODS_ROOT}/Headers/Public/UMFaceDetectorInterface" "${PODS_ROOT}/Headers/Public/UMFileSystemInterface" "${PODS_ROOT}/Headers/Public/UMFontInterface" "${PODS_ROOT}/Headers/Public/UMImageLoaderInterface" "${PODS_ROOT}/Headers/Public/UMPermissionsInterface" "${PODS_ROOT}/Headers/Public/UMReactNativeAdapter" "${PODS_ROOT}/Headers/Public/UMSensorsInterface" "${PODS_ROOT}/Headers/Public/UMTaskManagerInterface" "${PODS_ROOT}/Headers/Public/glog" "${PODS_ROOT}/Headers/Public/nanopb" "${PODS_ROOT}/Headers/Public/react-native-document-picker" "${PODS_ROOT}/Headers/Public/react-native-orientation-locker" "${PODS_ROOT}/Headers/Public/react-native-realm-path" "${PODS_ROOT}/Headers/Public/react-native-splash-screen" "${PODS_ROOT}/Headers/Public/react-native-webview" "${PODS_ROOT}/Headers/Public/rn-extensions-share" "${PODS_ROOT}/Headers/Public/yoga" $(inherited) ${PODS_ROOT}/Firebase/CoreOnly/Sources
|
||||||
LIBRARY_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/DoubleConversion" "${PODS_CONFIGURATION_BUILD_DIR}/EXAppLoaderProvider" "${PODS_CONFIGURATION_BUILD_DIR}/EXConstants" "${PODS_CONFIGURATION_BUILD_DIR}/EXFileSystem" "${PODS_CONFIGURATION_BUILD_DIR}/EXHaptics" "${PODS_CONFIGURATION_BUILD_DIR}/EXPermissions" "${PODS_CONFIGURATION_BUILD_DIR}/EXWebBrowser" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstanceID" "${PODS_CONFIGURATION_BUILD_DIR}/Folly" "${PODS_CONFIGURATION_BUILD_DIR}/GTMSessionFetcher" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleToolboxForMac" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/Protobuf" "${PODS_CONFIGURATION_BUILD_DIR}/QBImagePickerController" "${PODS_CONFIGURATION_BUILD_DIR}/RNDeviceInfo" "${PODS_CONFIGURATION_BUILD_DIR}/RNImageCropPicker" "${PODS_CONFIGURATION_BUILD_DIR}/RNScreens" "${PODS_CONFIGURATION_BUILD_DIR}/RSKImageCropper" "${PODS_CONFIGURATION_BUILD_DIR}/React" "${PODS_CONFIGURATION_BUILD_DIR}/UMCore" "${PODS_CONFIGURATION_BUILD_DIR}/UMReactNativeAdapter" "${PODS_CONFIGURATION_BUILD_DIR}/glog" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" "${PODS_CONFIGURATION_BUILD_DIR}/react-native-orientation-locker" "${PODS_CONFIGURATION_BUILD_DIR}/react-native-splash-screen" "${PODS_CONFIGURATION_BUILD_DIR}/react-native-webview" "${PODS_CONFIGURATION_BUILD_DIR}/yoga" "${PODS_ROOT}/GoogleIDFASupport/Libraries"
|
LIBRARY_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/DoubleConversion" "${PODS_CONFIGURATION_BUILD_DIR}/EXAppLoaderProvider" "${PODS_CONFIGURATION_BUILD_DIR}/EXConstants" "${PODS_CONFIGURATION_BUILD_DIR}/EXFileSystem" "${PODS_CONFIGURATION_BUILD_DIR}/EXHaptics" "${PODS_CONFIGURATION_BUILD_DIR}/EXPermissions" "${PODS_CONFIGURATION_BUILD_DIR}/EXWebBrowser" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstanceID" "${PODS_CONFIGURATION_BUILD_DIR}/Folly" "${PODS_CONFIGURATION_BUILD_DIR}/GTMSessionFetcher" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleToolboxForMac" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/Protobuf" "${PODS_CONFIGURATION_BUILD_DIR}/QBImagePickerController" "${PODS_CONFIGURATION_BUILD_DIR}/RNDeviceInfo" "${PODS_CONFIGURATION_BUILD_DIR}/RNImageCropPicker" "${PODS_CONFIGURATION_BUILD_DIR}/RNLocalize" "${PODS_CONFIGURATION_BUILD_DIR}/RNScreens" "${PODS_CONFIGURATION_BUILD_DIR}/RSKImageCropper" "${PODS_CONFIGURATION_BUILD_DIR}/React" "${PODS_CONFIGURATION_BUILD_DIR}/UMCore" "${PODS_CONFIGURATION_BUILD_DIR}/UMReactNativeAdapter" "${PODS_CONFIGURATION_BUILD_DIR}/glog" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" "${PODS_CONFIGURATION_BUILD_DIR}/react-native-document-picker" "${PODS_CONFIGURATION_BUILD_DIR}/react-native-orientation-locker" "${PODS_CONFIGURATION_BUILD_DIR}/react-native-realm-path" "${PODS_CONFIGURATION_BUILD_DIR}/react-native-splash-screen" "${PODS_CONFIGURATION_BUILD_DIR}/react-native-webview" "${PODS_CONFIGURATION_BUILD_DIR}/yoga" "${PODS_ROOT}/GoogleIDFASupport/Libraries"
|
||||||
OTHER_LDFLAGS = $(inherited) -ObjC -l"AdIdAccessLibrary" -l"DoubleConversion" -l"EXAppLoaderProvider" -l"EXConstants" -l"EXFileSystem" -l"EXHaptics" -l"EXPermissions" -l"EXWebBrowser" -l"FirebaseCore" -l"FirebaseInstanceID" -l"Folly" -l"GTMSessionFetcher" -l"GoogleToolboxForMac" -l"GoogleUtilities" -l"Protobuf" -l"QBImagePickerController" -l"RNDeviceInfo" -l"RNImageCropPicker" -l"RNScreens" -l"RSKImageCropper" -l"React" -l"UMCore" -l"UMReactNativeAdapter" -l"c++" -l"glog" -l"nanopb" -l"react-native-orientation-locker" -l"react-native-splash-screen" -l"react-native-webview" -l"sqlite3" -l"stdc++" -l"yoga" -l"z" -framework "AdSupport" -framework "CoreTelephony" -framework "Crashlytics" -framework "FIRAnalyticsConnector" -framework "Fabric" -framework "FirebaseABTesting" -framework "FirebaseAnalytics" -framework "FirebaseCoreDiagnostics" -framework "FirebasePerformance" -framework "FirebaseRemoteConfig" -framework "Foundation" -framework "GoogleAppMeasurement" -framework "JavaScriptCore" -framework "Photos" -framework "QuartzCore" -framework "Security" -framework "StoreKit" -framework "SystemConfiguration" -framework "UIKit"
|
OTHER_LDFLAGS = $(inherited) -ObjC -l"AdIdAccessLibrary" -l"DoubleConversion" -l"EXAppLoaderProvider" -l"EXConstants" -l"EXFileSystem" -l"EXHaptics" -l"EXPermissions" -l"EXWebBrowser" -l"FirebaseCore" -l"FirebaseInstanceID" -l"Folly" -l"GTMSessionFetcher" -l"GoogleToolboxForMac" -l"GoogleUtilities" -l"Protobuf" -l"QBImagePickerController" -l"RNDeviceInfo" -l"RNImageCropPicker" -l"RNLocalize" -l"RNScreens" -l"RSKImageCropper" -l"React" -l"UMCore" -l"UMReactNativeAdapter" -l"c++" -l"glog" -l"nanopb" -l"react-native-document-picker" -l"react-native-orientation-locker" -l"react-native-realm-path" -l"react-native-splash-screen" -l"react-native-webview" -l"sqlite3" -l"stdc++" -l"yoga" -l"z" -framework "AdSupport" -framework "CoreTelephony" -framework "Crashlytics" -framework "FIRAnalyticsConnector" -framework "Fabric" -framework "FirebaseABTesting" -framework "FirebaseAnalytics" -framework "FirebaseCoreDiagnostics" -framework "FirebasePerformance" -framework "FirebaseRemoteConfig" -framework "Foundation" -framework "GoogleAppMeasurement" -framework "JavaScriptCore" -framework "Photos" -framework "QuartzCore" -framework "Security" -framework "StoreKit" -framework "SystemConfiguration" -framework "UIKit"
|
||||||
PODS_BUILD_DIR = ${BUILD_DIR}
|
PODS_BUILD_DIR = ${BUILD_DIR}
|
||||||
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
|
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
|
||||||
PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
|
PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Crashlytics/iOS" "${PODS_ROOT}/Fabric/iOS" "${PODS_ROOT}/FirebaseABTesting/Frameworks" "${PODS_ROOT}/FirebaseAnalytics/Frameworks" "${PODS_ROOT}/FirebasePerformance/Frameworks" "${PODS_ROOT}/FirebaseRemoteConfig/Frameworks" "${PODS_ROOT}/GoogleAppMeasurement/Frameworks"
|
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Crashlytics/iOS" "${PODS_ROOT}/Fabric/iOS" "${PODS_ROOT}/FirebaseABTesting/Frameworks" "${PODS_ROOT}/FirebaseAnalytics/Frameworks" "${PODS_ROOT}/FirebasePerformance/Frameworks" "${PODS_ROOT}/FirebaseRemoteConfig/Frameworks" "${PODS_ROOT}/GoogleAppMeasurement/Frameworks"
|
||||||
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 $(inherited) GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS=1 $(inherited) PB_FIELD_32BIT=1 PB_NO_PACKED_STRUCTS=1 PB_ENABLE_MALLOC=1
|
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 $(inherited) GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS=1 $(inherited) PB_FIELD_32BIT=1 PB_NO_PACKED_STRUCTS=1 PB_ENABLE_MALLOC=1
|
||||||
HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/DoubleConversion" "${PODS_ROOT}/Headers/Public/EXAppLoaderProvider" "${PODS_ROOT}/Headers/Public/EXConstants" "${PODS_ROOT}/Headers/Public/EXFileSystem" "${PODS_ROOT}/Headers/Public/EXHaptics" "${PODS_ROOT}/Headers/Public/EXPermissions" "${PODS_ROOT}/Headers/Public/EXWebBrowser" "${PODS_ROOT}/Headers/Public/Firebase" "${PODS_ROOT}/Headers/Public/FirebaseCore" "${PODS_ROOT}/Headers/Public/FirebaseInstanceID" "${PODS_ROOT}/Headers/Public/GTMSessionFetcher" "${PODS_ROOT}/Headers/Public/GoogleToolboxForMac" "${PODS_ROOT}/Headers/Public/GoogleUtilities" "${PODS_ROOT}/Headers/Public/Protobuf" "${PODS_ROOT}/Headers/Public/QBImagePickerController" "${PODS_ROOT}/Headers/Public/RNDeviceInfo" "${PODS_ROOT}/Headers/Public/RNImageCropPicker" "${PODS_ROOT}/Headers/Public/RNScreens" "${PODS_ROOT}/Headers/Public/RSKImageCropper" "${PODS_ROOT}/Headers/Public/React" "${PODS_ROOT}/Headers/Public/UMBarCodeScannerInterface" "${PODS_ROOT}/Headers/Public/UMCameraInterface" "${PODS_ROOT}/Headers/Public/UMConstantsInterface" "${PODS_ROOT}/Headers/Public/UMCore" "${PODS_ROOT}/Headers/Public/UMFaceDetectorInterface" "${PODS_ROOT}/Headers/Public/UMFileSystemInterface" "${PODS_ROOT}/Headers/Public/UMFontInterface" "${PODS_ROOT}/Headers/Public/UMImageLoaderInterface" "${PODS_ROOT}/Headers/Public/UMPermissionsInterface" "${PODS_ROOT}/Headers/Public/UMReactNativeAdapter" "${PODS_ROOT}/Headers/Public/UMSensorsInterface" "${PODS_ROOT}/Headers/Public/UMTaskManagerInterface" "${PODS_ROOT}/Headers/Public/glog" "${PODS_ROOT}/Headers/Public/nanopb" "${PODS_ROOT}/Headers/Public/react-native-orientation-locker" "${PODS_ROOT}/Headers/Public/react-native-splash-screen" "${PODS_ROOT}/Headers/Public/react-native-webview" "${PODS_ROOT}/Headers/Public/yoga" $(inherited) ${PODS_ROOT}/Firebase/CoreOnly/Sources
|
HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/DoubleConversion" "${PODS_ROOT}/Headers/Public/EXAppLoaderProvider" "${PODS_ROOT}/Headers/Public/EXConstants" "${PODS_ROOT}/Headers/Public/EXFileSystem" "${PODS_ROOT}/Headers/Public/EXHaptics" "${PODS_ROOT}/Headers/Public/EXPermissions" "${PODS_ROOT}/Headers/Public/EXWebBrowser" "${PODS_ROOT}/Headers/Public/Firebase" "${PODS_ROOT}/Headers/Public/FirebaseCore" "${PODS_ROOT}/Headers/Public/FirebaseInstanceID" "${PODS_ROOT}/Headers/Public/GTMSessionFetcher" "${PODS_ROOT}/Headers/Public/GoogleToolboxForMac" "${PODS_ROOT}/Headers/Public/GoogleUtilities" "${PODS_ROOT}/Headers/Public/Protobuf" "${PODS_ROOT}/Headers/Public/QBImagePickerController" "${PODS_ROOT}/Headers/Public/RNDeviceInfo" "${PODS_ROOT}/Headers/Public/RNImageCropPicker" "${PODS_ROOT}/Headers/Public/RNLocalize" "${PODS_ROOT}/Headers/Public/RNScreens" "${PODS_ROOT}/Headers/Public/RSKImageCropper" "${PODS_ROOT}/Headers/Public/React" "${PODS_ROOT}/Headers/Public/UMBarCodeScannerInterface" "${PODS_ROOT}/Headers/Public/UMCameraInterface" "${PODS_ROOT}/Headers/Public/UMConstantsInterface" "${PODS_ROOT}/Headers/Public/UMCore" "${PODS_ROOT}/Headers/Public/UMFaceDetectorInterface" "${PODS_ROOT}/Headers/Public/UMFileSystemInterface" "${PODS_ROOT}/Headers/Public/UMFontInterface" "${PODS_ROOT}/Headers/Public/UMImageLoaderInterface" "${PODS_ROOT}/Headers/Public/UMPermissionsInterface" "${PODS_ROOT}/Headers/Public/UMReactNativeAdapter" "${PODS_ROOT}/Headers/Public/UMSensorsInterface" "${PODS_ROOT}/Headers/Public/UMTaskManagerInterface" "${PODS_ROOT}/Headers/Public/glog" "${PODS_ROOT}/Headers/Public/nanopb" "${PODS_ROOT}/Headers/Public/react-native-document-picker" "${PODS_ROOT}/Headers/Public/react-native-orientation-locker" "${PODS_ROOT}/Headers/Public/react-native-realm-path" "${PODS_ROOT}/Headers/Public/react-native-splash-screen" "${PODS_ROOT}/Headers/Public/react-native-webview" "${PODS_ROOT}/Headers/Public/rn-extensions-share" "${PODS_ROOT}/Headers/Public/yoga" $(inherited) ${PODS_ROOT}/Firebase/CoreOnly/Sources
|
||||||
LIBRARY_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/DoubleConversion" "${PODS_CONFIGURATION_BUILD_DIR}/EXAppLoaderProvider" "${PODS_CONFIGURATION_BUILD_DIR}/EXConstants" "${PODS_CONFIGURATION_BUILD_DIR}/EXFileSystem" "${PODS_CONFIGURATION_BUILD_DIR}/EXHaptics" "${PODS_CONFIGURATION_BUILD_DIR}/EXPermissions" "${PODS_CONFIGURATION_BUILD_DIR}/EXWebBrowser" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstanceID" "${PODS_CONFIGURATION_BUILD_DIR}/Folly" "${PODS_CONFIGURATION_BUILD_DIR}/GTMSessionFetcher" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleToolboxForMac" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/Protobuf" "${PODS_CONFIGURATION_BUILD_DIR}/QBImagePickerController" "${PODS_CONFIGURATION_BUILD_DIR}/RNDeviceInfo" "${PODS_CONFIGURATION_BUILD_DIR}/RNImageCropPicker" "${PODS_CONFIGURATION_BUILD_DIR}/RNScreens" "${PODS_CONFIGURATION_BUILD_DIR}/RSKImageCropper" "${PODS_CONFIGURATION_BUILD_DIR}/React" "${PODS_CONFIGURATION_BUILD_DIR}/UMCore" "${PODS_CONFIGURATION_BUILD_DIR}/UMReactNativeAdapter" "${PODS_CONFIGURATION_BUILD_DIR}/glog" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" "${PODS_CONFIGURATION_BUILD_DIR}/react-native-orientation-locker" "${PODS_CONFIGURATION_BUILD_DIR}/react-native-splash-screen" "${PODS_CONFIGURATION_BUILD_DIR}/react-native-webview" "${PODS_CONFIGURATION_BUILD_DIR}/yoga" "${PODS_ROOT}/GoogleIDFASupport/Libraries"
|
LIBRARY_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/DoubleConversion" "${PODS_CONFIGURATION_BUILD_DIR}/EXAppLoaderProvider" "${PODS_CONFIGURATION_BUILD_DIR}/EXConstants" "${PODS_CONFIGURATION_BUILD_DIR}/EXFileSystem" "${PODS_CONFIGURATION_BUILD_DIR}/EXHaptics" "${PODS_CONFIGURATION_BUILD_DIR}/EXPermissions" "${PODS_CONFIGURATION_BUILD_DIR}/EXWebBrowser" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstanceID" "${PODS_CONFIGURATION_BUILD_DIR}/Folly" "${PODS_CONFIGURATION_BUILD_DIR}/GTMSessionFetcher" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleToolboxForMac" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/Protobuf" "${PODS_CONFIGURATION_BUILD_DIR}/QBImagePickerController" "${PODS_CONFIGURATION_BUILD_DIR}/RNDeviceInfo" "${PODS_CONFIGURATION_BUILD_DIR}/RNImageCropPicker" "${PODS_CONFIGURATION_BUILD_DIR}/RNLocalize" "${PODS_CONFIGURATION_BUILD_DIR}/RNScreens" "${PODS_CONFIGURATION_BUILD_DIR}/RSKImageCropper" "${PODS_CONFIGURATION_BUILD_DIR}/React" "${PODS_CONFIGURATION_BUILD_DIR}/UMCore" "${PODS_CONFIGURATION_BUILD_DIR}/UMReactNativeAdapter" "${PODS_CONFIGURATION_BUILD_DIR}/glog" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" "${PODS_CONFIGURATION_BUILD_DIR}/react-native-document-picker" "${PODS_CONFIGURATION_BUILD_DIR}/react-native-orientation-locker" "${PODS_CONFIGURATION_BUILD_DIR}/react-native-realm-path" "${PODS_CONFIGURATION_BUILD_DIR}/react-native-splash-screen" "${PODS_CONFIGURATION_BUILD_DIR}/react-native-webview" "${PODS_CONFIGURATION_BUILD_DIR}/yoga" "${PODS_ROOT}/GoogleIDFASupport/Libraries"
|
||||||
OTHER_LDFLAGS = $(inherited) -ObjC -l"AdIdAccessLibrary" -l"DoubleConversion" -l"EXAppLoaderProvider" -l"EXConstants" -l"EXFileSystem" -l"EXHaptics" -l"EXPermissions" -l"EXWebBrowser" -l"FirebaseCore" -l"FirebaseInstanceID" -l"Folly" -l"GTMSessionFetcher" -l"GoogleToolboxForMac" -l"GoogleUtilities" -l"Protobuf" -l"QBImagePickerController" -l"RNDeviceInfo" -l"RNImageCropPicker" -l"RNScreens" -l"RSKImageCropper" -l"React" -l"UMCore" -l"UMReactNativeAdapter" -l"c++" -l"glog" -l"nanopb" -l"react-native-orientation-locker" -l"react-native-splash-screen" -l"react-native-webview" -l"sqlite3" -l"stdc++" -l"yoga" -l"z" -framework "AdSupport" -framework "CoreTelephony" -framework "Crashlytics" -framework "FIRAnalyticsConnector" -framework "Fabric" -framework "FirebaseABTesting" -framework "FirebaseAnalytics" -framework "FirebaseCoreDiagnostics" -framework "FirebasePerformance" -framework "FirebaseRemoteConfig" -framework "Foundation" -framework "GoogleAppMeasurement" -framework "JavaScriptCore" -framework "Photos" -framework "QuartzCore" -framework "Security" -framework "StoreKit" -framework "SystemConfiguration" -framework "UIKit"
|
OTHER_LDFLAGS = $(inherited) -ObjC -l"AdIdAccessLibrary" -l"DoubleConversion" -l"EXAppLoaderProvider" -l"EXConstants" -l"EXFileSystem" -l"EXHaptics" -l"EXPermissions" -l"EXWebBrowser" -l"FirebaseCore" -l"FirebaseInstanceID" -l"Folly" -l"GTMSessionFetcher" -l"GoogleToolboxForMac" -l"GoogleUtilities" -l"Protobuf" -l"QBImagePickerController" -l"RNDeviceInfo" -l"RNImageCropPicker" -l"RNLocalize" -l"RNScreens" -l"RSKImageCropper" -l"React" -l"UMCore" -l"UMReactNativeAdapter" -l"c++" -l"glog" -l"nanopb" -l"react-native-document-picker" -l"react-native-orientation-locker" -l"react-native-realm-path" -l"react-native-splash-screen" -l"react-native-webview" -l"sqlite3" -l"stdc++" -l"yoga" -l"z" -framework "AdSupport" -framework "CoreTelephony" -framework "Crashlytics" -framework "FIRAnalyticsConnector" -framework "Fabric" -framework "FirebaseABTesting" -framework "FirebaseAnalytics" -framework "FirebaseCoreDiagnostics" -framework "FirebasePerformance" -framework "FirebaseRemoteConfig" -framework "Foundation" -framework "GoogleAppMeasurement" -framework "JavaScriptCore" -framework "Photos" -framework "QuartzCore" -framework "Security" -framework "StoreKit" -framework "SystemConfiguration" -framework "UIKit"
|
||||||
PODS_BUILD_DIR = ${BUILD_DIR}
|
PODS_BUILD_DIR = ${BUILD_DIR}
|
||||||
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
|
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
|
||||||
PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
|
PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
|
||||||
|
|
1511
ios/Pods/Target Support Files/Pods-ShareRocketChatRN/Pods-ShareRocketChatRN-acknowledgements.markdown
generated
Normal file
1511
ios/Pods/Target Support Files/Pods-ShareRocketChatRN/Pods-ShareRocketChatRN-acknowledgements.markdown
generated
Normal file
File diff suppressed because it is too large
Load Diff
1675
ios/Pods/Target Support Files/Pods-ShareRocketChatRN/Pods-ShareRocketChatRN-acknowledgements.plist
generated
Normal file
1675
ios/Pods/Target Support Files/Pods-ShareRocketChatRN/Pods-ShareRocketChatRN-acknowledgements.plist
generated
Normal file
File diff suppressed because it is too large
Load Diff
5
ios/Pods/Target Support Files/Pods-ShareRocketChatRN/Pods-ShareRocketChatRN-dummy.m
generated
Normal file
5
ios/Pods/Target Support Files/Pods-ShareRocketChatRN/Pods-ShareRocketChatRN-dummy.m
generated
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
@interface PodsDummy_Pods_ShareRocketChatRN : NSObject
|
||||||
|
@end
|
||||||
|
@implementation PodsDummy_Pods_ShareRocketChatRN
|
||||||
|
@end
|
9
ios/Pods/Target Support Files/Pods-ShareRocketChatRN/Pods-ShareRocketChatRN.debug.xcconfig
generated
Normal file
9
ios/Pods/Target Support Files/Pods-ShareRocketChatRN/Pods-ShareRocketChatRN.debug.xcconfig
generated
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Crashlytics/iOS" "${PODS_ROOT}/Fabric/iOS" "${PODS_ROOT}/FirebaseABTesting/Frameworks" "${PODS_ROOT}/FirebaseAnalytics/Frameworks" "${PODS_ROOT}/FirebasePerformance/Frameworks" "${PODS_ROOT}/FirebaseRemoteConfig/Frameworks" "${PODS_ROOT}/GoogleAppMeasurement/Frameworks"
|
||||||
|
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 $(inherited) GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS=1 $(inherited) PB_FIELD_32BIT=1 PB_NO_PACKED_STRUCTS=1 PB_ENABLE_MALLOC=1
|
||||||
|
HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/DoubleConversion" "${PODS_ROOT}/Headers/Public/EXAppLoaderProvider" "${PODS_ROOT}/Headers/Public/EXConstants" "${PODS_ROOT}/Headers/Public/EXFileSystem" "${PODS_ROOT}/Headers/Public/EXHaptics" "${PODS_ROOT}/Headers/Public/EXPermissions" "${PODS_ROOT}/Headers/Public/EXWebBrowser" "${PODS_ROOT}/Headers/Public/Firebase" "${PODS_ROOT}/Headers/Public/FirebaseCore" "${PODS_ROOT}/Headers/Public/FirebaseInstanceID" "${PODS_ROOT}/Headers/Public/GTMSessionFetcher" "${PODS_ROOT}/Headers/Public/GoogleToolboxForMac" "${PODS_ROOT}/Headers/Public/GoogleUtilities" "${PODS_ROOT}/Headers/Public/Protobuf" "${PODS_ROOT}/Headers/Public/QBImagePickerController" "${PODS_ROOT}/Headers/Public/RNDeviceInfo" "${PODS_ROOT}/Headers/Public/RNImageCropPicker" "${PODS_ROOT}/Headers/Public/RNLocalize" "${PODS_ROOT}/Headers/Public/RNScreens" "${PODS_ROOT}/Headers/Public/RSKImageCropper" "${PODS_ROOT}/Headers/Public/React" "${PODS_ROOT}/Headers/Public/UMBarCodeScannerInterface" "${PODS_ROOT}/Headers/Public/UMCameraInterface" "${PODS_ROOT}/Headers/Public/UMConstantsInterface" "${PODS_ROOT}/Headers/Public/UMCore" "${PODS_ROOT}/Headers/Public/UMFaceDetectorInterface" "${PODS_ROOT}/Headers/Public/UMFileSystemInterface" "${PODS_ROOT}/Headers/Public/UMFontInterface" "${PODS_ROOT}/Headers/Public/UMImageLoaderInterface" "${PODS_ROOT}/Headers/Public/UMPermissionsInterface" "${PODS_ROOT}/Headers/Public/UMReactNativeAdapter" "${PODS_ROOT}/Headers/Public/UMSensorsInterface" "${PODS_ROOT}/Headers/Public/UMTaskManagerInterface" "${PODS_ROOT}/Headers/Public/glog" "${PODS_ROOT}/Headers/Public/nanopb" "${PODS_ROOT}/Headers/Public/react-native-document-picker" "${PODS_ROOT}/Headers/Public/react-native-orientation-locker" "${PODS_ROOT}/Headers/Public/react-native-realm-path" "${PODS_ROOT}/Headers/Public/react-native-splash-screen" "${PODS_ROOT}/Headers/Public/react-native-webview" "${PODS_ROOT}/Headers/Public/rn-extensions-share" "${PODS_ROOT}/Headers/Public/yoga" $(inherited) ${PODS_ROOT}/Firebase/CoreOnly/Sources
|
||||||
|
LIBRARY_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/DoubleConversion" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstanceID" "${PODS_CONFIGURATION_BUILD_DIR}/Folly" "${PODS_CONFIGURATION_BUILD_DIR}/GTMSessionFetcher" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleToolboxForMac" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/Protobuf" "${PODS_CONFIGURATION_BUILD_DIR}/RNDeviceInfo" "${PODS_CONFIGURATION_BUILD_DIR}/RNLocalize" "${PODS_CONFIGURATION_BUILD_DIR}/React" "${PODS_CONFIGURATION_BUILD_DIR}/glog" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" "${PODS_CONFIGURATION_BUILD_DIR}/react-native-realm-path" "${PODS_CONFIGURATION_BUILD_DIR}/rn-extensions-share" "${PODS_CONFIGURATION_BUILD_DIR}/yoga" "${PODS_ROOT}/GoogleIDFASupport/Libraries"
|
||||||
|
OTHER_LDFLAGS = $(inherited) -ObjC -l"AdIdAccessLibrary" -l"DoubleConversion" -l"FirebaseCore" -l"FirebaseInstanceID" -l"Folly" -l"GTMSessionFetcher" -l"GoogleToolboxForMac" -l"GoogleUtilities" -l"Protobuf" -l"RNDeviceInfo" -l"RNLocalize" -l"React" -l"c++" -l"glog" -l"nanopb" -l"react-native-realm-path" -l"rn-extensions-share" -l"sqlite3" -l"stdc++" -l"yoga" -l"z" -framework "AdSupport" -framework "CoreTelephony" -framework "Crashlytics" -framework "FIRAnalyticsConnector" -framework "Fabric" -framework "FirebaseABTesting" -framework "FirebaseAnalytics" -framework "FirebaseCoreDiagnostics" -framework "FirebasePerformance" -framework "FirebaseRemoteConfig" -framework "Foundation" -framework "GoogleAppMeasurement" -framework "JavaScriptCore" -framework "QuartzCore" -framework "Security" -framework "StoreKit" -framework "SystemConfiguration" -framework "UIKit"
|
||||||
|
PODS_BUILD_DIR = ${BUILD_DIR}
|
||||||
|
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
|
||||||
|
PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
|
||||||
|
PODS_ROOT = ${SRCROOT}/Pods
|
9
ios/Pods/Target Support Files/Pods-ShareRocketChatRN/Pods-ShareRocketChatRN.release.xcconfig
generated
Normal file
9
ios/Pods/Target Support Files/Pods-ShareRocketChatRN/Pods-ShareRocketChatRN.release.xcconfig
generated
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Crashlytics/iOS" "${PODS_ROOT}/Fabric/iOS" "${PODS_ROOT}/FirebaseABTesting/Frameworks" "${PODS_ROOT}/FirebaseAnalytics/Frameworks" "${PODS_ROOT}/FirebasePerformance/Frameworks" "${PODS_ROOT}/FirebaseRemoteConfig/Frameworks" "${PODS_ROOT}/GoogleAppMeasurement/Frameworks"
|
||||||
|
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 $(inherited) GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS=1 $(inherited) PB_FIELD_32BIT=1 PB_NO_PACKED_STRUCTS=1 PB_ENABLE_MALLOC=1
|
||||||
|
HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/DoubleConversion" "${PODS_ROOT}/Headers/Public/EXAppLoaderProvider" "${PODS_ROOT}/Headers/Public/EXConstants" "${PODS_ROOT}/Headers/Public/EXFileSystem" "${PODS_ROOT}/Headers/Public/EXHaptics" "${PODS_ROOT}/Headers/Public/EXPermissions" "${PODS_ROOT}/Headers/Public/EXWebBrowser" "${PODS_ROOT}/Headers/Public/Firebase" "${PODS_ROOT}/Headers/Public/FirebaseCore" "${PODS_ROOT}/Headers/Public/FirebaseInstanceID" "${PODS_ROOT}/Headers/Public/GTMSessionFetcher" "${PODS_ROOT}/Headers/Public/GoogleToolboxForMac" "${PODS_ROOT}/Headers/Public/GoogleUtilities" "${PODS_ROOT}/Headers/Public/Protobuf" "${PODS_ROOT}/Headers/Public/QBImagePickerController" "${PODS_ROOT}/Headers/Public/RNDeviceInfo" "${PODS_ROOT}/Headers/Public/RNImageCropPicker" "${PODS_ROOT}/Headers/Public/RNLocalize" "${PODS_ROOT}/Headers/Public/RNScreens" "${PODS_ROOT}/Headers/Public/RSKImageCropper" "${PODS_ROOT}/Headers/Public/React" "${PODS_ROOT}/Headers/Public/UMBarCodeScannerInterface" "${PODS_ROOT}/Headers/Public/UMCameraInterface" "${PODS_ROOT}/Headers/Public/UMConstantsInterface" "${PODS_ROOT}/Headers/Public/UMCore" "${PODS_ROOT}/Headers/Public/UMFaceDetectorInterface" "${PODS_ROOT}/Headers/Public/UMFileSystemInterface" "${PODS_ROOT}/Headers/Public/UMFontInterface" "${PODS_ROOT}/Headers/Public/UMImageLoaderInterface" "${PODS_ROOT}/Headers/Public/UMPermissionsInterface" "${PODS_ROOT}/Headers/Public/UMReactNativeAdapter" "${PODS_ROOT}/Headers/Public/UMSensorsInterface" "${PODS_ROOT}/Headers/Public/UMTaskManagerInterface" "${PODS_ROOT}/Headers/Public/glog" "${PODS_ROOT}/Headers/Public/nanopb" "${PODS_ROOT}/Headers/Public/react-native-document-picker" "${PODS_ROOT}/Headers/Public/react-native-orientation-locker" "${PODS_ROOT}/Headers/Public/react-native-realm-path" "${PODS_ROOT}/Headers/Public/react-native-splash-screen" "${PODS_ROOT}/Headers/Public/react-native-webview" "${PODS_ROOT}/Headers/Public/rn-extensions-share" "${PODS_ROOT}/Headers/Public/yoga" $(inherited) ${PODS_ROOT}/Firebase/CoreOnly/Sources
|
||||||
|
LIBRARY_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/DoubleConversion" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstanceID" "${PODS_CONFIGURATION_BUILD_DIR}/Folly" "${PODS_CONFIGURATION_BUILD_DIR}/GTMSessionFetcher" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleToolboxForMac" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/Protobuf" "${PODS_CONFIGURATION_BUILD_DIR}/RNDeviceInfo" "${PODS_CONFIGURATION_BUILD_DIR}/RNLocalize" "${PODS_CONFIGURATION_BUILD_DIR}/React" "${PODS_CONFIGURATION_BUILD_DIR}/glog" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" "${PODS_CONFIGURATION_BUILD_DIR}/react-native-realm-path" "${PODS_CONFIGURATION_BUILD_DIR}/rn-extensions-share" "${PODS_CONFIGURATION_BUILD_DIR}/yoga" "${PODS_ROOT}/GoogleIDFASupport/Libraries"
|
||||||
|
OTHER_LDFLAGS = $(inherited) -ObjC -l"AdIdAccessLibrary" -l"DoubleConversion" -l"FirebaseCore" -l"FirebaseInstanceID" -l"Folly" -l"GTMSessionFetcher" -l"GoogleToolboxForMac" -l"GoogleUtilities" -l"Protobuf" -l"RNDeviceInfo" -l"RNLocalize" -l"React" -l"c++" -l"glog" -l"nanopb" -l"react-native-realm-path" -l"rn-extensions-share" -l"sqlite3" -l"stdc++" -l"yoga" -l"z" -framework "AdSupport" -framework "CoreTelephony" -framework "Crashlytics" -framework "FIRAnalyticsConnector" -framework "Fabric" -framework "FirebaseABTesting" -framework "FirebaseAnalytics" -framework "FirebaseCoreDiagnostics" -framework "FirebasePerformance" -framework "FirebaseRemoteConfig" -framework "Foundation" -framework "GoogleAppMeasurement" -framework "JavaScriptCore" -framework "QuartzCore" -framework "Security" -framework "StoreKit" -framework "SystemConfiguration" -framework "UIKit"
|
||||||
|
PODS_BUILD_DIR = ${BUILD_DIR}
|
||||||
|
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
|
||||||
|
PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
|
||||||
|
PODS_ROOT = ${SRCROOT}/Pods
|
|
@ -0,0 +1,5 @@
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
@interface PodsDummy_RNLocalize : NSObject
|
||||||
|
@end
|
||||||
|
@implementation PodsDummy_RNLocalize
|
||||||
|
@end
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue