From 302df46d69dbd71782a2e5bf36585c07dabd8cf3 Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Sat, 21 Apr 2018 16:10:44 -0300 Subject: [PATCH] Sync develop on master (#275) * Create LICENSE --- .babelrc | 7 +- .circleci/changelog.sh | 7 + .circleci/config.yml | 238 + .eslintrc => .eslintrc.js | 16 +- .github/ISSUE_TEMPLATE.md | 19 + .github/PULL_REQUEST_TEMPLATE.md | 7 + .gitignore | 3 + .snyk | 26 + LICENSE | 22 + README.md | 66 +- __tests__/RoomItem.js | 25 +- __tests__/__snapshots__/RoomItem.js.snap | 1406 +- .../__snapshots__/Storyshots.test.js.snap | 2997 ++-- android/app/BUCK | 4 +- android/app/build.gradle | 51 +- android/app/src/main/AndroidManifest.xml | 34 +- android/app/src/main/assets/fonts/Feather.ttf | Bin 0 -> 55288 bytes android/app/src/main/assets/fonts/icomoon.ttf | Bin 0 -> 2084 bytes .../com/rocketchatrn/CustomTabsAndroid.java | 56 + .../com/rocketchatrn/CustomTabsHelper.java | 24 + .../java/com/rocketchatrn/MainActivity.java | 25 +- .../com/rocketchatrn/MainApplication.java | 55 +- .../rocketchatrn/RocketChatNativePackage.java | 33 + .../main/res/drawable-hdpi/launch_screen.png | Bin 0 -> 28199 bytes ...ctnavigation_src_views_assets_backicon.png | Bin 0 -> 134 bytes .../res/drawable-mdpi/app_images_logo.png | Bin .../main/res/drawable-mdpi/launch_screen.png | Bin 0 -> 16058 bytes ...ctnavigation_src_views_assets_backicon.png | Bin 0 -> 100 bytes .../main/res/drawable-xhdpi/launch_screen.png | Bin 0 -> 49582 bytes ...ctnavigation_src_views_assets_backicon.png | Bin 0 -> 134 bytes .../res/drawable-xxhdpi/launch_screen.png | Bin 0 -> 67564 bytes ...ctnavigation_src_views_assets_backicon.png | Bin 0 -> 167 bytes .../res/drawable-xxxhdpi/launch_screen.png | Bin 0 -> 86245 bytes ...ctnavigation_src_views_assets_backicon.png | Bin 0 -> 207 bytes .../app/src/main/res/layout/launch_screen.xml | 6 + .../main/res/mipmap-hdpi/ic_notification.png | Bin 0 -> 3006 bytes android/app/src/main/res/values/colors.xml | 1 + android/app/src/main/res/values/strings.xml | 2 + android/app/src/main/res/values/styles.xml | 1 + android/gradle.properties | 2 +- android/settings.gradle | 17 +- app/ReactotronConfig.js | 13 + app/actions/actionsTypes.js | 99 +- app/actions/activeUsers.js | 8 + app/actions/connect.js | 5 + app/actions/createChannel.js | 21 +- app/actions/index.js | 21 + app/actions/login.js | 112 +- app/actions/mentionedMessages.js | 21 + app/actions/messages.js | 164 + app/actions/pinnedMessages.js | 28 + app/actions/roles.js | 8 + app/actions/room.js | 77 + app/actions/roomFiles.js | 21 + app/actions/rooms.js | 8 + app/actions/server.js | 6 + app/actions/snippetedMessages.js | 21 + app/actions/starredMessages.js | 28 + app/animations/collapse.js | 64 + app/animations/fade.js | 6 +- app/components/KeyboardView.js | 22 - app/components/Message.js | 88 - app/components/MessageBox.js | 94 - app/components/RoomItem.js | 123 - app/components/avatar.js | 51 - app/components/message/card.js | 88 - app/constants/colors.js | 7 + app/constants/messagesStatus.js | 5 + app/constants/types.js | 3 + app/containers/Avatar.js | 88 + .../banner.js => containers/Banner.js} | 17 +- app/containers/EmojiPicker/CustomEmoji.js | 28 + app/containers/EmojiPicker/EmojiCategory.js | 71 + app/containers/EmojiPicker/TabBar.js | 31 + app/containers/EmojiPicker/categories.js | 44 + app/containers/EmojiPicker/index.js | 141 + app/containers/EmojiPicker/styles.js | 57 + app/containers/Header.js | 51 + app/containers/MessageActions.js | 347 + app/containers/MessageBox/EmojiKeyboard.js | 23 + app/containers/MessageBox/Recording.js | 127 + app/containers/MessageBox/index.js | 523 + app/containers/MessageBox/styles.js | 85 + app/containers/MessageErrorActions.js | 76 + app/containers/Routes.js | 58 + app/containers/Sidebar.js | 135 + app/containers/TextInput.js | 88 + app/containers/Typing.js | 42 + app/containers/icons.js | 4 + app/containers/message/Audio.js | 162 + app/containers/message/Emoji.js | 26 + app/containers/message/Image.js | 86 + app/containers/message/Markdown.js | 153 + app/containers/message/PhotoModal.js | 65 + app/containers/message/QuoteMark.js | 20 + app/containers/message/ReactionsModal.js | 124 + app/containers/message/Reply.js | 157 + app/containers/message/Url.js | 74 + app/containers/message/User.js | 83 + app/containers/message/Video.js | 84 + app/containers/message/index.js | 316 + app/containers/message/styles.js | 74 + app/containers/routes/AuthRoutes.js | 131 + app/containers/routes/NavigationService.js | 53 + app/containers/routes/PublicRoutes.js | 79 + app/containers/status.js | 39 + app/emojis.js | 2833 ++++ app/icons.json | 370 + app/images/logo.svg | 77 - app/index.js | 84 +- app/lib/createStore.js | 44 +- app/lib/ddp.js | 127 + app/lib/meteor-redux.js | 0 app/lib/realm.js | 313 +- app/lib/rocketchat.js | 942 +- app/nativeModules/CustomTabsAndroid.js | 9 + app/navigation.js | 32 - app/presentation/KeyboardView.js | 34 + app/presentation/RoomItem.js | 255 + app/push.js | 45 + app/reducers/activeUsers.js | 15 + app/reducers/app.js | 49 + app/reducers/connect.js | 18 +- app/reducers/createChannel.js | 24 +- app/reducers/customEmojis.js | 17 + app/reducers/index.js | 33 +- app/reducers/login.js | 111 +- app/reducers/mentionedMessages.js | 19 + app/reducers/messages.js | 92 +- app/reducers/navigator.js | 3 +- app/reducers/permissions.js | 24 + app/reducers/pinnedMessages.js | 30 + app/reducers/reducers.js | 9 +- app/reducers/roles.js | 15 + app/reducers/room.js | 43 + app/reducers/roomFiles.js | 19 + app/reducers/rooms.js | 19 +- app/reducers/server.js | 9 +- app/reducers/snippetedMessages.js | 19 + app/reducers/starredMessages.js | 30 + app/sagas/connect.js | 45 +- app/sagas/createChannel.js | 39 +- app/sagas/index.js | 36 +- app/sagas/init.js | 37 +- app/sagas/login.js | 197 +- app/sagas/mentionedMessages.js | 14 + app/sagas/messages.js | 81 +- app/sagas/pinnedMessages.js | 14 + app/sagas/roomFiles.js | 14 + app/sagas/rooms.js | 153 +- app/sagas/selectServer.js | 42 +- app/sagas/snippetedMessages.js | 14 + app/sagas/starredMessages.js | 14 + app/sagas/state.js | 37 + app/utils/debounce.js | 6 +- app/utils/info.js | 6 + app/utils/openLink.android.js | 5 + app/utils/openLink.ios.js | 5 + app/utils/random.js | 8 + app/utils/scrollPersistTaps.js | 4 + app/utils/touch/index.android.js | 3 + app/utils/touch/index.ios.js | 3 + app/views/CreateChannel.js | 83 - app/views/CreateChannelView.js | 136 + app/views/ForgotPasswordView.js | 120 + .../{serverList.js => ListServerView.js} | 116 +- app/views/LoginView.js | 374 + app/views/MentionedMessagesView/index.js | 76 + app/views/MentionedMessagesView/styles.js | 17 + app/views/NewServerView.js | 147 + app/views/Photo.js | 8 +- app/views/PinnedMessagesView/index.js | 112 + app/views/PinnedMessagesView/styles.js | 17 + app/views/PrivacyPolicyView.js | 28 + app/views/RegisterView.js | 208 + app/views/RoomActionsView/index.js | 295 + app/views/RoomActionsView/styles.js | 61 + app/views/RoomFilesView/index.js | 74 + app/views/RoomFilesView/styles.js | 17 + app/views/RoomInfoEditView/SwitchContainer.js | 45 + app/views/RoomInfoEditView/index.js | 384 + app/views/RoomInfoEditView/styles.js | 46 + app/views/RoomInfoView/index.js | 193 + app/views/RoomInfoView/styles.js | 70 + app/views/RoomMembersView/index.js | 141 + app/views/RoomMembersView/styles.js | 57 + app/views/RoomView/DateSeparator.js | 42 + app/views/RoomView/Header/index.js | 161 + app/views/RoomView/Header/styles.js | 49 + app/views/RoomView/ListView.js | 181 + app/views/RoomView/ReactionPicker.js | 61 + app/views/RoomView/UnreadSeparator.js | 37 + app/views/RoomView/banner.js | 22 + app/views/RoomView/index.js | 211 + app/views/RoomView/styles.js | 45 + app/views/RoomsListView/Header/index.js | 231 + app/views/RoomsListView/Header/styles.js | 75 + app/views/RoomsListView/index.js | 216 + app/views/RoomsListView/styles.js | 43 + app/views/SelectUsersView.js | 322 + app/views/SnippetedMessagesView/index.js | 76 + app/views/SnippetedMessagesView/styles.js | 17 + app/views/StarredMessagesView/index.js | 112 + app/views/StarredMessagesView/styles.js | 17 + app/views/Styles.js | 164 +- app/views/TermsServiceView.js | 28 + app/views/View.js | 9 + app/views/login.js | 150 - app/views/room.js | 217 - app/views/roomsList.js | 280 - app/views/serverNew.js | 178 - icons/20x20/at.svg | 17 + icons/20x20/image.svg | 17 + icons/20x20/location.svg | 14 + icons/20x20/video.svg | 16 + icons/20x20/volume.svg | 20 + index.android.js | 12 +- index.ios.js | 12 +- ios/Crashlytics.framework/Crashlytics | Bin 0 -> 13185656 bytes .../Headers/ANSCompatibility.h | 31 + ios/Crashlytics.framework/Headers/Answers.h | 210 + .../Headers/CLSAttributes.h | 33 + .../Headers/CLSLogging.h | 64 + ios/Crashlytics.framework/Headers/CLSReport.h | 103 + .../Headers/CLSStackFrame.h | 38 + .../Headers/Crashlytics.h | 288 + ios/Crashlytics.framework/Info.plist | Bin 0 -> 923 bytes .../Modules/module.modulemap | 14 + ios/Crashlytics.framework/run | 28 + ios/Crashlytics.framework/submit | Bin 0 -> 301328 bytes ios/Crashlytics.framework/uploadDSYM | Bin 0 -> 721120 bytes ios/Fabric.framework/Fabric | Bin 0 -> 6122704 bytes ios/Fabric.framework/Headers/FABAttributes.h | 51 + ios/Fabric.framework/Headers/Fabric.h | 82 + ios/Fabric.framework/Info.plist | Bin 0 -> 872 bytes ios/Fabric.framework/Modules/module.modulemap | 6 + ios/Fabric.framework/run | 28 + ios/Fabric.framework/uploadDSYM | Bin 0 -> 721120 bytes ios/RocketChatRN-tvOS/Info.plist | 2 +- ios/RocketChatRN-tvOSTests/Info.plist | 2 +- ios/RocketChatRN.xcodeproj/project.pbxproj | 592 +- .../xcschemes/RocketChatRN-tvOS.xcscheme | 4 +- .../xcschemes/RocketChatRN.xcscheme | 4 +- ios/RocketChatRN/AppDelegate.m | 68 +- ios/RocketChatRN/Base.lproj/LaunchScreen.xib | 49 +- ios/RocketChatRN/Fabric.sh | 1 + .../AppIcon.appiconset/Contents.json | 8 +- .../AppIcon.appiconset/icon-1024.png | Bin 0 -> 209856 bytes .../Images.xcassets/Contents.json | 6 + .../Image.imageset/1024x1024.png | Bin 0 -> 12100 bytes .../Image.imageset/Contents.json | 21 + ios/RocketChatRN/Info.plist | 23 +- ios/RocketChatRN/RocketChatRN.entitlements | 8 + ios/RocketChatRNTests/Info.plist | 2 +- ios/fastlane/Appfile | 8 + ios/fastlane/Fastfile | 102 + ios/fastlane/Matchfile | 9 + ios/fastlane/README.md | 60 + ios/fastlane/report.xml | 33 + ios/icomoon.ttf | Bin 0 -> 2084 bytes package-lock.json | 11951 ---------------- package.json | 139 +- resources/fonts/icomoon.ttf | Bin 0 -> 2084 bytes scripts/fabric-android.sh | 19 + scripts/fabric-ios.sh | 19 + static/images/logo.png | Bin 0 -> 56449 bytes static/images/logo_with_text.png | Bin 0 -> 27580 bytes storybook/stories/Avatar.js | 22 +- storybook/stories/Channels/DirectMessage.js | 26 +- storybook/stories/index.js | 13 +- storybook/storybook.js | 15 +- yarn.lock | 5722 ++++++-- 272 files changed, 25087 insertions(+), 17358 deletions(-) create mode 100644 .circleci/changelog.sh create mode 100644 .circleci/config.yml rename .eslintrc => .eslintrc.js (90%) create mode 100644 .github/ISSUE_TEMPLATE.md create mode 100644 .github/PULL_REQUEST_TEMPLATE.md create mode 100644 .snyk create mode 100644 LICENSE create mode 100755 android/app/src/main/assets/fonts/Feather.ttf create mode 100755 android/app/src/main/assets/fonts/icomoon.ttf create mode 100644 android/app/src/main/java/com/rocketchatrn/CustomTabsAndroid.java create mode 100644 android/app/src/main/java/com/rocketchatrn/CustomTabsHelper.java create mode 100644 android/app/src/main/java/com/rocketchatrn/RocketChatNativePackage.java create mode 100644 android/app/src/main/res/drawable-hdpi/launch_screen.png create mode 100644 android/app/src/main/res/drawable-hdpi/node_modules_reactnavigation_src_views_assets_backicon.png rename app/images/logo.png => android/app/src/main/res/drawable-mdpi/app_images_logo.png (100%) create mode 100644 android/app/src/main/res/drawable-mdpi/launch_screen.png create mode 100644 android/app/src/main/res/drawable-mdpi/node_modules_reactnavigation_src_views_assets_backicon.png create mode 100644 android/app/src/main/res/drawable-xhdpi/launch_screen.png create mode 100644 android/app/src/main/res/drawable-xhdpi/node_modules_reactnavigation_src_views_assets_backicon.png create mode 100644 android/app/src/main/res/drawable-xxhdpi/launch_screen.png create mode 100644 android/app/src/main/res/drawable-xxhdpi/node_modules_reactnavigation_src_views_assets_backicon.png create mode 100644 android/app/src/main/res/drawable-xxxhdpi/launch_screen.png create mode 100644 android/app/src/main/res/drawable-xxxhdpi/node_modules_reactnavigation_src_views_assets_backicon.png create mode 100644 android/app/src/main/res/layout/launch_screen.xml create mode 100644 android/app/src/main/res/mipmap-hdpi/ic_notification.png create mode 100644 android/app/src/main/res/values/colors.xml create mode 100644 app/ReactotronConfig.js create mode 100644 app/actions/activeUsers.js create mode 100644 app/actions/mentionedMessages.js create mode 100644 app/actions/pinnedMessages.js create mode 100644 app/actions/roles.js create mode 100644 app/actions/room.js create mode 100644 app/actions/roomFiles.js create mode 100644 app/actions/snippetedMessages.js create mode 100644 app/actions/starredMessages.js create mode 100644 app/animations/collapse.js delete mode 100644 app/components/KeyboardView.js delete mode 100644 app/components/Message.js delete mode 100644 app/components/MessageBox.js delete mode 100644 app/components/RoomItem.js delete mode 100644 app/components/avatar.js delete mode 100644 app/components/message/card.js create mode 100644 app/constants/messagesStatus.js create mode 100644 app/containers/Avatar.js rename app/{components/banner.js => containers/Banner.js} (99%) create mode 100644 app/containers/EmojiPicker/CustomEmoji.js create mode 100644 app/containers/EmojiPicker/EmojiCategory.js create mode 100644 app/containers/EmojiPicker/TabBar.js create mode 100644 app/containers/EmojiPicker/categories.js create mode 100644 app/containers/EmojiPicker/index.js create mode 100644 app/containers/EmojiPicker/styles.js create mode 100644 app/containers/Header.js create mode 100644 app/containers/MessageActions.js create mode 100644 app/containers/MessageBox/EmojiKeyboard.js create mode 100644 app/containers/MessageBox/Recording.js create mode 100644 app/containers/MessageBox/index.js create mode 100644 app/containers/MessageBox/styles.js create mode 100644 app/containers/MessageErrorActions.js create mode 100644 app/containers/Routes.js create mode 100644 app/containers/Sidebar.js create mode 100644 app/containers/TextInput.js create mode 100644 app/containers/Typing.js create mode 100644 app/containers/icons.js create mode 100644 app/containers/message/Audio.js create mode 100644 app/containers/message/Emoji.js create mode 100644 app/containers/message/Image.js create mode 100644 app/containers/message/Markdown.js create mode 100644 app/containers/message/PhotoModal.js create mode 100644 app/containers/message/QuoteMark.js create mode 100644 app/containers/message/ReactionsModal.js create mode 100644 app/containers/message/Reply.js create mode 100644 app/containers/message/Url.js create mode 100644 app/containers/message/User.js create mode 100644 app/containers/message/Video.js create mode 100644 app/containers/message/index.js create mode 100644 app/containers/message/styles.js create mode 100644 app/containers/routes/AuthRoutes.js create mode 100644 app/containers/routes/NavigationService.js create mode 100644 app/containers/routes/PublicRoutes.js create mode 100644 app/containers/status.js create mode 100644 app/emojis.js create mode 100755 app/icons.json delete mode 100644 app/images/logo.svg create mode 100644 app/lib/ddp.js delete mode 100644 app/lib/meteor-redux.js create mode 100644 app/nativeModules/CustomTabsAndroid.js delete mode 100644 app/navigation.js create mode 100644 app/presentation/KeyboardView.js create mode 100644 app/presentation/RoomItem.js create mode 100644 app/push.js create mode 100644 app/reducers/activeUsers.js create mode 100644 app/reducers/app.js create mode 100644 app/reducers/customEmojis.js create mode 100644 app/reducers/mentionedMessages.js create mode 100644 app/reducers/permissions.js create mode 100644 app/reducers/pinnedMessages.js create mode 100644 app/reducers/roles.js create mode 100644 app/reducers/room.js create mode 100644 app/reducers/roomFiles.js create mode 100644 app/reducers/snippetedMessages.js create mode 100644 app/reducers/starredMessages.js create mode 100644 app/sagas/mentionedMessages.js create mode 100644 app/sagas/pinnedMessages.js create mode 100644 app/sagas/roomFiles.js create mode 100644 app/sagas/snippetedMessages.js create mode 100644 app/sagas/starredMessages.js create mode 100644 app/sagas/state.js create mode 100644 app/utils/info.js create mode 100644 app/utils/openLink.android.js create mode 100644 app/utils/openLink.ios.js create mode 100644 app/utils/random.js create mode 100644 app/utils/scrollPersistTaps.js create mode 100644 app/utils/touch/index.android.js create mode 100644 app/utils/touch/index.ios.js delete mode 100644 app/views/CreateChannel.js create mode 100644 app/views/CreateChannelView.js create mode 100644 app/views/ForgotPasswordView.js rename app/views/{serverList.js => ListServerView.js} (59%) create mode 100644 app/views/LoginView.js create mode 100644 app/views/MentionedMessagesView/index.js create mode 100644 app/views/MentionedMessagesView/styles.js create mode 100644 app/views/NewServerView.js create mode 100644 app/views/PinnedMessagesView/index.js create mode 100644 app/views/PinnedMessagesView/styles.js create mode 100644 app/views/PrivacyPolicyView.js create mode 100644 app/views/RegisterView.js create mode 100644 app/views/RoomActionsView/index.js create mode 100644 app/views/RoomActionsView/styles.js create mode 100644 app/views/RoomFilesView/index.js create mode 100644 app/views/RoomFilesView/styles.js create mode 100644 app/views/RoomInfoEditView/SwitchContainer.js create mode 100644 app/views/RoomInfoEditView/index.js create mode 100644 app/views/RoomInfoEditView/styles.js create mode 100644 app/views/RoomInfoView/index.js create mode 100644 app/views/RoomInfoView/styles.js create mode 100644 app/views/RoomMembersView/index.js create mode 100644 app/views/RoomMembersView/styles.js create mode 100644 app/views/RoomView/DateSeparator.js create mode 100644 app/views/RoomView/Header/index.js create mode 100644 app/views/RoomView/Header/styles.js create mode 100644 app/views/RoomView/ListView.js create mode 100644 app/views/RoomView/ReactionPicker.js create mode 100644 app/views/RoomView/UnreadSeparator.js create mode 100644 app/views/RoomView/banner.js create mode 100644 app/views/RoomView/index.js create mode 100644 app/views/RoomView/styles.js create mode 100644 app/views/RoomsListView/Header/index.js create mode 100644 app/views/RoomsListView/Header/styles.js create mode 100644 app/views/RoomsListView/index.js create mode 100644 app/views/RoomsListView/styles.js create mode 100644 app/views/SelectUsersView.js create mode 100644 app/views/SnippetedMessagesView/index.js create mode 100644 app/views/SnippetedMessagesView/styles.js create mode 100644 app/views/StarredMessagesView/index.js create mode 100644 app/views/StarredMessagesView/styles.js create mode 100644 app/views/TermsServiceView.js create mode 100644 app/views/View.js delete mode 100644 app/views/login.js delete mode 100644 app/views/room.js delete mode 100644 app/views/roomsList.js delete mode 100644 app/views/serverNew.js create mode 100644 icons/20x20/at.svg create mode 100644 icons/20x20/image.svg create mode 100644 icons/20x20/location.svg create mode 100644 icons/20x20/video.svg create mode 100644 icons/20x20/volume.svg create mode 100755 ios/Crashlytics.framework/Crashlytics create mode 100644 ios/Crashlytics.framework/Headers/ANSCompatibility.h create mode 100644 ios/Crashlytics.framework/Headers/Answers.h create mode 100644 ios/Crashlytics.framework/Headers/CLSAttributes.h create mode 100644 ios/Crashlytics.framework/Headers/CLSLogging.h create mode 100644 ios/Crashlytics.framework/Headers/CLSReport.h create mode 100644 ios/Crashlytics.framework/Headers/CLSStackFrame.h create mode 100644 ios/Crashlytics.framework/Headers/Crashlytics.h create mode 100644 ios/Crashlytics.framework/Info.plist create mode 100644 ios/Crashlytics.framework/Modules/module.modulemap create mode 100755 ios/Crashlytics.framework/run create mode 100755 ios/Crashlytics.framework/submit create mode 100755 ios/Crashlytics.framework/uploadDSYM create mode 100755 ios/Fabric.framework/Fabric create mode 100644 ios/Fabric.framework/Headers/FABAttributes.h create mode 100644 ios/Fabric.framework/Headers/Fabric.h create mode 100644 ios/Fabric.framework/Info.plist create mode 100644 ios/Fabric.framework/Modules/module.modulemap create mode 100755 ios/Fabric.framework/run create mode 100755 ios/Fabric.framework/uploadDSYM create mode 100644 ios/RocketChatRN/Fabric.sh create mode 100644 ios/RocketChatRN/Images.xcassets/AppIcon.appiconset/icon-1024.png create mode 100644 ios/RocketChatRN/Images.xcassets/Contents.json create mode 100644 ios/RocketChatRN/Images.xcassets/Image.imageset/1024x1024.png create mode 100644 ios/RocketChatRN/Images.xcassets/Image.imageset/Contents.json create mode 100644 ios/RocketChatRN/RocketChatRN.entitlements create mode 100644 ios/fastlane/Appfile create mode 100644 ios/fastlane/Fastfile create mode 100644 ios/fastlane/Matchfile create mode 100644 ios/fastlane/README.md create mode 100644 ios/fastlane/report.xml create mode 100755 ios/icomoon.ttf delete mode 100644 package-lock.json create mode 100755 resources/fonts/icomoon.ttf create mode 100755 scripts/fabric-android.sh create mode 100755 scripts/fabric-ios.sh create mode 100644 static/images/logo.png create mode 100644 static/images/logo_with_text.png diff --git a/.babelrc b/.babelrc index d0cf03dfa..34739bdc9 100644 --- a/.babelrc +++ b/.babelrc @@ -1,4 +1,9 @@ { "presets": ["react-native"], - "plugins": ["transform-decorators-legacy"] + "plugins": ["transform-decorators-legacy"], + "env": { + "production": { + "plugins": ["transform-remove-console"] + } + } } diff --git a/.circleci/changelog.sh b/.circleci/changelog.sh new file mode 100644 index 000000000..deb042836 --- /dev/null +++ b/.circleci/changelog.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +git log --format="%cd" -n 14 --date=short | sort -u -r | while read DATE ; do + echo $DATE + GIT_PAGER=cat git log --no-merges --format="- %s" --since="$DATE 00:00:00" --until="$DATE 24:00:00" + echo +done diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 000000000..95ae45cbd --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,238 @@ +defaults: &defaults + working_directory: ~/repo + +version: 2 +jobs: + lint-testunit: + <<: *defaults + docker: + - image: circleci/node:8 + + environment: + CODECOV_TOKEN: caa771ab-3d45-4756-8e2a-e1f25996fef6 + + steps: + - checkout + + - run: + name: Install NPM modules + command: | + npm install + # npm install codecov + + - run: + name: Lint + command: | + npm run lint + + - run: + name: Test + command: | + npm test + + - run: + name: Codecov + command: | + npx codecov + + android-build: + <<: *defaults + docker: + - image: circleci/android:api-26-alpha + + environment: + GRADLE_OPTS: -Dorg.gradle.jvmargs="-Xmx4096m -XX:+HeapDumpOnOutOfMemoryError" + JVM_OPTS: -Xmx4096m + TERM: dumb + BASH_ENV: "~/.nvm/nvm.sh" + + steps: + - checkout + + - run: + name: Install Node 8 + command: | + curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.6/install.sh | bash + source ~/.nvm/nvm.sh + nvm install 8 + + - restore_cache: + key: node-modules-{{ checksum ".circleci/config.yml" }}-{{ checksum "package.json" }} + + - run: + name: Install NPM modules + command: | + npm install + + - restore_cache: + key: android-{{ checksum ".circleci/config.yml" }}-{{ checksum "android/build.gradle" }}-{{ checksum "android/app/build.gradle" }} + + - run: + name: Configure Gradle + command: | + cd android + + echo -e "" > ./gradle.properties + + if [[ $KEYSTORE ]]; then + echo $KEYSTORE_BASE64 | base64 --decode > ./app/$KEYSTORE + echo -e "KEYSTORE=$KEYSTORE" >> ./gradle.properties + echo -e "KEYSTORE_PASSWORD=$KEYSTORE_PASSWORD" >> ./gradle.properties + echo -e "KEY_ALIAS=$KEY_ALIAS" >> ./gradle.properties + echo -e "KEY_PASSWORD=$KEYSTORE_PASSWORD" >> ./gradle.properties + fi + + echo -e "VERSIONCODE=$CIRCLE_BUILD_NUM" >> ./gradle.properties + + echo -e "" > ./app/fabric.properties + echo -e "apiKey=$FABRIC_KEY" >> ./app/fabric.properties + echo -e "apiSecret=$FABRIC_SECRET" >> ./app/fabric.properties + + - run: + name: Install Android Depedencies + command: | + cd android + ./gradlew androidDependencies + + - run: + name: Build Android App + command: | + cd android + if [[ $KEYSTORE ]]; then + ./gradlew assembleRelease + else + ./gradlew assembleDebug + fi + + mkdir -p /tmp/build + + mv app/build/outputs /tmp/build/ + + - store_artifacts: + path: /tmp/build/outputs + + - save_cache: + key: node-modules-{{ checksum ".circleci/config.yml" }}-{{ checksum "package.json" }} + paths: + - ./node_modules + + - save_cache: + key: android-{{ checksum ".circleci/config.yml" }}-{{ checksum "android/build.gradle" }}-{{ checksum "android/app/build.gradle" }} + paths: + - ~/.gradle + + ios-build: + macos: + xcode: "9.0" + + environment: + BASH_ENV: "~/.nvm/nvm.sh" + + steps: + - checkout + + - run: + name: Install Node 8 + command: | + curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.6/install.sh | bash + source ~/.nvm/nvm.sh + # https://github.com/creationix/nvm/issues/1394 + set +e + nvm install 8 + + - run: + name: Update Fastlane + command: | + brew update + brew install ruby + sudo gem install fastlane + + - run: + name: Install NPM modules + command: | + rm -rf node_modules + # npm install --save react-native@0.51 + npm install + # npm install react-native + + - run: + name: Fix known build error + command: | + # Fix error https://github.com/facebook/react-native/issues/14382 + cd node_modules/react-native/scripts/ + curl https://raw.githubusercontent.com/facebook/react-native/5c53f89dd86160301feee024bce4ce0c89e8c187/scripts/ios-configure-glog.sh > ios-configure-glog.sh + chmod +x ios-configure-glog.sh + + - run: + name: Fastlane Build + no_output_timeout: 1200 + command: | + cd ios + agvtool new-version -all $CIRCLE_BUILD_NUM + /usr/libexec/PlistBuddy -c "Set Fabric:APIKey $FABRIC_KEY" ./RocketChatRN/Info.plist + echo -e "./Fabric.framework/run $FABRIC_KEY $FABRIC_SECRET" > ./RocketChatRN/Fabric.sh + + if [[ $MATCH_KEYCHAIN_NAME ]]; then + fastlane ios release + else + export MATCH_KEYCHAIN_NAME="temp" + export MATCH_KEYCHAIN_PASSWORD="temp" + fastlane ios build + fi + + - store_artifacts: + path: ios/RocketChatRN.ipa + + - persist_to_workspace: + root: . + paths: + - ios/*.ipa + - ios/fastlane/report.xml + + ios-testflight: + macos: + xcode: "9.0" + + steps: + - checkout + + - attach_workspace: + at: ios + + - run: + name: Update Fastlane + command: | + brew update + brew install ruby + sudo gem install fastlane + + - run: + name: Fastlane Tesflight Upload + command: | + cd ios + fastlane pilot upload --ipa ios/RocketChatRN.ipa --changelog "$(sh ../.circleci/changelog.sh)" + +workflows: + version: 2 + build-and-test: + jobs: + - lint-testunit + + - ios-build: + requires: + - lint-testunit + - ios-testflight: + requires: + - ios-build + filters: + branches: + only: + - develop + - master + # - ios-testflight: + # requires: + # - ios-hold-testflight + + - android-build: + requires: + - lint-testunit diff --git a/.eslintrc b/.eslintrc.js similarity index 90% rename from .eslintrc rename to .eslintrc.js index a55acafff..94d3a23e1 100644 --- a/.eslintrc +++ b/.eslintrc.js @@ -1,4 +1,11 @@ -{ +module.exports = { + "settings": { + "import/resolver": { + "node": { + "extensions": [".js", ".ios.js", ".android.js"] + } + } + }, "parser": "babel-eslint", "extends": "airbnb", "parserOptions": { @@ -30,6 +37,7 @@ "react/no-unused-prop-types": [2, { "skipShapeProps": true }], + "react/no-did-mount-set-state": 0, "react/no-multi-comp": [0], "react/jsx-indent": [2, "tab"], "react/jsx-indent-props": [2, "tab"], @@ -37,6 +45,7 @@ "jsx-quotes": [2, "prefer-single"], "jsx-a11y/href-no-hash": 0, "import/prefer-default-export": 0, + "camelcase": 0, "no-underscore-dangle": 0, "no-return-assign": 0, "no-param-reassign": 0, @@ -115,9 +124,10 @@ "prefer-const": 2, "object-shorthand": 2, "consistent-return": 0, - "global-require": "off" + "global-require": "off", + "react/prop-types": [0, { skipUndeclared: true }] }, "globals": { "__DEV__": true } -} +}; diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 000000000..3d2c4a2b6 --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,19 @@ +Before writing an issue, please make sure you're talking about the native application and not the Cordova one. If you are looking to open an issue to the Cordova application, go to this URL: https://github.com/RocketChat/Rocket.Chat.Cordova. + +- Your Rocket.Chat.Android app version: #### + + +- Your Rocket.Chat.iOS app version: #### + + +- Your Rocket.Chat server version: #### + +- Device model (or emulator) you're running with: #### + + + +**The app isn't connecting to your server?** +Make sure your server supports WebSocket. These are the minimum requirements for Apache 2.4 and Nginx 1.3 or greater. diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 000000000..c868686af --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,7 @@ + +@RocketChat/ReactNative + + +Closes #ISSUE_NUMBER + + diff --git a/.gitignore b/.gitignore index 5b8a7f053..1a68faf71 100644 --- a/.gitignore +++ b/.gitignore @@ -28,6 +28,7 @@ build/ .idea .gradle local.properties +fabric.properties *.iml # node.js @@ -55,3 +56,5 @@ fastlane/Preview.html fastlane/screenshots coverage + +.vscode/ diff --git a/.snyk b/.snyk new file mode 100644 index 000000000..1c6af145e --- /dev/null +++ b/.snyk @@ -0,0 +1,26 @@ +# Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities. +version: v1.7.1 +ignore: {} +# patches apply the minimum changes required to fix a vulnerability +patch: + 'npm:debug:20170905': + - react-native > connect > debug: + patched: '2017-09-29T23:29:20.238Z' + - react-native > connect > express-session > debug: + patched: '2017-09-29T23:29:20.238Z' + - react-native > connect > finalhandler > debug: + patched: '2017-09-29T23:29:20.238Z' + - react-native > connect > morgan > debug: + patched: '2017-09-29T23:29:20.238Z' + - react-native > connect > serve-index > debug: + patched: '2017-09-29T23:29:20.238Z' + - react-native > connect > body-parser > debug: + patched: '2017-09-29T23:29:20.238Z' + - react-native > connect > compression > debug: + patched: '2017-09-29T23:29:20.238Z' + - react-native > connect > connect-timeout > debug: + patched: '2017-09-29T23:29:20.238Z' + - react-native > connect > serve-static > send > debug: + patched: '2017-09-29T23:29:20.238Z' + - realm > extract-zip > debug: + patched: '2017-09-29T23:29:20.238Z' diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000..de5de8728 --- /dev/null +++ b/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2015-2018 Rocket.Chat Technologies Corp. + +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. + diff --git a/README.md b/README.md index 64074bdff..321649b79 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # 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) [![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) @@ -10,74 +12,32 @@ **Supported Server Versions:** 0.58.0+ (We are working to support earlier versions) -# Installing Dependencies +# Installing dependencies Follow the [React Native Getting Started Guide](https://facebook.github.io/react-native/docs/getting-started.html) for detailed instructions on setting up your local machine for development. -# Detailed configuration: - -## Mac - -- General requirements - - - XCode 8.3 - - Install required packages using homebrew: - ```bash - $ brew install watchman - $ brew install yarn - ``` - -- Clone repository and configure: +# How to run +- Clone repository and install dependencies: ```bash $ git clone git@github.com:RocketChat/Rocket.Chat.ReactNative.git $ cd Rocket.Chat.ReactNative - $ npm install $ npm install -g react-native-cli + $ yarn + ``` +- Configuration + ```bash + $ yarn fabric-ios --key="YOUR_API_KEY" --secret="YOUR_API_SECRET" + $ yarn fabric-android --key="YOUR_API_KEY" --secret="YOUR_API_SECRET" ``` - Run application ```bash - $ react-native run-ios + $ yarn ios ``` ```bash - $ react-native run-android + $ yarn android ``` -## Linux: - -- General requiriments: - - - JDK 7 or greater - - Android SDK - - Virtualbox - - An Android emulator: Genymotion or Android emulator. If using genymotion ensure that it uses existing adb tools (Settings: "Use custom Android SDK Tools") - - Install watchman (do this globally): - ```bash - $ git clone https://github.com/facebook/watchman.git - $ cd watchman - $ git checkout master - $ ./autogen.sh - $ ./configure make - $ sudo make install - ``` - Configure your kernel to accept a lot of file watches, using a command like: - ```bash - $ sudo sysctl -w fs.inotify.max_user_watches=1048576 - ``` - -- Clone repository and configure: - ```bash - $ git clone git@github.com:RocketChat/Rocket.Chat.ReactNative.git - $ cd Rocket.Chat.ReactNative - $ npm install - $ npm install -g react-native-cli - ``` - -- Run application - - Start emulator - - Start react packager: `$ react-native start` - - Run in emulator: `$ react-native run-android` - # Storybook - General requirements - Install storybook diff --git a/__tests__/RoomItem.js b/__tests__/RoomItem.js index 1244a4437..253b5d45c 100644 --- a/__tests__/RoomItem.js +++ b/__tests__/RoomItem.js @@ -1,32 +1,41 @@ -import 'react-native'; +import {View} from 'react-native'; +import { Provider } from 'react-redux'; + +import { createStore, combineReducers } from 'redux'; + +const reducers = combineReducers({login:() => ({user: {}}), settings:() => ({})}); +const store = createStore(reducers); + import React from 'react'; -import RoomItem from '../app/components/RoomItem'; +import RoomItem from '../app/presentation/RoomItem'; // Note: test renderer must be required after react-native. import renderer from 'react-test-renderer'; +const date = new Date(2017, 10, 10, 10); + jest.mock('react-native-img-cache', () => { return { CachedImage: 'View' } }); it('renders correctly', () => { - expect(renderer.create().toJSON()).toMatchSnapshot(); + expect(renderer.create().toJSON()).toMatchSnapshot(); }); it('render unread', () => { - expect(renderer.create().toJSON()).toMatchSnapshot(); + expect(renderer.create().toJSON()).toMatchSnapshot(); }); it('render unread +999', () => { - expect(renderer.create().toJSON()).toMatchSnapshot(); + expect(renderer.create().toJSON()).toMatchSnapshot(); }); it('render no icon', () => { - expect(renderer.create().toJSON()).toMatchSnapshot(); + expect(renderer.create().toJSON()).toMatchSnapshot(); }); it('render private group', () => { - expect(renderer.create( ).toJSON()).toMatchSnapshot(); + expect(renderer.create( ).toJSON()).toMatchSnapshot(); }); it('render channel', () => { - expect(renderer.create().toJSON()).toMatchSnapshot(); + expect(renderer.create().toJSON()).toMatchSnapshot(); }); diff --git a/__tests__/__snapshots__/RoomItem.js.snap b/__tests__/__snapshots__/RoomItem.js.snap index 11d20cb8f..81cea847b 100644 --- a/__tests__/__snapshots__/RoomItem.js.snap +++ b/__tests__/__snapshots__/RoomItem.js.snap @@ -1,503 +1,1041 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`render channel 1`] = ` - + - -  - + + +  + + + + + + general + + + Nov 10 + + + + + - - general - `; exports[`render no icon 1`] = ` - - + - name - + + + + + + + + + + name + + + Nov 10 + + + + + + `; exports[`render private group 1`] = ` - - + - private-group - + + + + + + + + + + private-group + + + Nov 10 + + + + + + + `; exports[`render unread +999 1`] = ` - + - - NA - + + + NA + + + + + + + + name + + + Nov 10 + + + + + 999+ + + + + - - name - - - 999+ - `; exports[`render unread 1`] = ` - + - - NA - + + + NA + + + + + + + + name + + + Nov 10 + + + + + 1 + + + + - - name - - - 1 - `; exports[`renders correctly 1`] = ` - + - - NA - + + + NA + + + + + + + + name + + + Nov 10 + + + + + - - name - `; diff --git a/__tests__/__snapshots__/Storyshots.test.js.snap b/__tests__/__snapshots__/Storyshots.test.js.snap index c07669703..86e9a4e19 100644 --- a/__tests__/__snapshots__/Storyshots.test.js.snap +++ b/__tests__/__snapshots__/Storyshots.test.js.snap @@ -9,11 +9,10 @@ exports[`Storyshots Avatar avatar 1`] = ` Object { "alignItems": "center", "justifyContent": "center", - "overflow": "hidden", }, Object { "backgroundColor": "#3F51B5", - "borderRadius": 5, + "borderRadius": 4, "height": 25, "width": 25, }, @@ -23,8 +22,7 @@ exports[`Storyshots Avatar avatar 1`] = ` > TE + AA + BB + TE + @@ -160,10 +156,10 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = ` @@ -192,1052 +179,1952 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = ` Array [ Object { "alignItems": "center", - "justifyContent": "center", - "overflow": "hidden", - }, - Object { - "backgroundColor": "#8BC34A", - "borderRadius": 20, - "height": 40, - "width": 40, + "borderBottomColor": "#ddd", + "borderBottomWidth": 0.5, + "flexDirection": "row", + "paddingHorizontal": 16, + "paddingVertical": 12, }, undefined, ] } > - - RC - - - - - rocket.cat - - - - - - RC - - - - - rocket.cat - - - - - - RC - - - - - rocket.cat - - - 1 - - - - - - LC - - - - - Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries - - - 9 - - - - - - LC - - - - - Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries - - - 99 - - - - - - LC - - - - - Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries - - - 100 - - - - - - LC - - - - - Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries - - - 999+ - - - - - - W - - - - W - - - - - - WW - - - - WW - - - - - + > + RC + - - - + + + + + rocket.cat + + + Nov 10 + + + + + + + + - - + + + RC + + + + + + + + rocket.cat + + + Nov 10 + + + + + + + + + + + RC + + + + + + + + rocket.cat + + + Nov 10 + + + + + 1 + + + + + + + + + + LC + + + + + + + + Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries + + + Nov 10 + + + + + 9 + + + + + + + + + + LC + + + + + + + + Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries + + + Nov 10 + + + + + 99 + + + + + + + + + + LC + + + + + + + + Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries + + + Nov 10 + + + + + 100 + + + + + + + + + + LC + + + + + + + + Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries + + + Nov 10 + + + + + 999+ + + + + + + + + + + LC + + + + + + + + Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries + + + Nov 10 + + + + + @ 999+ + + + + + + + + + + W + + + + + + + + W + + + Nov 10 + + + + + + + + + + + WW + + + + + + + + WW + + + Nov 10 + + + + + + + + + + + + + + + + + + + + + + Nov 10 + + + + + diff --git a/android/app/BUCK b/android/app/BUCK index ea619878b..a6395be89 100644 --- a/android/app/BUCK +++ b/android/app/BUCK @@ -45,12 +45,12 @@ android_library( android_build_config( name = "build_config", - package = "com.rocketchatrn", + package = "chat.rocket.reactnative", ) android_resource( name = "res", - package = "com.rocketchatrn", + package = "chat.rocket.reactnative", res = "src/main/res", ) diff --git a/android/app/build.gradle b/android/app/build.gradle index 7129e4ac0..1183adc62 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -94,22 +94,22 @@ android { buildToolsVersion "25.0.1" defaultConfig { - applicationId "com.rocketchatrn" + applicationId "chat.rocket.reactnative" minSdkVersion 16 targetSdkVersion 22 - versionCode 1 - versionName "1.0" + versionCode VERSIONCODE as Integer + versionName "1.1" ndk { abiFilters "armeabi-v7a", "x86" } } signingConfigs { release { - if (project.hasProperty('ROCKETCHAT_RN_RELEASE_STORE_FILE')) { - storeFile file(ROCKETCHAT_RN_RELEASE_STORE_FILE) - storePassword ROCKETCHAT_RN_RELEASE_STORE_PASSWORD - keyAlias ROCKETCHAT_RN_RELEASE_KEY_ALIAS - keyPassword ROCKETCHAT_RN_RELEASE_KEY_PASSWORD + if (project.hasProperty('KEYSTORE')) { + storeFile file(KEYSTORE) + storePassword KEYSTORE_PASSWORD + keyAlias KEY_ALIAS + keyPassword KEY_PASSWORD } } } @@ -143,17 +143,50 @@ android { } } +buildscript { + repositories { + maven { url 'https://maven.fabric.io/public' } + } + + dependencies { + // These docs use an open ended version so that our plugin + // can be updated quickly in response to Android tooling updates + + // We recommend changing it to the latest version from our changelog: + // https://docs.fabric.io/android/changelog.html#fabric-gradle-plugin + classpath 'io.fabric.tools:gradle:1.+' + } +} + +apply plugin: 'io.fabric' + +repositories { + maven { url 'https://maven.fabric.io/public' } +} + dependencies { - compile project(':react-native-navigation') + compile project(':react-native-fabric') + compile project(':react-native-audio') + compile project(":reactnativekeyboardinput") + compile project(':react-native-splash-screen') + compile project(':react-native-video') + compile project(':react-native-push-notification') compile project(':react-native-svg') compile project(':react-native-image-picker') compile project(':react-native-vector-icons') compile project(':react-native-fetch-blob') compile project(':react-native-zeroconf') + compile project(':react-native-toast') compile project(':realm') compile fileTree(dir: "libs", include: ["*.jar"]) compile "com.android.support:appcompat-v7:23.0.1" + compile 'com.android.support:customtabs:23.0.1' compile "com.facebook.react:react-native:+" // From node_modules + compile 'com.facebook.fresco:fresco:1.7.1' + compile 'com.facebook.fresco:animated-gif:1.7.1' + compile('com.crashlytics.sdk.android:crashlytics:2.9.1@aar') { + transitive = true; + } } // Run this once to be able to run the application with BUCK diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index d498890f4..0137ae666 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -1,5 +1,5 @@ @@ -7,6 +7,16 @@ + + + + + + + + @@ -28,6 +38,28 @@ + + + + + + + + + + + + + + + + + diff --git a/android/app/src/main/assets/fonts/Feather.ttf b/android/app/src/main/assets/fonts/Feather.ttf new file mode 100755 index 0000000000000000000000000000000000000000..244854c5492eecee3ff136fbe461a517079dcdde GIT binary patch literal 55288 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 literal 0 HcmV?d00001 diff --git a/android/app/src/main/assets/fonts/icomoon.ttf b/android/app/src/main/assets/fonts/icomoon.ttf new file mode 100755 index 0000000000000000000000000000000000000000..3601ae802a70d87413410b7655bcf92d5685e5e0 GIT binary patch literal 2084 zcmaJ?O>7%g5T3Vx{z>h`wY{6Tabm~yZkk^ww$~(asI=Vz6C7zq??XTY{KY?Z)bZTm@u%I2gdzFYaLq0lPSX#i`0GZFu z>Ddcse;T;{4&?Jh(!q1Z!kLDN7iA*3f_3v86wZ@U5%M39cb}UppKn7VUgd()`(bu@5ZSaYqeRlteQ!pXP|eJ zlLY)2MIOqV8=IS!SL7jCm~GzIB=~KQ%ZS0Mew$7p$_!X0|JeP%4y&6L1g;>q18Mt` zJ{Ao|+07g5<`ZNlRyeO7x`AwDTB4-*mYB!QMyZ^jNe_3C2<; zWHsmuD3JBEPX>bys(@m^5Oy#Ns17ZoWekVm&?k;Z)drAq?T1%;KD~GC`;<`O)?1!i4&3>-nnz+ZZ@Iwj*VA`S?0xOq!q@zwah`kB zF6uZ(f}W?dv`7?p7(L8>bUq{H%wCp3+FA?Kkh;Um913T($KZ>WMLK2K$J#85V8F8H z3=fRNZKsc=w;f+-YHDJN?5KBYy=rTyDduu%+L5$5JZz?qXqw9vYYMfhy_&P$AuDW$ z+7Sq=YOB-b+c{*kcXziNLpyygXRE4)10AZQh@v8S_$_eS6_4)%Wdi|0mK3kEF%|CU z>^RZY)jgc%!TCn%;qI=k6Htd!jZUv3$-+y)zK|Z*bGjbyHjE)3#*krj$91UUdZ;fb zIz&8-CI*KlCWZzla(amG6w>k8ki2uuz-;;svO**aUV9$@9_=K?JK&DC#M*{;#EVnqz$EjwukX|#*iXw(;tgE1}b$e3!F z1(aTv&cvhXXoam+^8#(G3Hi0P4~%Tqc=TxFJ(jPo3CZdub}7H{KnPVo9=t#J#*VJ` z2Yb3axgT?1O3$(++%I zX;HPxB-wA3P{yz-ONq5vrDQk+>d0n0IE~NDjC0a+6_%>rzRLXm@r-%!pqUx>`&o{8 zy=MC!)7;Z;dc7omq?JXAZA$&y~Y78!H&86uW(N-^g)IRkh}vA=r;!0UIP{qp7d?C(^^TO-kTxi@)FwP$pTRdfq9PQ3HlfREMtNLu9za4Vd> z$|rX%Qcc6%xC~kX-GjZng)Iv=1*nBm^gi3qF0*xEH?%yW8~q0z8e?l`OR$-jKC|~_ zyp!2j06t}7-r-CeOTf!EmhrC@w6OyHVH>+CL|1svm0Zwxu~NeV@U)FZ;9(m}z!z;S z<2#7hSb=`R#%`SJlbNZ~T&XlqGc-jdngf++{#bEwX{IzE>FY_*F)E@fEx`Z_h|@E+qNA~r1|(Pf&Y0xdq(a;!98j!YNli;IPF@l53Og~*|)QXaYW(3rJ% l8M{v-%)FIRfy$WAKzEuhfFH6Bkgpv8Iie7@zmosrzW{V{QOW=S literal 0 HcmV?d00001 diff --git a/android/app/src/main/java/com/rocketchatrn/CustomTabsAndroid.java b/android/app/src/main/java/com/rocketchatrn/CustomTabsAndroid.java new file mode 100644 index 000000000..e0a9db1fe --- /dev/null +++ b/android/app/src/main/java/com/rocketchatrn/CustomTabsAndroid.java @@ -0,0 +1,56 @@ +package chat.rocket.reactnative; + +import android.content.Intent; +import android.content.pm.ResolveInfo; +import android.net.Uri; +import android.support.customtabs.CustomTabsIntent; +import android.widget.Toast; + +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.bridge.ReactContextBaseJavaModule; +import com.facebook.react.bridge.ReactMethod; + +import java.util.List; + +import chat.rocket.reactnative.R; + +/** + * Launches custom tabs. + */ + +public class CustomTabsAndroid extends ReactContextBaseJavaModule { + + + public CustomTabsAndroid(ReactApplicationContext reactContext) { + super(reactContext); + } + + @Override + public String getName() { + return "CustomTabsAndroid"; + } + + @ReactMethod + public void openURL(String url) throws NullPointerException { + CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder(); + CustomTabsIntent customTabsIntent = builder.build(); + + if (CustomTabsHelper.isChromeCustomTabsSupported(getReactApplicationContext())) { + customTabsIntent.launchUrl(getReactApplicationContext().getCurrentActivity(), Uri.parse(url)); + } else { + //open in browser + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse(url)); + //ensure browser is present + final List customTabsApps = getReactApplicationContext() + .getCurrentActivity().getPackageManager().queryIntentActivities(i, 0); + + if (customTabsApps.size() > 0) { + getReactApplicationContext().startActivity(i); + } else { + // no browser + Toast.makeText(getReactApplicationContext(), R.string.no_browser_found, Toast.LENGTH_SHORT).show(); + } + } + } +} diff --git a/android/app/src/main/java/com/rocketchatrn/CustomTabsHelper.java b/android/app/src/main/java/com/rocketchatrn/CustomTabsHelper.java new file mode 100644 index 000000000..b7f3eb72f --- /dev/null +++ b/android/app/src/main/java/com/rocketchatrn/CustomTabsHelper.java @@ -0,0 +1,24 @@ +package chat.rocket.reactnative; + +import android.content.Context; +import android.content.Intent; +import android.content.pm.ResolveInfo; + +import java.util.List; + +/** + * Contains helper methods for custom tabs. + */ + +public class CustomTabsHelper { + + private static final String SERVICE_ACTION = "android.support.customtabs.action.CustomTabsService"; + private static final String CHROME_PACKAGE = "com.android.chrome"; + + public static boolean isChromeCustomTabsSupported(final Context context) { + Intent serviceIntent = new Intent(SERVICE_ACTION); + serviceIntent.setPackage(CHROME_PACKAGE); + List resolveInfos = context.getPackageManager().queryIntentServices(serviceIntent, 0); + return !(resolveInfos == null || resolveInfos.isEmpty()); + } +} diff --git a/android/app/src/main/java/com/rocketchatrn/MainActivity.java b/android/app/src/main/java/com/rocketchatrn/MainActivity.java index 57a754e0b..a539ec30f 100644 --- a/android/app/src/main/java/com/rocketchatrn/MainActivity.java +++ b/android/app/src/main/java/com/rocketchatrn/MainActivity.java @@ -1,7 +1,26 @@ -package com.rocketchatrn; +package chat.rocket.reactnative; -import com.reactnativenavigation.controllers.SplashActivity; +import android.os.Bundle; +import com.facebook.react.ReactActivity; +import org.devio.rn.splashscreen.SplashScreen; +import com.crashlytics.android.Crashlytics; +import io.fabric.sdk.android.Fabric; -public class MainActivity extends SplashActivity { +public class MainActivity extends ReactActivity { + /** + * Returns the name of the main component registered from JavaScript. + * This is used to schedule rendering of the component. + */ + @Override + protected String getMainComponentName() { + return "RocketChatRN"; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + SplashScreen.show(this); + super.onCreate(savedInstanceState); + Fabric.with(this, new Crashlytics()); + } } diff --git a/android/app/src/main/java/com/rocketchatrn/MainApplication.java b/android/app/src/main/java/com/rocketchatrn/MainApplication.java index 277cfd500..689cee99f 100644 --- a/android/app/src/main/java/com/rocketchatrn/MainApplication.java +++ b/android/app/src/main/java/com/rocketchatrn/MainApplication.java @@ -1,9 +1,8 @@ -package com.rocketchatrn; +package chat.rocket.reactnative; import android.app.Application; import com.facebook.react.ReactApplication; -// import com.reactnativenavigation.NavigationReactPackage; import com.horcrux.svg.SvgPackage; import com.imagepicker.ImagePickerPackage; import com.oblador.vectoricons.VectorIconsPackage; @@ -14,31 +13,55 @@ import com.facebook.react.ReactNativeHost; import com.facebook.react.ReactPackage; import com.facebook.react.shell.MainReactPackage; import com.facebook.soloader.SoLoader; -import com.reactnativenavigation.NavigationApplication; +import com.dieam.reactnativepushnotification.ReactNativePushNotificationPackage; +import com.brentvatne.react.ReactVideoPackage; +import com.remobile.toast.RCTToastPackage; +import com.wix.reactnativekeyboardinput.KeyboardInputPackage; +import com.rnim.rn.audio.ReactNativeAudioPackage; +import com.smixx.fabric.FabricPackage; import java.util.Arrays; import java.util.List; +import org.devio.rn.splashscreen.SplashScreenReactPackage; -public class MainApplication extends NavigationApplication { +public class MainApplication extends Application implements ReactApplication { + + private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) { @Override - public boolean isDebug() { - // Make sure you are using BuildConfig from your own application + public boolean getUseDeveloperSupport() { return BuildConfig.DEBUG; } + @Override protected List getPackages() { return Arrays.asList( - new SvgPackage(), - new ImagePickerPackage(), - new VectorIconsPackage(), - new RNFetchBlobPackage(), - new ZeroconfReactPackage(), - new RealmReactPackage() + new MainReactPackage(), + new SvgPackage(), + new ImagePickerPackage(), + new VectorIconsPackage(), + new RNFetchBlobPackage(), + new ZeroconfReactPackage(), + new RealmReactPackage(), + new ReactNativePushNotificationPackage(), + new ReactVideoPackage(), + new SplashScreenReactPackage(), + new RCTToastPackage(), + new ReactNativeAudioPackage(), + new KeyboardInputPackage(MainApplication.this), + new RocketChatNativePackage(), + new FabricPackage() ); } + }; - @Override - public List createAdditionalReactPackages() { - return getPackages(); - } + @Override + public ReactNativeHost getReactNativeHost() { + return mReactNativeHost; + } + + @Override + public void onCreate() { + super.onCreate(); + SoLoader.init(this, /* native exopackage */ false); + } } diff --git a/android/app/src/main/java/com/rocketchatrn/RocketChatNativePackage.java b/android/app/src/main/java/com/rocketchatrn/RocketChatNativePackage.java new file mode 100644 index 000000000..16cef0197 --- /dev/null +++ b/android/app/src/main/java/com/rocketchatrn/RocketChatNativePackage.java @@ -0,0 +1,33 @@ +package chat.rocket.reactnative; + +import com.facebook.react.ReactPackage; +import com.facebook.react.bridge.JavaScriptModule; +import com.facebook.react.bridge.NativeModule; +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.uimanager.ViewManager; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class RocketChatNativePackage implements ReactPackage { + + public List> createJSModules() { + return Collections.emptyList(); + } + + @Override + public List createViewManagers(ReactApplicationContext reactContext) { + List managers = new ArrayList<>(); + return managers; + } + + @Override + public List createNativeModules( + ReactApplicationContext reactContext) { + List modules = new ArrayList<>(); + modules.add(new CustomTabsAndroid(reactContext)); + return modules; + } + +} diff --git a/android/app/src/main/res/drawable-hdpi/launch_screen.png b/android/app/src/main/res/drawable-hdpi/launch_screen.png new file mode 100644 index 0000000000000000000000000000000000000000..f2dee7926481fe19eccf0584db89eb6fa9e9a3bd GIT binary patch literal 28199 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 z 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 ?-D89Byz&Eo3jT8XM$M!$ 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 S#Y+PGnHpJMF1zIP@c#gn@C>N{ literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/drawable-hdpi/node_modules_reactnavigation_src_views_assets_backicon.png b/android/app/src/main/res/drawable-hdpi/node_modules_reactnavigation_src_views_assets_backicon.png new file mode 100644 index 0000000000000000000000000000000000000000..ad03a63bf3caba175695f5acca85a690dda2d02c GIT binary patch literal 134 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 literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/drawable-mdpi/node_modules_reactnavigation_src_views_assets_backicon.png b/android/app/src/main/res/drawable-mdpi/node_modules_reactnavigation_src_views_assets_backicon.png new file mode 100644 index 0000000000000000000000000000000000000000..083db295f474b9903408258c71818c2c49151d35 GIT binary patch literal 100 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM0wlfaz7_*1ZBG}+kP60RiDL^GIXr{@&3`D~ x%$9kI*}bEvWrn42Vb! zFyzqnoOyk||HQM_`v=#()N|jb_rCVEuRZUc=&0Se&Tt(9f!xqgf2a?E;EzBc*B~TB z;9oq3?B&4&52mlC0;w8eLW92$Ix1@`Lm)MAWarPXfxnZ!P&b7^AQWA=KX^T!pY0%! zZ>ky(l?`87ZKB?$F&iCTU983(!-?Pdy(d(;m8f(pTj_Tnw$puBrZ#7fq>aXxOpxhwg~3LkKp zFo@LJbxAJtp9*y*)NjMNjfUlfCWqU(`Ep-s@_KYadAFOmEc^wM_p&_G3dn>~zV8e9 zttT!_2hc%#m#^acWOF)A`cE7|Q*&COwuSS6;@nV;DfoG5#nn0A40ivj@UAE{GX`4d ze&B+3ajWg5fN&kJ_I-%Si+jUNlO;5sSE5inI_ z;=4o4Du~{vNS(NIrrC#>xs~~)KnZ!`_U`LyD^uZh5V

hBiZ2ew_0Y7&LL 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

?WC+387KXC#RH0J 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 literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/drawable-xxhdpi/launch_screen.png b/android/app/src/main/res/drawable-xxhdpi/launch_screen.png new file mode 100644 index 0000000000000000000000000000000000000000..b9a85b34b98f6bf81650688da764ae53b583cbe5 GIT binary patch literal 67564 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�uDCtzyjcCVQ|yGUf%I1`X4UtWYR(0gFNI(Y&wzu>jos#yQ^V1J zULTnaRVq9!ESaAQ6BFu@!aw@f>*D5i(>;`@4gM`=Tf)@TLnmB}j`t4xo8*X-2?e)T zJsNw*SkRs~8-sm#K!r}!T)a0~=e4PR7f4OPq>K3<;Y1bWt?xZBtR=qn2ehW5o)bal zEa7?8)k87cOXaI%wkfWwCXxP-Xh`1$Hjd12*z-I+4i zvO^x%$yjvWa%O1(;f>m8V*`{Enl@7_hCYQ8RIr>)wZ%=&p!xwn@0xizQ|j{4DpVd2 z{TRV79bkbUtU{%B98ZI7VvsePDeI7zr`o3I`{$Es7{jRQ?=mH?rE*}82DCDFS=)uJ z4u<8NIukFPq3*pmtWE1s)>nA@1Ai8nhql(2mqUSiLqc0y`^cOUdL~-f@8RRCJ4~)S z&!S<JifoMu!Y!2P= z1=a^E8H=|+Mtfh%&tHrOd3H)^V0zjCa{NKW>N*=le5HJ&%kOB8`+AdxQ zy^KU{2%I`9zSrqK9b2vwLv0Z`AsV3sq(fQJ6}snK{iCQqth|yo5BE$n9+z*ZE3;e- ze(<8wDn)He1U_9MmC2f3WR1=P*h}-Zr{`>bTLGaEVCJlVq7mCVh81zN4A?&uRl}%WCG+AL#vT4tDd#A;7kNM`AzjkdrHK72ud1;Z zdZoaQt@k(*WZQY4iaVP)i;N4Eyn$*pW-BE%HM2_fW4!Dxniw)OXo^EHjDRpM!r_#F zlm*&?0?q-}z|MvOduywj!9HsFPmft<5;3)I|VJip&Y zJbus*L|C}OmXi0A;H$y4!+d_7JiYDil_c}8u4X54NAk6b(?97#lpG7J!WiTunkOoy z8VlgVN986<1Z*?V(NI;x6t#oAVJG%{@JdjU0RQkG&KrTa;#8Pl=SQ=DvrcQzobKX{ zX-epb9IR=a1Rtag_wn-bQpji0L;=s*%rA->x86&SEpXP`dNkJ12cJ~J@zZ}JUi_=ubZc~vTeH-7jNAj& zOmfyckfk#9j(LEpHaclZ83Nw|4qu>wu3vR4=x{r|-AVXQ?h)D@#k?9VmzSEa$v$@_ zF&Wq%Kqv3v^k_c$TWbbBIeWI*zB^>*>%9673}~`{p*B1QVvcE^kR4z$AA^CUdM#BH zC=zleeibkEA{>V38v2>kV8C&D#}7mE zI*lsjH}1lr6kY~W8Hb%D<0i3|%;N_#2-ZJ+4_>Sn*70>f2rvFC6J(S%E~`_no;=y; zSM6n23s?hkomPOxV^9J0gzm_HjJO) zr`Gm~xI*p87Pd0%%BwAC-#g06q6&WF?W6#|I0%59=p8~D56zTATFrn2N#8zEWOfFy z%$eMHpju+$lRZA#vO*+(0~npugO!Y^(-J{6w`Q$p?hOxdtE}C?@hh}vQ%g8RA4>q< zFSS9#ii#3|#YMVUlz)Ud++(!Lebo|=iuCe- zWO`{wB$P0#wdVSR{o(a`mqN17IMCh(;EW|jr zld!VdOo+na{cDBlgzhY<%>g!w0Zm$}K_%9r@9#9whhCT%De4BymBrh(QcWuP7SUd_ z?=Epta`Kw*b7n2`2LHLsq0$Fwy3M0$D!S-_7ZrmbDSsE$q!3tTrbfG{aoKi)HrMBr zT#qiA*z;#)*%t=$WMSuzOz#gP6)lohh6X(Zd6uVRV223^U=E;F15J_C||glmBWa z%Hb!c%O!h2wwlE5KUcg~!+?P5w5iX~jN^izjDhEk>r&9a>?};FLCoZxl!&bf^P8Jr z&tp$-K8)onl#~-coTm4rSF*?ak?{5}^S>Nu!?8>+It6k=Lw696s$=7F2 zZ$FGZC9K>fYTUlP+nK`_utg@sUR&|t?Dj&1Ut+{(crE0l+ zS_ncyoRZ5oA0scWXy|UlDd_+z`QVMaLu?9( z$8?Af7kvumom6t7FMzW0=(Z$u0wv=(Hg(ZZB<%iZ*jnWS7%W|V1h~Mkh zL3O}HclRY_ukGR^H2N*TNP%yLL20)n7WfL4^PWqe6*zSa;@ijIp7M?Z_0d`D8R3|0 z`6XfO&CbvXMR&dijCdQhtNkIFcM*`yP=m{%2g(p7VyHv}i13KAm-Ti66w{506~YeD z9+79$1DaNU*CTSWSYEu0WAi8~TQ{XQ!%({`RBcg5G;9MoicO{Y(axRO z<%)E9xM3UiNV5YqpWWy2TL#z|?t&JM_Ts?e+B9$I5alkIj{MxjnoVtdvUYeZbJ{IH zgGGuX+3w~8G`-xSWO=G9#CW--EWDiFh^L0^KLE1Qu3Q8;6^MPMYSURk2Y1WKrTXV5 z&#>evaejGi>8@zF-f%8M-Y5(vXsQx2KY%MV9Nww2FBsoFD?3Q{$>tJ@?K_+`#9>yh z0x}>JUhrbm1=y&(2dcy>QjoA9UoT3B5)} zpC|q1J)2Ir#Q%@}d^w_rIw$O@wZ1x_R1tt8r^B}gs+4)R@Tc|zYU&JzIv-WZ+e*j- zNHZWOOxo~}5plhFM*(mJZ$}CSrI{)Dx6CW?prB=9?oQKr?ZK#Y$&to_n$q7`(N&PcmxeGg^aAE+i^A-{VF(pP z*cV@~{s62je0ZQDIRO)Sz?Pe*wK21I=Lf<1Pu#z5>mvjlWk;+@L~cV>GpY}Br|!cC z@C|Ae)#!UFmX`SeR43|8k;Qvacc6V@W;I1$*ZCwHwtXdUuU@bI{-F2e+YGuW60`Xv zo&C^T&zwZEL}aBotj5lD3%q z7@C*=f7fjMY;2`>U}2IIV+^BLd-oOHt0XZkJVG`@D6i-~tQM1AL^;aP9TQNLhKX*n z%QAzKD)L;PL)%avF7fSw6cfIVgoWhuqJp#MMS@EmD2g4D6rOO&_TIe|$&Oyep!})P zZU>(zU%SSDOO}na>_J$m_^coDmq_04T0`qTn2kN9@z8Czi8_^*Skm{w+<)``tE_A) zj}k&~_u?}MwiMQubF^$1YmDjSlTGa?(^k&%*wp{7Dr!eu*0WW4H3bwV zH6G(vey3iSUyfh)rRFKf8ICp|CX|Mf9$D=Evaebj{hd#Xa_=Fx0DA;)ozwR~*Oce8 z59JmtMVfYANAcBZDG!N9S(qmTa%D<-S>|mXmV~cd9m4WrSS>!*ewFBSo2?9bEx-PR zC;w4}wz-dywFsp#-SroKbJ)FP>`6tftzXNQN||jA7ZUpaW8fMhp_>gOgeN)f!10ZT zU8xNSfYUdFcLjD>ceK6WXjsH%*YAj;M0%&Y=>rpTvTV*Poe-JzuNH(7F-pR5;l%!| zpIL;6089%%sNip&0^&*LBchU#(F}j}u-{cd&duB7mbL-B+S|6?7T|p!cAq2+tI#J3 zDB-u36V0)^Z?0n~cP)a3G`idM8kdo@?W7*^sAZNPfR=p$=yB<|kXKv;r}50p&fIkl zqxAKX0jN}1qZKB-n2{ZU9hyYD8!jl7?1h`!BobR@uvBxOFwp5fY_nQf!~G4F z-Yvt*4H@5=*&V0JHpXwVP{%jy)i~%VNmt zrgA?)GlvI`E`rjF*jO$`0w=L2z}Ds*}j(4}$J~qwCW!i4q zfW82A&p&C&$w4+Km&NBp8x*iHdNC3^YOp-r+%`$2XT_3ID52yt8f5_iRY=lJS0Jk3 zFD?cL7~S0hO}v>tyR75`~c4 z#iaffSTFXW>fL<~(#LUy>EUlF*x%7iKkfY`XTPw~w$ryA!UB;e7b}(G^+ht(b*N8J z9i{O$6)$bMS|osy`4wB%4`4<#hT<%2`$_2X?bIMeu4LdSw)k{o2xw zb_Bw%CO$&WK=>$SX5uUX+f&{Fq_irW&!dWaI1Pe!uMce6IH`P@NnL!{^JRcr-3Oyp zJx(h&HsuEjNA&lP^XmKF96f6Im~Y3kG(sB#a@9f)YU{~iU z6=~=ILi@kGcfq1aqClIlpkF45hntFImps@rF*P2WIV%&0vYP4#L#o?FA@qBzMvL&o6TR*IzN)Zac9Dv?Q&Aop5dyyYizo+e^0)1uAq`|3c^K z6@xz0k=l=7v~guH+NX{OM6Zud^J8@;O4W1Jqc}hnh4;vSooAi3d|^l|?@|LdV?R6* z$uMGa6A^DJpq0+8_1@@An^VG~6LP1M19C#iExW*|UqVr2s zCPD41uK~BAX)RVLYe+A;oV|wp6_jTHO?fN$oc=BDgjY(c>Xg75+S0FvxR0sr5WrmK zZlJJolc~DkdkxvdIt<_VRipxg52nMP?GE#+A2A&gf#|qLR@X_YpzjmEuHi%+M*nBTnz%o4{7M8Z<~)%P+^`GjI`7y4$I{;RU$!c1Ew``HNQTyw?>vUw`3_x7-KD4NtR?uNMf># zrMtQ-VKj&=L&!+BZiB*%X|u=JmttheSjt#GlPvRnUwyy-#OLvF{c`u*E#1p z=ly=Yo@c|o>62G=P4-^wzGVWGTEdMx5c0f;H=M#M1bzdGaGOs@uScmdDPx`8?+}UK zb}?UkJZdi6F>+vjg_+y;{AD{>QAZ_O8^68-b;!<$qPi5tRsW7a{L`y1rgSL)!q|~&Cma(vk?RZxRW=_BI zlJ7m}Hh&sgQ-h^6a@i`Vge|vylH^dGi^-kjOgb#H8xhjCT@+&yVu7_Y2}S^0QK9b6|db z7)-9MRrI3o7VjpL*brWzag+)mpbnAjd1qj_peE7q+Q8SD2L!K&+6z98D?MjT^Isax zRxyX>9xkk!l`n-g?5-OPh~A*-EwI8J54~ckfVi3j(c;0Ge1@KDxduAdCKFHh|2E#0 zr;@;?kHWia?}B%C*YY2wQ`|$^Ev3Pg0c~XNYnw1X6-IOgEm}4P?4}cIYP`=JIqsB~ z96L<{B=oq6u++28)RL63m;}w#_YG;@Os%g~1z~aAhX{Gt|0!x0N_j>Dmfq)5MRIQW zb=fb^YYE7(KS>OZ=I1d>_foEw&s`meYp@tlXP_P!=N%MJrg3$X8c%Y~etZm+51JDJ zjp~c7zvbav_iCTmbr*6vNwG4yA61w=9Ga@6vUw;_hbH~RzsU7LkSED`B59aTcDw9Y z&~dhfB$ly2$kieuL0@kQPY5K4?_s8RAcT;Yb9kwDSX6SaQPe`Gn z{QjNkafJ)cVMd35+pn48B%duy3@D9;K$~~#et)MW{}Kt@w7amR^4slQ?$E(-juCY3 zRisi~o}v^Ah!dU#ucz#r`U$U>XEgXv8>f<7$rBQ%zAIr49e_TCsAxnjfI?&BBhowd zR(?OHUwS=oeP+LMT7(@@tnT>y@NwM~E=E4G#PE>Fub5KAh*4A3qH|O2wAOZ}?)!|u z4E1Ye;Ne^IP%ce&>Rs5`KWTh!>W;Aqi`39ek&aq$o>S@Efc@zv$mLo4jiyw>sL=dc}K|$~0r;XW@e0@aAARb zXu3q2XqQxD6VpQ0O@3Tu6N{ItBIpkdOg=B>awa!8>UH))*J~GtTiXI6iAvF)Af!I$ zf@8&~nvJ{cGD8p^bNkpPz&nsT@flr{==CJQzjtnW%xn?-i4_O=RZ>r5Q~PeL?099; z)%=)s1m@YOh&a9scbH3gkZi_-B3$2~4I^DB#qq@3({1%y0_US}PiI{4cWrsqa5I?a zpq`XRu&$s?_q0{N(RUKjEKzPv(C3o}^b~niraZ5UDgSewYk3Jo8H<(*L+Ems^n&Jz z;lI#`{pO2ZjXBRyd zeVA6Thh1ekOn7ZL0UP_WR?lc%_)I&e1^4}vU*JSEP@0q8H`-A5(g(8k^# zqdXxwt_RPke551=7x&>KcPhXB3GKpoJ#<}a8!j%kBd%m{EY4J=)&Q0&VWq&jLM zUQcM3JyVTv=I9a_zL}&m%6Vyq`mDMjKf}67<*D5f>(etQfFx4(vq$5ZUyD7*4(UA` z(0lk8ii``C@LF3jg9P2w_r_)b*+JmC0~g*sSB3UnmW|?4iIhL7BY(&;?h1d2O?4+8 zX<_*ji^9I*smapt|4sM#2IH5W=NfTYs;Sl2k`~Mw-^AF2^H=u<_g_JS(|Ewzc9dQX zquQg`!*AA~6-UO{4h6h&7ry)nBg3x}X1w?yAVDqU8Pu&x;c$rKr&oT9&O=bJiM{xj z$o8^;+$877ip8&?Tai0><1V~kMn8Y+xxwpHFuR48`ofiR+Je`meH(bgN;qhp)ymdGcJM= zw0jTW(Vpg@xPKRWc!-_^#?0Ph)@8;Rs0ck1*YT}XOI<`^fFPd;V>dZ}AcWz+AMy>h zRMwLh2p_kD(gA7$Ck=AWQ2K8Q=7}$AW<3&-nTEK*mRY0p$cqO_cjAxQ90nteTyT)L z0r*rW;^p@^D^|RHi3mJOJ)sVs@d;j69awtLOgOoy7d+m_ZaFR^7n-2yTOL|G0WnZp z#&QY52Q76+E*6E0+f~~~BD`=Db859NmD^>SL@-04XVO+YddeVtH&HP|JEsPhT8jw0 z-iEKNY=UU*ahD>zp?8Do=ev)_;mJap=A3hd{MYk+m5GE>H>BKSg4cHeKM2hAI!b`L zlRxS<=wEwX%;2Z4Cz<0K>|ih-x(6~t#GvxZu>bo7OpkAf$D#pjUZ*=ClKN4r3 z?i)_%ZN;++;iaG|vr(MCzni7tSZ5oWm^=o<)D>w&a%RV{v4O#^(iq%Brj|=@4p=*{5SrW^A>zZeaQQ)cWN9wI%vJvnvbc0P{WMz^m)) zWW5|B)bYXG{HFL9sdmWeLXN``fJ&Eow|MQ8^fS&}t9>eF5O$)?$3i3148{-5w&x&; zaqqGcqMcKK8=Mn@r@!jV(C?+K)`FHXZC`X}#eLt0MkX9X7ssDkUCUeqTRXZ|K0Vxm5ax3zrPma(xKPdvgKX`WG7k zqvjB#9)Wuq(bLe&;ID6yv0G*@@34c-hiCcCn)2mm~uX*Opge?+vj1h*fZ<`>l1yrtayP$|A6&TwQp~Jmq zMbP;MS_e&3C7cYbL?mdP+x~TaA{Sc!8oNjNN6Y^#vO}>4j(pV^RGQ&&^Bnj~834?H z50t1t2&&^44XlPOSs|uK8W@<#sTGM@ioVT9yPn~q>K(fZXZrA!w~0R{m?xcgv%+eM zR)1i;FI0T0Nkn?ZhW-|*r$JjSf*YMy*37I!K52Sh@P^(`Eh(Fcy~Ic`FtIW=<2(qM z{nx14eyD0&AbcbNz9|o2#e0zShH>8(S%DRoI78OfqsPZT4Pz7dAKk_zF-ghZvnQI5 zPIZL9%w93FzP-aUF6>uIn>U+~wqy>TOJ}XmpJ+8=P>P9^_!rx*0rclRswBjs|B$in z1o{|NhcSu?#D&+a@8QLi<6Np_+#8@ci>dXQqZqp8jrI}i@R7W-@oa1!c*ef($mkJ* zXBtNk(H1>E?qgit<^`UPviu&WKeG!kAaz!+KPNN5z!9hIdDX% zfz-e#;0Ze@@&fJym+L>>z9sTT$UyLaVr%XrjX*1^Xk?2tcLxB?%$ZbE{HWN+31vwD81x)HT=qSWI}NN zMf54I0j4-~Y?p3o1r3ogN+Qt%;c#)+Ab`!c#xB`07BiKq7o8FRQ1nMl^JAdZ)abq; zm^d&64{DQuuE$A5Ly!emKeL#i=%-B_n_78p@^&^P!-vQ|BOl>B2*$RuNwL|5W9t33Or9y95OV`i&{ zzbO{wDTBaJbgyQcxEsd$Tap_F--jl6lII`HJ9PywKcSSUH}F>|DMZ4)3xypG>egdA z#^lNjicJc+;TlCX{-#iApkG0s(q&>egm!US4z(?1@J@UZq;NcQ|CF3E7dLrz z_)p{0XO0;)V9EOXcwLoaxgO`dX)wk~;J65xSR~Ny9xlA3ywE};;zW~ z)*nElLXIN{iwzF@r@&Byqeu_9ad4dfn@<=yzXV(}a^5Upvko@f!De6B91k|fL}VQJ z?`a1gAB)tXP}|yZhWfUfpE-DSo1gm4IzYPcW;@udgUxoZx%~MrTmteP;zgzU^B%OE Sl(0vdFwV%*u*AUi_WuI?l$}}t literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/drawable-xxhdpi/node_modules_reactnavigation_src_views_assets_backicon.png b/android/app/src/main/res/drawable-xxhdpi/node_modules_reactnavigation_src_views_assets_backicon.png new file mode 100644 index 0000000000000000000000000000000000000000..15a983a67d97c9a6c39d91550a528c37c53a9e3e GIT binary patch literal 167 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY0wn)GsXhaw@;qG}Ln;{G-aN{9*nr0&aBl6p z15q2fw>DO<$f$_t-m`#N(R0!@qfL6}is!BA-aP5mqcux*S)AYDzOuXc@WF!zU-mWw z!RNIrdq3B7GJgpV3USMNx+#Bt3lxOZSlm}!I$z&?|8f=2ODy@*gQAaCs?P@6%;4$j K=d#Wzp$P!X&_+4{ literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/drawable-xxxhdpi/launch_screen.png b/android/app/src/main/res/drawable-xxxhdpi/launch_screen.png new file mode 100644 index 0000000000000000000000000000000000000000..603e7c1fa19aa546412b76448df2133d74f15743 GIT binary patch literal 86245 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 literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/layout/launch_screen.xml b/android/app/src/main/res/layout/launch_screen.xml new file mode 100644 index 000000000..86d6a72e7 --- /dev/null +++ b/android/app/src/main/res/layout/launch_screen.xml @@ -0,0 +1,6 @@ + + + \ No newline at end of file diff --git a/android/app/src/main/res/mipmap-hdpi/ic_notification.png b/android/app/src/main/res/mipmap-hdpi/ic_notification.png new file mode 100644 index 0000000000000000000000000000000000000000..912112d2c9794607a75a6b0a76187da730810f8e GIT binary patch literal 3006 zcmb7``8U*$8^zzoHg;o|WkzI_eVJ^TW~`BAtSOOH)*@N*vCW9Fha^hb_iTlxk!6Mm zAzMhuknA!-Of&e_pYT2Bp7Xl*oadM4ocqH~!dRQ}aGu}<0D#B*g0UR{F#WYm0GRnN z{A!#X{$d(q>0t7g9dPCUOCzoxU&10OkFytxN~nGP^k2V@kB_?%dNc7!8?9~oi$D4d z%~tAO?M#08>=!VIabPeQTU%S-Tid4^ne}f=5B0k zdqu6(M_|j>pP8u_j0B_dRK>Sjx&bmJ-CD zWLg}j`38s)?%P!dN<_CU0w&*6(u3p zZ3w;=%CW}3n%Y(5FUrCfF>O#D6KOneik5@=$QIjNOpC2nuBM22+joLnE%RN03fVi> zpMTEyP)kJ~X|&1S%e^CJP;e-@!QEzLSrL{m$2qeVO2@IV$7uSy(_gUsva1ZsEXw20 zTnN*>Xy41zB+CZB1T=Pj8?AdKjX`}Ac!>`+tI}Y_9qL=P80*J?$X1mpP4*t$!eleN z)}~lnCX|>vgFVyaXJIHrPWWMZQNJe*rx?Fn%I1r^-hhT702PcN3tWPN^;SBJF{Hvy zv1Zm2)dUL@R4krS6cC5W$ueyix2j=6{L*)WDFjawT zzxav%tpIR~5*{e(UbrNFz)wlXrK#Yo4-2aCB%w3GOj&q0%J6RvGDUQ%L$nJ-2moKp z&O%vP4Z~B`*Kj>p$h+3sqp*=E`_df#@Wa zWUU>`-MBf>6%yp!U>5FzsENaIEQtgDPE8;Jj;ssh0k_+eF!b9+tgcXR$l3k9x2(vT zKpC9|gxUqRoV@%TvTuSaKespgZ__Y%2)gV+35$Hpjf##w`8_2+{7?KTn7&#P9yOZ+ zn7%@tBuAtIswl{9C)|EBi7{)3s}x&c1J!IY3lN}g>H};jQwp;aK;~qw$i4AGlX6EY z)ZdyaGbxaHHD2R*8}^-Io5ZBbfb46)bgwC|jV0%n7P^g%+98kP){~LumZ9nL-U(lG zOS8h_>0?90c4Flz5h?G_ToM2ZOuUdndvPaeHaWLgTp1&c_+3H-wMKUw1yf8WM7BmC z>%6;r1dD_N5+hkkpc#Tp-DMm- z5N321)+B_}c=$a^gED6vjOTBsM|&DBC}1VE+UPseLrrniWzbvd9i{ZOA=Y?UJ8i!4 zS%J-LjRp)ds0v&E_*}%;koL2ups%I=yknpOFQq6xZ8~Cv{pJe~eK4`+)(QIYv5EfX zw}CVdFkALwG&G8Cd$M40G47ooIjh;&lT9%)(lwEKQzbLEeAnZ$*@8wh#27(2zLzM8r7*yh~}w3@gw#dTrlN`$GUZvT%S06Wj@Irsrhx~K-A?1GMOyPFel zc{&3O*ZcGumHF~2ko)D9XBS{|gl1M$=655D!`d+{XFl{S_jHBu#h0~>@0S_c2Vi_v z%y0lG9sBCmx~zb+9XGQaHd8Yc11|F^RQm+L2A@TEA7nNS6XW5l@og!|^5KHQ8Vod{ zqo;C3&gH>bz3-s>+7k!|F3b6PvPtMkk~oahk?LgEc=|Lc^@{>5d ztbTioVilgQ7h8SKQRz0xu4M{0)-pVEwY$m*5q>y!2Xs|#dYnaYv;8n`r1E-qV(XFmhyNs92j{tWsuez|bM>10{rz=&Tj*$#;h9L}oXYO@NB0zEV3VxbhocH@>x2Ge4_G)p`cSd$C?57xkcR&QXP@(=a15$kUO9&JJTsRXbAE!WPPxuxcJ?I<1sm8W0=W z;2s%ysD}TZ$>Cq%qo1fBeyi(zz)tpkjPlyTgkoigG%}dap^xqD$K9(uAu?SF@~8P{ z=c4#q=kddIPJ_~S|Zy%_RfaQk= zgS-?GaymWVNf%_E!Xznd+?UX!V9BAIZpDut3QV+sm&oH8H6X`*?ypzhFhJuYAww{? vird0+B #660B0B0B \ No newline at end of file diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml index 758ba54dd..23925e195 100644 --- a/android/app/src/main/res/values/strings.xml +++ b/android/app/src/main/res/values/strings.xml @@ -1,3 +1,5 @@ RocketChatRN + + No Browser Found diff --git a/android/app/src/main/res/values/styles.xml b/android/app/src/main/res/values/styles.xml index 319eb0ca1..654ec9502 100644 --- a/android/app/src/main/res/values/styles.xml +++ b/android/app/src/main/res/values/styles.xml @@ -3,6 +3,7 @@ diff --git a/android/gradle.properties b/android/gradle.properties index 1fd964e90..d94d12020 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -11,10 +11,10 @@ # The setting is particularly useful for tweaking memory settings. # Default value: -Xmx10248m -XX:MaxPermSize=256m # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 - # When configured, Gradle will run in incubating parallel mode. # This option should only be used with decoupled projects. More details, visit # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects # org.gradle.parallel=true android.useDeprecatedNdk=true +VERSIONCODE=999999999 diff --git a/android/settings.gradle b/android/settings.gradle index aacf704b9..bba1bd27f 100644 --- a/android/settings.gradle +++ b/android/settings.gradle @@ -1,6 +1,14 @@ rootProject.name = 'RocketChatRN' -include ':react-native-navigation' -project(':react-native-navigation').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-navigation/android/app/') +include ':react-native-fabric' +project(':react-native-fabric').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-fabric/android') +include ':react-native-audio' +project(':react-native-audio').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-audio/android') +include ':reactnativekeyboardinput' +project(':reactnativekeyboardinput').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-keyboard-input/lib/android') +include ':react-native-splash-screen' +project(':react-native-splash-screen').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-splash-screen/android') +include ':react-native-video' +project(':react-native-video').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-video/android') include ':react-native-svg' project(':react-native-svg').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-svg/android') include ':react-native-image-picker' @@ -13,5 +21,8 @@ include ':react-native-zeroconf' project(':react-native-zeroconf').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-zeroconf/android') include ':realm' project(':realm').projectDir = new File(rootProject.projectDir, '../node_modules/realm/android') - +include ':react-native-push-notification' +project(':react-native-push-notification').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-push-notification/android') +include ':react-native-toast' +project(':react-native-toast').projectDir = new File(settingsDir, '../node_modules/@remobile/react-native-toast/android') include ':app' diff --git a/app/ReactotronConfig.js b/app/ReactotronConfig.js new file mode 100644 index 000000000..c6d66e7a3 --- /dev/null +++ b/app/ReactotronConfig.js @@ -0,0 +1,13 @@ +/* eslint-disable */ +import Reactotron from 'reactotron-react-native'; +import { reactotronRedux } from 'reactotron-redux'; +import sagaPlugin from 'reactotron-redux-saga' + +if (__DEV__) { + Reactotron + .configure() + .useReactNative() + .use(reactotronRedux()) + .use(sagaPlugin()) + .connect(); +} diff --git a/app/actions/actionsTypes.js b/app/actions/actionsTypes.js index 0aca14405..f4daf9a81 100644 --- a/app/actions/actionsTypes.js +++ b/app/actions/actionsTypes.js @@ -1,24 +1,107 @@ - const REQUEST = 'REQUEST'; const SUCCESS = 'SUCCESS'; const FAILURE = 'FAILURE'; const defaultTypes = [REQUEST, SUCCESS, FAILURE]; function createRequestTypes(base, types = defaultTypes) { const res = {}; - types.forEach(type => res[type] = `${ base }_${ type }`); + types.forEach(type => (res[type] = `${ base }_${ type }`)); return res; } // Login events -export const LOGIN = createRequestTypes('LOGIN', [...defaultTypes, 'SET_TOKEN', 'SUBMIT']); -export const ROOMS = createRequestTypes('ROOMS'); +export const LOGIN = createRequestTypes('LOGIN', [ + ...defaultTypes, + 'SET_TOKEN', + 'RESTORE_TOKEN', + 'SUBMIT', + 'REGISTER_SUBMIT', + 'REGISTER_REQUEST', + 'REGISTER_SUCCESS', + 'REGISTER_INCOMPLETE', + 'SET_USERNAME_SUBMIT', + 'SET_USERNAME_REQUEST', + 'SET_USERNAME_SUCCESS', + 'OPEN', + 'CLOSE', + 'SET_SERVICES', + 'REMOVE_SERVICES' +]); +export const FORGOT_PASSWORD = createRequestTypes('FORGOT_PASSWORD', [ + ...defaultTypes, + 'INIT' +]); +export const USER = createRequestTypes('USER', ['SET']); +export const ROOMS = createRequestTypes('ROOMS', [...defaultTypes, 'SET_SEARCH']); +export const ROOM = createRequestTypes('ROOM', [ + 'ADD_USER_TYPING', + 'REMOVE_USER_TYPING', + 'SOMEONE_TYPING', + 'OPEN', + 'CLOSE', + 'LEAVE', + 'ERASE', + 'USER_TYPING', + 'MESSAGE_RECEIVED', + 'SET_LAST_OPEN', + 'LAYOUT_ANIMATION' +]); export const APP = createRequestTypes('APP', ['READY', 'INIT']); -export const MESSAGES = createRequestTypes('MESSAGES'); -export const CREATE_CHANNEL = createRequestTypes('CREATE_CHANNEL', [...defaultTypes, 'REQUEST_USERS', 'SUCCESS_USERS', 'FAILURE_USERS', 'SET_USERS']); +export const MESSAGES = createRequestTypes('MESSAGES', [ + ...defaultTypes, + 'ACTIONS_SHOW', + 'ACTIONS_HIDE', + 'ERROR_ACTIONS_SHOW', + 'ERROR_ACTIONS_HIDE', + 'DELETE_REQUEST', + 'DELETE_SUCCESS', + 'DELETE_FAILURE', + 'EDIT_INIT', + 'EDIT_CANCEL', + 'EDIT_REQUEST', + 'EDIT_SUCCESS', + 'EDIT_FAILURE', + 'TOGGLE_STAR_REQUEST', + 'TOGGLE_STAR_SUCCESS', + 'TOGGLE_STAR_FAILURE', + 'PERMALINK_REQUEST', + 'PERMALINK_SUCCESS', + 'PERMALINK_FAILURE', + 'PERMALINK_CLEAR', + 'TOGGLE_PIN_REQUEST', + 'TOGGLE_PIN_SUCCESS', + 'TOGGLE_PIN_FAILURE', + 'SET_INPUT', + 'CLEAR_INPUT', + 'TOGGLE_REACTION_PICKER' +]); +export const CREATE_CHANNEL = createRequestTypes('CREATE_CHANNEL', [ + ...defaultTypes, + 'REQUEST_USERS', + 'SUCCESS_USERS', + 'FAILURE_USERS', + 'SET_USERS', + 'ADD_USER', + 'REMOVE_USER', + 'RESET' +]); export const NAVIGATION = createRequestTypes('NAVIGATION', ['SET']); -export const SERVER = createRequestTypes('SERVER', [...defaultTypes, 'SELECT', 'CHANGED', 'ADD']); -export const METEOR = createRequestTypes('METEOR_CONNECT', [...defaultTypes, 'DISCONNECT']); +export const SERVER = createRequestTypes('SERVER', [ + ...defaultTypes, + 'SELECT', + 'CHANGED', + 'ADD', + 'GOTO_ADD' +]); +export const METEOR = createRequestTypes('METEOR_CONNECT', [...defaultTypes, 'DISCONNECT', 'DISCONNECT_BY_USER']); export const LOGOUT = 'LOGOUT'; // logout is always success +export const ACTIVE_USERS = createRequestTypes('ACTIVE_USERS', ['SET']); +export const ROLES = createRequestTypes('ROLES', ['SET']); +export const STARRED_MESSAGES = createRequestTypes('STARRED_MESSAGES', ['OPEN', 'CLOSE', 'MESSAGES_RECEIVED', 'MESSAGE_UNSTARRED']); +export const PINNED_MESSAGES = createRequestTypes('PINNED_MESSAGES', ['OPEN', 'CLOSE', 'MESSAGES_RECEIVED', 'MESSAGE_UNPINNED']); +export const MENTIONED_MESSAGES = createRequestTypes('MENTIONED_MESSAGES', ['OPEN', 'CLOSE', 'MESSAGES_RECEIVED']); +export const SNIPPETED_MESSAGES = createRequestTypes('SNIPPETED_MESSAGES', ['OPEN', 'CLOSE', 'MESSAGES_RECEIVED']); +export const ROOM_FILES = createRequestTypes('ROOM_FILES', ['OPEN', 'CLOSE', 'MESSAGES_RECEIVED']); export const INCREMENT = 'INCREMENT'; export const DECREMENT = 'DECREMENT'; + diff --git a/app/actions/activeUsers.js b/app/actions/activeUsers.js new file mode 100644 index 000000000..1e7c5ecb7 --- /dev/null +++ b/app/actions/activeUsers.js @@ -0,0 +1,8 @@ +import * as types from './actionsTypes'; + +export function setActiveUser(data) { + return { + type: types.ACTIVE_USERS.SET, + data + }; +} diff --git a/app/actions/connect.js b/app/actions/connect.js index 412c096f3..40049f28e 100644 --- a/app/actions/connect.js +++ b/app/actions/connect.js @@ -25,3 +25,8 @@ export function disconnect(err) { err }; } +export function disconnect_by_user() { + return { + type: types.METEOR.DISCONNECT_BY_USER + }; +} diff --git a/app/actions/createChannel.js b/app/actions/createChannel.js index df4cad35a..435a42ddc 100644 --- a/app/actions/createChannel.js +++ b/app/actions/createChannel.js @@ -21,7 +21,6 @@ export function createChannelFailure(err) { }; } - export function createChannelRequestUsers(data) { return { type: types.CREATE_CHANNEL.REQUEST_USERS, @@ -49,3 +48,23 @@ export function createChannelFailureUsers(err) { err }; } + +export function addUser(user) { + return { + type: types.CREATE_CHANNEL.ADD_USER, + user + }; +} + +export function removeUser(user) { + return { + type: types.CREATE_CHANNEL.REMOVE_USER, + user + }; +} + +export function reset() { + return { + type: types.CREATE_CHANNEL.RESET + }; +} diff --git a/app/actions/index.js b/app/actions/index.js index dba8b7e18..b597699b4 100644 --- a/app/actions/index.js +++ b/app/actions/index.js @@ -19,12 +19,33 @@ export function setCurrentServer(server) { }; } +export function addSettings(settings) { + return { + type: types.ADD_SETTINGS, + payload: settings + }; +} export function setAllSettings(settings) { return { type: types.SET_ALL_SETTINGS, payload: settings }; } + +export function setAllPermissions(permissions) { + return { + type: types.SET_ALL_PERMISSIONS, + payload: permissions + }; +} + +export function setCustomEmojis(emojis) { + return { + type: types.SET_CUSTOM_EMOJIS, + payload: emojis + }; +} + export function login() { return { type: 'LOGIN' diff --git a/app/actions/login.js b/app/actions/login.js index 7969c8090..875c46706 100644 --- a/app/actions/login.js +++ b/app/actions/login.js @@ -13,6 +13,50 @@ export function loginRequest(credentials) { }; } +export function registerSubmit(credentials) { + return { + type: types.LOGIN.REGISTER_SUBMIT, + credentials + }; +} +export function registerRequest(credentials) { + return { + type: types.LOGIN.REGISTER_REQUEST, + credentials + }; +} +export function registerSuccess(credentials) { + return { + type: types.LOGIN.REGISTER_SUCCESS, + credentials + }; +} +export function registerIncomplete() { + return { + type: types.LOGIN.REGISTER_INCOMPLETE + }; +} + +export function setUsernameSubmit(credentials) { + return { + type: types.LOGIN.SET_USERNAME_SUBMIT, + credentials + }; +} + +export function setUsernameRequest(credentials) { + return { + type: types.LOGIN.SET_USERNAME_REQUEST, + credentials + }; +} + +export function setUsernameSuccess() { + return { + type: types.LOGIN.SET_USERNAME_SUCCESS + }; +} + export function loginSuccess(user) { return { type: types.LOGIN.SUCCESS, @@ -31,8 +75,14 @@ export function loginFailure(err) { export function setToken(user = {}) { return { type: types.LOGIN.SET_TOKEN, - token: user.token, - user + ...user + }; +} + +export function restoreToken(token) { + return { + type: types.LOGIN.RESTORE_TOKEN, + token }; } @@ -41,3 +91,61 @@ export function logout() { type: types.LOGOUT }; } + +export function forgotPasswordInit() { + return { + type: types.FORGOT_PASSWORD.INIT + }; +} + +export function forgotPasswordRequest(email) { + return { + type: types.FORGOT_PASSWORD.REQUEST, + email + }; +} + +export function forgotPasswordSuccess() { + return { + type: types.FORGOT_PASSWORD.SUCCESS + }; +} + +export function forgotPasswordFailure(err) { + return { + type: types.FORGOT_PASSWORD.FAILURE, + err + }; +} + +export function setUser(action) { + return { + type: types.USER.SET, + ...action + }; +} + +export function open() { + return { + type: types.LOGIN.OPEN + }; +} + +export function close() { + return { + type: types.LOGIN.CLOSE + }; +} + +export function setLoginServices(data) { + return { + type: types.LOGIN.SET_SERVICES, + data + }; +} + +export function removeLoginServices() { + return { + type: types.LOGIN.REMOVE_SERVICES + }; +} diff --git a/app/actions/mentionedMessages.js b/app/actions/mentionedMessages.js new file mode 100644 index 000000000..5c938bbce --- /dev/null +++ b/app/actions/mentionedMessages.js @@ -0,0 +1,21 @@ +import * as types from './actionsTypes'; + +export function openMentionedMessages(rid) { + return { + type: types.MENTIONED_MESSAGES.OPEN, + rid + }; +} + +export function closeMentionedMessages() { + return { + type: types.MENTIONED_MESSAGES.CLOSE + }; +} + +export function mentionedMessagesReceived(messages) { + return { + type: types.MENTIONED_MESSAGES.MESSAGES_RECEIVED, + messages + }; +} diff --git a/app/actions/messages.js b/app/actions/messages.js index 2f92816ec..ed9bf4971 100644 --- a/app/actions/messages.js +++ b/app/actions/messages.js @@ -19,3 +19,167 @@ export function messagesFailure(err) { err }; } + +export function actionsShow(actionMessage) { + return { + type: types.MESSAGES.ACTIONS_SHOW, + actionMessage + }; +} + +export function actionsHide() { + return { + type: types.MESSAGES.ACTIONS_HIDE + }; +} + +export function errorActionsShow(actionMessage) { + return { + type: types.MESSAGES.ERROR_ACTIONS_SHOW, + actionMessage + }; +} + +export function errorActionsHide() { + return { + type: types.MESSAGES.ERROR_ACTIONS_HIDE + }; +} + +export function deleteRequest(message) { + return { + type: types.MESSAGES.DELETE_REQUEST, + message + }; +} + +export function deleteSuccess() { + return { + type: types.MESSAGES.DELETE_SUCCESS + }; +} + +export function deleteFailure() { + return { + type: types.MESSAGES.DELETE_FAILURE + }; +} + + +export function editInit(message) { + return { + type: types.MESSAGES.EDIT_INIT, + message + }; +} + +export function editCancel() { + return { + type: types.MESSAGES.EDIT_CANCEL + }; +} + +export function editRequest(message) { + return { + type: types.MESSAGES.EDIT_REQUEST, + message + }; +} + +export function editSuccess() { + return { + type: types.MESSAGES.EDIT_SUCCESS + }; +} + +export function editFailure() { + return { + type: types.MESSAGES.EDIT_FAILURE + }; +} + +export function toggleStarRequest(message) { + return { + type: types.MESSAGES.TOGGLE_STAR_REQUEST, + message + }; +} + +export function toggleStarSuccess() { + return { + type: types.MESSAGES.TOGGLE_STAR_SUCCESS + }; +} + +export function toggleStarFailure() { + return { + type: types.MESSAGES.TOGGLE_STAR_FAILURE + }; +} + +export function permalinkRequest(message) { + return { + type: types.MESSAGES.PERMALINK_REQUEST, + message + }; +} + +export function permalinkSuccess(permalink) { + return { + type: types.MESSAGES.PERMALINK_SUCCESS, + permalink + }; +} + +export function permalinkFailure(err) { + return { + type: types.MESSAGES.PERMALINK_FAILURE, + err + }; +} + +export function permalinkClear() { + return { + type: types.MESSAGES.PERMALINK_CLEAR + }; +} + +export function togglePinRequest(message) { + return { + type: types.MESSAGES.TOGGLE_PIN_REQUEST, + message + }; +} + +export function togglePinSuccess() { + return { + type: types.MESSAGES.TOGGLE_PIN_SUCCESS + }; +} + +export function togglePinFailure(err) { + return { + type: types.MESSAGES.TOGGLE_PIN_FAILURE, + err + }; +} + +export function setInput(message) { + return { + type: types.MESSAGES.SET_INPUT, + message + }; +} + +export function clearInput() { + return { + type: types.MESSAGES.CLEAR_INPUT + }; +} + +export function toggleReactionPicker(message) { + return { + type: types.MESSAGES.TOGGLE_REACTION_PICKER, + message + }; +} diff --git a/app/actions/pinnedMessages.js b/app/actions/pinnedMessages.js new file mode 100644 index 000000000..e344b441f --- /dev/null +++ b/app/actions/pinnedMessages.js @@ -0,0 +1,28 @@ +import * as types from './actionsTypes'; + +export function openPinnedMessages(rid) { + return { + type: types.PINNED_MESSAGES.OPEN, + rid + }; +} + +export function closePinnedMessages() { + return { + type: types.PINNED_MESSAGES.CLOSE + }; +} + +export function pinnedMessagesReceived(messages) { + return { + type: types.PINNED_MESSAGES.MESSAGES_RECEIVED, + messages + }; +} + +export function pinnedMessageUnpinned(messageId) { + return { + type: types.PINNED_MESSAGES.MESSAGE_UNPINNED, + messageId + }; +} diff --git a/app/actions/roles.js b/app/actions/roles.js new file mode 100644 index 000000000..074111985 --- /dev/null +++ b/app/actions/roles.js @@ -0,0 +1,8 @@ +import * as types from './actionsTypes'; + +export function setRoles(data) { + return { + type: types.ROLES.SET, + data + }; +} diff --git a/app/actions/room.js b/app/actions/room.js new file mode 100644 index 000000000..ef6430c3b --- /dev/null +++ b/app/actions/room.js @@ -0,0 +1,77 @@ +import * as types from './actionsTypes'; + + +export function removeUserTyping(username) { + return { + type: types.ROOM.REMOVE_USER_TYPING, + username + }; +} + +export function someoneTyping(data) { + return { + type: types.ROOM.SOMEONE_TYPING, + ...data + }; +} + +export function addUserTyping(username) { + return { + type: types.ROOM.ADD_USER_TYPING, + username + }; +} + +export function openRoom(room) { + return { + type: types.ROOM.OPEN, + room + }; +} + +export function closeRoom() { + return { + type: types.ROOM.CLOSE + }; +} + +export function leaveRoom(rid) { + return { + type: types.ROOM.LEAVE, + rid + }; +} + +export function eraseRoom(rid) { + return { + type: types.ROOM.ERASE, + rid + }; +} + +export function userTyping(status = true) { + return { + type: types.ROOM.USER_TYPING, + status + }; +} + +export function roomMessageReceived(message) { + return { + type: types.ROOM.MESSAGE_RECEIVED, + message + }; +} + +export function setLastOpen(date = new Date()) { + return { + type: types.ROOM.SET_LAST_OPEN, + date + }; +} + +export function layoutAnimation() { + return { + type: types.ROOM.LAYOUT_ANIMATION + }; +} diff --git a/app/actions/roomFiles.js b/app/actions/roomFiles.js new file mode 100644 index 000000000..e8c674b7b --- /dev/null +++ b/app/actions/roomFiles.js @@ -0,0 +1,21 @@ +import * as types from './actionsTypes'; + +export function openRoomFiles(rid) { + return { + type: types.ROOM_FILES.OPEN, + rid + }; +} + +export function closeRoomFiles() { + return { + type: types.ROOM_FILES.CLOSE + }; +} + +export function roomFilesReceived(messages) { + return { + type: types.ROOM_FILES.MESSAGES_RECEIVED, + messages + }; +} diff --git a/app/actions/rooms.js b/app/actions/rooms.js index bdbf94d05..1555a8c85 100644 --- a/app/actions/rooms.js +++ b/app/actions/rooms.js @@ -1,5 +1,6 @@ import * as types from './actionsTypes'; + export function roomsRequest() { return { type: types.ROOMS.REQUEST @@ -18,3 +19,10 @@ export function roomsFailure(err) { err }; } + +export function setSearch(searchText) { + return { + type: types.ROOMS.SET_SEARCH, + searchText + }; +} diff --git a/app/actions/server.js b/app/actions/server.js index cfc46ad89..b334981b5 100644 --- a/app/actions/server.js +++ b/app/actions/server.js @@ -41,3 +41,9 @@ export function changedServer(server) { server }; } + +export function gotoAddServer() { + return { + type: SERVER.GOTO_ADD + }; +} diff --git a/app/actions/snippetedMessages.js b/app/actions/snippetedMessages.js new file mode 100644 index 000000000..54c6edeea --- /dev/null +++ b/app/actions/snippetedMessages.js @@ -0,0 +1,21 @@ +import * as types from './actionsTypes'; + +export function openSnippetedMessages(rid) { + return { + type: types.SNIPPETED_MESSAGES.OPEN, + rid + }; +} + +export function closeSnippetedMessages() { + return { + type: types.SNIPPETED_MESSAGES.CLOSE + }; +} + +export function snippetedMessagesReceived(messages) { + return { + type: types.SNIPPETED_MESSAGES.MESSAGES_RECEIVED, + messages + }; +} diff --git a/app/actions/starredMessages.js b/app/actions/starredMessages.js new file mode 100644 index 000000000..36b701a86 --- /dev/null +++ b/app/actions/starredMessages.js @@ -0,0 +1,28 @@ +import * as types from './actionsTypes'; + +export function openStarredMessages(rid) { + return { + type: types.STARRED_MESSAGES.OPEN, + rid + }; +} + +export function closeStarredMessages() { + return { + type: types.STARRED_MESSAGES.CLOSE + }; +} + +export function starredMessagesReceived(messages) { + return { + type: types.STARRED_MESSAGES.MESSAGES_RECEIVED, + messages + }; +} + +export function starredMessageUnstarred(messageId) { + return { + type: types.STARRED_MESSAGES.MESSAGE_UNSTARRED, + messageId + }; +} diff --git a/app/animations/collapse.js b/app/animations/collapse.js new file mode 100644 index 000000000..05cfce52a --- /dev/null +++ b/app/animations/collapse.js @@ -0,0 +1,64 @@ +import { View, Animated } from 'react-native'; + +import PropTypes from 'prop-types'; +import React from 'react'; + +export default class Panel extends React.Component { + static propTypes = { + open: PropTypes.bool.isRequired, + children: PropTypes.node.isRequired, + style: PropTypes.object + } + constructor(props) { + super(props); + this.state = { + animation: new Animated.Value() + }; + this.first = true; + this.open = false; + this.opacity = 0; + } + componentDidMount() { + const initialValue = !this.props.open ? this.height : 0; + this.state.animation.setValue(initialValue); + } + componentWillReceiveProps(nextProps) { + if (this.first) { + this.first = false; + if (!this.props.open) { + this.state.animation.setValue(0); + return; + } + } + if (this.open === nextProps.open) { + return; + } + this.open = nextProps.open; + const initialValue = !nextProps.open ? this.height : 0; + const finalValue = !nextProps.open ? 0 : this.height; + + this.state.animation.setValue(initialValue); + Animated.timing( + this.state.animation, + { + toValue: finalValue, + duration: 150, + useNativeDriver: true + } + ).start(); + } + set _height(h) { + this.height = h || this.height; + } + render() { + return ( + + this._height = nativeEvent.layout.height} style={{ position: !this.first ? 'relative' : 'absolute' }}> + {this.props.children} + + + ); + } +} diff --git a/app/animations/fade.js b/app/animations/fade.js index b9f276903..97693d03a 100644 --- a/app/animations/fade.js +++ b/app/animations/fade.js @@ -17,9 +17,6 @@ export default class Fade extends React.Component { this.state = { visible: props.visible }; - } - - componentWillMount() { this._visibility = new Animated.Value(this.props.visible ? 1 : 0); } @@ -29,7 +26,8 @@ export default class Fade extends React.Component { } Animated.timing(this._visibility, { toValue: nextProps.visible ? 1 : 0, - duration: 300 + duration: 300, + useNativeDriver: true }).start(() => { this.setState({ visible: nextProps.visible }); }); diff --git a/app/components/KeyboardView.js b/app/components/KeyboardView.js deleted file mode 100644 index ba1e50ea0..000000000 --- a/app/components/KeyboardView.js +++ /dev/null @@ -1,22 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { KeyboardAvoidingView, Platform } from 'react-native'; - -export default class KeyboardView extends React.PureComponent { - static propTypes = { - style: KeyboardAvoidingView.propTypes.style, - keyboardVerticalOffset: PropTypes.number, - children: PropTypes.oneOfType([ - PropTypes.arrayOf(PropTypes.node), - PropTypes.node - ]) - } - - render() { - return ( - - {this.props.children} - - ); - } -} diff --git a/app/components/Message.js b/app/components/Message.js deleted file mode 100644 index b1dee59ed..000000000 --- a/app/components/Message.js +++ /dev/null @@ -1,88 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { View, Text, StyleSheet } from 'react-native'; -import { emojify } from 'react-emojione'; -import Markdown from 'react-native-easy-markdown'; -import moment from 'moment'; -import Avatar from './avatar'; -import Card from './message/card'; - -const styles = StyleSheet.create({ - content: { - flexGrow: 1 - }, - message: { - padding: 12, - paddingTop: 6, - paddingBottom: 6, - flexDirection: 'row', - transform: [{ scaleY: -1 }] - }, - texts: { - flex: 1 - }, - msg: { - flex: 1 - }, - username: { - fontWeight: 'bold' - }, - usernameView: { - flexDirection: 'row', - alignItems: 'center', - marginBottom: 2 - }, - alias: { - fontSize: 10, - color: '#888', - paddingLeft: 5 - }, - time: { - fontSize: 10, - color: '#888', - paddingLeft: 5 - } -}); - -export default class Message extends React.PureComponent { - static propTypes = { - item: PropTypes.object.isRequired, - baseUrl: PropTypes.string.isRequired, - Message_TimeFormat: PropTypes.string.isRequired - } - attachments() { - return this.props.item.attachments.length ? : null; - } - render() { - const { item } = this.props; - - const extraStyle = {}; - if (item.temp) { - extraStyle.opacity = 0.3; - } - - const msg = emojify(item.msg, { output: 'unicode' }); - - const username = item.alias || item.u.username; - - const time = moment(item.ts).format(this.props.Message_TimeFormat); - - return ( - - - - - - {username} - - {item.alias && @{item.u.username}}{time} - - {this.attachments()} - - {msg} - - - - ); - } -} diff --git a/app/components/MessageBox.js b/app/components/MessageBox.js deleted file mode 100644 index e1f809073..000000000 --- a/app/components/MessageBox.js +++ /dev/null @@ -1,94 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { View, TextInput, StyleSheet } from 'react-native'; -import Icon from 'react-native-vector-icons/MaterialIcons'; -import ImagePicker from 'react-native-image-picker'; -import RocketChat from '../lib/rocketchat'; - -const styles = StyleSheet.create({ - textBox: { - paddingTop: 1, - borderTopWidth: 1, - borderTopColor: '#ccc', - backgroundColor: '#fff', - flexDirection: 'row', - alignItems: 'center' - }, - textBoxInput: { - height: 40, - alignSelf: 'stretch', - backgroundColor: '#fff', - flexGrow: 1 - }, - fileButton: { - color: '#aaa', - paddingLeft: 23, - paddingRight: 20, - paddingTop: 10, - paddingBottom: 10, - fontSize: 20 - } -}); - -export default class MessageBox extends React.PureComponent { - static propTypes = { - onSubmit: PropTypes.func.isRequired, - rid: PropTypes.string.isRequired - } - - submit(message) { - const text = message; - if (text.trim() === '') { - return; - } - if (this.component) { - this.component.setNativeProps({ text: '' }); - } - this.props.onSubmit(text); - } - - addFile = () => { - const options = { - customButtons: [{ - name: 'import', title: 'Import File From' - }] - }; - - ImagePicker.showImagePicker(options, (response) => { - if (response.didCancel) { - console.log('User cancelled image picker'); - } else if (response.error) { - console.log('ImagePicker Error: ', response.error); - } else if (response.customButton) { - console.log('User tapped custom button: ', response.customButton); - } else { - const fileInfo = { - name: response.fileName, - size: response.fileSize, - type: response.type || 'image/jpeg', - // description: '', - store: 'Uploads' - }; - RocketChat.sendFileMessage(this.props.rid, fileInfo, response.data); - } - }); - } - - render() { - return ( - - - this.component = component} - style={styles.textBoxInput} - returnKeyType='send' - onSubmitEditing={event => this.submit(event.nativeEvent.text)} - blurOnSubmit={false} - placeholder='New message' - underlineColorAndroid='transparent' - defaultValue={''} - /> - - ); - } -} diff --git a/app/components/RoomItem.js b/app/components/RoomItem.js deleted file mode 100644 index b1957787e..000000000 --- a/app/components/RoomItem.js +++ /dev/null @@ -1,123 +0,0 @@ -import React from 'react'; -import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons'; -import PropTypes from 'prop-types'; -import { View, Text, StyleSheet, TouchableOpacity } from 'react-native'; -import Avatar from './avatar'; -import avatarInitialsAndColor from '../utils/avatarInitialsAndColor'; - -const styles = StyleSheet.create({ - container: { - // flex: 1, - flexDirection: 'row', - paddingLeft: 16, - paddingRight: 16, - height: 56, - alignItems: 'center' - }, - number: { - minWidth: 20, - borderRadius: 5, - backgroundColor: '#1d74f5', - color: '#fff', - textAlign: 'center', - overflow: 'hidden', - fontSize: 14, - paddingLeft: 5, - paddingRight: 5 - }, - roomName: { - flex: 1, - fontSize: 16, - color: '#444', - marginLeft: 16, - marginRight: 4 - }, - iconContainer: { - height: 40, - width: 40, - borderRadius: 20, - overflow: 'hidden', - justifyContent: 'center', - alignItems: 'center' - }, - icon: { - fontSize: 20, - color: '#fff' - }, - avatar: { - width: 40, - height: 40, - position: 'absolute', - borderRadius: 20 - }, - avatarInitials: { - fontSize: 20, - color: '#ffffff' - } -}); - -export default class RoomItem extends React.PureComponent { - static propTypes = { - type: PropTypes.string.isRequired, - name: PropTypes.string.isRequired, - unread: PropTypes.number, - baseUrl: PropTypes.string, - onPress: PropTypes.func - } - - get icon() { - const { type, name, baseUrl } = this.props; - - const icon = { - d: 'at', - c: 'pound', - p: 'lock', - l: 'account' - }[type]; - - if (!icon) { - return null; - } - - if (type === 'd') { - return ( - - ); - } - - const { color } = avatarInitialsAndColor(name); - - return ( - - - - ); - } - - renderNumber = (unread) => { - if (!unread || unread <= 0) { - return; - } - - if (unread >= 1000) { - unread = '999+'; - } - - return ( - - { unread } - - ); - } - - render() { - const { unread, name } = this.props; - return ( - - {this.icon} - { name } - {this.renderNumber(unread)} - - ); - } -} diff --git a/app/components/avatar.js b/app/components/avatar.js deleted file mode 100644 index 8cc05a7fc..000000000 --- a/app/components/avatar.js +++ /dev/null @@ -1,51 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { StyleSheet, Text, View } from 'react-native'; -import { CachedImage } from 'react-native-img-cache'; -import avatarInitialsAndColor from '../utils/avatarInitialsAndColor'; - -const styles = StyleSheet.create({ - iconContainer: { - overflow: 'hidden', - justifyContent: 'center', - alignItems: 'center' - }, - avatar: { - position: 'absolute' - }, - avatarInitials: { - color: '#ffffff' - } }); - -class Avatar extends React.PureComponent { - render() { - const { text = '', size = 25, baseUrl = this.props.baseUrl, - borderRadius = 5, style, avatar } = this.props; - const { initials, color } = avatarInitialsAndColor(`${ text }`); - return ( - - {initials} - { (avatar || baseUrl) && } - ); - } -} - -Avatar.propTypes = { - style: PropTypes.object, - baseUrl: PropTypes.string, - text: PropTypes.string.isRequired, - avatar: PropTypes.string, - size: PropTypes.number, - borderRadius: PropTypes.number -}; -export default Avatar; diff --git a/app/components/message/card.js b/app/components/message/card.js deleted file mode 100644 index c039c26d8..000000000 --- a/app/components/message/card.js +++ /dev/null @@ -1,88 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import Meteor from 'react-native-meteor'; -import { connect } from 'react-redux'; -import { CachedImage } from 'react-native-img-cache'; -import { Text, TouchableOpacity } from 'react-native'; -import { Navigation } from 'react-native-navigation'; -import { - Card, - CardImage, - // CardTitle, - CardContent - // CardAction -} from 'react-native-card-view'; -import RocketChat from '../../lib/rocketchat'; - -const close = () => Navigation.dismissModal({ - animationType: 'slide-down' -}); - -const CustomButton = ({ text }) => ( - - {text} - -); - -CustomButton.propTypes = { - text: PropTypes.string -}; - -Navigation.registerComponent('CustomButton', () => CustomButton); - -@connect(state => ({ - base: state.settings.Site_Url, - canShowList: state.login.token.length || state.login.user.token -})) - -export default class Cards extends React.PureComponent { - static propTypes = { - data: PropTypes.object.isRequired, - base: PropTypes.string - } - constructor() { - super(); - const user = Meteor.user(); - this.state = {}; - RocketChat.getUserToken().then((token) => { - this.setState({ img: `${ this.props.base }${ this.props.data.image_url }?rc_uid=${ user._id }&rc_token=${ token }` }); - }); - } - _onPressButton() { - Navigation.showModal({ - screen: 'Photo', - title: this.props.data.title, // title of the screen as appears in the nav bar (optional) - passProps: { image: this.state.img }, - // navigatorStyle: {}, // override the navigator style for the screen, see "Styling the navigator" below (optional) - navigatorButtons: { - leftButtons: [{ - id: 'custom-button', - component: 'CustomButton', - passProps: { - text: 'close' - } - }] - }, // override the nav buttons for the screen, see "Adding buttons to the navigator" below (optional) - animationType: 'slide-up' // 'none' / 'slide-up' , appear animation for the modal (optional, default 'slide-up') - }); - } - render() { - return this.state.img ? ( - this._onPressButton()}> - - - - - - {this.props.data.title} - {this.props.data.description} - - - - ) : - {this.props.data.title}; - } -} diff --git a/app/constants/colors.js b/app/constants/colors.js index 145e665be..5caf08c58 100644 --- a/app/constants/colors.js +++ b/app/constants/colors.js @@ -1,2 +1,9 @@ export const AVATAR_COLORS = ['#F44336', '#E91E63', '#9C27B0', '#673AB7', '#3F51B5', '#2196F3', '#03A9F4', '#00BCD4', '#009688', '#4CAF50', '#8BC34A', '#CDDC39', '#FFC107', '#FF9800', '#FF5722', '#795548', '#9E9E9E', '#607D8B']; export const ESLINT_FIX = null; +export const COLOR_DANGER = '#f5455c'; +export const STATUS_COLORS = { + online: '#2de0a5', + busy: COLOR_DANGER, + away: '#ffd21f', + offline: '#cbced1' +}; diff --git a/app/constants/messagesStatus.js b/app/constants/messagesStatus.js new file mode 100644 index 000000000..4f945f939 --- /dev/null +++ b/app/constants/messagesStatus.js @@ -0,0 +1,5 @@ +export default { + SENT: 0, + TEMP: 1, + ERROR: 2 +}; diff --git a/app/constants/types.js b/app/constants/types.js index f772c2b92..3e65838cf 100644 --- a/app/constants/types.js +++ b/app/constants/types.js @@ -1,2 +1,5 @@ export const SET_CURRENT_SERVER = 'SET_CURRENT_SERVER'; export const SET_ALL_SETTINGS = 'SET_ALL_SETTINGS'; +export const SET_ALL_PERMISSIONS = 'SET_ALL_PERMISSIONS'; +export const SET_CUSTOM_EMOJIS = 'SET_CUSTOM_EMOJIS'; +export const ADD_SETTINGS = 'ADD_SETTINGS'; diff --git a/app/containers/Avatar.js b/app/containers/Avatar.js new file mode 100644 index 000000000..3ab6c266b --- /dev/null +++ b/app/containers/Avatar.js @@ -0,0 +1,88 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { connect } from 'react-redux'; +import { StyleSheet, Text, View, ViewPropTypes } from 'react-native'; +import { CachedImage } from 'react-native-img-cache'; +import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons'; +import avatarInitialsAndColor from '../utils/avatarInitialsAndColor'; + +const styles = StyleSheet.create({ + iconContainer: { + // overflow: 'hidden', + justifyContent: 'center', + alignItems: 'center' + }, + avatar: { + position: 'absolute' + }, + avatarInitials: { + color: '#ffffff' + } +}); + +@connect(state => ({ + baseUrl: state.settings.Site_Url || state.server ? state.server.server : '' +})) +export default class Avatar extends React.PureComponent { + static propTypes = { + style: ViewPropTypes.style, + baseUrl: PropTypes.string, + text: PropTypes.string.isRequired, + avatar: PropTypes.string, + size: PropTypes.number, + borderRadius: PropTypes.number, + type: PropTypes.string, + children: PropTypes.object + }; + render() { + const { + text = '', size = 25, baseUrl, borderRadius = 4, style, avatar, type = 'd' + } = this.props; + const { initials, color } = avatarInitialsAndColor(`${ text }`); + + const iconContainerStyle = { + backgroundColor: color, + width: size, + height: size, + borderRadius + }; + + const avatarInitialsStyle = { + fontSize: size / 2 + }; + + const avatarStyle = { + width: size, + height: size, + borderRadius + }; + + if (type === 'd') { + const uri = avatar || `${ baseUrl }/avatar/${ text }`; + const image = (avatar || baseUrl) && ( + + ); + return ( + + {initials} + {image} + {this.props.children} + ); + } + + const icon = { + c: 'pound', + p: 'lock', + l: 'account' + }[type]; + + return ( + + + + ); + } +} diff --git a/app/components/banner.js b/app/containers/Banner.js similarity index 99% rename from app/components/banner.js rename to app/containers/Banner.js index 1192500bc..5cc765c39 100644 --- a/app/components/banner.js +++ b/app/containers/Banner.js @@ -30,9 +30,16 @@ export default class Banner extends React.PureComponent { authenticating: PropTypes.bool, offline: PropTypes.bool } - render() { const { connecting, authenticating, offline } = this.props; + + if (offline) { + return ( + + offline... + + ); + } if (connecting) { return ( @@ -48,13 +55,7 @@ export default class Banner extends React.PureComponent { ); } - if (offline) { - return ( - - offline... - - ); - } + return null; } } diff --git a/app/containers/EmojiPicker/CustomEmoji.js b/app/containers/EmojiPicker/CustomEmoji.js new file mode 100644 index 000000000..8215f0ea6 --- /dev/null +++ b/app/containers/EmojiPicker/CustomEmoji.js @@ -0,0 +1,28 @@ +import React from 'react'; +import { ViewPropTypes } from 'react-native'; +import PropTypes from 'prop-types'; +import { CachedImage } from 'react-native-img-cache'; +import { connect } from 'react-redux'; + +@connect(state => ({ + baseUrl: state.settings.Site_Url +})) +export default class CustomEmoji extends React.Component { + static propTypes = { + baseUrl: PropTypes.string.isRequired, + emoji: PropTypes.object.isRequired, + style: ViewPropTypes.style + } + shouldComponentUpdate() { + return false; + } + render() { + const { baseUrl, emoji, style } = this.props; + return ( + + ); + } +} diff --git a/app/containers/EmojiPicker/EmojiCategory.js b/app/containers/EmojiPicker/EmojiCategory.js new file mode 100644 index 000000000..3e3823ba8 --- /dev/null +++ b/app/containers/EmojiPicker/EmojiCategory.js @@ -0,0 +1,71 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { Text, TouchableOpacity, Platform } from 'react-native'; +import { emojify } from 'react-emojione'; +import { responsive } from 'react-native-responsive-ui'; +import { OptimizedFlatList } from 'react-native-optimized-flatlist'; +import styles from './styles'; +import CustomEmoji from './CustomEmoji'; +import scrollPersistTaps from '../../utils/scrollPersistTaps'; + +const emojisPerRow = Platform.OS === 'ios' ? 8 : 9; + +const renderEmoji = (emoji, size) => { + if (emoji.isCustom) { + return ; + } + return ( + + {emojify(`:${ emoji }:`, { output: 'unicode' })} + + ); +}; + + +@responsive +export default class EmojiCategory extends React.Component { + static propTypes = { + emojis: PropTypes.any, + window: PropTypes.any, + onEmojiSelected: PropTypes.func, + emojisPerRow: PropTypes.number, + width: PropTypes.number + }; + constructor(props) { + super(props); + const { width, height } = this.props.window; + + this.size = Math.min(this.props.width || width, height) / (this.props.emojisPerRow || emojisPerRow); + this.emojis = props.emojis; + } + + shouldComponentUpdate() { + return false; + } + + renderItem(emoji, size) { + return ( + this.props.onEmojiSelected(emoji)} + > + {renderEmoji(emoji, size)} + ); + } + + render() { + return ( + (item.isCustom && item.content) || item} + data={this.props.emojis} + renderItem={({ item }) => this.renderItem(item, this.size)} + numColumns={emojisPerRow} + initialNumToRender={45} + getItemLayout={(data, index) => ({ length: this.size, offset: this.size * index, index })} + removeClippedSubviews + {...scrollPersistTaps} + /> + ); + } +} diff --git a/app/containers/EmojiPicker/TabBar.js b/app/containers/EmojiPicker/TabBar.js new file mode 100644 index 000000000..4886006a6 --- /dev/null +++ b/app/containers/EmojiPicker/TabBar.js @@ -0,0 +1,31 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { View, TouchableOpacity, Text } from 'react-native'; +import styles from './styles'; + +export default class TabBar extends React.PureComponent { + static propTypes = { + goToPage: PropTypes.func, + activeTab: PropTypes.number, + tabs: PropTypes.array, + tabEmojiStyle: PropTypes.object + } + + render() { + return ( + + {this.props.tabs.map((tab, i) => ( + this.props.goToPage(i)} + style={styles.tab} + > + {tab} + {this.props.activeTab === i ? : } + + ))} + + ); + } +} diff --git a/app/containers/EmojiPicker/categories.js b/app/containers/EmojiPicker/categories.js new file mode 100644 index 000000000..a95f67cf6 --- /dev/null +++ b/app/containers/EmojiPicker/categories.js @@ -0,0 +1,44 @@ +const list = ['frequentlyUsed', 'custom', 'people', 'nature', 'food', 'activity', 'travel', 'objects', 'symbols', 'flags']; +const tabs = [ + { + tabLabel: '🕒', + category: list[0] + }, + { + tabLabel: '🚀', + category: list[1] + }, + { + tabLabel: '😃', + category: list[2] + }, + { + tabLabel: '🐶', + category: list[3] + }, + { + tabLabel: '🍔', + category: list[4] + }, + { + tabLabel: '⚽', + category: list[5] + }, + { + tabLabel: '🚌', + category: list[6] + }, + { + tabLabel: '💡', + category: list[7] + }, + { + tabLabel: '💛', + category: list[8] + }, + { + tabLabel: '🏁', + category: list[9] + } +]; +export default { list, tabs }; diff --git a/app/containers/EmojiPicker/index.js b/app/containers/EmojiPicker/index.js new file mode 100644 index 000000000..104b496a3 --- /dev/null +++ b/app/containers/EmojiPicker/index.js @@ -0,0 +1,141 @@ +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import { ScrollView } from 'react-native'; +import ScrollableTabView from 'react-native-scrollable-tab-view'; +import _ from 'lodash'; +import { emojify } from 'react-emojione'; +import TabBar from './TabBar'; +import EmojiCategory from './EmojiCategory'; +import styles from './styles'; +import categories from './categories'; +import database from '../../lib/realm'; +import { emojisByCategory } from '../../emojis'; + +const scrollProps = { + keyboardShouldPersistTaps: 'always', + keyboardDismissMode: 'none' +}; + +export default class EmojiPicker extends Component { + static propTypes = { + onEmojiSelected: PropTypes.func, + tabEmojiStyle: PropTypes.object, + emojisPerRow: PropTypes.number, + width: PropTypes.number + }; + + constructor(props) { + super(props); + this.state = { + frequentlyUsed: [], + customEmojis: [] + }; + this.frequentlyUsed = database.objects('frequentlyUsedEmoji').sorted('count', true); + this.customEmojis = database.objects('customEmojis'); + this.updateFrequentlyUsed = this.updateFrequentlyUsed.bind(this); + this.updateCustomEmojis = this.updateCustomEmojis.bind(this); + } + // + // shouldComponentUpdate(nextProps) { + // return false; + // } + + componentDidMount() { + requestAnimationFrame(() => this.setState({ show: true })); + this.frequentlyUsed.addListener(this.updateFrequentlyUsed); + this.customEmojis.addListener(this.updateCustomEmojis); + this.updateFrequentlyUsed(); + this.updateCustomEmojis(); + } + componentWillUnmount() { + this.frequentlyUsed.removeAllListeners(); + this.customEmojis.removeAllListeners(); + } + + onEmojiSelected(emoji) { + if (emoji.isCustom) { + const count = this._getFrequentlyUsedCount(emoji.content); + this._addFrequentlyUsed({ + content: emoji.content, extension: emoji.extension, count, isCustom: true + }); + this.props.onEmojiSelected(`:${ emoji.content }:`); + } else { + const content = emoji; + const count = this._getFrequentlyUsedCount(content); + this._addFrequentlyUsed({ content, count, isCustom: false }); + const shortname = `:${ emoji }:`; + this.props.onEmojiSelected(emojify(shortname, { output: 'unicode' }), shortname); + } + } + + _addFrequentlyUsed = (emoji) => { + database.write(() => { + database.create('frequentlyUsedEmoji', emoji, true); + }); + } + _getFrequentlyUsedCount = (content) => { + const emojiRow = this.frequentlyUsed.filtered('content == $0', content); + return emojiRow.length ? emojiRow[0].count + 1 : 1; + } + updateFrequentlyUsed() { + const frequentlyUsed = _.map(this.frequentlyUsed.slice(), (item) => { + if (item.isCustom) { + return item; + } + return emojify(`${ item.content }`, { output: 'unicode' }); + }); + this.setState({ frequentlyUsed }); + } + + updateCustomEmojis() { + const customEmojis = _.map(this.customEmojis.slice(), item => + ({ content: item.name, extension: item.extension, isCustom: true })); + this.setState({ customEmojis }); + } + + renderCategory(category, i) { + let emojis = []; + if (i === 0) { + emojis = this.state.frequentlyUsed; + } else if (i === 1) { + emojis = this.state.customEmojis; + } else { + emojis = emojisByCategory[category]; + } + return ( + this.onEmojiSelected(emoji)} + style={styles.categoryContainer} + size={this.props.emojisPerRow} + width={this.props.width} + /> + ); + } + + render() { + if (!this.state.show) { + return null; + } + return ( + // + } + contentProps={scrollProps} + > + { + categories.tabs.map((tab, i) => ( + + {this.renderCategory(tab.category, i)} + + )) + } + + // + ); + } +} diff --git a/app/containers/EmojiPicker/styles.js b/app/containers/EmojiPicker/styles.js new file mode 100644 index 000000000..038d11b20 --- /dev/null +++ b/app/containers/EmojiPicker/styles.js @@ -0,0 +1,57 @@ +import { StyleSheet } from 'react-native'; + +export default StyleSheet.create({ + container: { + flex: 1 + }, + tabsContainer: { + height: 45, + flexDirection: 'row', + paddingTop: 5 + }, + tab: { + flex: 1, + alignItems: 'center', + justifyContent: 'center', + paddingBottom: 10 + }, + tabEmoji: { + fontSize: 20, + color: 'black' + }, + activeTabLine: { + position: 'absolute', + left: 0, + right: 0, + height: 2, + backgroundColor: '#007aff', + bottom: 0 + }, + tabLine: { + position: 'absolute', + left: 0, + right: 0, + height: 2, + backgroundColor: 'rgba(0,0,0,0.05)', + bottom: 0 + }, + categoryContainer: { + flex: 1, + alignItems: 'flex-start' + }, + categoryInner: { + flexWrap: 'wrap', + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'flex-start', + flex: 1 + }, + categoryEmoji: { + color: 'black', + backgroundColor: 'transparent', + textAlign: 'center' + }, + customCategoryEmoji: { + margin: 4 + } +}); diff --git a/app/containers/Header.js b/app/containers/Header.js new file mode 100644 index 000000000..277f73fec --- /dev/null +++ b/app/containers/Header.js @@ -0,0 +1,51 @@ +import React from 'react'; +import { View, StyleSheet, Platform } from 'react-native'; +import PropTypes from 'prop-types'; +import SafeAreaView from 'react-native-safe-area-view'; + +let platformContainerStyles; +if (Platform.OS === 'ios') { + platformContainerStyles = { + borderBottomWidth: StyleSheet.hairlineWidth, + borderBottomColor: 'rgba(0, 0, 0, .3)' + }; +} else { + platformContainerStyles = { + shadowColor: 'black', + shadowOpacity: 0.1, + shadowRadius: StyleSheet.hairlineWidth, + shadowOffset: { + height: StyleSheet.hairlineWidth + }, + elevation: 4 + }; +} + +const height = Platform.OS === 'ios' ? 44 : 56; +const backgroundColor = Platform.OS === 'ios' ? '#F7F7F7' : '#FFF'; +const styles = StyleSheet.create({ + container: { + backgroundColor, + ...platformContainerStyles + }, + appBar: { + height, + backgroundColor + } +}); + +export default class Header extends React.PureComponent { + static propTypes = { + subview: PropTypes.object.isRequired + } + + render() { + return ( + + + {this.props.subview} + + + ); + } +} diff --git a/app/containers/MessageActions.js b/app/containers/MessageActions.js new file mode 100644 index 000000000..0a82d50ff --- /dev/null +++ b/app/containers/MessageActions.js @@ -0,0 +1,347 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { Alert, Clipboard, Vibration, Share } from 'react-native'; +import { connect } from 'react-redux'; +import ActionSheet from 'react-native-actionsheet'; +import * as moment from 'moment'; + +import { + deleteRequest, + editInit, + toggleStarRequest, + permalinkRequest, + permalinkClear, + togglePinRequest, + setInput, + actionsHide, + toggleReactionPicker +} from '../actions/messages'; +import { showToast } from '../utils/info'; +import RocketChat from '../lib/rocketchat'; + +@connect( + state => ({ + showActions: state.messages.showActions, + actionMessage: state.messages.actionMessage, + user: state.login.user, + permissions: state.permissions, + permalink: state.messages.permalink, + Message_AllowDeleting: state.settings.Message_AllowDeleting, + Message_AllowDeleting_BlockDeleteInMinutes: state.settings.Message_AllowDeleting_BlockDeleteInMinutes, + Message_AllowEditing: state.settings.Message_AllowEditing, + Message_AllowEditing_BlockEditInMinutes: state.settings.Message_AllowEditing_BlockEditInMinutes, + Message_AllowPinning: state.settings.Message_AllowPinning, + Message_AllowStarring: state.settings.Message_AllowStarring + }), + dispatch => ({ + actionsHide: () => dispatch(actionsHide()), + deleteRequest: message => dispatch(deleteRequest(message)), + editInit: message => dispatch(editInit(message)), + toggleStarRequest: message => dispatch(toggleStarRequest(message)), + permalinkRequest: message => dispatch(permalinkRequest(message)), + permalinkClear: () => dispatch(permalinkClear()), + togglePinRequest: message => dispatch(togglePinRequest(message)), + setInput: message => dispatch(setInput(message)), + toggleReactionPicker: message => dispatch(toggleReactionPicker(message)) + }) +) +export default class MessageActions extends React.Component { + static propTypes = { + actionsHide: PropTypes.func.isRequired, + showActions: PropTypes.bool.isRequired, + room: PropTypes.object, + actionMessage: PropTypes.object, + user: PropTypes.object, + permissions: PropTypes.object.isRequired, + deleteRequest: PropTypes.func.isRequired, + editInit: PropTypes.func.isRequired, + toggleStarRequest: PropTypes.func.isRequired, + permalinkRequest: PropTypes.func.isRequired, + permalinkClear: PropTypes.func.isRequired, + togglePinRequest: PropTypes.func.isRequired, + setInput: PropTypes.func.isRequired, + permalink: PropTypes.string, + toggleReactionPicker: PropTypes.func.isRequired, + Message_AllowDeleting: PropTypes.bool, + Message_AllowDeleting_BlockDeleteInMinutes: PropTypes.number, + Message_AllowEditing: PropTypes.bool, + Message_AllowEditing_BlockEditInMinutes: PropTypes.number, + Message_AllowPinning: PropTypes.bool, + Message_AllowStarring: PropTypes.bool + }; + + constructor(props) { + super(props); + this.state = { + copyPermalink: false, + reply: false, + quote: false + }; + this.handleActionPress = this.handleActionPress.bind(this); + this.options = ['']; + this.setPermissions(this.props.permissions); + } + + async componentWillReceiveProps(nextProps) { + if (nextProps.showActions !== this.props.showActions && nextProps.showActions) { + const { actionMessage } = nextProps; + // Cancel + this.options = ['Cancel']; + this.CANCEL_INDEX = 0; + // Reply + if (!this.isRoomReadOnly()) { + this.options.push('Reply'); + this.REPLY_INDEX = this.options.length - 1; + } + // Edit + if (this.allowEdit(nextProps)) { + this.options.push('Edit'); + this.EDIT_INDEX = this.options.length - 1; + } + // Permalink + this.options.push('Copy Permalink'); + this.PERMALINK_INDEX = this.options.length - 1; + // Copy + this.options.push('Copy Message'); + this.COPY_INDEX = this.options.length - 1; + // Share + this.options.push('Share Message'); + this.SHARE_INDEX = this.options.length - 1; + // Quote + if (!this.isRoomReadOnly()) { + this.options.push('Quote'); + this.QUOTE_INDEX = this.options.length - 1; + } + // Star + if (this.props.Message_AllowStarring) { + this.options.push(actionMessage.starred ? 'Unstar' : 'Star'); + this.STAR_INDEX = this.options.length - 1; + } + // Pin + if (this.props.Message_AllowPinning) { + this.options.push(actionMessage.pinned ? 'Unpin' : 'Pin'); + this.PIN_INDEX = this.options.length - 1; + } + // Reaction + if (!this.isRoomReadOnly() || this.canReactWhenReadOnly()) { + this.options.push('Add Reaction'); + this.REACTION_INDEX = this.options.length - 1; + } + // Delete + if (this.allowDelete(nextProps)) { + this.options.push('Delete'); + this.DELETE_INDEX = this.options.length - 1; + } + setTimeout(() => { + this.ActionSheet.show(); + Vibration.vibrate(50); + }); + } else if (this.props.permalink !== nextProps.permalink && nextProps.permalink) { + // copy permalink + if (this.state.copyPermalink) { + this.setState({ copyPermalink: false }); + await Clipboard.setString(nextProps.permalink); + showToast('Permalink copied to clipboard!'); + this.props.permalinkClear(); + // quote + } else if (this.state.quote) { + this.setState({ quote: false }); + const msg = `[ ](${ nextProps.permalink }) `; + this.props.setInput({ msg }); + + // reply + } else if (this.state.reply) { + this.setState({ reply: false }); + let msg = `[ ](${ nextProps.permalink }) `; + + // if original message wasn't sent by current user and neither from a direct room + if (this.props.user.username !== this.props.actionMessage.u.username && this.props.room.t !== 'd') { + msg += `@${ this.props.actionMessage.u.username } `; + } + this.props.setInput({ msg }); + } + } + } + + componentDidUpdate() { + this.setPermissions(this.props.permissions); + } + + setPermissions() { + const permissions = ['edit-message', 'delete-message', 'force-delete-message']; + const result = RocketChat.hasPermission(permissions, this.props.room.rid); + this.hasEditPermission = result[permissions[0]]; + this.hasDeletePermission = result[permissions[1]]; + this.hasForceDeletePermission = result[permissions[2]]; + } + + isOwn = props => props.actionMessage.u && props.actionMessage.u._id === props.user.id; + + isRoomReadOnly = () => this.props.room.ro; + + canReactWhenReadOnly = () => this.props.room.reactWhenReadOnly; + + allowEdit = (props) => { + if (this.isRoomReadOnly()) { + return false; + } + const editOwn = this.isOwn(props); + const { Message_AllowEditing: isEditAllowed } = this.props; + if (!(this.hasEditPermission || (isEditAllowed && editOwn))) { + return false; + } + const blockEditInMinutes = this.props.Message_AllowEditing_BlockEditInMinutes; + if (blockEditInMinutes) { + let msgTs; + if (props.actionMessage.ts != null) { + msgTs = moment(props.actionMessage.ts); + } + let currentTsDiff; + if (msgTs != null) { + currentTsDiff = moment().diff(msgTs, 'minutes'); + } + return currentTsDiff < blockEditInMinutes; + } + return true; + } + + allowDelete = (props) => { + if (this.isRoomReadOnly()) { + return false; + } + const deleteOwn = this.isOwn(props); + const { Message_AllowDeleting: isDeleteAllowed } = this.props; + if (!(this.hasDeletePermission || (isDeleteAllowed && deleteOwn) || this.hasForceDeletePermission)) { + return false; + } + if (this.hasForceDeletePermission) { + return true; + } + const blockDeleteInMinutes = this.props.Message_AllowDeleting_BlockDeleteInMinutes; + if (blockDeleteInMinutes != null && blockDeleteInMinutes !== 0) { + let msgTs; + if (props.actionMessage.ts != null) { + msgTs = moment(props.actionMessage.ts); + } + let currentTsDiff; + if (msgTs != null) { + currentTsDiff = moment().diff(msgTs, 'minutes'); + } + return currentTsDiff < blockDeleteInMinutes; + } + return true; + } + + handleDelete() { + Alert.alert( + 'Are you sure?', + 'You will not be able to recover this message!', + [ + { + text: 'Cancel', + style: 'cancel' + }, + { + text: 'Yes, delete it!', + style: 'destructive', + onPress: () => this.props.deleteRequest(this.props.actionMessage) + } + ], + { cancelable: false } + ); + } + + handleEdit() { + const { _id, msg, rid } = this.props.actionMessage; + this.props.editInit({ _id, msg, rid }); + } + + handleCopy = async() => { + await Clipboard.setString(this.props.actionMessage.msg); + showToast('Copied to clipboard!'); + } + + handleShare = async() => { + Share.share({ + message: this.props.actionMessage.msg.content.replace(/<(?:.|\n)*?>/gm, '') + }); + }; + + handleStar() { + this.props.toggleStarRequest(this.props.actionMessage); + } + + handlePermalink() { + this.setState({ copyPermalink: true }); + this.props.permalinkRequest(this.props.actionMessage); + } + + handlePin() { + this.props.togglePinRequest(this.props.actionMessage); + } + + handleReply() { + this.setState({ reply: true }); + this.props.permalinkRequest(this.props.actionMessage); + } + + handleQuote() { + this.setState({ quote: true }); + this.props.permalinkRequest(this.props.actionMessage); + } + + handleReaction() { + this.props.toggleReactionPicker(this.props.actionMessage); + } + + handleActionPress = (actionIndex) => { + switch (actionIndex) { + case this.REPLY_INDEX: + this.handleReply(); + break; + case this.EDIT_INDEX: + this.handleEdit(); + break; + case this.PERMALINK_INDEX: + this.handlePermalink(); + break; + case this.COPY_INDEX: + this.handleCopy(); + break; + case this.SHARE_INDEX: + this.handleShare(); + break; + case this.QUOTE_INDEX: + this.handleQuote(); + break; + case this.STAR_INDEX: + this.handleStar(); + break; + case this.PIN_INDEX: + this.handlePin(); + break; + case this.REACTION_INDEX: + this.handleReaction(); + break; + case this.DELETE_INDEX: + this.handleDelete(); + break; + default: + break; + } + this.props.actionsHide(); + } + + render() { + return ( + this.ActionSheet = o} + title='Messages actions' + options={this.options} + cancelButtonIndex={this.CANCEL_INDEX} + destructiveButtonIndex={this.DELETE_INDEX} + onPress={this.handleActionPress} + /> + ); + } +} diff --git a/app/containers/MessageBox/EmojiKeyboard.js b/app/containers/MessageBox/EmojiKeyboard.js new file mode 100644 index 000000000..9a6cb8b91 --- /dev/null +++ b/app/containers/MessageBox/EmojiKeyboard.js @@ -0,0 +1,23 @@ +import React from 'react'; +import { View } from 'react-native'; +import { KeyboardRegistry } from 'react-native-keyboard-input'; +import { Provider } from 'react-redux'; +import store from '../../lib/createStore'; +import EmojiPicker from '../EmojiPicker'; +import styles from './styles'; + +export default class EmojiKeyboard extends React.PureComponent { + onEmojiSelected = (emoji) => { + KeyboardRegistry.onItemSelected('EmojiKeyboard', { emoji }); + } + render() { + return ( + + + this.onEmojiSelected(emoji)} /> + + + ); + } +} +KeyboardRegistry.registerKeyboard('EmojiKeyboard', () => EmojiKeyboard); diff --git a/app/containers/MessageBox/Recording.js b/app/containers/MessageBox/Recording.js new file mode 100644 index 000000000..10e32b898 --- /dev/null +++ b/app/containers/MessageBox/Recording.js @@ -0,0 +1,127 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { View, SafeAreaView, Platform, PermissionsAndroid, Text } from 'react-native'; +import { AudioRecorder, AudioUtils } from 'react-native-audio'; +import Icon from 'react-native-vector-icons/MaterialIcons'; +import styles from './styles'; + +export const _formatTime = function(seconds) { + let minutes = Math.floor(seconds / 60); + seconds %= 60; + if (minutes < 10) { minutes = `0${ minutes }`; } + if (seconds < 10) { seconds = `0${ seconds }`; } + return `${ minutes }:${ seconds }`; +}; + +export default class extends React.PureComponent { + static propTypes = { + onFinish: PropTypes.func.isRequired + } + + static async permission() { + if (Platform.OS !== 'android') { + return true; + } + + const rationale = { + title: 'Microphone Permission', + message: 'Rocket Chat needs access to your microphone so you can send audio message.' + }; + + const result = await PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.RECORD_AUDIO, rationale); + return result === true || result === PermissionsAndroid.RESULTS.GRANTED; + } + + constructor() { + super(); + + this.recordingCanceled = false; + this.state = { + currentTime: '00:00' + }; + } + + componentDidMount() { + const audioPath = `${ AudioUtils.CachesDirectoryPath }/${ Date.now() }.aac`; + + AudioRecorder.prepareRecordingAtPath(audioPath, { + SampleRate: 22050, + Channels: 1, + AudioQuality: 'Low', + AudioEncoding: 'aac' + }); + + AudioRecorder.onProgress = (data) => { + this.setState({ + currentTime: _formatTime(Math.floor(data.currentTime)) + }); + }; + // + AudioRecorder.onFinished = (data) => { + if (!this.recordingCanceled && Platform.OS === 'ios') { + this._finishRecording(data.status === 'OK', data.audioFileURL); + } + }; + AudioRecorder.startRecording(); + } + + _finishRecording(didSucceed, filePath) { + if (!didSucceed) { + return this.props.onFinish && this.props.onFinish(didSucceed); + } + + const path = filePath.startsWith('file://') ? filePath.split('file://')[1] : filePath; + const fileInfo = { + type: 'audio/aac', + store: 'Uploads', + path + }; + return this.props.onFinish && this.props.onFinish(fileInfo); + } + + finishAudioMessage = async() => { + try { + const filePath = await AudioRecorder.stopRecording(); + if (Platform.OS === 'android') { + this._finishRecording(true, filePath); + } + } catch (err) { + this._finishRecording(false); + console.error(err); + } + } + + cancelAudioMessage = async() => { + this.recordingCanceled = true; + await AudioRecorder.stopRecording(); + return this._finishRecording(false); + } + + render() { + return ( + + + + {this.state.currentTime} + + + ); + } +} diff --git a/app/containers/MessageBox/index.js b/app/containers/MessageBox/index.js new file mode 100644 index 000000000..d88dcaa95 --- /dev/null +++ b/app/containers/MessageBox/index.js @@ -0,0 +1,523 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { View, TextInput, FlatList, Text, TouchableOpacity } from 'react-native'; +import Icon from 'react-native-vector-icons/MaterialIcons'; +import ImagePicker from 'react-native-image-picker'; +import { connect } from 'react-redux'; +import { emojify } from 'react-emojione'; +import { KeyboardAccessoryView } from 'react-native-keyboard-input'; +import { isIphoneX } from 'react-native-iphone-x-helper'; + +import { userTyping, layoutAnimation } from '../../actions/room'; +import RocketChat from '../../lib/rocketchat'; +import { editRequest, editCancel, clearInput } from '../../actions/messages'; +import styles from './styles'; +import MyIcon from '../icons'; +import database from '../../lib/realm'; +import Avatar from '../Avatar'; +import CustomEmoji from '../EmojiPicker/CustomEmoji'; +import { emojis } from '../../emojis'; +import Recording from './Recording'; +import './EmojiKeyboard'; + + +const MENTIONS_TRACKING_TYPE_USERS = '@'; +const MENTIONS_TRACKING_TYPE_EMOJIS = ':'; + +const onlyUnique = function onlyUnique(value, index, self) { + return self.indexOf(({ _id }) => value._id === _id) === index; +}; + +@connect(state => ({ + room: state.room, + message: state.messages.message, + editing: state.messages.editing, + baseUrl: state.settings.Site_Url || state.server ? state.server.server : '' +}), dispatch => ({ + editCancel: () => dispatch(editCancel()), + editRequest: message => dispatch(editRequest(message)), + typing: status => dispatch(userTyping(status)), + clearInput: () => dispatch(clearInput()), + layoutAnimation: () => dispatch(layoutAnimation()) +})) +export default class MessageBox extends React.PureComponent { + static propTypes = { + onSubmit: PropTypes.func.isRequired, + rid: PropTypes.string.isRequired, + editCancel: PropTypes.func.isRequired, + editRequest: PropTypes.func.isRequired, + baseUrl: PropTypes.string.isRequired, + message: PropTypes.object, + editing: PropTypes.bool, + typing: PropTypes.func, + clearInput: PropTypes.func, + layoutAnimation: PropTypes.func + } + + constructor(props) { + super(props); + this.state = { + text: '', + mentions: [], + showMentionsContainer: false, + showEmojiKeyboard: false, + recording: false + }; + this.users = []; + this.rooms = []; + this.emojis = []; + this.customEmojis = []; + this._onEmojiSelected = this._onEmojiSelected.bind(this); + } + componentWillReceiveProps(nextProps) { + if (this.props.message !== nextProps.message && nextProps.message.msg) { + this.setState({ text: nextProps.message.msg }); + this.component.focus(); + } else if (!nextProps.message) { + this.setState({ text: '' }); + } + } + + onChangeText(text) { + this.setState({ text }); + + requestAnimationFrame(() => { + const { start, end } = this.component._lastNativeSelection; + + const cursor = Math.max(start, end); + + const lastNativeText = this.component._lastNativeText; + + const regexp = /(#|@|:)([a-z0-9._-]+)$/im; + + const result = lastNativeText.substr(0, cursor).match(regexp); + + if (!result) { + return this.stopTrackingMention(); + } + const [, lastChar, name] = result; + + this.identifyMentionKeyword(name, lastChar); + }); + } + + onKeyboardResigned() { + this.closeEmoji(); + } + + get leftButtons() { + const { editing } = this.props; + if (editing) { + return ( this.editCancel()} + />); + } + return !this.state.showEmojiKeyboard ? ( this.openEmoji()} + accessibilityLabel='Open emoji selector' + accessibilityTraits='button' + name='mood' + />) : ( this.closeEmoji()} + style={styles.actionButtons} + accessibilityLabel='Close emoji selector' + accessibilityTraits='button' + name='keyboard' + />); + } + get rightButtons() { + const icons = []; + + if (this.state.text) { + icons.push( this.submit(this.state.text)} + />); + return icons; + } + icons.push( this.recordAudioMessage()} + />); + icons.push( this.addFile()} + />); + return icons; + } + + addFile = () => { + const options = { + maxHeight: 1960, + maxWidth: 1960, + quality: 0.8, + customButtons: [{ + name: 'import', title: 'Import File From' + }] + }; + ImagePicker.showImagePicker(options, (response) => { + if (response.didCancel) { + console.log('User cancelled image picker'); + } else if (response.error) { + console.log('ImagePicker Error: ', response.error); + } else if (response.customButton) { + console.log('User tapped custom button: ', response.customButton); + } else { + const fileInfo = { + name: response.fileName, + size: response.fileSize, + type: response.type || 'image/jpeg', + // description: '', + store: 'Uploads' + }; + RocketChat.sendFileMessage(this.props.rid, fileInfo, response.data); + } + }); + } + editCancel() { + this.props.editCancel(); + this.setState({ text: '' }); + } + async openEmoji() { + await this.setState({ + showEmojiKeyboard: true + }); + } + + async recordAudioMessage() { + const recording = await Recording.permission(); + this.setState({ recording }); + } + + finishAudioMessage = async(fileInfo) => { + if (fileInfo) { + RocketChat.sendFileMessage(this.props.rid, fileInfo); + } + this.setState({ + recording: false + }); + } + + closeEmoji() { + this.setState({ showEmojiKeyboard: false }); + } + + submit(message) { + this.setState({ text: '' }); + this.closeEmoji(); + this.stopTrackingMention(); + this.props.typing(false); + if (message.trim() === '') { + return; + } + // if is editing a message + const { editing } = this.props; + if (editing) { + const { _id, rid } = this.props.message; + this.props.editRequest({ _id, msg: message, rid }); + } else { + // if is submiting a new message + this.props.onSubmit(message); + } + this.props.clearInput(); + } + + _getFixedMentions(keyword) { + if ('all'.indexOf(keyword) !== -1) { + this.users = [{ _id: -1, username: 'all', desc: 'all' }, ...this.users]; + } + if ('here'.indexOf(keyword) !== -1) { + this.users = [{ _id: -2, username: 'here', desc: 'active users' }, ...this.users]; + } + } + + async _getUsers(keyword) { + this.users = database.objects('users'); + if (keyword) { + this.users = this.users.filtered('username CONTAINS[c] $0', keyword); + } + this._getFixedMentions(keyword); + this.setState({ mentions: this.users.slice() }); + + const usernames = []; + + if (keyword && this.users.length > 7) { + return; + } + + this.users.forEach(user => usernames.push(user.username)); + + if (this.oldPromise) { + this.oldPromise(); + } + try { + const results = await Promise.race([ + RocketChat.spotlight(keyword, usernames, { users: true }), + new Promise((resolve, reject) => (this.oldPromise = reject)) + ]); + database.write(() => { + results.users.forEach((user) => { + database.create('users', user, true); + }); + }); + } catch (e) { + console.log('spotlight canceled'); + } finally { + delete this.oldPromise; + this.users = database.objects('users').filtered('username CONTAINS[c] $0', keyword).slice(); + this._getFixedMentions(keyword); + this.setState({ mentions: this.users }); + } + } + + async _getRooms(keyword = '') { + this.roomsCache = this.roomsCache || []; + this.rooms = database.objects('subscriptions') + .filtered('t != $0', 'd'); + if (keyword) { + this.rooms = this.rooms.filtered('name CONTAINS[c] $0', keyword); + } + + const rooms = []; + this.rooms.forEach(room => rooms.push(room)); + + this.roomsCache.forEach((room) => { + if (room.name && room.name.toUpperCase().indexOf(keyword.toUpperCase()) !== -1) { + rooms.push(room); + } + }); + + if (rooms.length > 3) { + this.setState({ mentions: rooms }); + return; + } + + if (this.oldPromise) { + this.oldPromise(); + } + + try { + const results = await Promise.race([ + RocketChat.spotlight(keyword, [...rooms, ...this.roomsCache].map(r => r.name), { rooms: true }), + new Promise((resolve, reject) => (this.oldPromise = reject)) + ]); + this.roomsCache = [...this.roomsCache, ...results.rooms].filter(onlyUnique); + this.setState({ mentions: [...rooms.slice(), ...results.rooms] }); + } catch (e) { + console.log('spotlight canceled'); + } finally { + delete this.oldPromise; + } + } + + _getEmojis(keyword) { + if (keyword) { + this.customEmojis = database.objects('customEmojis').filtered('name CONTAINS[c] $0', keyword).slice(0, 4); + this.emojis = emojis.filter(emoji => emoji.indexOf(keyword) !== -1).slice(0, 4); + const mergedEmojis = [...this.customEmojis, ...this.emojis]; + this.setState({ mentions: mergedEmojis }); + } + } + + stopTrackingMention() { + this.setState({ + showMentionsContainer: false, + mentions: [], + trackingType: '' + }); + this.users = []; + this.rooms = []; + this.customEmojis = []; + this.emojis = []; + } + + identifyMentionKeyword(keyword, type) { + if (!this.state.showMentionsContainer) { + this.props.layoutAnimation(); + } + this.setState({ + showMentionsContainer: true, + showEmojiKeyboard: false, + trackingType: type + }); + this.updateMentions(keyword, type); + } + + updateMentions = (keyword, type) => { + if (type === MENTIONS_TRACKING_TYPE_USERS) { + this._getUsers(keyword); + } else if (type === MENTIONS_TRACKING_TYPE_EMOJIS) { + this._getEmojis(keyword); + } else { + this._getRooms(keyword); + } + } + + _onPressMention(item) { + const msg = this.component._lastNativeText; + + const { start, end } = this.component._lastNativeSelection; + + const cursor = Math.max(start, end); + + const regexp = /([a-z0-9._-]+)$/im; + + const result = msg.substr(0, cursor).replace(regexp, ''); + const mentionName = this.state.trackingType === MENTIONS_TRACKING_TYPE_EMOJIS ? + `${ item.name || item }:` : (item.username || item.name); + const text = `${ result }${ mentionName } ${ msg.slice(cursor) }`; + this.component.setNativeProps({ text }); + this.setState({ text }); + this.component.focus(); + requestAnimationFrame(() => this.stopTrackingMention()); + } + _onEmojiSelected(keyboardId, params) { + const { text } = this.state; + const { emoji } = params; + let newText = ''; + + // if messagebox has an active cursor + if (this.component._lastNativeSelection) { + const { start, end } = this.component._lastNativeSelection; + const cursor = Math.max(start, end); + newText = `${ text.substr(0, cursor) }${ emoji }${ text.substr(cursor) }`; + } else { + // if messagebox doesn't have a cursor, just append selected emoji + newText = `${ text }${ emoji }`; + } + this.component.setNativeProps({ text: newText }); + this.setState({ text: newText }); + } + renderFixedMentionItem = item => ( + this._onPressMention(item)} + > + {item.username} + Notify {item.desc} in this room + + ) + renderMentionEmoji = (item) => { + if (item.name) { + return ( + + ); + } + return ( + + {emojify(`:${ item }:`, { output: 'unicode' })} + + ); + } + renderMentionItem = (item) => { + if (item.username === 'all' || item.username === 'here') { + return this.renderFixedMentionItem(item); + } + return ( + this._onPressMention(item)} + > + {this.state.trackingType === MENTIONS_TRACKING_TYPE_EMOJIS ? + [ + this.renderMentionEmoji(item), + :{ item.name || item }: + ] + : [ + , + { item.username || item.name } + ] + } + + ); + } + renderMentions = () => ( + this.renderMentionItem(item)} + keyExtractor={item => item._id || item} + keyboardShouldPersistTaps='always' + /> + ); + + renderContent() { + if (this.state.recording) { + return (); + } + return ( + [ + this.renderMentions(), + + {this.leftButtons} + this.component = component} + style={styles.textBoxInput} + returnKeyType='default' + keyboardType='twitter' + blurOnSubmit={false} + placeholder='New Message' + onChangeText={text => this.onChangeText(text)} + value={this.state.text} + underlineColorAndroid='transparent' + defaultValue='' + multiline + placeholderTextColor='#9EA2A8' + /> + {this.rightButtons} + + ] + ); + } + + render() { + return ( + [ + this.renderContent()} + kbInputRef={this.component} + kbComponent={this.state.showEmojiKeyboard ? 'EmojiKeyboard' : null} + onKeyboardResigned={() => this.onKeyboardResigned()} + onItemSelected={this._onEmojiSelected} + trackInteractive + // revealKeyboardInteractive + requiresSameParentToManageScrollView + />, + isIphoneX() ? : null + ] + ); + } +} diff --git a/app/containers/MessageBox/styles.js b/app/containers/MessageBox/styles.js new file mode 100644 index 000000000..5c0388bc1 --- /dev/null +++ b/app/containers/MessageBox/styles.js @@ -0,0 +1,85 @@ +import { StyleSheet, Platform } from 'react-native'; + +const MENTION_HEIGHT = 50; + +export default StyleSheet.create({ + textBox: { + backgroundColor: '#fff', + flex: 0, + alignItems: 'center', + borderTopWidth: 1, + borderTopColor: '#D8D8D8', + zIndex: 2 + }, + textArea: { + flexDirection: 'row', + alignItems: 'center', + flexGrow: 0, + backgroundColor: '#fff' + }, + textBoxInput: { + textAlignVertical: 'center', + maxHeight: 120, + flexGrow: 1, + width: 1, + paddingTop: 15, + paddingBottom: 15, + paddingLeft: 0, + paddingRight: 0 + }, + editing: { + backgroundColor: '#fff5df' + }, + actionButtons: { + color: '#2F343D', + fontSize: 20, + textAlign: 'center', + padding: 15, + paddingHorizontal: 21, + flex: 0 + }, + mentionList: { + maxHeight: MENTION_HEIGHT * 4, + borderTopColor: '#ECECEC', + borderTopWidth: 1, + paddingHorizontal: 5, + backgroundColor: '#fff' + }, + mentionItem: { + height: MENTION_HEIGHT, + backgroundColor: '#F7F8FA', + borderBottomWidth: 1, + borderBottomColor: '#ECECEC', + flexDirection: 'row', + alignItems: 'center' + }, + mentionItemCustomEmoji: { + margin: 8, + width: 30, + height: 30 + }, + mentionItemEmoji: { + width: 46, + height: 36, + fontSize: Platform.OS === 'ios' ? 30 : 25, + textAlign: 'center' + }, + fixedMentionAvatar: { + fontWeight: 'bold', + textAlign: 'center', + width: 46 + }, + emojiKeyboardContainer: { + flex: 1, + borderTopColor: '#ECECEC', + borderTopWidth: 1 + }, + iphoneXArea: { + height: 50, + backgroundColor: '#fff', + position: 'absolute', + bottom: 0, + left: 0, + right: 0 + } +}); diff --git a/app/containers/MessageErrorActions.js b/app/containers/MessageErrorActions.js new file mode 100644 index 000000000..4f3439fae --- /dev/null +++ b/app/containers/MessageErrorActions.js @@ -0,0 +1,76 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { connect } from 'react-redux'; +import ActionSheet from 'react-native-actionsheet'; + +import { errorActionsHide } from '../actions/messages'; +import RocketChat from '../lib/rocketchat'; +import database from '../lib/realm'; + +@connect( + state => ({ + showErrorActions: state.messages.showErrorActions, + actionMessage: state.messages.actionMessage + }), + dispatch => ({ + errorActionsHide: () => dispatch(errorActionsHide()) + }) +) +export default class MessageErrorActions extends React.Component { + static propTypes = { + errorActionsHide: PropTypes.func.isRequired, + showErrorActions: PropTypes.bool.isRequired, + actionMessage: PropTypes.object + }; + + constructor(props) { + super(props); + this.handleActionPress = this.handleActionPress.bind(this); + this.options = ['Cancel', 'Delete', 'Resend']; + this.CANCEL_INDEX = 0; + this.DELETE_INDEX = 1; + this.RESEND_INDEX = 2; + } + + componentWillReceiveProps(nextProps) { + if (nextProps.showErrorActions !== this.props.showErrorActions && nextProps.showErrorActions) { + this.ActionSheet.show(); + } + } + + handleResend = () => RocketChat.resendMessage(this.props.actionMessage._id); + + handleDelete = () => { + database.write(() => { + const msg = database.objects('messages').filtered('_id = $0', this.props.actionMessage._id); + database.delete(msg); + }); + } + + handleActionPress = (actionIndex) => { + switch (actionIndex) { + case this.RESEND_INDEX: + this.handleResend(); + break; + case this.DELETE_INDEX: + this.handleDelete(); + break; + default: + break; + } + this.props.errorActionsHide(); + } + + render() { + return ( + this.ActionSheet = o} + title='Messages actions' + options={this.options} + cancelButtonIndex={this.CANCEL_INDEX} + destructiveButtonIndex={this.DELETE_INDEX} + onPress={this.handleActionPress} + /> + ); + } +} diff --git a/app/containers/Routes.js b/app/containers/Routes.js new file mode 100644 index 000000000..067327970 --- /dev/null +++ b/app/containers/Routes.js @@ -0,0 +1,58 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import { bindActionCreators } from 'redux'; +import { connect } from 'react-redux'; +import SplashScreen from 'react-native-splash-screen'; +import { appInit } from '../actions'; + +import AuthRoutes from './routes/AuthRoutes'; +import PublicRoutes from './routes/PublicRoutes'; +import * as NavigationService from './routes/NavigationService'; + +@connect( + state => ({ + login: state.login, + app: state.app, + background: state.app.background + }), + dispatch => bindActionCreators({ + appInit + }, dispatch) +) +export default class Routes extends React.Component { + static propTypes = { + login: PropTypes.object.isRequired, + app: PropTypes.object.isRequired, + appInit: PropTypes.func.isRequired + } + + componentDidMount() { + if (this.props.app.ready) { + return SplashScreen.hide(); + } + this.props.appInit(); + } + + componentWillReceiveProps(nextProps) { + if (nextProps.app.ready && this.props.app.ready !== nextProps.app.ready) { + SplashScreen.hide(); + } + } + + componentDidUpdate() { + NavigationService.setNavigator(this.navigator); + } + + render() { + const { login } = this.props; + + if (this.props.app.starting) { + return null; + } + + if (!login.token || login.isRegistering) { + return ( this.navigator = nav} />); + } + return ( this.navigator = nav} />); + } +} diff --git a/app/containers/Sidebar.js b/app/containers/Sidebar.js new file mode 100644 index 000000000..9e9122751 --- /dev/null +++ b/app/containers/Sidebar.js @@ -0,0 +1,135 @@ +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import { ScrollView, Text, View, StyleSheet, FlatList, TouchableHighlight } from 'react-native'; +import { connect } from 'react-redux'; + +import database from '../lib/realm'; +import { setServer, gotoAddServer } from '../actions/server'; +import { logout } from '../actions/login'; + +const styles = StyleSheet.create({ + scrollView: { + paddingTop: 20 + }, + imageContainer: { + width: '100%', + alignItems: 'center' + }, + image: { + width: 200, + height: 200, + borderRadius: 100 + }, + serverTitle: { + fontSize: 16, + color: 'grey', + padding: 10, + width: '100%' + }, + serverItem: { + backgroundColor: 'white', + padding: 10, + flex: 1 + }, + selectedServer: { + backgroundColor: '#eeeeee' + } +}); +const keyExtractor = item => item.id; +@connect(state => ({ + server: state.server.server +}), dispatch => ({ + selectServer: server => dispatch(setServer(server)), + logout: () => dispatch(logout()), + gotoAddServer: () => dispatch(gotoAddServer()) +})) +export default class Sidebar extends Component { + static propTypes = { + server: PropTypes.string.isRequired, + selectServer: PropTypes.func.isRequired, + navigation: PropTypes.object.isRequired, + logout: PropTypes.func.isRequired, + gotoAddServer: PropTypes.func.isRequired + } + + constructor(props) { + super(props); + this.state = { servers: [] }; + } + + componentDidMount() { + database.databases.serversDB.addListener('change', this.updateState); + this.setState(this.getState()); + } + + componentWillUnmount() { + database.databases.serversDB.removeListener('change', this.updateState); + } + + onItemPress = ({ route, focused }) => { + this.props.navigation.navigate({ key: 'DrawerClose', routeName: 'DrawerClose' }); + if (!focused) { + this.props.navigation.navigate(route.routeName, undefined); + } + } + + onPressItem = (item) => { + this.props.selectServer(item.id); + this.props.navigation.navigate({ key: 'DrawerClose', routeName: 'DrawerClose' }); + } + + getState = () => ({ + servers: database.databases.serversDB.objects('servers') + }) + + updateState = () => { + this.setState(this.getState()); + } + + renderItem = ({ item, separators }) => ( + + { this.onPressItem(item); }} + > + + + {item.id} + + + + ); + + render() { + return ( + + + + { this.props.logout(); }} + > + + + Logout + + + + { this.props.gotoAddServer(); }} + > + + + Add Server + + + + + + ); + } +} diff --git a/app/containers/TextInput.js b/app/containers/TextInput.js new file mode 100644 index 000000000..3abf75459 --- /dev/null +++ b/app/containers/TextInput.js @@ -0,0 +1,88 @@ +import React from 'react'; +import { View, StyleSheet, Text, TextInput } from 'react-native'; +import PropTypes from 'prop-types'; + +import Icon from 'react-native-vector-icons/FontAwesome'; + +import sharedStyles from '../views/Styles'; +import { COLOR_DANGER } from '../constants/colors'; + +const styles = StyleSheet.create({ + inputContainer: { + marginBottom: 20 + }, + label: { + marginBottom: 4, + fontSize: 16 + }, + input: { + paddingTop: 12, + paddingBottom: 12, + paddingHorizontal: 10, + borderWidth: 2, + borderRadius: 2, + backgroundColor: 'white', + borderColor: 'rgba(0,0,0,.15)', + color: 'black' + }, + labelError: { + color: COLOR_DANGER + }, + inputError: { + color: COLOR_DANGER, + borderColor: COLOR_DANGER + }, + wrap: { + flex: 1, + position: 'relative' + }, + icon: { + position: 'absolute', + right: 0, + padding: 10, + color: 'rgba(0,0,0,.45)' + } +}); + + +export default class RCTextInput extends React.PureComponent { + static propTypes = { + label: PropTypes.string, + error: PropTypes.object, + secureTextEntry: PropTypes.bool + } + static defaultProps = { + error: {} + } + state = { + showPassword: false + } + + get icon() { return ; } + + tooglePassword = () => this.setState({ showPassword: !this.state.showPassword }) + + render() { + const { + label, error, secureTextEntry, ...inputProps + } = this.props; + const { showPassword } = this.state; + return ( + + { label && {label} } + + + {secureTextEntry && this.icon} + + {error.error && {error.reason}} + + ); + } +} diff --git a/app/containers/Typing.js b/app/containers/Typing.js new file mode 100644 index 000000000..0e2db6e1f --- /dev/null +++ b/app/containers/Typing.js @@ -0,0 +1,42 @@ +import React from 'react'; + +import PropTypes from 'prop-types'; +import { StyleSheet, Text, Keyboard } from 'react-native'; +import { connect } from 'react-redux'; + +const styles = StyleSheet.create({ + typing: { + + transform: [{ scaleY: -1 }], + fontWeight: 'bold', + paddingHorizontal: 15, + height: 25 + } +}); + +@connect(state => ({ + username: state.login.user && state.login.user.username, + usersTyping: state.room.usersTyping +})) + +export default class Typing extends React.Component { + shouldComponentUpdate(nextProps) { + return this.props.usersTyping.join() !== nextProps.usersTyping.join(); + } + onPress = () => { + Keyboard.dismiss(); + } + get usersTyping() { + const users = this.props.usersTyping.filter(_username => this.props.username !== _username); + return users.length ? `${ users.join(' ,') } ${ users.length > 1 ? 'are' : 'is' } typing` : ''; + } + render() { + return ( this.onPress()}>{this.usersTyping}); + } +} + + +Typing.propTypes = { + username: PropTypes.string, + usersTyping: PropTypes.array +}; diff --git a/app/containers/icons.js b/app/containers/icons.js new file mode 100644 index 000000000..236466031 --- /dev/null +++ b/app/containers/icons.js @@ -0,0 +1,4 @@ +import { createIconSetFromIcoMoon } from 'react-native-vector-icons'; +import iconConfig from '../icons.json'; + +export default createIconSetFromIcoMoon(iconConfig); diff --git a/app/containers/message/Audio.js b/app/containers/message/Audio.js new file mode 100644 index 000000000..d9db162a2 --- /dev/null +++ b/app/containers/message/Audio.js @@ -0,0 +1,162 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { View, StyleSheet, TouchableOpacity, Text, Easing } from 'react-native'; +import Video from 'react-native-video'; +import Icon from 'react-native-vector-icons/MaterialIcons'; +import Slider from 'react-native-slider'; +import Markdown from './Markdown'; + + +const styles = StyleSheet.create({ + audioContainer: { + flex: 1, + flexDirection: 'row', + justifyContent: 'center', + alignItems: 'center', + height: 50, + margin: 5, + backgroundColor: '#eee', + borderRadius: 6 + }, + playPauseButton: { + width: 50, + alignItems: 'center', + backgroundColor: 'transparent', + borderRightColor: '#ccc', + borderRightWidth: 1 + }, + playPauseIcon: { + color: '#ccc', + backgroundColor: 'transparent' + }, + progressContainer: { + flex: 1, + justifyContent: 'center', + height: '100%', + marginHorizontal: 10 + }, + label: { + color: '#888', + fontSize: 10 + }, + currentTime: { + position: 'absolute', + left: 0, + bottom: 2 + }, + duration: { + position: 'absolute', + right: 0, + bottom: 2 + } +}); + +const formatTime = (t = 0, duration = 0) => { + const time = Math.min( + Math.max(t, 0), + duration + ); + const formattedMinutes = Math.floor(time / 60).toFixed(0).padStart(2, 0); + const formattedSeconds = Math.floor(time % 60).toFixed(0).padStart(2, 0); + return `${ formattedMinutes }:${ formattedSeconds }`; +}; + +export default class Audio extends React.PureComponent { + static propTypes = { + file: PropTypes.object.isRequired, + baseUrl: PropTypes.string.isRequired, + user: PropTypes.object.isRequired + } + + constructor(props) { + super(props); + this.onLoad = this.onLoad.bind(this); + this.onProgress = this.onProgress.bind(this); + this.onEnd = this.onEnd.bind(this); + const { baseUrl, file, user } = props; + this.state = { + currentTime: 0, + duration: 0, + paused: true, + uri: `${ baseUrl }${ file.audio_url }?rc_uid=${ user.id }&rc_token=${ user.token }` + }; + } + + onLoad(data) { + this.setState({ duration: data.duration > 0 ? data.duration : 0 }); + } + + onProgress(data) { + if (data.currentTime < this.state.duration) { + this.setState({ currentTime: data.currentTime }); + } + } + + onEnd() { + this.setState({ paused: true, currentTime: 0 }); + requestAnimationFrame(() => { + this.player.seek(0); + }); + } + + getCurrentTime() { + return formatTime(this.state.currentTime, this.state.duration); + } + + getDuration() { + return formatTime(this.state.duration); + } + + togglePlayPause() { + this.setState({ paused: !this.state.paused }); + } + + render() { + const { uri, paused } = this.state; + const { description } = this.props.file; + return ( + + + + + + ); + } +} diff --git a/app/containers/message/Emoji.js b/app/containers/message/Emoji.js new file mode 100644 index 000000000..edbcd470c --- /dev/null +++ b/app/containers/message/Emoji.js @@ -0,0 +1,26 @@ +import React from 'react'; +import { Text, ViewPropTypes } from 'react-native'; +import PropTypes from 'prop-types'; +import { emojify } from 'react-emojione'; +import CustomEmoji from '../EmojiPicker/CustomEmoji'; + +export default class Emoji extends React.PureComponent { + static propTypes = { + content: PropTypes.string, + standardEmojiStyle: Text.propTypes.style, + customEmojiStyle: ViewPropTypes.style, + customEmojis: PropTypes.object.isRequired + }; + render() { + const { + content, standardEmojiStyle, customEmojiStyle, customEmojis + } = this.props; + const parsedContent = content.replace(/^:|:$/g, ''); + const emojiExtension = customEmojis[parsedContent]; + if (emojiExtension) { + const emoji = { extension: emojiExtension, content: parsedContent }; + return ; + } + return { emojify(`${ content }`, { output: 'unicode' }) }; + } +} diff --git a/app/containers/message/Image.js b/app/containers/message/Image.js new file mode 100644 index 000000000..942676dcc --- /dev/null +++ b/app/containers/message/Image.js @@ -0,0 +1,86 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import { CachedImage } from 'react-native-img-cache'; +import { Text, TouchableOpacity, View, StyleSheet } from 'react-native'; +import PhotoModal from './PhotoModal'; + +const styles = StyleSheet.create({ + button: { + flex: 1, + flexDirection: 'column', + height: 320, + borderColor: '#ccc', + borderWidth: 1, + borderRadius: 6 + }, + image: { + flex: 1, + height: undefined, + width: undefined, + resizeMode: 'contain' + }, + labelContainer: { + height: 62, + alignItems: 'center', + justifyContent: 'center' + }, + imageName: { + fontSize: 12, + alignSelf: 'center', + fontStyle: 'italic' + }, + message: { + alignSelf: 'center', + fontWeight: 'bold' + } +}); + +export default class Image extends React.PureComponent { + static propTypes = { + file: PropTypes.object.isRequired, + baseUrl: PropTypes.string.isRequired, + user: PropTypes.object.isRequired + } + + state = { modalVisible: false }; + + getDescription() { + if (this.props.file.description) { + return {this.props.file.description}; + } + } + + _onPressButton() { + this.setState({ + modalVisible: true + }); + } + + render() { + const { baseUrl, file, user } = this.props; + const img = `${ baseUrl }${ file.image_url }?rc_uid=${ user.id }&rc_token=${ user.token }`; + return ( + + this._onPressButton()} + style={styles.button} + > + + + {this.props.file.title} + {this.getDescription()} + + + this.setState({ modalVisible: false })} + /> + + ); + } +} diff --git a/app/containers/message/Markdown.js b/app/containers/message/Markdown.js new file mode 100644 index 000000000..1b50f901d --- /dev/null +++ b/app/containers/message/Markdown.js @@ -0,0 +1,153 @@ +import React from 'react'; +import { Text, StyleSheet, ViewPropTypes } from 'react-native'; +import PropTypes from 'prop-types'; +import EasyMarkdown from 'react-native-easy-markdown'; // eslint-disable-line +import SimpleMarkdown from 'simple-markdown'; +import { emojify } from 'react-emojione'; +import styles from './styles'; +import CustomEmoji from '../EmojiPicker/CustomEmoji'; + +const BlockCode = ({ node, state }) => ( + + {node.content} + +); +const mentionStyle = { color: '#13679a' }; + +const Markdown = ({ + msg, customEmojis, style, markdownStyle, customRules, renderInline +}) => { + if (!msg) { + return null; + } + msg = emojify(msg, { output: 'unicode' }); + + const defaultRules = { + username: { + order: -1, + match: SimpleMarkdown.inlineRegex(/^@[0-9a-zA-Z-_.]+/), + parse: capture => ({ content: capture[0] }), + react: (node, output, state) => ({ + type: 'custom', + key: state.key, + props: { + children: ( + alert('Username')} + > + {node.content} + + ) + } + }) + }, + heading: { + order: -2, + match: SimpleMarkdown.inlineRegex(/^#[0-9a-zA-Z-_.]+/), + parse: capture => ({ content: capture[0] }), + react: (node, output, state) => ({ + type: 'custom', + key: state.key, + props: { + children: ( + alert('Room')} + > + {node.content} + + ) + } + }) + }, + fence: { + order: -3, + match: SimpleMarkdown.blockRegex(/^ *(`{3,}|~{3,}) *(\S+)? *\n([\s\S]+?)\s*\1 *(?:\n *)+\n/), + parse: capture => ({ + lang: capture[2] || undefined, + content: capture[3] + }), + react: (node, output, state) => ({ + type: 'custom', + key: state.key, + props: { + children: ( + + ) + } + }) + }, + blockCode: { + order: -4, + match: SimpleMarkdown.blockRegex(/^(```)\s*([\s\S]*?[^`])\s*\1(?!```)/), + parse: capture => ({ content: capture[2] }), + react: (node, output, state) => ({ + type: 'custom', + key: state.key, + props: { + children: ( + + ) + } + }) + }, + customEmoji: { + order: -5, + match: SimpleMarkdown.inlineRegex(/^:([0-9a-zA-Z-_.]+):/), + parse: capture => ({ content: capture }), + react: (node, output, state) => { + const element = { + type: 'custom', + key: state.key, + props: { + children: {node.content[0]} + } + }; + const content = node.content[1]; + const emojiExtension = customEmojis[content]; + if (emojiExtension) { + const emoji = { extension: emojiExtension, content }; + element.props.children = ( + + ); + } + return element; + } + } + }; + + const codeStyle = StyleSheet.flatten(styles.codeStyle); + style = StyleSheet.flatten(style); + return ( + {msg} + + ); +}; + +Markdown.propTypes = { + msg: PropTypes.string.isRequired, + customEmojis: PropTypes.object, + // eslint-disable-next-line react/no-typos + style: ViewPropTypes.style, + markdownStyle: PropTypes.object, + customRules: PropTypes.object, + renderInline: PropTypes.bool +}; + +BlockCode.propTypes = { + node: PropTypes.object, + state: PropTypes.object +}; + +export default Markdown; diff --git a/app/containers/message/PhotoModal.js b/app/containers/message/PhotoModal.js new file mode 100644 index 000000000..7d378794e --- /dev/null +++ b/app/containers/message/PhotoModal.js @@ -0,0 +1,65 @@ +import React from 'react'; +import { ScrollView, View, Text, TouchableWithoutFeedback } from 'react-native'; +import { CachedImage } from 'react-native-img-cache'; +import PropTypes from 'prop-types'; +import Modal from 'react-native-modal'; + +const styles = { + imageWrapper: { + alignItems: 'stretch', + flex: 1 + }, + image: { + flex: 1 + }, + titleContainer: { + width: '100%', + alignItems: 'center', + marginVertical: 10 + }, + title: { + color: '#ffffff', + textAlign: 'center', + fontSize: 16, + fontWeight: '600' + } +}; + +export default class PhotoModal extends React.PureComponent { + static propTypes = { + title: PropTypes.string.isRequired, + image: PropTypes.string.isRequired, + isVisible: PropTypes.bool, + onClose: PropTypes.func.isRequired + } + render() { + const { + image, isVisible, onClose, title + } = this.props; + return ( + + + + {title} + + + + + + + + + + + ); + } +} diff --git a/app/containers/message/QuoteMark.js b/app/containers/message/QuoteMark.js new file mode 100644 index 000000000..2c010c6e2 --- /dev/null +++ b/app/containers/message/QuoteMark.js @@ -0,0 +1,20 @@ +import React from 'react'; +import { View, StyleSheet } from 'react-native'; +import PropTypes from 'prop-types'; + +const styles = StyleSheet.create({ + quoteSign: { + borderWidth: 2, + borderRadius: 4, + height: '100%', + marginRight: 5 + } +}); + +const QuoteMark = ({ color }) => ; + +QuoteMark.propTypes = { + color: PropTypes.string +}; + +export default QuoteMark; diff --git a/app/containers/message/ReactionsModal.js b/app/containers/message/ReactionsModal.js new file mode 100644 index 000000000..08491518f --- /dev/null +++ b/app/containers/message/ReactionsModal.js @@ -0,0 +1,124 @@ +import React from 'react'; +import { View, Text, TouchableWithoutFeedback, FlatList, StyleSheet } from 'react-native'; +import PropTypes from 'prop-types'; +import Modal from 'react-native-modal'; +import Icon from 'react-native-vector-icons/MaterialIcons'; +import Emoji from './Emoji'; + +const styles = StyleSheet.create({ + titleContainer: { + width: '100%', + alignItems: 'center', + paddingVertical: 10 + }, + title: { + color: '#ffffff', + textAlign: 'center', + fontSize: 16, + fontWeight: '600' + }, + reactCount: { + color: '#dddddd', + fontSize: 10 + }, + peopleReacted: { + color: '#ffffff', + fontWeight: '500' + }, + peopleItemContainer: { + flex: 1, + flexDirection: 'column', + justifyContent: 'center' + }, + emojiContainer: { + width: 50, + height: 50, + alignItems: 'center', + justifyContent: 'center' + }, + itemContainer: { + height: 50, + flexDirection: 'row' + }, + listContainer: { + flex: 1 + }, + closeButton: { + position: 'absolute', + left: 0, + top: 10, + color: '#ffffff' + } +}); +const standardEmojiStyle = { fontSize: 20 }; +const customEmojiStyle = { width: 20, height: 20 }; +export default class ReactionsModal extends React.PureComponent { + static propTypes = { + isVisible: PropTypes.bool.isRequired, + onClose: PropTypes.func.isRequired, + reactions: PropTypes.object.isRequired, + user: PropTypes.object.isRequired, + customEmojis: PropTypes.object.isRequired + } + renderItem = (item) => { + const count = item.usernames.length; + let usernames = item.usernames.slice(0, 3) + .map(username => (username.value === this.props.user.username ? 'you' : username.value)).join(', '); + if (count > 3) { + usernames = `${ usernames } and more ${ count - 3 }`; + } else { + usernames = usernames.replace(/,(?=[^,]*$)/, ' and'); + } + return ( + + + + + + + {count === 1 ? '1 person' : `${ count } people`} reacted + + { usernames } + + + ); + } + + render() { + const { + isVisible, onClose, reactions + } = this.props; + return ( + + + + + Reactions + + + + this.renderItem(item)} + keyExtractor={item => item.emoji} + /> + + + ); + } +} diff --git a/app/containers/message/Reply.js b/app/containers/message/Reply.js new file mode 100644 index 000000000..f6df68380 --- /dev/null +++ b/app/containers/message/Reply.js @@ -0,0 +1,157 @@ +import React from 'react'; +import { View, Text, TouchableOpacity, StyleSheet } from 'react-native'; +import PropTypes from 'prop-types'; +import moment from 'moment'; + +import Markdown from './Markdown'; +import QuoteMark from './QuoteMark'; +import Avatar from '../Avatar'; +import openLink from '../../utils/openLink'; + + +const styles = StyleSheet.create({ + button: { + flex: 1, + flexDirection: 'row', + alignItems: 'center', + marginTop: 2, + alignSelf: 'flex-end' + }, + quoteSign: { + borderWidth: 2, + borderRadius: 4, + borderColor: '#a0a0a0', + height: '100%', + marginRight: 5 + }, + attachmentContainer: { + flex: 1, + flexDirection: 'column' + }, + authorContainer: { + flexDirection: 'row', + alignItems: 'center' + }, + author: { + fontWeight: 'bold', + marginHorizontal: 5, + flex: 1 + }, + time: { + fontSize: 10, + fontWeight: 'normal', + color: '#888', + marginLeft: 5 + }, + fieldsContainer: { + flex: 1, + flexWrap: 'wrap', + flexDirection: 'row' + }, + fieldContainer: { + flexDirection: 'column', + padding: 10 + }, + fieldTitle: { + fontWeight: 'bold' + } +}); + +const onPress = (attachment) => { + const url = attachment.title_link || attachment.author_link; + if (!url) { + return; + } + openLink(attachment.title_link || attachment.author_link); +}; + +// Support +const formatText = text => + text.replace( + new RegExp('(?:<|<)((?:https|http):\\/\\/[^\\|]+)\\|(.+?)(?=>|>)(?:>|>)', 'gm'), + (match, url, title) => `[${ title }](${ url })` + ); + +const Reply = ({ attachment, timeFormat }) => { + if (!attachment) { + return null; + } + + const renderAvatar = () => { + if (!attachment.author_icon && !attachment.author_name) { + return null; + } + return ( + + ); + }; + + const renderAuthor = () => ( + attachment.author_name ? {attachment.author_name} : null + ); + + const renderTime = () => { + const time = attachment.ts ? moment(attachment.ts).format(timeFormat) : null; + return time ? { time } : null; + }; + + const renderTitle = () => { + if (!(attachment.author_icon || attachment.author_name || attachment.ts)) { + return null; + } + return ( + + {renderAvatar()} + {renderAuthor()} + {renderTime()} + + ); + }; + + const renderText = () => ( + attachment.text ? : null + ); + + const renderFields = () => { + if (!attachment.fields) { + return null; + } + + return ( + + {attachment.fields.map(field => ( + + {field.title} + {field.value} + + ))} + + ); + }; + + return ( + onPress(attachment)} + style={styles.button} + > + + + {renderTitle()} + {renderText()} + {renderFields()} + {attachment.attachments && attachment.attachments.map(attach => )} + + + ); +}; + +Reply.propTypes = { + attachment: PropTypes.object.isRequired, + timeFormat: PropTypes.string.isRequired +}; + +export default Reply; diff --git a/app/containers/message/Url.js b/app/containers/message/Url.js new file mode 100644 index 000000000..5ec48a999 --- /dev/null +++ b/app/containers/message/Url.js @@ -0,0 +1,74 @@ +import React from 'react'; +import { View, Text, TouchableOpacity, StyleSheet, Image } from 'react-native'; +import PropTypes from 'prop-types'; + +import QuoteMark from './QuoteMark'; +import openLink from '../../utils/openLink'; + +const styles = StyleSheet.create({ + button: { + flex: 1, + flexDirection: 'row', + alignItems: 'center', + marginVertical: 2 + }, + quoteSign: { + borderWidth: 2, + borderRadius: 4, + borderColor: '#a0a0a0', + height: '100%', + marginRight: 5 + }, + image: { + height: 80, + width: 80, + resizeMode: 'cover', + borderRadius: 6 + }, + textContainer: { + flex: 1, + height: '100%', + flexDirection: 'column', + padding: 4, + justifyContent: 'flex-start', + alignItems: 'flex-start' + }, + title: { + fontWeight: 'bold', + fontSize: 12 + }, + description: { + fontSize: 12 + } +}); + +const onPress = (url) => { + openLink(url); +}; +const Url = ({ url }) => { + if (!url) { + return null; + } + return ( + onPress(url.url)} style={styles.button}> + + {url.image ? + + : null + } + + {url.title} + {url.description} + + + ); +}; + +Url.propTypes = { + url: PropTypes.object.isRequired +}; + +export default Url; diff --git a/app/containers/message/User.js b/app/containers/message/User.js new file mode 100644 index 000000000..4921b48e8 --- /dev/null +++ b/app/containers/message/User.js @@ -0,0 +1,83 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { View, Text, StyleSheet } from 'react-native'; +import moment from 'moment'; +import Icon from 'react-native-vector-icons/FontAwesome'; +import Avatar from '../Avatar'; + +const styles = StyleSheet.create({ + username: { + fontWeight: 'bold' + }, + usernameView: { + flexDirection: 'row', + alignItems: 'center', + marginBottom: 2 + }, + alias: { + fontSize: 10, + color: '#888', + paddingLeft: 5 + }, + time: { + fontSize: 10, + color: '#888', + paddingLeft: 5 + }, + edited: { + marginLeft: 5, + flexDirection: 'row', + alignItems: 'center' + } +}); + +export default class User extends React.PureComponent { + static propTypes = { + item: PropTypes.object.isRequired, + Message_TimeFormat: PropTypes.string.isRequired, + onPress: PropTypes.func, + baseUrl: PropTypes.string + } + + renderEdited(item) { + if (!item.editedBy) { + return null; + } + return ( + + + + + ); + } + + render() { + const { item } = this.props; + + const extraStyle = {}; + if (item.temp) { + extraStyle.opacity = 0.3; + } + + const username = item.alias || item.u.username; + const aliasUsername = item.alias ? (@{item.u.username}) : null; + const time = moment(item.ts).format(this.props.Message_TimeFormat); + + return ( + + + {username} + + {aliasUsername} + {time} + {this.renderEdited(item)} + + ); + } +} diff --git a/app/containers/message/Video.js b/app/containers/message/Video.js new file mode 100644 index 000000000..0b8a019ab --- /dev/null +++ b/app/containers/message/Video.js @@ -0,0 +1,84 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { View, StyleSheet, TouchableOpacity, Image, Platform } from 'react-native'; +import Modal from 'react-native-modal'; +import VideoPlayer from 'react-native-video-controls'; +import Markdown from './Markdown'; +import openLink from '../../utils/openLink'; + +const SUPPORTED_TYPES = ['video/quicktime', 'video/mp4', ...(Platform.OS === 'ios' ? [] : ['video/webm', 'video/3gp', 'video/mkv'])]; +const isTypeSupported = type => SUPPORTED_TYPES.indexOf(type) !== -1; + +const styles = StyleSheet.create({ + container: { + flex: 1, + height: 100, + margin: 5 + }, + modal: { + margin: 0, + backgroundColor: '#000' + }, + image: { + flex: 1, + width: null, + height: null, + resizeMode: 'contain' + } +}); + +export default class Video extends React.PureComponent { + static propTypes = { + file: PropTypes.object.isRequired, + baseUrl: PropTypes.string.isRequired, + user: PropTypes.object.isRequired + } + + state = { isVisible: false }; + + toggleModal() { + this.setState({ + isVisible: !this.state.isVisible + }); + } + + open() { + if (isTypeSupported(this.props.file.video_type)) { + return this.toggleModal(); + } + openLink(this.state.uri); + } + + render() { + const { isVisible } = this.state; + const { video_url, description } = this.props.file; + const { baseUrl, user } = this.props; + const uri = `${ baseUrl }${ video_url }?rc_uid=${ user.id }&rc_token=${ user.token }`; + return ( + + this.open()} + > + + + + this.toggleModal()} + > + this.toggleModal()} + disableVolume + /> + + + ); + } +} diff --git a/app/containers/message/index.js b/app/containers/message/index.js new file mode 100644 index 000000000..babf15cec --- /dev/null +++ b/app/containers/message/index.js @@ -0,0 +1,316 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { View, TouchableHighlight, Text, TouchableOpacity, Vibration, ViewPropTypes } from 'react-native'; +import { connect } from 'react-redux'; +import Icon from 'react-native-vector-icons/MaterialIcons'; +import moment from 'moment'; +import equal from 'deep-equal'; +import { KeyboardUtils } from 'react-native-keyboard-input'; + +import { actionsShow, errorActionsShow, toggleReactionPicker } from '../../actions/messages'; +import Image from './Image'; +import User from './User'; +import Avatar from '../Avatar'; +import Audio from './Audio'; +import Video from './Video'; +import Markdown from './Markdown'; +import Url from './Url'; +import Reply from './Reply'; +import ReactionsModal from './ReactionsModal'; +import Emoji from './Emoji'; +import messageStatus from '../../constants/messagesStatus'; +import styles from './styles'; + +@connect(state => ({ + message: state.messages.message, + editing: state.messages.editing, + customEmojis: state.customEmojis +}), dispatch => ({ + actionsShow: actionMessage => dispatch(actionsShow(actionMessage)), + errorActionsShow: actionMessage => dispatch(errorActionsShow(actionMessage)), + toggleReactionPicker: message => dispatch(toggleReactionPicker(message)) +})) +export default class Message extends React.Component { + static propTypes = { + status: PropTypes.any, + item: PropTypes.object.isRequired, + reactions: PropTypes.any.isRequired, + baseUrl: PropTypes.string.isRequired, + Message_TimeFormat: PropTypes.string.isRequired, + message: PropTypes.object.isRequired, + user: PropTypes.object.isRequired, + editing: PropTypes.bool, + errorActionsShow: PropTypes.func, + customEmojis: PropTypes.object, + toggleReactionPicker: PropTypes.func, + onReactionPress: PropTypes.func, + style: ViewPropTypes.style, + onLongPress: PropTypes.func, + _updatedAt: PropTypes.instanceOf(Date), + archived: PropTypes.bool + } + + static defaultProps = { + onLongPress: () => {}, + _updatedAt: new Date(), + archived: false + } + + constructor(props) { + super(props); + this.state = { reactionsModal: false }; + this.onClose = this.onClose.bind(this); + } + + shouldComponentUpdate(nextProps, nextState) { + if (!equal(this.props.reactions, nextProps.reactions)) { + return true; + } + if (this.state.reactionsModal !== nextState.reactionsModal) { + return true; + } + return this.props._updatedAt.toGMTString() !== nextProps._updatedAt.toGMTString() || this.props.status !== nextProps.status; + } + + onPress = () => { + KeyboardUtils.dismiss(); + } + + onLongPress() { + this.props.onLongPress(this.parseMessage()); + } + + onErrorPress() { + this.props.errorActionsShow(this.parseMessage()); + } + + onReactionPress(emoji) { + this.props.onReactionPress(emoji, this.props.item._id); + } + onClose() { + this.setState({ reactionsModal: false }); + } + onReactionLongPress() { + this.setState({ reactionsModal: true }); + Vibration.vibrate(50); + } + + getInfoMessage() { + let message = ''; + const { + t, role, msg, u + } = this.props.item; + + if (t === 'rm') { + message = 'Message removed'; + } else if (t === 'uj') { + message = 'Has joined the channel.'; + } else if (t === 'r') { + message = `Room name changed to: ${ msg } by ${ u.username }`; + } else if (t === 'message_pinned') { + message = 'Message pinned'; + } else if (t === 'ul') { + message = 'Has left the channel.'; + } else if (t === 'ru') { + message = `User ${ msg } removed by ${ u.username }`; + } else if (t === 'au') { + message = `User ${ msg } added by ${ u.username }`; + } else if (t === 'user-muted') { + message = `User ${ msg } muted by ${ u.username }`; + } else if (t === 'user-unmuted') { + message = `User ${ msg } unmuted by ${ u.username }`; + } else if (t === 'subscription-role-added') { + message = `${ msg } was set ${ role } by ${ u.username }`; + } else if (t === 'subscription-role-removed') { + message = `${ msg } is no longer ${ role } by ${ u.username }`; + } else if (t === 'room_changed_description') { + message = `Room description changed to: ${ msg } by ${ u.username }`; + } else if (t === 'room_changed_announcement') { + message = `Room announcement changed to: ${ msg } by ${ u.username }`; + } else if (t === 'room_changed_topic') { + message = `Room topic changed to: ${ msg } by ${ u.username }`; + } else if (t === 'room_changed_privacy') { + message = `Room type changed to: ${ msg } by ${ u.username }`; + } + + return message; + } + + parseMessage = () => JSON.parse(JSON.stringify(this.props.item)); + + isInfoMessage() { + return [ + 'r', + 'au', + 'ru', + 'ul', + 'uj', + 'rm', + 'user-muted', + 'user-unmuted', + 'message_pinned', + 'subscription-role-added', + 'subscription-role-removed', + 'room_changed_description', + 'room_changed_announcement', + 'room_changed_topic', + 'room_changed_privacy' + ].includes(this.props.item.t); + } + + isDeleted() { + return this.props.item.t === 'rm'; + } + + isTemp() { + return this.props.item.status === messageStatus.TEMP || this.props.item.status === messageStatus.ERROR; + } + + hasError() { + return this.props.item.status === messageStatus.ERROR; + } + + attachments() { + if (this.props.item.attachments.length === 0) { + return null; + } + + const file = this.props.item.attachments[0]; + const { baseUrl, user } = this.props; + if (file.image_type) { + return ; + } else if (file.audio_type) { + return

} /> + }); + + constructor(props) { + super('RoomView', props); + this.rid = + props.rid || + props.navigation.state.params.room.rid; + this.name = props.name || + props.navigation.state.params.name || + props.navigation.state.params.room.name; + this.rooms = database.objects('subscriptions').filtered('rid = $0', this.rid); + this.state = { + loaded: true, + joined: typeof props.rid === 'undefined', + room: {} + }; + this.onReactionPress = this.onReactionPress.bind(this); + } + + async componentDidMount() { + this.props.navigation.setParams({ + title: this.name + }); + this.updateRoom(); + await this.props.openRoom({ rid: this.rid, name: this.name, ls: this.state.room.ls }); + if (this.state.room.alert || this.state.room.unread || this.state.room.userMentions) { + this.props.setLastOpen(this.state.room.ls); + } else { + this.props.setLastOpen(null); + } + + this.rooms.addListener(this.updateRoom); + } + shouldComponentUpdate(nextProps, nextState) { + return !(equal(this.props, nextProps) && equal(this.state, nextState) && this.state.room.ro === nextState.room.ro); + } + componentWillUnmount() { + this.rooms.removeAllListeners(); + this.props.editCancel(); + } + + onEndReached = (data) => { + if (this.props.loading || this.state.end) { + return; + } + + requestAnimationFrame(() => { + const lastRowData = data[data.length - 1]; + if (!lastRowData) { + return; + } + RocketChat.loadMessagesForRoom(this.rid, lastRowData.ts, ({ end }) => end && this.setState({ + end + })); + }); + } + + onMessageLongPress = (message) => { + this.props.actionsShow(message); + } + + onReactionPress = (shortname, messageId) => { + if (!messageId) { + RocketChat.setReaction(shortname, this.props.actionMessage._id); + return this.props.toggleReactionPicker(); + } + RocketChat.setReaction(shortname, messageId); + }; + + updateRoom = () => { + this.setState({ room: this.rooms[0] }); + this.forceUpdate(); + } + + sendMessage = (message) => { + RocketChat.sendMessage(this.rid, message).then(() => { + this.props.setLastOpen(null); + }); + }; + + joinRoom = async() => { + await RocketChat.joinRoom(this.props.rid); + this.setState({ + joined: true + }); + }; + + renderItem = item => ( + + ); + + renderSeparator = () => ; + + renderFooter = () => { + if (!this.state.joined) { + return ( + + You are in preview mode. +