From 2e245e4d7c1dc73d265c53f6495a1cf5559e21eb Mon Sep 17 00:00:00 2001 From: Diego Mello <diegolmello@gmail.com> Date: Tue, 17 Jul 2018 16:10:27 -0300 Subject: [PATCH] Image upload improvements (#368) <!-- INSTRUCTION: Keep the line below to notify all core developers about this new PR --> @RocketChat/ReactNative <!-- INSTRUCTION: Inform the issue number that this PR closes, or remove the line below --> - [x] Crop image - [x] Type image description (like web) - [x] Show upload progress - [x] "Try again" in case of error - [x] Cancel upload while in progress - [x] [Android] Zoom on photos <!-- INSTRUCTION: Tell us more about your PR with screen shots if you can -->   --- android/app/build.gradle | 7 +- .../assets/fonts/MaterialCommunityIcons.ttf | Bin 292556 -> 322456 bytes .../app/src/main/assets/fonts/Octicons.ttf | Bin 27428 -> 27520 bytes .../rocket/reactnative/MainApplication.java | 4 +- android/build.gradle | 1 + android/settings.gradle | 12 +- app/containers/Button/index.js | 19 +- app/containers/MessageBox/FilesActions.js | 59 ++ app/containers/MessageBox/UploadModal.js | 133 +++++ app/containers/MessageBox/index.js | 135 +++-- app/containers/message/Image.js | 1 + app/containers/message/PhotoModal.js | 71 ++- app/i18n/locales/en.js | 7 + app/lib/createStore.js | 2 +- app/lib/methods/sendFileMessage.js | 89 +++ app/lib/realm.js | 19 +- app/lib/rocketchat.js | 88 +-- app/presentation/RoomItem.js | 2 +- app/views/ProfileView/index.js | 26 +- app/views/RoomView/UploadProgress.js | 158 ++++++ app/views/RoomView/index.js | 2 + ios/RocketChatRN.xcodeproj/project.pbxproj | 178 +++--- ios/RocketChatRN/Info.plist | 1 + package-lock.json | 515 +++++++++++------- package.json | 24 +- 25 files changed, 1089 insertions(+), 464 deletions(-) create mode 100644 app/containers/MessageBox/FilesActions.js create mode 100644 app/containers/MessageBox/UploadModal.js create mode 100644 app/lib/methods/sendFileMessage.js create mode 100644 app/views/RoomView/UploadProgress.js diff --git a/android/app/build.gradle b/android/app/build.gradle index d224d8bbe..b5061cd0c 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -103,6 +103,7 @@ android { abiFilters "armeabi-v7a", "x86" } missingDimensionStrategy "RNN.reactNativeVersion", "reactNative55" + vectorDrawables.useSupportLibrary = true } compileOptions { @@ -178,17 +179,17 @@ repositories { } dependencies { + implementation project(':react-native-image-crop-picker') implementation project(':react-native-i18n') implementation project(':react-native-fabric') implementation project(':react-native-audio') implementation project(":reactnativekeyboardinput") implementation project(':react-native-video') implementation project(':react-native-svg') - implementation project(':react-native-image-picker') implementation project(':react-native-vector-icons') - implementation project(':react-native-fetch-blob') + implementation project(':rn-fetch-blob') implementation project(':react-native-zeroconf') - implementation project(':react-native-toast') + implementation project(':@remobile/react-native-toast') implementation project(':react-native-fast-image') implementation project(':realm') implementation project(':react-native-navigation') diff --git a/android/app/src/main/assets/fonts/MaterialCommunityIcons.ttf b/android/app/src/main/assets/fonts/MaterialCommunityIcons.ttf index 69404e3d9758bf3d6a7e4ce27e5362089366542f..82524a0c1223bfc2bf060a9b16390c3cc21577c1 100644 GIT binary patch delta 42753 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 C4>a=t delta 14905 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 W$n{;z4?=3$(9xe;uD6V@@cs|bD}N{e diff --git a/android/app/src/main/assets/fonts/Octicons.ttf b/android/app/src/main/assets/fonts/Octicons.ttf index 5b1f7d6ea2c870df4f29f4b40a300334844d2214..09f5a96c05af2c82a0002f0d8b0fca6ba3f08fc7 100644 GIT binary patch delta 5784 zcmbU_ZE$1Nb@#sSr;lfS%eG|uS+XUsy|T5kEqTAZHY{d=W!K?jv%>=Mlk{w9E$NB( zq+Q!dBL~7xvXgF@zA2q%Na7G?3rWi`7&5>##k7S|Lbp4RkR8I5CF!I)6euN-00VZ< zee&)?r|pkE>79Gdx%ZxX@A<sa1FzuaU*ZPB2q7n0Ml_n9n!4%wyB_-JT7>5FzzrX~ zaVT~054W8`2p<M|CRbLfzy6_r10i}V@UG1rtI5cX_aekBKtD657}bppkc8%M1zMOZ zEzTDA{pbKf>;;65JWx=Ty!00JEcCqwZ@N%W8w&jn1_t&4qo+`=EwKNNUj+IIc=eK& zQy%w!|JNY<D?lGDD+^WZz+VD<493e9rK~PJ&)tZS@-5&!S=Ef%L%FB#LnyZo*7sS5 zg9B=Tsq4Sgvg-q6r(haFul(B^J<YcBjh>B9HlC(1eg+r<YW9OH_&&4ov>C=B%$j4k zj3>?0IA;DU<u)~%3&~`<^~gwuw)ql>%&qi*nPfr^Pz8Bpgf`aAZl=rph;o^|w9h<9 z3+B5NXKtYf%}F`{I0Hf@r!{=zQ%e{!Pts8u=B_?W--a89&@4KJPM~|yY4j8H9C`(N z@P536&rlS#i+X~3k3K-Z$1u!crob#QCz<=07uYHGFWH}STe&;A?{P2iE`Ex?fqz&) z!kDli+%KFF*2M`?7r!T-5kI!|*>1AkYdd2P+i$Wj*-tyh9ZQZ!9T%MA&XdlwlBXe^ zlAdefS{7RFciCLJ>w@Q7p3|P^J@0$_y@$Lfyytw9FYCMC_oBbuKjweXf7btDU@)*2 z><JzV{%!EB))Q^EwyCyL?Vk2`LXnUjdL?WN-x_`_{91>rqtda`ajw(RxzPDeSF-C* zx}NHKPnP8aa#lVje?z`kJ|kb~R{FYUx<85dBDY7Li&D|q=u^>8dQv?ndLHa~zE|iy z)O#W(#qzQ5#9oMf9M|K&jj#9h_33>N_I<czYRkfw2e!P`zpsC#|H8n?z{J4*fx`p& zfztz@Z2g-=Poj`Gomfk}WFF-X9|B9g4z93*T*!x7!3DelzmMml-H~`~B;!q|yrWTn z2439pI>U(G^+~UdVa|&&X>xKB-?P5Vi-O>C@g5#8yVjQ{CT5nG!GbQH#$kD54gUtO zAvX%55b8ov6o<G75aBU1DMT{A;=S(mJDpy-Bx6~=@NVDA4CtZxcwHS{C(r$ES(cY) zK&UKFz-JlU1Fe2T_&b^f4FAlWc3j`D&f1T7Bx{<}dy8G2nNjVxc%3eL_l~P4yc1K~ zyLksMd5+j;SO39r0=K#FGM+#zLL!c5f*HKLftHigXR*til~$9}cmm6$H$ysuD=W!r zH95VKTv$jV42~+JckvAA_XhbOA75L&rsV`jC()SslD{8Q=BNHI!d}{AvG$4fC2zae z+rF9&{Fqr)Lw&6Isr-oJWmtX<4S|4Y(0sDH7v{X)J&<l07<8oY8gAX09&}0FHhZ}J z2Cj7|G}767^={GC-x;+##)jlW*Lm!T%<i-=5Q{puA#+#c&$uq4*k1G1$brOzf#{B& zur$8ArK4wO)HnQj^2=k>V`I|@@g(5znt3={z&|jbiGJjV7)1DSybK2uk%Zb1WQ&aX z&pkc(BlClvy{lurPHO6P*!c=dpfNOoAlvk&0zNJpiG!=e{hgGb5V6sb%;+FBIx>!j zQ{YM*9|#75{xm-_h@%nC7f7Yelksptl*Haps8@#8-RTbXO15Bc|4z^2Hjm8}2*`o7 zOdy6AzUO13y|T|2F<5WF*52D2>hZqBdIC0>*&A|n3fnrmFz#N1xxubr5N{!{>z5W> zZRxv$-%H#(hEiw;C_OfsggvH*Q$fqqBSHT#IQ#%6rx=Z<GwIAQY&qWC>*&ZJO->n! zjhOchb?v%te*WJ1j^y4upStU=r|!a{=){sBLL-Ud#Eet4*#v3EVG}VHZ9jscNB8&c zO?LFd*t?#3H2KF=11bet!7G^9patRrr9pHWmI!RNX=|}`YHwdS+!y}31y=wI_cbBm zh9T5R3$lnjs8e8;O?fU$8W-U<+lz9oY2nV#%*MA`LO#31>dDkwG}NVy^Z08ZvIT;6 z2<=2SBEvkH{(>*)<I_ZI#ORs8a0;|TneU{72Pr{()yci><eCW43kLvrz_?L95^4?F zy8QGE#kk#4i{S8j+q|u~S7KYk{>~PcL-J6(!xnPd93EePo6r10<|>I{8LCxs*nDoU z+as<%ka>+=ePs6zx(A9(E8f5g<dso$1-NN6klKS`SH$_^F)(a~H>F9ru>*6daXdN_ zi$)~u3w(@ej$YcQUDNNT+2OC_4+P-@n*OefVJ2ACl@WyZDca_dM6VN^QZzA+O$XcB zg5p=U&He@6PrK;-7;hUCy@J4tH%QVAr1gqp9?DH!KgS3RFTz(qq@ZqW;Qz$<Zu8N} zJ-D#?-sCSZo;IJqvQJKD#xX<!xY{6{8K;L+opdlDVP3+WxC?hOX3O3lJ{X3hvy{1g z@0BBdiDEd`&S07se4U|i+$XY5e-wh>=49<WM`4O@4Z+<6LFCFC=P880W<I=kI=-cq z&tRP4TmPet&rno`ZyPx`eD1@He{B7|bM6E1IfvWbV`lGFFS2jrRY(KBzbc8ZH{(+$ z*;nw}c*Xq5)Nbh>USz*1cwP4_0iv4t>OXJy`iK2de{?iDIy?%QS)Q4}69mdL=3`es z&O%zj%VuR?7hW|_?fZ7)O?(=%iihMAuSEGF?mCIBnwf%?@PFex+qbQq75&lHM07Cq z1I+Boe1^KJedNl1?CxoeC8n-;<hGshL*thz&;TfZ<4w@OGuC=Z$Wb?n=n%RE9fifs z?_SgIYp$LlTj04!e2{`XW&Zq{tqso2g+c&0uBC-L;^4ZwIft7|B)H!UbanZqR_Xhm zP=a&waQT3T^m_iu=TVcP<xo=f_++Si^29PsAyOQi%f(@y<HCLMFo<+>u7rzouR27L zgR0KEo&4bB<RJG@XTaa-Y?T6cU+0?)0fVDhmSb5eGL(#PZs*Ik_4j2NJ8Uh+gp7AP zxbVR+*%pxo=^B!_3!jBrVu#~((tgOW{&?o>>QAq|KsOlB#Tw{h1$5DdI#4%4?veCx zHzZ{@sK1*ZB_{B?hy9suHwz{mh1cuEYfi7%2?cS&>6K@uv1<cOz=M|wd;PrAySxm8 z<n{B@(^y`cIKNChk9a&;YYp{5l0_Kur}@NztvF-;_CU&PJD4I_YIXm?U$J(QT0VqL z?MKsQ>gFpP<9HAvluM07@Rerc=5dCj7{+}1<~?j=XEf<GsY8DnYD0riY=S;gO(Y!W z<3YZY8csnhQRX9ux`)5nD~3Ak!R>Cl$Nr`}h{x!i!{6TC?>!l7+3IfH{<586<%5A? zvA^$xw}-QHtuFg2^~FBiwy^;>lvA*65q=N2kss1s4=KzU^UA|R@!!o@SB?o8o(b8} z*SpopdnnA{?LUj-Nt)pXcE(u7W`5`J!0O*0ewJZ3;39RmdFr;Uly95)*SGC*JTnsW zcl2!u2VA3mlevAc0eT`A?=`5P`_SERsDQ5pb1hiHR>MVxaBK)PVl}amJvhAwk5g8Y zPIch`qzFh8fgle_4JsDb0cmX~22Bj7N$Mk?XoTm;$3Hx>4ayw(Tr73G`S9(*#_w&m zsE9eL)t#2?1I~zZz~M~0TPaA`5xYGi0^;!4GtP^BnU*#R()g;#%bd-|$-J1t6vx>e zE|1USb~)^VI6-5Ur8&mI@jPqeIhLj=oW_`<X#v}KhUfpKxlYE_YWil{8g{P(UtW)D zb-{8^UKB6>kd<5xhaj+UyBB%MZNn^0u?)r>=YTT7vv599VBsFh!iT3gfe|+I?nUj6 z|DU>@1^xc-%4IX)Vm$tT>S_Jcv&of-Bss7t&2)wTr=$MknG_6xkXV@E@fPxfQo}PO ziZgJb<m1hY=N}f}$~k0xlTQ*nX+Egz1Q&upBS8mH0GDmz6qNtLO`L{{_E$G?2F5(L ziL-DCdVLe;kbo(;JYYt&WRZ&m!7+@XH*pH?ft{N;jiykV;1L+az@Ym#JD}*GpKjtD z@ZW`BgKuW%M^bQ29Dz55l4u*aJDSoewJA-XQ{~iPQr;mS%+-oHtzrP0N{l2@$!%jW zvBNx_I|#oDA)}CIV-2;LZ%}^IpP#4DkIm)$DG5pNBk;@kEBKG_S5d@lRc~#eBlxda zrKIXLo1*L5@kCxbUfD!T>TJ#4<m$z_Le160jj~cIS>ry(Afw%%9bwIpKFg_Bg(g|A za#>ZGSM>&yRZAr%tCjKqw0VJmvZBw6S-q&v<`hE(OjGiJ)p)>;8>&uc>vKX5HeJap zI-4t~xp~oorJ_-D0Cr5*D%J)s5oB}Di#^uHY!=mkf%U2*SJZPQHDQz#qu?Y&y;w_R zHAT;Jxl*xOU1W3c@4~zUu%5RhmtaqhCRwi%g2`!lmCtGAvRbKmHrqtLXyodKQPe8- zoUZ0UY7T@ld00mzpkXZ{<dvF|g|oWysxe>Fs+X2<=G9}xoC>qbs;+oHM<tFG^QtCo z@-}B)oKV)X#gfY8i?g#f0uo9-ujU;VTAZtBuo)*1joCz5gSL3FPgl#@vC9Pc&m>Q) ziz+h<;_L(@vc-y`FNzjU4lP+&zNo9Ynx-$>EE1*_6~RKQ`Pt?Wqn?Gu>LoQ`@r}iD zsZp%VgOWC<x-anwn-EP2OT{WXTY{}Hv&2#6R7GdzinBEUM$Jw@!calKHQOAqo32!H z1q&r+D3TGNcdcAibX6oc=yFbV5v)<IgD>mq9d*^Hv2!IYtMYTYlFh0*3vIQ)!rxGO zjW56&a5ko(mDQGlrWcnWCKZ?or(p~AtX5--m8`bF6f3iuqi7g)uvtknK$A^EtEv?> zFEt5WZIWEE0YZv7?x?C8>Y{62%_`Z%W${vzaSWof2>wpbtBV4>me0^7<+!ax!ZMMq zm$FO=ROTcgp)S-^y`q#HBpec&o>#%xl10?P@D?eMKg()Gtx;i!V~ZtiPD@zY+{9{d zD5k6wOCkZFAti4oaS4M+mq2imD#Wrn2WrwPDo-3A99=Af-9TFvl`9t^rRa{brq>j` z8Ba{PUQ=xqEm2XA!)_ZYQ_*Uwpn>bmDmm2wX-=sWm&o2Kd{xQKD|4z)Rf?5bPN{I9 z#9Xlijc#Zax>~F-)lz-V2Ea&IX~|jDi(v8MF%?3n=DJK7chtf9d{x(uf}65nc0*<F zs5fA7yRPJmTB4>M2czq1wY10p)NBM0BUaQF3!T+;h{S5$DA+I3^J-qSaN<T6F{8i{ zo?hd0P_0^{b;DrvdUnxnfRCz`#4HSUHt|LRECTtIGr-Mq1!#1zwqU5WTCp-`a7Ll1 zmh!v-A)6>x1gq8RHO?SPUKHR|pklSe7@%MPT9q*tD>=HR%n3Ecm?uUTYbw|y2OcMY zUz8zuOTb!ykSQ*y4O^`MdrD*#-2k*+&Kkt3LKCf5*_x)6456k&t^xx%YkE<s%s~<$ zqb^e<y-Jt*to&-fL_)H!LsXRV&{)>5SKy3R&Jp%p!T=#@(qNA(wOoN-QmRnIF#KR8 U^~|c&zj!rcwU_^oeWT~U07H+3{{R30 delta 5557 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 diff --git a/android/app/src/main/java/chat/rocket/reactnative/MainApplication.java b/android/app/src/main/java/chat/rocket/reactnative/MainApplication.java index 6f4059c82..fdd50ce07 100644 --- a/android/app/src/main/java/chat/rocket/reactnative/MainApplication.java +++ b/android/app/src/main/java/chat/rocket/reactnative/MainApplication.java @@ -4,6 +4,7 @@ import android.content.Context; import android.os.Bundle; import com.AlexanderZaytsev.RNI18n.RNI18nPackage; +import com.reactnative.ivpusic.imagepicker.PickerPackage; import com.RNFetchBlob.RNFetchBlobPackage; import com.balthazargronon.RCTZeroconf.ZeroconfReactPackage; import com.brentvatne.react.ReactVideoPackage; @@ -12,7 +13,6 @@ import com.dylanvann.fastimage.FastImageViewPackage; import com.facebook.react.ReactPackage; import com.facebook.react.shell.MainReactPackage; import com.horcrux.svg.SvgPackage; -import com.imagepicker.ImagePickerPackage; import com.oblador.vectoricons.VectorIconsPackage; import com.reactnativenavigation.NavigationApplication; import com.remobile.toast.RCTToastPackage; @@ -57,8 +57,8 @@ public class MainApplication extends NavigationApplication implements INotificat public List<ReactPackage> createAdditionalReactPackages() { return Arrays.<ReactPackage>asList( new MainReactPackage(), + new PickerPackage(), new SvgPackage(), - new ImagePickerPackage(), new VectorIconsPackage(), new RNFetchBlobPackage(), new ZeroconfReactPackage(), diff --git a/android/build.gradle b/android/build.gradle index d6cd4cf1b..7b1e283f5 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -25,6 +25,7 @@ allprojects { maven { url 'https://maven.google.com' } + maven { url "https://jitpack.io" } maven { // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm url "$rootDir/../node_modules/react-native/android" diff --git a/android/settings.gradle b/android/settings.gradle index 0cc5136b6..7a7576153 100644 --- a/android/settings.gradle +++ b/android/settings.gradle @@ -1,4 +1,10 @@ rootProject.name = 'RocketChatRN' +include ':@remobile/react-native-toast' +project(':@remobile/react-native-toast').projectDir = new File(rootProject.projectDir, '../node_modules/@remobile/react-native-toast/android') +include ':rn-fetch-blob' +project(':rn-fetch-blob').projectDir = new File(rootProject.projectDir, '../node_modules/rn-fetch-blob/android') +include ':react-native-image-crop-picker' +project(':react-native-image-crop-picker').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-image-crop-picker/android') include ':react-native-i18n' project(':react-native-i18n').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-i18n/android') include ':react-native-fast-image' @@ -13,18 +19,12 @@ 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' -project(':react-native-image-picker').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-image-picker/android') include ':react-native-vector-icons' project(':react-native-vector-icons').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-vector-icons/android') -include ':react-native-fetch-blob' -project(':react-native-fetch-blob').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-fetch-blob/android') 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-toast' -project(':react-native-toast').projectDir = new File(settingsDir, '../node_modules/@remobile/react-native-toast/android') include ':react-native-navigation' project(':react-native-navigation').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-navigation/android/app/') include ':reactnativenotifications' diff --git a/app/containers/Button/index.js b/app/containers/Button/index.js index f72880b2c..32eb7de94 100644 --- a/app/containers/Button/index.js +++ b/app/containers/Button/index.js @@ -16,8 +16,7 @@ const colors = { const styles = StyleSheet.create({ container: { paddingHorizontal: 15, - paddingVertical: 10, - borderRadius: 2 + paddingVertical: 10 }, text: { textAlign: 'center', @@ -40,6 +39,9 @@ const styles = StyleSheet.create({ }, disabled: { opacity: 0.5 + }, + border: { + borderRadius: 2 } }); @@ -48,7 +50,9 @@ export default class Button extends React.PureComponent { title: PropTypes.string, type: PropTypes.string, onPress: PropTypes.func, - disabled: PropTypes.bool + disabled: PropTypes.bool, + margin: PropTypes.any, + backgroundColor: PropTypes.string } static defaultProps = { @@ -60,21 +64,22 @@ export default class Button extends React.PureComponent { render() { const { - title, type, onPress, disabled, ...otherProps + title, type, onPress, disabled, margin, backgroundColor, ...otherProps } = this.props; return ( <Touch onPress={onPress} accessibilityTraits='button' - style={Platform.OS === 'ios' && styles.margin} + style={Platform.OS === 'ios' && [(margin || styles.margin), styles.border]} disabled={disabled} {...otherProps} > <View style={[ styles.container, - styles[`background_${ type }`], - Platform.OS === 'android' && styles.margin, + styles.border, + backgroundColor ? { backgroundColor } : styles[`background_${ type }`], + Platform.OS === 'android' && (margin || styles.margin), disabled && styles.disabled ]} > diff --git a/app/containers/MessageBox/FilesActions.js b/app/containers/MessageBox/FilesActions.js new file mode 100644 index 000000000..e7def299d --- /dev/null +++ b/app/containers/MessageBox/FilesActions.js @@ -0,0 +1,59 @@ +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import ActionSheet from 'react-native-actionsheet'; + +import I18n from '../../i18n'; + +export default class FilesActions extends Component { + static propTypes = { + hideActions: PropTypes.func.isRequired, + takePhoto: PropTypes.func.isRequired, + chooseFromLibrary: PropTypes.func.isRequired + } + + constructor(props) { + super(props); + + // Cancel + this.options = [I18n.t('Cancel')]; + this.CANCEL_INDEX = 0; + + // Photo + this.options.push(I18n.t('Take_a_photo')); + this.PHOTO_INDEX = 1; + + // Library + this.options.push(I18n.t('Choose_from_library')); + this.LIBRARY_INDEX = 2; + + setTimeout(() => { + this.ActionSheet.show(); + }); + } + + handleActionPress = (actionIndex) => { + const { takePhoto, chooseFromLibrary } = this.props; + switch (actionIndex) { + case this.PHOTO_INDEX: + takePhoto(); + break; + case this.LIBRARY_INDEX: + chooseFromLibrary(); + break; + default: + break; + } + this.props.hideActions(); + } + + render() { + return ( + <ActionSheet + ref={o => this.ActionSheet = o} + options={this.options} + cancelButtonIndex={this.CANCEL_INDEX} + onPress={this.handleActionPress} + /> + ); + } +} diff --git a/app/containers/MessageBox/UploadModal.js b/app/containers/MessageBox/UploadModal.js new file mode 100644 index 000000000..53f91ed45 --- /dev/null +++ b/app/containers/MessageBox/UploadModal.js @@ -0,0 +1,133 @@ +import React, { Component } from 'react'; +import { View, Text, StyleSheet, Image, ScrollView, Platform } from 'react-native'; +import PropTypes from 'prop-types'; +import Modal from 'react-native-modal'; +import { responsive } from 'react-native-responsive-ui'; +import equal from 'deep-equal'; + +import TextInput from '../TextInput'; +import Button from '../Button'; +import I18n from '../../i18n'; + +const cancelButtonColor = '#f7f8fa'; + +const styles = StyleSheet.create({ + titleContainer: { + flexDirection: 'row', + paddingHorizontal: 16, + paddingTop: 16 + }, + title: { + fontWeight: 'bold' + }, + container: { + height: Platform.OS === 'ios' ? 404 : 430, + backgroundColor: '#ffffff', + flexDirection: 'column' + }, + scrollView: { + flex: 1, + padding: 16 + }, + image: { + height: 150, + flex: 1, + marginBottom: 16, + resizeMode: 'contain' + }, + buttonContainer: { + flexDirection: 'row', + justifyContent: 'space-between', + padding: 16, + backgroundColor: '#f7f8fa' + }, + buttonMargin: { + margin: 0 + } +}); + +@responsive +export default class UploadModal extends Component { + static propTypes = { + isVisible: PropTypes.bool, + file: PropTypes.object, + close: PropTypes.func, + submit: PropTypes.func, + window: PropTypes.object + } + + state = { + name: '', + description: '', + file: {} + }; + + static getDerivedStateFromProps(props, state) { + if (!equal(props.file, state.file) && props.file && props.file.path) { + return { + file: props.file, + name: props.file.filename || 'Filename', + description: '' + }; + } + return null; + } + + _submit = () => { + const { file, submit } = this.props; + const { name, description } = this.state; + submit({ ...file, name, description }); + } + + render() { + const { window: { width }, isVisible, close } = this.props; + const { name, description, file } = this.state; + return ( + <Modal + isVisible={isVisible} + style={{ alignItems: 'center' }} // TODO: need this? + onBackdropPress={() => this.props.close()} + onBackButtonPress={() => this.props.close()} + animationIn='fadeIn' + animationOut='fadeOut' + useNativeDriver + hideModalContentWhileAnimating + > + <View style={[styles.container, { width: width - 32 }]}> + <View style={styles.titleContainer}> + <Text style={styles.title}>Upload file?</Text> + </View> + + <ScrollView style={styles.scrollView}> + <Image source={{ isStatic: true, uri: file.path }} style={styles.image} /> + <TextInput + placeholder='File name' + value={name} + onChangeText={value => this.setState({ name: value })} + /> + <TextInput + placeholder='File description' + value={description} + onChangeText={value => this.setState({ description: value })} + /> + </ScrollView> + <View style={styles.buttonContainer}> + <Button + title={I18n.t('Cancel')} + type='secondary' + backgroundColor={cancelButtonColor} + margin={styles.buttonMargin} + onPress={close} + /> + <Button + title={I18n.t('Send')} + type='primary' + margin={styles.buttonMargin} + onPress={this._submit} + /> + </View> + </View> + </Modal> + ); + } +} diff --git a/app/containers/MessageBox/index.js b/app/containers/MessageBox/index.js index 25925ad5f..c16cc3f81 100644 --- a/app/containers/MessageBox/index.js +++ b/app/containers/MessageBox/index.js @@ -2,10 +2,10 @@ import React from 'react'; import PropTypes from 'prop-types'; import { View, TextInput, FlatList, Text, TouchableOpacity, Alert } 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 ImagePicker from 'react-native-image-crop-picker'; import { userTyping } from '../../actions/room'; import RocketChat from '../../lib/rocketchat'; @@ -17,6 +17,8 @@ import Avatar from '../Avatar'; import CustomEmoji from '../EmojiPicker/CustomEmoji'; import { emojis } from '../../emojis'; import Recording from './Recording'; +import FilesActions from './FilesActions'; +import UploadModal from './UploadModal'; import './EmojiKeyboard'; import log from '../../utils/log'; import I18n from '../../i18n'; @@ -28,6 +30,14 @@ const onlyUnique = function onlyUnique(value, index, self) { return self.indexOf(({ _id }) => value._id === _id) === index; }; +const imagePickerConfig = { + cropping: true, + compressImageQuality: 0.8, + cropperAvoidEmptySpaceAroundImage: false, + cropperChooseText: I18n.t('Choose'), + cropperCancelText: I18n.t('Cancel') +}; + @connect(state => ({ room: state.room, message: state.messages.message, @@ -58,7 +68,11 @@ export default class MessageBox extends React.PureComponent { text: '', mentions: [], showEmojiKeyboard: false, - recording: false + showFilesAction: false, + recording: false, + file: { + isVisible: false + } }; this.users = []; this.rooms = []; @@ -160,43 +174,60 @@ export default class MessageBox extends React.PureComponent { key='fileIcon' accessibilityLabel={I18n.t('Message actions')} accessibilityTraits='button' - onPress={() => this.addFile()} + onPress={this.toggleFilesActions} testID='messagebox-actions' />); return icons; } - addFile = () => { - const options = { - maxHeight: 1960, - maxWidth: 1960, - quality: 0.8 + toggleFilesActions = () => { + this.setState(prevState => ({ showFilesAction: !prevState.showFilesAction })); + } + + sendImageMessage = async(file) => { + this.setState({ file: { isVisible: false } }); + const fileInfo = { + name: file.name, + description: file.description, + size: file.size, + type: file.mime, + store: 'Uploads', + path: file.path }; - ImagePicker.showImagePicker(options, async(response) => { - if (response.didCancel) { - console.warn('User cancelled image picker'); - } else if (response.error) { - log('ImagePicker Error', response.error); - } else { - const fileInfo = { - name: response.fileName, - size: response.fileSize, - type: response.type || 'image/jpeg', - // description: '', - store: 'Uploads' - }; - try { - await RocketChat.sendFileMessage(this.props.rid, fileInfo, response.data); - } catch (e) { - log('addFile', e); - } - } - }); + try { + await RocketChat.sendFileMessage(this.props.rid, fileInfo); + } catch (e) { + log('sendImageMessage', e); + } } + + takePhoto = async() => { + try { + const image = await ImagePicker.openCamera(imagePickerConfig); + this.showUploadModal(image); + } catch (e) { + log('takePhoto', e); + } + } + + chooseFromLibrary = async() => { + try { + const image = await ImagePicker.openPicker(imagePickerConfig); + this.showUploadModal(image); + } catch (e) { + log('chooseFromLibrary', e); + } + } + + showUploadModal = (file) => { + this.setState({ file: { ...file, isVisible: true } }); + } + editCancel() { this.props.editCancel(); this.setState({ text: '' }); } + async openEmoji() { await this.setState({ showEmojiKeyboard: true @@ -489,6 +520,20 @@ export default class MessageBox extends React.PureComponent { ); }; + renderFilesActions = () => { + if (!this.state.showFilesAction) { + return null; + } + return ( + <FilesActions + key='files-actions' + hideActions={this.toggleFilesActions} + takePhoto={this.takePhoto} + chooseFromLibrary={this.chooseFromLibrary} + /> + ); + } + renderContent() { if (this.state.recording) { return (<Recording onFinish={this.finishAudioMessage} />); @@ -525,18 +570,28 @@ export default class MessageBox extends React.PureComponent { render() { return ( - <KeyboardAccessoryView - key='input' - renderContent={() => this.renderContent()} - kbInputRef={this.component} - kbComponent={this.state.showEmojiKeyboard ? 'EmojiKeyboard' : null} - onKeyboardResigned={() => this.onKeyboardResigned()} - onItemSelected={this._onEmojiSelected} - trackInteractive - // revealKeyboardInteractive - requiresSameParentToManageScrollView - addBottomView - /> + [ + <KeyboardAccessoryView + key='input' + renderContent={() => this.renderContent()} + kbInputRef={this.component} + kbComponent={this.state.showEmojiKeyboard ? 'EmojiKeyboard' : null} + onKeyboardResigned={() => this.onKeyboardResigned()} + onItemSelected={this._onEmojiSelected} + trackInteractive + // revealKeyboardInteractive + requiresSameParentToManageScrollView + addBottomView + />, + this.renderFilesActions(), + <UploadModal + key='upload-modal' + isVisible={(this.state.file && this.state.file.isVisible)} + file={this.state.file} + close={() => this.setState({ file: {} })} + submit={this.sendImageMessage} + /> + ] ); } } diff --git a/app/containers/message/Image.js b/app/containers/message/Image.js index 1cbdf3a1f..7ef8eefa2 100644 --- a/app/containers/message/Image.js +++ b/app/containers/message/Image.js @@ -66,6 +66,7 @@ export default class extends React.PureComponent { <PhotoModal key='modal' title={this.props.file.title} + description={this.props.file.description} image={img} isVisible={this.state.modalVisible} onClose={() => this.setState({ modalVisible: false })} diff --git a/app/containers/message/PhotoModal.js b/app/containers/message/PhotoModal.js index 0bb21888e..c3b83480b 100644 --- a/app/containers/message/PhotoModal.js +++ b/app/containers/message/PhotoModal.js @@ -1,15 +1,13 @@ import React from 'react'; -import { ScrollView, View, Text, TouchableWithoutFeedback } from 'react-native'; +import { View, Text, TouchableWithoutFeedback, ActivityIndicator, StyleSheet } from 'react-native'; import FastImage from 'react-native-fast-image'; import PropTypes from 'prop-types'; import Modal from 'react-native-modal'; +import ImageViewer from 'react-native-image-zoom-viewer'; +import { responsive } from 'react-native-responsive-ui'; -const styles = { +const styles = StyleSheet.create({ imageWrapper: { - alignItems: 'stretch', - flex: 1 - }, - image: { flex: 1 }, titleContainer: { @@ -22,42 +20,67 @@ const styles = { textAlign: 'center', fontSize: 16, fontWeight: '600' + }, + description: { + color: '#ffffff', + textAlign: 'center', + fontSize: 14, + fontWeight: '500' + }, + indicatorContainer: { + alignItems: 'center', + justifyContent: 'center' } -}; +}); + +const margin = 40; +@responsive export default class PhotoModal extends React.PureComponent { static propTypes = { title: PropTypes.string.isRequired, + description: PropTypes.string, image: PropTypes.string.isRequired, isVisible: PropTypes.bool, - onClose: PropTypes.func.isRequired + onClose: PropTypes.func.isRequired, + window: PropTypes.object } render() { const { - image, isVisible, onClose, title + image, isVisible, onClose, title, description, window: { width, height } } = this.props; return ( <Modal isVisible={isVisible} + style={{ alignItems: 'center' }} onBackdropPress={onClose} onBackButtonPress={onClose} + animationIn='fadeIn' + animationOut='fadeOut' > - <TouchableWithoutFeedback onPress={onClose}> - <View style={styles.titleContainer}> - <Text style={styles.title}>{title}</Text> + <View style={{ width: width - margin, height: height - margin }}> + <TouchableWithoutFeedback onPress={onClose}> + <View style={styles.titleContainer}> + <Text style={styles.title}>{title}</Text> + <Text style={styles.description}>{description}</Text> + </View> + </TouchableWithoutFeedback> + <View style={styles.imageWrapper}> + <ImageViewer + imageUrls={[{ url: encodeURI(image) }]} + onClick={onClose} + backgroundColor='transparent' + enableSwipeDown + onSwipeDown={onClose} + renderIndicator={() => {}} + renderImage={props => <FastImage {...props} />} + loadingRender={() => ( + <View style={[styles.indicatorContainer, { width, height }]}> + <ActivityIndicator /> + </View> + )} + /> </View> - </TouchableWithoutFeedback> - <View style={styles.imageWrapper}> - <ScrollView contentContainerStyle={styles.imageWrapper} maximumZoomScale={5}> - <TouchableWithoutFeedback onPress={onClose}> - <FastImage - style={styles.image} - source={{ uri: encodeURI(image) }} - mutable - resizeMode='contain' - /> - </TouchableWithoutFeedback> - </ScrollView> </View> </Modal> ); diff --git a/app/i18n/locales/en.js b/app/i18n/locales/en.js index 79702e574..ef8175340 100644 --- a/app/i18n/locales/en.js +++ b/app/i18n/locales/en.js @@ -111,6 +111,8 @@ export default { Chats: 'Chats', Close: 'Close', Close_emoji_selector: 'Close emoji selector', + Choose: 'Choose', + Choose_from_library: 'Choose from library', Code: 'Code', Colaborative: 'Colaborative', Connect: 'Connect', @@ -136,6 +138,7 @@ export default { Email: 'Email', Enable_notifications: 'Enable notifications', Everyone_can_access_this_channel: 'Everyone can access this channel', + Error_uploading: 'Error uploading', Files: 'Files', Finish_recording: 'Finish recording', For_your_security_you_must_enter_your_current_password_to_continue: 'For your security, you must enter your current password to continue', @@ -246,6 +249,7 @@ export default { Search: 'Search', Select_Avatar: 'Select Avatar', Select_Users: 'Select Users', + Send: 'Send', Send_audio_message: 'Send audio message', Send_message: 'Send message', Servers: 'Servers', @@ -266,6 +270,7 @@ export default { Starred: 'Starred', Start_of_conversation: 'Start of conversation', Submit: 'Submit', + Take_a_photo: 'Take a photo', tap_to_change_status: 'tap to change status', Tap_to_view_servers_list: 'Tap to view servers list', Terms_of_Service: ' Terms of Service ', @@ -276,6 +281,7 @@ export default { Toggle_Drawer: 'Toggle_Drawer', topic: 'topic', Topic: 'Topic', + Try_again: 'Try again', Type_the_channel_name_here: 'Type the channel name here', unarchive: 'unarchive', UNARCHIVE: 'UNARCHIVE', @@ -285,6 +291,7 @@ export default { Unpin: 'Unpin', unread_messages: 'unread messages', Unstar: 'Unstar', + Uploading: 'Uploading', User_added_by: 'User {{userAdded}} added by {{userBy}}', User_has_been_key: 'User has been {{key}}!', User_is_no_longer_role_by_: '{{user}} is no longer {{role}} by {{userBy}}', diff --git a/app/lib/createStore.js b/app/lib/createStore.js index 24106225d..c9188f082 100644 --- a/app/lib/createStore.js +++ b/app/lib/createStore.js @@ -14,7 +14,7 @@ if (__DEV__) { /* eslint-disable global-require */ const reduxImmutableStateInvariant = require('redux-immutable-state-invariant').default(); sagaMiddleware = createSagaMiddleware({ - // sagaMonitor: Reactotron.createSagaMonitor() + sagaMonitor: Reactotron.createSagaMonitor() }); enhancers = compose( diff --git a/app/lib/methods/sendFileMessage.js b/app/lib/methods/sendFileMessage.js new file mode 100644 index 000000000..4e813eaf7 --- /dev/null +++ b/app/lib/methods/sendFileMessage.js @@ -0,0 +1,89 @@ +import RNFetchBlob from 'rn-fetch-blob'; + +import reduxStore from '../createStore'; +import database from '../realm'; + +const promises = {}; + +function _ufsCreate(fileInfo) { + return this.ddp.call('ufsCreate', fileInfo); +} + +function _ufsComplete(fileId, store, token) { + return this.ddp.call('ufsComplete', fileId, store, token); +} + +function _sendFileMessage(rid, data, msg = {}) { + return this.ddp.call('sendFileMessage', rid, null, data, msg); +} + +export function isUploadActive(path) { + return !!promises[path]; +} + +export async function cancelUpload(path) { + if (promises[path]) { + await promises[path].cancel(); + } +} + +export async function sendFileMessage(rid, fileInfo) { + try { + const data = await RNFetchBlob.wrap(fileInfo.path); + if (!fileInfo.size) { + const fileStat = await RNFetchBlob.fs.stat(fileInfo.path); + fileInfo.size = fileStat.size; + fileInfo.name = fileStat.filename; + } + + const { FileUpload_MaxFileSize } = reduxStore.getState().settings; + + // -1 maxFileSize means there is no limit + if (FileUpload_MaxFileSize > -1 && fileInfo.size > FileUpload_MaxFileSize) { + return Promise.reject({ error: 'error-file-too-large' }); // eslint-disable-line + } + + fileInfo.rid = rid; + + database.write(() => { + database.create('uploads', fileInfo, true); + }); + + const result = await _ufsCreate.call(this, fileInfo); + + promises[fileInfo.path] = RNFetchBlob.fetch('POST', result.url, { + 'Content-Type': 'octet-stream' + }, data); + // Workaround for https://github.com/joltup/rn-fetch-blob/issues/96 + setTimeout(() => { + promises[fileInfo.path].uploadProgress((loaded, total) => { + database.write(() => { + fileInfo.progress = Math.floor((loaded / total) * 100); + database.create('uploads', fileInfo, true); + }); + }); + }); + await promises[fileInfo.path]; + + const completeResult = await _ufsComplete.call(this, result.fileId, fileInfo.store, result.token); + + await _sendFileMessage.call(this, completeResult.rid, { + _id: completeResult._id, + type: completeResult.type, + size: completeResult.size, + name: completeResult.name, + description: completeResult.description, + url: completeResult.path + }); + + database.write(() => { + const upload = database.objects('uploads').filtered('path = $0', fileInfo.path); + database.delete(upload); + }); + } catch (e) { + database.write(() => { + fileInfo.error = true; + database.create('uploads', fileInfo, true); + }); + } +} diff --git a/app/lib/realm.js b/app/lib/realm.js index 081643e57..94583fee0 100644 --- a/app/lib/realm.js +++ b/app/lib/realm.js @@ -260,6 +260,22 @@ const rolesSchema = { } }; +const uploadsSchema = { + name: 'uploads', + primaryKey: 'path', + properties: { + path: 'string', + rid: 'string', + name: { type: 'string', optional: true }, + description: { type: 'string', optional: true }, + size: { type: 'int', optional: true }, + type: { type: 'string', optional: true }, + store: { type: 'string', optional: true }, + progress: { type: 'int', default: 1 }, + error: { type: 'bool', default: false } + } +}; + const schema = [ settingsSchema, subscriptionSchema, @@ -279,7 +295,8 @@ const schema = [ messagesReactionsSchema, messagesReactionsUsernamesSchema, rolesSchema, - userMutedInRoomSchema + userMutedInRoomSchema, + uploadsSchema ]; // class DebouncedDb { diff --git a/app/lib/rocketchat.js b/app/lib/rocketchat.js index c990626e7..1d8eb7db9 100644 --- a/app/lib/rocketchat.js +++ b/app/lib/rocketchat.js @@ -1,7 +1,7 @@ import { AsyncStorage, Platform } from 'react-native'; import { hashPassword } from 'react-native-meteor/lib/utils'; import foreach from 'lodash/forEach'; -import RNFetchBlob from 'react-native-fetch-blob'; +import RNFetchBlob from 'rn-fetch-blob'; import reduxStore from './createStore'; import defaultSettings from '../constants/settings'; @@ -39,6 +39,7 @@ import loadMessagesForRoom from './methods/loadMessagesForRoom'; import loadMissedMessages from './methods/loadMissedMessages'; import sendMessage, { getMessage, _sendMessageCall } from './methods/sendMessage'; +import { sendFileMessage, cancelUpload, isUploadActive } from './methods/sendFileMessage'; import { getDeviceToken } from '../push'; @@ -615,88 +616,9 @@ const RocketChat = { joinRoom(rid) { return call('joinRoom', rid); }, - - - /* - "name":"yXfExLErmNR5eNPx7.png" - "size":961 - "type":"image/png" - "rid":"GENERAL" - "description":"" - "store":"fileSystem" - */ - _ufsCreate(fileInfo) { - // return call('ufsCreate', fileInfo); - return call('ufsCreate', fileInfo); - }, - - // ["ZTE8CKHJt7LATv7Me","fileSystem","e8E96b2819" - _ufsComplete(fileId, store, token) { - return call('ufsComplete', fileId, store, token); - }, - - /* - - "GENERAL" - - { - "type":"image/png", - "size":961, - "name":"yXfExLErmNR5eNPx7.png", - "description":"", - "url":"/ufs/fileSystem/ZTE8CKHJt7LATv7Me/yXfExLErmNR5eNPx7.png" - } - */ - _sendFileMessage(rid, data, msg = {}) { - return call('sendFileMessage', rid, null, data, msg); - }, - async sendFileMessage(rid, fileInfo, data) { - let placeholder; - try { - if (!data) { - data = await RNFetchBlob.wrap(fileInfo.path); - const fileStat = await RNFetchBlob.fs.stat(fileInfo.path); - fileInfo.size = fileStat.size; - fileInfo.name = fileStat.filename; - } - - const { FileUpload_MaxFileSize } = reduxStore.getState().settings; - - // -1 maxFileSize means there is no limit - if (FileUpload_MaxFileSize > -1 && fileInfo.size > FileUpload_MaxFileSize) { - return Promise.reject({ error: 'error-file-too-large' }); // eslint-disable-line - } - - placeholder = RocketChat.getMessage(rid, 'Sending a file'); - - const result = await RocketChat._ufsCreate({ ...fileInfo, rid }); - await RNFetchBlob.fetch('POST', result.url, { - 'Content-Type': 'application/octet-stream' - }, data); - - const completeRresult = await RocketChat._ufsComplete(result.fileId, fileInfo.store, result.token); - - return await RocketChat._sendFileMessage(completeRresult.rid, { - _id: completeRresult._id, - type: completeRresult.type, - size: completeRresult.size, - name: completeRresult.name, - url: completeRresult.path - }); - } catch (e) { - return e; - } finally { - // TODO: fix that - try { - if (placeholder) { - database.write(() => { - const msg = database.objects('messages').filtered('_id = $0', placeholder._id); - database.delete(msg); - }); - } - } catch (e) { - console.error(e); - } - } - }, + sendFileMessage, + cancelUpload, + isUploadActive, getSettings, getPermissions, getCustomEmoji, diff --git a/app/presentation/RoomItem.js b/app/presentation/RoomItem.js index 4797370b4..6ec261f8a 100644 --- a/app/presentation/RoomItem.js +++ b/app/presentation/RoomItem.js @@ -254,7 +254,7 @@ export default class RoomItem extends React.Component { <Markdown msg={this.lastMessage} style={{ - view: { + root: { flex: 1 } }} diff --git a/app/views/ProfileView/index.js b/app/views/ProfileView/index.js index 752b5c494..70dfafcee 100644 --- a/app/views/ProfileView/index.js +++ b/app/views/ProfileView/index.js @@ -5,7 +5,7 @@ import { connect } from 'react-redux'; import Dialog from 'react-native-dialog'; import SHA256 from 'js-sha256'; import Icon from 'react-native-vector-icons/MaterialIcons'; -import ImagePicker from 'react-native-image-picker'; +import ImagePicker from 'react-native-image-crop-picker'; import RNPickerSelect from 'react-native-picker-select'; import LoggedView from '../View'; @@ -243,19 +243,21 @@ export default class ProfileView extends LoggedView { } } - pickImage = () => { + pickImage = async() => { const options = { - title: I18n.t('Select_Avatar') + cropping: true, + compressImageQuality: 0.8, + cropperAvoidEmptySpaceAroundImage: false, + cropperChooseText: I18n.t('Choose'), + cropperCancelText: I18n.t('Cancel'), + includeBase64: true }; - ImagePicker.showImagePicker(options, async(response) => { - if (response.didCancel) { - console.warn('User cancelled image picker'); - } else if (response.error) { - log('ImagePicker Error', response.error); - } else { - this.setAvatar({ url: response.uri, data: `data:image/jpeg;base64,${ response.data }`, service: 'upload' }); - } - }); + try { + const response = await ImagePicker.openPicker(options); + this.setAvatar({ url: response.path, data: `data:image/jpeg;base64,${ response.data }`, service: 'upload' }); + } catch (error) { + console.warn(error); + } } renderAvatarButton = ({ diff --git a/app/views/RoomView/UploadProgress.js b/app/views/RoomView/UploadProgress.js new file mode 100644 index 000000000..f97d09264 --- /dev/null +++ b/app/views/RoomView/UploadProgress.js @@ -0,0 +1,158 @@ +import React, { Component } from 'react'; +import { View, Text, StyleSheet, TouchableOpacity, ScrollView } from 'react-native'; +import PropTypes from 'prop-types'; +import Icon from 'react-native-vector-icons/MaterialIcons'; +import { responsive } from 'react-native-responsive-ui'; + +import database from '../../lib/realm'; +import RocketChat from '../../lib/rocketchat'; +import log from '../../utils/log'; +import I18n from '../../i18n'; + +const styles = StyleSheet.create({ + container: { + position: 'absolute', + top: 0, + width: '100%', + maxHeight: 246 + }, + item: { + backgroundColor: '#F1F2F4', + height: 54, + borderBottomWidth: StyleSheet.hairlineWidth, + borderColor: '#CACED1', + justifyContent: 'center', + paddingHorizontal: 20 + }, + row: { + flexDirection: 'row', + alignItems: 'center' + }, + descriptionContainer: { + flexDirection: 'column', + flex: 1, + marginLeft: 10 + }, + descriptionText: { + fontSize: 16, + lineHeight: 20, + color: '#54585E' + }, + progress: { + position: 'absolute', + bottom: 0, + backgroundColor: '#1D74F5', + height: 3 + }, + tryAgainButtonText: { + color: '#1D74F5', + fontSize: 16, + fontWeight: '500', + lineHeight: 20 + } +}); + +@responsive +export default class UploadProgress extends Component { + static propTypes = { + window: PropTypes.object, + rid: PropTypes.string + } + + constructor(props) { + super(props); + this.state = { + uploads: [] + }; + this.uploads = database.objects('uploads').filtered('rid = $0', this.props.rid); + this.uploads.addListener(this.updateUploads); + } + + componentDidMount() { + this.uploads.forEach((u) => { + if (!RocketChat.isUploadActive(u.path)) { + database.write(() => { + const [upload] = database.objects('uploads').filtered('path = $0', u.path); + if (upload) { + upload.error = true; + } + }); + } + }); + } + + componentWillUnmount() { + this.uploads.removeAllListeners(); + } + + deleteUpload = (item) => { + database.write(() => database.delete(item)); + } + + cancelUpload = async(item) => { + try { + await RocketChat.cancelUpload(item.path); + } catch (e) { + log('UploadProgess.cancelUpload', e); + } + } + + tryAgain = async(item) => { + try { + database.write(() => { + item.error = false; + }); + await RocketChat.sendFileMessage(this.props.rid, JSON.parse(JSON.stringify(item))); + } catch (e) { + log('UploadProgess.tryAgain', e); + } + } + + updateUploads = () => { + this.setState({ uploads: this.uploads }); + } + + renderItemContent = (item) => { + if (!item.error) { + return ( + [ + <View key='row' style={styles.row}> + <Icon name='image' size={20} color='#9EA2A8' /> + <Text style={[styles.descriptionContainer, styles.descriptionText]} ellipsizeMode='tail' numberOfLines={1}> + {I18n.t('Uploading')} {item.name} + </Text> + <Icon name='close' size={20} color='#9EA2A8' onPress={() => this.cancelUpload(item)} /> + </View>, + <View key='progress' style={[styles.progress, { width: (this.props.window.width * item.progress) / 100 }]} /> + ] + ); + } + return ( + <View style={styles.row}> + <Icon name='warning' size={20} color='#FF5050' /> + <View style={styles.descriptionContainer}> + <Text style={styles.descriptionText}>{I18n.t('Error_uploading')} {item.name}</Text> + <TouchableOpacity onPress={() => this.tryAgain(item)}> + <Text style={styles.tryAgainButtonText}>{I18n.t('Try_again')}</Text> + </TouchableOpacity> + </View> + <Icon name='close' size={20} color='#9EA2A8' onPress={() => this.deleteUpload(item)} /> + </View> + ); + } + + renderItem = (item, index) => ( + <View key={item.path} style={[styles.item, index !== 0 ? { marginTop: 10 } : {}]}> + {this.renderItemContent(item)} + </View> + ); + + render() { + const { uploads } = this.state; + return ( + <ScrollView style={styles.container}> + {uploads.map((item, i) => this.renderItem(item, i))} + </ScrollView> + ); + } +} diff --git a/app/views/RoomView/index.js b/app/views/RoomView/index.js index 747e851f4..d55ffc468 100644 --- a/app/views/RoomView/index.js +++ b/app/views/RoomView/index.js @@ -15,6 +15,7 @@ import MessageActions from '../../containers/MessageActions'; import MessageErrorActions from '../../containers/MessageErrorActions'; import MessageBox from '../../containers/MessageBox'; import ReactionPicker from './ReactionPicker'; +import UploadProgress from './UploadProgress'; import styles from './styles'; import log from '../../utils/log'; import I18n from '../../i18n'; @@ -289,6 +290,7 @@ export default class RoomView extends LoggedView { null} {this.props.showErrorActions ? <MessageErrorActions /> : null} <ReactionPicker onEmojiSelected={this.onReactionPress} /> + <UploadProgress rid={this.rid} /> </View> ); } diff --git a/ios/RocketChatRN.xcodeproj/project.pbxproj b/ios/RocketChatRN.xcodeproj/project.pbxproj index 6d9c468d1..22d04ece0 100644 --- a/ios/RocketChatRN.xcodeproj/project.pbxproj +++ b/ios/RocketChatRN.xcodeproj/project.pbxproj @@ -14,6 +14,7 @@ 00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */; }; 00E356F31AD99517003FC87E /* RocketChatRNTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* RocketChatRNTests.m */; }; 09CB5909C1E64707832358CE /* libRNI18n-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C01CD6D4653143EEB5100C3A /* libRNI18n-tvOS.a */; }; + 0AC2050A2CA1485DAC130425 /* Feather.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 72FB6BA830CE4EEBAC92BF54 /* Feather.ttf */; }; 0C6E2DE448364EA896869ADF /* libc++.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = B37C79D9BD0742CE936B6982 /* libc++.tbd */; }; 0DC38A29B0E54AF4AF96CB95 /* MaterialCommunityIcons.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 2EADB1731B5E47D093292B59 /* MaterialCommunityIcons.ttf */; }; 133E29F31AD74F7200F7D852 /* libRCTLinking.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 78C398B91ACF4ADC00677621 /* libRCTLinking.a */; }; @@ -56,6 +57,11 @@ 7A3562E620E1569000A4CF66 /* libReactNativeNavigation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7A3562E520E1567900A4CF66 /* libReactNativeNavigation.a */; }; 7A430E4F20238C46008F55BC /* libRCTCustomInputController.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7A430E1E20238C02008F55BC /* libRCTCustomInputController.a */; }; 7A8DEB5A20ED0BEC00C5DCE4 /* libRNNotifications.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7A8DEB5220ED0BDE00C5DCE4 /* libRNNotifications.a */; }; + 7A6EDBDC20ED6DCF0086E097 /* ImageCropPickerSDK in Resources */ = {isa = PBXBuildFile; fileRef = 7A6EDBDB20ED6DCF0086E097 /* ImageCropPickerSDK */; }; + 7A6EDBDE20ED6E010086E097 /* RSKImageCropper.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7A6EDBDD20ED6E010086E097 /* RSKImageCropper.framework */; }; + 7A6EDBDF20ED6E010086E097 /* RSKImageCropper.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 7A6EDBDD20ED6E010086E097 /* RSKImageCropper.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 7A6EDBE220ED6E0E0086E097 /* QBImagePicker.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7A6EDBE120ED6E0E0086E097 /* QBImagePicker.framework */; }; + 7A6EDBE320ED6E0E0086E097 /* QBImagePicker.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 7A6EDBE120ED6E0E0086E097 /* QBImagePicker.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 7AFB806E205AE65700D004E7 /* libRCTToast.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7AFB804C205AE63100D004E7 /* libRCTToast.a */; }; 832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 832341B51AAA6A8300B99B32 /* libRCTText.a */; }; 8A159EDB97C44E52AF62D69C /* libRNSVG.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DA50CE47374C4C35BE6D9D58 /* libRNSVG.a */; }; @@ -70,9 +76,9 @@ B8E79AF41F3CD167005B464F /* Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB61A68108700A75B9A /* Info.plist */; }; BAB7DC22804246F3923A1833 /* libFastImage.a in Frameworks */ = {isa = PBXBuildFile; fileRef = FD2E2837F110483CA29EE0D4 /* libFastImage.a */; }; BED2B77AA660460E8BC9F8E0 /* libRNFetchBlob.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 6533FB90166345D29F1B91C0 /* libRNFetchBlob.a */; }; - C758F0BD5C3244E2BA073E61 /* libRNImagePicker.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B696712EE2345A59F007A88 /* libRNImagePicker.a */; }; CBD0E0A35B174C4DBFED3B31 /* Zocial.ttf in Resources */ = {isa = PBXBuildFile; fileRef = E528DE3A405E43B4A37ABA68 /* Zocial.ttf */; }; D6408D9E4A864FF6BA986857 /* SimpleLineIcons.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 8A2DD67ADD954AD9873F45FC /* SimpleLineIcons.ttf */; }; + E27A0F0529F74A6E80BBAA8C /* libimageCropPicker.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A34D902CC074FF1BCC7DB48 /* libimageCropPicker.a */; }; EF736EF520A64AE8820E684A /* libRealmReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DF26CC845883492D8AC8869B /* libRealmReact.a */; }; F5BF54DC78E1411B8343933B /* libRNI18n.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 921481B47B50490CA761932E /* libRNI18n.a */; }; /* End PBXBuildFile section */ @@ -295,13 +301,6 @@ remoteGlobalIDString = F60690131CA2766F0003FB26; remoteInfo = RealmReact; }; - 60B837831F3F6F4C00677E56 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4B38C7E37A8748E0BC665078 /* RNImagePicker.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 014A3B5C1C6CF33500B6D375; - remoteInfo = RNImagePicker; - }; 78C398B81ACF4ADC00677621 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */; @@ -337,6 +336,13 @@ remoteGlobalIDString = 39DF4FE71E00394E00F5B4B2; remoteInfo = RCTCustomInputController; }; + 7A6EDBD920ED6CBB0086E097 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 8031BD2B0F824A0D8510616B /* imageCropPicker.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 3400A8081CEB54A6008A0BC7; + remoteInfo = imageCropPicker; + }; 7A770EC120BECDC7001AD51A /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 1845C223DA364898A8400573 /* FastImage.xcodeproj */; @@ -372,6 +378,13 @@ remoteGlobalIDString = 641E28441F0EEC8500443AF6; remoteInfo = "RCTVideo-tvOS"; }; + 7A8C915220F39A8000C8F5EE /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 0B82BCC462E84F308C5B5CD1 /* RNFetchBlob.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = A15C300E1CD25C330074CB35; + remoteInfo = RNFetchBlob; + }; 7A8DEB5120ED0BDE00C5DCE4 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 7A8DEB1B20ED0BDE00C5DCE4 /* RNNotifications.xcodeproj */; @@ -470,13 +483,6 @@ remoteGlobalIDString = D834CED81CC64F2400FA5668; remoteInfo = KeyboardTrackingView; }; - B8E79A8D1F3CCC6D005B464F /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4CD38E4891ED4601B7481448 /* RNFetchBlob.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = A15C300E1CD25C330074CB35; - remoteInfo = RNFetchBlob; - }; B8E79A901F3CCC6D005B464F /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 22A8B76C8EBA443BB97CE82D /* RNVectorIcons.xcodeproj */; @@ -500,6 +506,21 @@ }; /* End PBXContainerItemProxy section */ +/* Begin PBXCopyFilesBuildPhase section */ + 7A6EDBE020ED6E020086E097 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 7A6EDBDF20ED6E010086E097 /* RSKImageCropper.framework in Embed Frameworks */, + 7A6EDBE320ED6E0E0086E097 /* QBImagePicker.framework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + /* Begin PBXFileReference section */ 008F07F21AC5B25A0029DE68 /* main.jsbundle */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = main.jsbundle; sourceTree = "<group>"; }; 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTActionSheet.xcodeproj; path = "../node_modules/react-native/Libraries/ActionSheetIOS/RCTActionSheet.xcodeproj"; sourceTree = "<group>"; }; @@ -511,6 +532,7 @@ 00E356F11AD99517003FC87E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; 00E356F21AD99517003FC87E /* RocketChatRNTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RocketChatRNTests.m; sourceTree = "<group>"; }; 06BB44DD4855498082A744AD /* libz.tbd */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; }; + 0B82BCC462E84F308C5B5CD1 /* RNFetchBlob.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RNFetchBlob.xcodeproj; path = "../node_modules/rn-fetch-blob/ios/RNFetchBlob.xcodeproj"; sourceTree = "<group>"; }; 1142E3442BA94B19BCF52814 /* libRNAudio.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNAudio.a; sourceTree = "<group>"; }; 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTSettings.xcodeproj; path = "../node_modules/react-native/Libraries/Settings/RCTSettings.xcodeproj"; sourceTree = "<group>"; }; 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTWebSocket.xcodeproj; path = "../node_modules/react-native/Libraries/WebSocket/RCTWebSocket.xcodeproj"; sourceTree = "<group>"; }; @@ -523,6 +545,7 @@ 13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = RocketChatRN/main.m; sourceTree = "<group>"; }; 146833FF1AC3E56700842450 /* React.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = React.xcodeproj; path = "../node_modules/react-native/React/React.xcodeproj"; sourceTree = "<group>"; }; 1845C223DA364898A8400573 /* FastImage.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = FastImage.xcodeproj; path = "../node_modules/react-native-fast-image/ios/FastImage.xcodeproj"; sourceTree = "<group>"; }; + 1A34D902CC074FF1BCC7DB48 /* libimageCropPicker.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libimageCropPicker.a; sourceTree = "<group>"; }; 1B0746E708284151B8AD1198 /* Ionicons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = file; name = Ionicons.ttf; path = "../node_modules/react-native-vector-icons/Fonts/Ionicons.ttf"; sourceTree = "<group>"; }; 1D3BB00B9ABF44EA9BD71318 /* libSafariViewManager.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libSafariViewManager.a; sourceTree = "<group>"; }; 20CE3E407E0D4D9E8C9885F2 /* libRCTVideo.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRCTVideo.a; sourceTree = "<group>"; }; @@ -535,13 +558,12 @@ 3B696712EE2345A59F007A88 /* libRNImagePicker.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNImagePicker.a; sourceTree = "<group>"; }; 4019A5E1911B4C61944FBCEC /* SafariViewManager.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = SafariViewManager.xcodeproj; path = "../node_modules/react-native-safari-view/SafariViewManager.xcodeproj"; sourceTree = "<group>"; }; 41FE03CD3B554249859F01BA /* RNZeroconf.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RNZeroconf.xcodeproj; path = "../node_modules/react-native-zeroconf/ios/RNZeroconf.xcodeproj"; sourceTree = "<group>"; }; - 4B38C7E37A8748E0BC665078 /* RNImagePicker.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RNImagePicker.xcodeproj; path = "../node_modules/react-native-image-picker/ios/RNImagePicker.xcodeproj"; sourceTree = "<group>"; }; - 4CD38E4891ED4601B7481448 /* RNFetchBlob.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RNFetchBlob.xcodeproj; path = "../node_modules/react-native-fetch-blob/ios/RNFetchBlob.xcodeproj"; sourceTree = "<group>"; }; 5A0EEFAF8AB14F5B9E796CDD /* libRNVectorIcons.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNVectorIcons.a; sourceTree = "<group>"; }; 5A8684E7C27E426C9206E980 /* RealmReact.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RealmReact.xcodeproj; path = "../node_modules/realm/react-native/ios/RealmReact.xcodeproj"; sourceTree = "<group>"; }; 5E91572D1DD0AC6500FF2AA8 /* RCTAnimation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTAnimation.xcodeproj; path = "../node_modules/react-native/Libraries/NativeAnimation/RCTAnimation.xcodeproj"; sourceTree = "<group>"; }; 60B2A6A31FC4588700BD58E5 /* RocketChatRN.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = RocketChatRN.entitlements; path = RocketChatRN/RocketChatRN.entitlements; sourceTree = "<group>"; }; 6533FB90166345D29F1B91C0 /* libRNFetchBlob.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNFetchBlob.a; sourceTree = "<group>"; }; + 72FB6BA830CE4EEBAC92BF54 /* Feather.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Feather.ttf; path = "../node_modules/react-native-vector-icons/Fonts/Feather.ttf"; sourceTree = "<group>"; }; 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTLinking.xcodeproj; path = "../node_modules/react-native/Libraries/LinkingIOS/RCTLinking.xcodeproj"; sourceTree = "<group>"; }; 7A2D1FE620726EF600D0AA04 /* SMXCrashlytics.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = SMXCrashlytics.xcodeproj; path = "../node_modules/react-native-fabric/ios/SMXCrashlytics.xcodeproj"; sourceTree = "<group>"; }; 7A309C9B20724870000C6B13 /* Fabric.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; name = Fabric.sh; path = RocketChatRN/Fabric.sh; sourceTree = "<group>"; }; @@ -551,7 +573,11 @@ 7A3562E020E1567900A4CF66 /* ReactNativeNavigation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = ReactNativeNavigation.xcodeproj; path = "../node_modules/react-native-navigation/ios/ReactNativeNavigation.xcodeproj"; sourceTree = "<group>"; }; 7A430E1620238C01008F55BC /* RCTCustomInputController.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTCustomInputController.xcodeproj; path = "../node_modules/react-native-keyboard-input/lib/ios/RCTCustomInputController.xcodeproj"; sourceTree = "<group>"; }; 7A8DEB1B20ED0BDE00C5DCE4 /* RNNotifications.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RNNotifications.xcodeproj; path = "../node_modules/react-native-notifications/RNNotifications/RNNotifications.xcodeproj"; sourceTree = "<group>"; }; + 7A6EDBDB20ED6DCF0086E097 /* ImageCropPickerSDK */ = {isa = PBXFileReference; lastKnownFileType = folder; name = ImageCropPickerSDK; path = "../node_modules/react-native-image-crop-picker/ios/ImageCropPickerSDK"; sourceTree = "<group>"; }; + 7A6EDBDD20ED6E010086E097 /* RSKImageCropper.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = RSKImageCropper.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 7A6EDBE120ED6E0E0086E097 /* QBImagePicker.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = QBImagePicker.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 7AFB8035205AE63000D004E7 /* RCTToast.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTToast.xcodeproj; path = "../node_modules/@remobile/react-native-toast/ios/RCTToast.xcodeproj"; sourceTree = "<group>"; }; + 8031BD2B0F824A0D8510616B /* imageCropPicker.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = imageCropPicker.xcodeproj; path = "../node_modules/react-native-image-crop-picker/ios/imageCropPicker.xcodeproj"; sourceTree = "<group>"; }; 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTText.xcodeproj; path = "../node_modules/react-native/Libraries/Text/RCTText.xcodeproj"; sourceTree = "<group>"; }; 8A2DD67ADD954AD9873F45FC /* SimpleLineIcons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = SimpleLineIcons.ttf; path = "../node_modules/react-native-vector-icons/Fonts/SimpleLineIcons.ttf"; sourceTree = "<group>"; }; 921481B47B50490CA761932E /* libRNI18n.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNI18n.a; sourceTree = "<group>"; }; @@ -610,17 +636,19 @@ EF736EF520A64AE8820E684A /* libRealmReact.a in Frameworks */, 0C6E2DE448364EA896869ADF /* libc++.tbd in Frameworks */, 24A2AEF2383D44B586D31C01 /* libz.tbd in Frameworks */, + 7A6EDBE220ED6E0E0086E097 /* QBImagePicker.framework in Frameworks */, 33647F7997A2493E9E1343B3 /* libRNZeroconf.a in Frameworks */, BED2B77AA660460E8BC9F8E0 /* libRNFetchBlob.a in Frameworks */, 77C35F50C01C43668188886C /* libRNVectorIcons.a in Frameworks */, 8A159EDB97C44E52AF62D69C /* libRNSVG.a in Frameworks */, - C758F0BD5C3244E2BA073E61 /* libRNImagePicker.a in Frameworks */, + 7A6EDBDE20ED6E010086E097 /* RSKImageCropper.framework in Frameworks */, 8ECBD927DDAC4987B98E102E /* libRCTVideo.a in Frameworks */, 7A32C247206D791D001C80E9 /* Crashlytics.framework in Frameworks */, 2C800DF680F8451599E80AF1 /* libSafariViewManager.a in Frameworks */, 74815BBCB91147C08C8F7B3D /* libRNAudio.a in Frameworks */, BAB7DC22804246F3923A1833 /* libFastImage.a in Frameworks */, F5BF54DC78E1411B8343933B /* libRNI18n.a in Frameworks */, + E27A0F0529F74A6E80BBAA8C /* libimageCropPicker.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -793,14 +821,6 @@ name = Products; sourceTree = "<group>"; }; - 60B8375C1F3F6F4B00677E56 /* Products */ = { - isa = PBXGroup; - children = ( - 60B837841F3F6F4C00677E56 /* libRNImagePicker.a */, - ); - name = Products; - sourceTree = "<group>"; - }; 78C398B11ACF4ADC00677621 /* Products */ = { isa = PBXGroup; children = ( @@ -835,6 +855,14 @@ name = Products; sourceTree = "<group>"; }; + 7A6EDBD620ED6CBB0086E097 /* Products */ = { + isa = PBXGroup; + children = ( + 7A6EDBDA20ED6CBB0086E097 /* libimageCropPicker.a */, + ); + name = Products; + sourceTree = "<group>"; + }; 7A770EBC20BECDC7001AD51A /* Products */ = { isa = PBXGroup; children = ( @@ -861,6 +889,14 @@ name = Products; sourceTree = "<group>"; }; + 7A8C912120F39A8000C8F5EE /* Products */ = { + isa = PBXGroup; + children = ( + 7A8C915320F39A8000C8F5EE /* libRNFetchBlob.a */, + ); + name = Products; + sourceTree = "<group>"; + }; 7A8DEB1C20ED0BDE00C5DCE4 /* Products */ = { isa = PBXGroup; children = ( @@ -900,15 +936,15 @@ 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */, 5A8684E7C27E426C9206E980 /* RealmReact.xcodeproj */, 41FE03CD3B554249859F01BA /* RNZeroconf.xcodeproj */, - 4CD38E4891ED4601B7481448 /* RNFetchBlob.xcodeproj */, 22A8B76C8EBA443BB97CE82D /* RNVectorIcons.xcodeproj */, C23AEF1D9EBE4A38A1A6B97B /* RNSVG.xcodeproj */, - 4B38C7E37A8748E0BC665078 /* RNImagePicker.xcodeproj */, AD0379F2BCE84C968538CDAF /* RCTVideo.xcodeproj */, 4019A5E1911B4C61944FBCEC /* SafariViewManager.xcodeproj */, C21010507E5B4B37BA0E4C9D /* RNAudio.xcodeproj */, 1845C223DA364898A8400573 /* FastImage.xcodeproj */, 22D3971EAF2E4660B4FAB3DD /* RNI18n.xcodeproj */, + 8031BD2B0F824A0D8510616B /* imageCropPicker.xcodeproj */, + 0B82BCC462E84F308C5B5CD1 /* RNFetchBlob.xcodeproj */, ); name = Libraries; sourceTree = "<group>"; @@ -925,6 +961,9 @@ 83CBB9F61A601CBA00E9B192 = { isa = PBXGroup; children = ( + 7A6EDBE120ED6E0E0086E097 /* QBImagePicker.framework */, + 7A6EDBDD20ED6E010086E097 /* RSKImageCropper.framework */, + 7A6EDBDB20ED6DCF0086E097 /* ImageCropPickerSDK */, 7A32C245206D791D001C80E9 /* Crashlytics.framework */, 7A32C20F206D791D001C80E9 /* Fabric.framework */, 13B07FAE1A68108700A75B9A /* RocketChatRN */, @@ -972,6 +1011,7 @@ F88C6541BD764BEEABB87272 /* Octicons.ttf */, 8A2DD67ADD954AD9873F45FC /* SimpleLineIcons.ttf */, E528DE3A405E43B4A37ABA68 /* Zocial.ttf */, + 72FB6BA830CE4EEBAC92BF54 /* Feather.ttf */, ); name = Resources; sourceTree = "<group>"; @@ -1017,18 +1057,11 @@ FD2E2837F110483CA29EE0D4 /* libFastImage.a */, 921481B47B50490CA761932E /* libRNI18n.a */, C01CD6D4653143EEB5100C3A /* libRNI18n-tvOS.a */, + 1A34D902CC074FF1BCC7DB48 /* libimageCropPicker.a */, ); name = "Recovered References"; sourceTree = "<group>"; }; - B8E79A881F3CCC6C005B464F /* Products */ = { - isa = PBXGroup; - children = ( - B8E79A8E1F3CCC6D005B464F /* libRNFetchBlob.a */, - ); - name = Products; - sourceTree = "<group>"; - }; B8E79A8A1F3CCC6C005B464F /* Products */ = { isa = PBXGroup; children = ( @@ -1084,6 +1117,7 @@ 13B07F8C1A680F5B00A75B9A /* Frameworks */, 13B07F8E1A680F5B00A75B9A /* Resources */, 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */, + 7A6EDBE020ED6E020086E097 /* Embed Frameworks */, ); buildRules = ( ); @@ -1182,6 +1216,10 @@ ProductGroup = 7A770EBE20BECDC7001AD51A /* Products */; ProjectRef = 1845C223DA364898A8400573 /* FastImage.xcodeproj */; }, + { + ProductGroup = 7A6EDBD620ED6CBB0086E097 /* Products */; + ProjectRef = 8031BD2B0F824A0D8510616B /* imageCropPicker.xcodeproj */; + }, { ProductGroup = B8971BAD202A091D0000D245 /* Products */; ProjectRef = B8971BAC202A091D0000D245 /* KeyboardTrackingView.xcodeproj */; @@ -1259,17 +1297,13 @@ ProjectRef = C21010507E5B4B37BA0E4C9D /* RNAudio.xcodeproj */; }, { - ProductGroup = B8E79A881F3CCC6C005B464F /* Products */; - ProjectRef = 4CD38E4891ED4601B7481448 /* RNFetchBlob.xcodeproj */; + ProductGroup = 7A8C912120F39A8000C8F5EE /* Products */; + ProjectRef = 0B82BCC462E84F308C5B5CD1 /* RNFetchBlob.xcodeproj */; }, { ProductGroup = 7A770EBC20BECDC7001AD51A /* Products */; ProjectRef = 22D3971EAF2E4660B4FAB3DD /* RNI18n.xcodeproj */; }, - { - ProductGroup = 60B8375C1F3F6F4B00677E56 /* Products */; - ProjectRef = 4B38C7E37A8748E0BC665078 /* RNImagePicker.xcodeproj */; - }, { ProductGroup = 7A8DEB1C20ED0BDE00C5DCE4 /* Products */; ProjectRef = 7A8DEB1B20ED0BDE00C5DCE4 /* RNNotifications.xcodeproj */; @@ -1509,13 +1543,6 @@ remoteRef = 607D61151F325B7E00F639C4 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 60B837841F3F6F4C00677E56 /* libRNImagePicker.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libRNImagePicker.a; - remoteRef = 60B837831F3F6F4C00677E56 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; 78C398B91ACF4ADC00677621 /* libRCTLinking.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; @@ -1551,6 +1578,13 @@ remoteRef = 7A430E1D20238C02008F55BC /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; + 7A6EDBDA20ED6CBB0086E097 /* libimageCropPicker.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libimageCropPicker.a; + remoteRef = 7A6EDBD920ED6CBB0086E097 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; 7A770EC220BECDC7001AD51A /* libFastImage.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; @@ -1586,6 +1620,13 @@ remoteRef = 7A7F5C9A1FCC982500024129 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; + 7A8C915320F39A8000C8F5EE /* libRNFetchBlob.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libRNFetchBlob.a; + remoteRef = 7A8C915220F39A8000C8F5EE /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; 7A8DEB5220ED0BDE00C5DCE4 /* libRNNotifications.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; @@ -1684,13 +1725,6 @@ remoteRef = B8971BB0202A091D0000D245 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - B8E79A8E1F3CCC6D005B464F /* libRNFetchBlob.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libRNFetchBlob.a; - remoteRef = B8E79A8D1F3CCC6D005B464F /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; B8E79A911F3CCC6D005B464F /* libRNVectorIcons.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; @@ -1736,12 +1770,14 @@ 70A8D9B456894EFFAF027CAB /* FontAwesome.ttf in Resources */, 435AB658888F41D69A230652 /* Foundation.ttf in Resources */, 4529B474417149059A180775 /* Ionicons.ttf in Resources */, + 7A6EDBDC20ED6DCF0086E097 /* ImageCropPickerSDK in Resources */, 0DC38A29B0E54AF4AF96CB95 /* MaterialCommunityIcons.ttf in Resources */, 334A709FA3B448BC9A8563F6 /* MaterialIcons.ttf in Resources */, 2684481F67844BE398381564 /* Octicons.ttf in Resources */, D6408D9E4A864FF6BA986857 /* SimpleLineIcons.ttf in Resources */, CBD0E0A35B174C4DBFED3B31 /* Zocial.ttf in Resources */, B8E79AF41F3CD167005B464F /* Info.plist in Resources */, + 0AC2050A2CA1485DAC130425 /* Feather.ttf in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1871,10 +1907,8 @@ "$(inherited)", "$(SRCROOT)/../node_modules/realm/src/**", "$(SRCROOT)/../node_modules/react-native-zeroconf/ios/RNZeroconf", - "$(SRCROOT)/../node_modules/react-native-fetch-blob/ios/**", "$(SRCROOT)/../node_modules/react-native-vector-icons/RNVectorIconsManager", "$(SRCROOT)/../node_modules/react-native-svg/ios/**", - "$(SRCROOT)/../node_modules/react-native-image-picker/ios", "$(SRCROOT)/../node_modules/react-native-navigation/ios/**", "$(SRCROOT)/../node_modules/react-native-autogrow-textinput/ios", "$(SRCROOT)/../node_modules/react-native-video/ios", @@ -1883,6 +1917,8 @@ "$(SRCROOT)/../node_modules/react-native-audio/ios", "$(SRCROOT)/../node_modules/react-native-fast-image/ios/FastImage/**", "$(SRCROOT)/../node_modules/react-native-i18n/ios", + "$(SRCROOT)/../node_modules/react-native-image-crop-picker/ios/**", + "$(SRCROOT)/../node_modules/rn-fetch-blob/ios/**", ); INFOPLIST_FILE = RocketChatRNTests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.0; @@ -1899,6 +1935,7 @@ "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", + "\"$(SRCROOT)/$(TARGET_NAME)\"", ); OTHER_LDFLAGS = ( "-ObjC", @@ -1919,10 +1956,8 @@ "$(inherited)", "$(SRCROOT)/../node_modules/realm/src/**", "$(SRCROOT)/../node_modules/react-native-zeroconf/ios/RNZeroconf", - "$(SRCROOT)/../node_modules/react-native-fetch-blob/ios/**", "$(SRCROOT)/../node_modules/react-native-vector-icons/RNVectorIconsManager", "$(SRCROOT)/../node_modules/react-native-svg/ios/**", - "$(SRCROOT)/../node_modules/react-native-image-picker/ios", "$(SRCROOT)/../node_modules/react-native-navigation/ios/**", "$(SRCROOT)/../node_modules/react-native-autogrow-textinput/ios", "$(SRCROOT)/../node_modules/react-native-video/ios", @@ -1931,6 +1966,8 @@ "$(SRCROOT)/../node_modules/react-native-audio/ios", "$(SRCROOT)/../node_modules/react-native-fast-image/ios/FastImage/**", "$(SRCROOT)/../node_modules/react-native-i18n/ios", + "$(SRCROOT)/../node_modules/react-native-image-crop-picker/ios/**", + "$(SRCROOT)/../node_modules/rn-fetch-blob/ios/**", ); INFOPLIST_FILE = RocketChatRNTests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.0; @@ -1947,6 +1984,7 @@ "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", + "\"$(SRCROOT)/$(TARGET_NAME)\"", ); OTHER_LDFLAGS = ( "-ObjC", @@ -1976,10 +2014,8 @@ "$(inherited)", "$(SRCROOT)/../node_modules/realm/src/**", "$(SRCROOT)/../node_modules/react-native-zeroconf/ios/RNZeroconf", - "$(SRCROOT)/../node_modules/react-native-fetch-blob/ios/**", "$(SRCROOT)/../node_modules/react-native-vector-icons/RNVectorIconsManager", "$(SRCROOT)/../node_modules/react-native-svg/ios/**", - "$(SRCROOT)/../node_modules/react-native-image-picker/ios", "$(SRCROOT)/../node_modules/react-native-navigation/ios/**", "$(SRCROOT)/../node_modules/react-native-autogrow-textinput/ios", "$(SRCROOT)/../node_modules/react-native/Libraries/PushNotificationIOS/RCTPushNotification.xcodeproj/**", @@ -1990,6 +2026,8 @@ "$(SRCROOT)/../node_modules/react-native-fast-image/ios/FastImage/**", "$(SRCROOT)/../node_modules/react-native-i18n/ios", "$(SRCROOT)/../node_modules/react-native-notifications/RNNotifications", + "$(SRCROOT)/../node_modules/react-native-image-crop-picker/ios/**", + "$(SRCROOT)/../node_modules/rn-fetch-blob/ios/**", ); INFOPLIST_FILE = RocketChatRN/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; @@ -2024,10 +2062,8 @@ "$(inherited)", "$(SRCROOT)/../node_modules/realm/src/**", "$(SRCROOT)/../node_modules/react-native-zeroconf/ios/RNZeroconf", - "$(SRCROOT)/../node_modules/react-native-fetch-blob/ios/**", "$(SRCROOT)/../node_modules/react-native-vector-icons/RNVectorIconsManager", "$(SRCROOT)/../node_modules/react-native-svg/ios/**", - "$(SRCROOT)/../node_modules/react-native-image-picker/ios", "$(SRCROOT)/../node_modules/react-native-navigation/ios/**", "$(SRCROOT)/../node_modules/react-native-autogrow-textinput/ios", "$(SRCROOT)/../node_modules/react-native/Libraries/PushNotificationIOS/RCTPushNotification.xcodeproj/**", @@ -2038,6 +2074,8 @@ "$(SRCROOT)/../node_modules/react-native-fast-image/ios/FastImage/**", "$(SRCROOT)/../node_modules/react-native-i18n/ios", "$(SRCROOT)/../node_modules/react-native-notifications/RNNotifications", + "$(SRCROOT)/../node_modules/react-native-image-crop-picker/ios/**", + "$(SRCROOT)/../node_modules/rn-fetch-blob/ios/**", ); INFOPLIST_FILE = RocketChatRN/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; @@ -2071,10 +2109,8 @@ "$(inherited)", "$(SRCROOT)/../node_modules/realm/src/**", "$(SRCROOT)/../node_modules/react-native-zeroconf/ios/RNZeroconf", - "$(SRCROOT)/../node_modules/react-native-fetch-blob/ios/**", "$(SRCROOT)/../node_modules/react-native-vector-icons/RNVectorIconsManager", "$(SRCROOT)/../node_modules/react-native-svg/ios/**", - "$(SRCROOT)/../node_modules/react-native-image-picker/ios", "$(SRCROOT)/../node_modules/react-native-navigation/ios/**", "$(SRCROOT)/../node_modules/react-native-autogrow-textinput/ios", "$(SRCROOT)/../node_modules/react-native-video/ios", @@ -2083,6 +2119,8 @@ "$(SRCROOT)/../node_modules/react-native-audio/ios", "$(SRCROOT)/../node_modules/react-native-fast-image/ios/FastImage/**", "$(SRCROOT)/../node_modules/react-native-i18n/ios", + "$(SRCROOT)/../node_modules/react-native-image-crop-picker/ios/**", + "$(SRCROOT)/../node_modules/rn-fetch-blob/ios/**", ); INFOPLIST_FILE = "RocketChatRN-tvOS/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; @@ -2098,6 +2136,7 @@ "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", + "\"$(SRCROOT)/$(TARGET_NAME)\"", ); OTHER_LDFLAGS = ( "-ObjC", @@ -2128,10 +2167,8 @@ "$(inherited)", "$(SRCROOT)/../node_modules/realm/src/**", "$(SRCROOT)/../node_modules/react-native-zeroconf/ios/RNZeroconf", - "$(SRCROOT)/../node_modules/react-native-fetch-blob/ios/**", "$(SRCROOT)/../node_modules/react-native-vector-icons/RNVectorIconsManager", "$(SRCROOT)/../node_modules/react-native-svg/ios/**", - "$(SRCROOT)/../node_modules/react-native-image-picker/ios", "$(SRCROOT)/../node_modules/react-native-navigation/ios/**", "$(SRCROOT)/../node_modules/react-native-autogrow-textinput/ios", "$(SRCROOT)/../node_modules/react-native-video/ios", @@ -2140,6 +2177,8 @@ "$(SRCROOT)/../node_modules/react-native-audio/ios", "$(SRCROOT)/../node_modules/react-native-fast-image/ios/FastImage/**", "$(SRCROOT)/../node_modules/react-native-i18n/ios", + "$(SRCROOT)/../node_modules/react-native-image-crop-picker/ios/**", + "$(SRCROOT)/../node_modules/rn-fetch-blob/ios/**", ); INFOPLIST_FILE = "RocketChatRN-tvOS/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; @@ -2155,6 +2194,7 @@ "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", + "\"$(SRCROOT)/$(TARGET_NAME)\"", ); OTHER_LDFLAGS = ( "-ObjC", @@ -2194,6 +2234,7 @@ "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", + "\"$(SRCROOT)/$(TARGET_NAME)\"", ); PRODUCT_BUNDLE_IDENTIFIER = "com.facebook.REACT.RocketChatRN-tvOSTests"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -2229,6 +2270,7 @@ "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", + "\"$(SRCROOT)/$(TARGET_NAME)\"", ); PRODUCT_BUNDLE_IDENTIFIER = "com.facebook.REACT.RocketChatRN-tvOSTests"; PRODUCT_NAME = "$(TARGET_NAME)"; diff --git a/ios/RocketChatRN/Info.plist b/ios/RocketChatRN/Info.plist index 9f7b25264..863c480db 100644 --- a/ios/RocketChatRN/Info.plist +++ b/ios/RocketChatRN/Info.plist @@ -83,6 +83,7 @@ <string>SimpleLineIcons.ttf</string> <string>Zocial.ttf</string> <string>icomoon.ttf</string> + <string>Feather.ttf</string> </array> <key>UILaunchStoryboardName</key> <string>LaunchScreen</string> diff --git a/package-lock.json b/package-lock.json index 2c5e80014..832b7625c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1243,9 +1243,9 @@ } }, "@types/react-native": { - "version": "0.55.27", - "resolved": "https://registry.npmjs.org/@types/react-native/-/react-native-0.55.27.tgz", - "integrity": "sha512-ysM2ih3WZZ7wYSZtuUwbDz3922qfupwCupc9wy3UgbOiU/J7JCLIKkZ1BMU6apXJEvbTwHmlH+kSPwDh8UF7Ug==", + "version": "0.56.0", + "resolved": "https://registry.npmjs.org/@types/react-native/-/react-native-0.56.0.tgz", + "integrity": "sha512-7qoX7Rb/Uu3A6uUwn4CGGOPahnh/vSDNdSywzEgUy6znbzUpx9cMmmRuyHaq/V7NCJlI+D4lE9bUCqg13xoP0Q==", "requires": { "@types/react": "*" } @@ -7255,12 +7255,14 @@ "dependencies": { "abbrev": { "version": "1.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-0FVMIlZjbi9W58LlrRg/hZQo2B8=", "optional": true }, "ajv": { "version": "4.11.8", - "bundled": true, + "resolved": false, + "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", "optional": true, "requires": { "co": "^4.6.0", @@ -7269,16 +7271,19 @@ }, "ansi-regex": { "version": "2.1.1", - "bundled": true + "resolved": false, + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" }, "aproba": { "version": "1.1.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-ldNgDwdxCqDpKYxyatXs8urLq6s=", "optional": true }, "are-we-there-yet": { "version": "1.1.4", - "bundled": true, + "resolved": false, + "integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=", "optional": true, "requires": { "delegates": "^1.0.0", @@ -7287,36 +7292,43 @@ }, "asn1": { "version": "0.2.3", - "bundled": true, + "resolved": false, + "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=", "optional": true }, "assert-plus": { "version": "0.2.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=", "optional": true }, "asynckit": { "version": "0.4.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", "optional": true }, "aws-sign2": { "version": "0.6.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=", "optional": true }, "aws4": { "version": "1.6.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=", "optional": true }, "balanced-match": { "version": "0.4.2", - "bundled": true + "resolved": false, + "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=" }, "bcrypt-pbkdf": { "version": "1.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", "optional": true, "requires": { "tweetnacl": "^0.14.3" @@ -7324,21 +7336,24 @@ }, "block-stream": { "version": "0.0.9", - "bundled": true, + "resolved": false, + "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", "requires": { "inherits": "~2.0.0" } }, "boom": { "version": "2.10.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", "requires": { "hoek": "2.x.x" } }, "brace-expansion": { "version": "1.1.7", - "bundled": true, + "resolved": false, + "integrity": "sha1-Pv/DxQ4ABTH7cg6v+A8K6O8jz1k=", "requires": { "balanced-match": "^0.4.1", "concat-map": "0.0.1" @@ -7346,51 +7361,61 @@ }, "buffer-shims": { "version": "1.0.0", - "bundled": true + "resolved": false, + "integrity": "sha1-mXjOMXOIxkmth5MCjDR37wRKi1E=" }, "caseless": { "version": "0.12.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", "optional": true }, "co": { "version": "4.6.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", "optional": true }, "code-point-at": { "version": "1.1.0", - "bundled": true + "resolved": false, + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" }, "combined-stream": { "version": "1.0.5", - "bundled": true, + "resolved": false, + "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=", "requires": { "delayed-stream": "~1.0.0" } }, "concat-map": { "version": "0.0.1", - "bundled": true + "resolved": false, + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, "console-control-strings": { "version": "1.1.0", - "bundled": true + "resolved": false, + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" }, "core-util-is": { "version": "1.0.2", - "bundled": true + "resolved": false, + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, "cryptiles": { "version": "2.0.5", - "bundled": true, + "resolved": false, + "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", "requires": { "boom": "2.x.x" } }, "dashdash": { "version": "1.14.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", "optional": true, "requires": { "assert-plus": "^1.0.0" @@ -7398,14 +7423,16 @@ "dependencies": { "assert-plus": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", "optional": true } } }, "debug": { "version": "2.6.8", - "bundled": true, + "resolved": false, + "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", "optional": true, "requires": { "ms": "2.0.0" @@ -7413,26 +7440,31 @@ }, "deep-extend": { "version": "0.4.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-SLaZwn4zS/ifEIkr5DL25MfTSn8=", "optional": true }, "delayed-stream": { "version": "1.0.0", - "bundled": true + "resolved": false, + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" }, "delegates": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", "optional": true }, "detect-libc": { "version": "1.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-ca1dIEvxempsqPRQxhRUBm70YeE=", "optional": true }, "ecc-jsbn": { "version": "0.1.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", "optional": true, "requires": { "jsbn": "~0.1.0" @@ -7440,21 +7472,25 @@ }, "extend": { "version": "3.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", "optional": true }, "extsprintf": { "version": "1.0.2", - "bundled": true + "resolved": false, + "integrity": "sha1-4QgOBljjALBilJkMxw4VAiNf1VA=" }, "forever-agent": { "version": "0.6.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", "optional": true }, "form-data": { "version": "2.1.4", - "bundled": true, + "resolved": false, + "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", "optional": true, "requires": { "asynckit": "^0.4.0", @@ -7464,11 +7500,13 @@ }, "fs.realpath": { "version": "1.0.0", - "bundled": true + "resolved": false, + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, "fstream": { "version": "1.0.11", - "bundled": true, + "resolved": false, + "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=", "requires": { "graceful-fs": "^4.1.2", "inherits": "~2.0.0", @@ -7478,7 +7516,8 @@ }, "fstream-ignore": { "version": "1.0.5", - "bundled": true, + "resolved": false, + "integrity": "sha1-nDHa40dnAY/h0kmyTa2mfQktoQU=", "optional": true, "requires": { "fstream": "^1.0.0", @@ -7488,7 +7527,8 @@ }, "gauge": { "version": "2.7.4", - "bundled": true, + "resolved": false, + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", "optional": true, "requires": { "aproba": "^1.0.3", @@ -7503,7 +7543,8 @@ }, "getpass": { "version": "0.1.7", - "bundled": true, + "resolved": false, + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", "optional": true, "requires": { "assert-plus": "^1.0.0" @@ -7511,14 +7552,16 @@ "dependencies": { "assert-plus": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", "optional": true } } }, "glob": { "version": "7.1.2", - "bundled": true, + "resolved": false, + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -7530,16 +7573,19 @@ }, "graceful-fs": { "version": "4.1.11", - "bundled": true + "resolved": false, + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" }, "har-schema": { "version": "1.0.5", - "bundled": true, + "resolved": false, + "integrity": "sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4=", "optional": true }, "har-validator": { "version": "4.2.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-M0gdDxu/9gDdID11gSpqX7oALio=", "optional": true, "requires": { "ajv": "^4.9.1", @@ -7548,12 +7594,14 @@ }, "has-unicode": { "version": "2.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", "optional": true }, "hawk": { "version": "3.1.3", - "bundled": true, + "resolved": false, + "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", "requires": { "boom": "2.x.x", "cryptiles": "2.x.x", @@ -7563,11 +7611,13 @@ }, "hoek": { "version": "2.16.3", - "bundled": true + "resolved": false, + "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=" }, "http-signature": { "version": "1.1.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", "optional": true, "requires": { "assert-plus": "^0.2.0", @@ -7577,7 +7627,8 @@ }, "inflight": { "version": "1.0.6", - "bundled": true, + "resolved": false, + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "requires": { "once": "^1.3.0", "wrappy": "1" @@ -7585,37 +7636,44 @@ }, "inherits": { "version": "2.0.3", - "bundled": true + "resolved": false, + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" }, "ini": { "version": "1.3.4", - "bundled": true, + "resolved": false, + "integrity": "sha1-BTfLedr1m1mhpRff9wbIbsA5Fi4=", "optional": true }, "is-fullwidth-code-point": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "requires": { "number-is-nan": "^1.0.0" } }, "is-typedarray": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", "optional": true }, "isarray": { "version": "1.0.0", - "bundled": true + "resolved": false, + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, "isstream": { "version": "0.1.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", "optional": true }, "jodid25519": { "version": "1.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-BtSRIlUJNBlHfUJWM2BuDpB4KWc=", "optional": true, "requires": { "jsbn": "~0.1.0" @@ -7623,17 +7681,20 @@ }, "jsbn": { "version": "0.1.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", "optional": true }, "json-schema": { "version": "0.2.3", - "bundled": true, + "resolved": false, + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", "optional": true }, "json-stable-stringify": { "version": "1.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", "optional": true, "requires": { "jsonify": "~0.0.0" @@ -7641,17 +7702,20 @@ }, "json-stringify-safe": { "version": "5.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", "optional": true }, "jsonify": { "version": "0.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", "optional": true }, "jsprim": { "version": "1.4.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-o7h+QCmNjDgFUtjMdiigu5WiKRg=", "optional": true, "requires": { "assert-plus": "1.0.0", @@ -7662,48 +7726,56 @@ "dependencies": { "assert-plus": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", "optional": true } } }, "mime-db": { "version": "1.27.0", - "bundled": true + "resolved": false, + "integrity": "sha1-gg9XIpa70g7CXtVeW13oaeVDbrE=" }, "mime-types": { "version": "2.1.15", - "bundled": true, + "resolved": false, + "integrity": "sha1-pOv1BkCUVpI3uM9wBGd20J/JKu0=", "requires": { "mime-db": "~1.27.0" } }, "minimatch": { "version": "3.0.4", - "bundled": true, + "resolved": false, + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "requires": { "brace-expansion": "^1.1.7" } }, "minimist": { "version": "0.0.8", - "bundled": true + "resolved": false, + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" }, "mkdirp": { "version": "0.5.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", "requires": { "minimist": "0.0.8" } }, "ms": { "version": "2.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "optional": true }, "node-pre-gyp": { "version": "0.6.39", - "bundled": true, + "resolved": false, + "integrity": "sha512-OsJV74qxnvz/AMGgcfZoDaeDXKD3oY3QVIbBmwszTFkRisTSXbMQyn4UWzUMOtA5SVhrBZOTp0wcoSBgfMfMmQ==", "optional": true, "requires": { "detect-libc": "^1.0.2", @@ -7721,7 +7793,8 @@ }, "nopt": { "version": "4.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", "optional": true, "requires": { "abbrev": "1", @@ -7730,7 +7803,8 @@ }, "npmlog": { "version": "4.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-ocolIkZYZt8UveuiDS0yAkkIjid1o7lPG8cYm05yNYzBn8ykQtaiPMEGp8fY9tKdDgm8okpdKzkvu1y9hUYugA==", "optional": true, "requires": { "are-we-there-yet": "~1.1.2", @@ -7741,38 +7815,45 @@ }, "number-is-nan": { "version": "1.0.1", - "bundled": true + "resolved": false, + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" }, "oauth-sign": { "version": "0.8.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", "optional": true }, "object-assign": { "version": "4.1.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", "optional": true }, "once": { "version": "1.4.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "requires": { "wrappy": "1" } }, "os-homedir": { "version": "1.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", "optional": true }, "os-tmpdir": { "version": "1.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "optional": true }, "osenv": { "version": "0.1.4", - "bundled": true, + "resolved": false, + "integrity": "sha1-Qv5tWVPfBsgGS+bxdsPQWqqjRkQ=", "optional": true, "requires": { "os-homedir": "^1.0.0", @@ -7781,30 +7862,36 @@ }, "path-is-absolute": { "version": "1.0.1", - "bundled": true + "resolved": false, + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" }, "performance-now": { "version": "0.2.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=", "optional": true }, "process-nextick-args": { "version": "1.0.7", - "bundled": true + "resolved": false, + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" }, "punycode": { "version": "1.4.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", "optional": true }, "qs": { "version": "6.4.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=", "optional": true }, "rc": { "version": "1.2.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-LgPo5C7kULjLPc5lvhv4l04d/ZU=", "optional": true, "requires": { "deep-extend": "~0.4.0", @@ -7815,14 +7902,16 @@ "dependencies": { "minimist": { "version": "1.2.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "optional": true } } }, "readable-stream": { "version": "2.2.9", - "bundled": true, + "resolved": false, + "integrity": "sha1-z3jsb0ptHrQ9JkiMrJfwQudLf8g=", "requires": { "buffer-shims": "~1.0.0", "core-util-is": "~1.0.0", @@ -7835,7 +7924,8 @@ }, "request": { "version": "2.81.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA=", "optional": true, "requires": { "aws-sign2": "~0.6.0", @@ -7864,40 +7954,47 @@ }, "rimraf": { "version": "2.6.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-wjOOxkPfeht/5cVPqG9XQopV8z0=", "requires": { "glob": "^7.0.5" } }, "safe-buffer": { "version": "5.0.1", - "bundled": true + "resolved": false, + "integrity": "sha1-0mPKVGls2KMGtcplUekt5XkY++c=" }, "semver": { "version": "5.3.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", "optional": true }, "set-blocking": { "version": "2.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "optional": true }, "signal-exit": { "version": "3.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", "optional": true }, "sntp": { "version": "1.0.9", - "bundled": true, + "resolved": false, + "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", "requires": { "hoek": "2.x.x" } }, "sshpk": { "version": "1.13.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-/yo+T9BEl1Vf7Zezmg/YL6+zozw=", "optional": true, "requires": { "asn1": "~0.2.3", @@ -7913,14 +8010,16 @@ "dependencies": { "assert-plus": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", "optional": true } } }, "string-width": { "version": "1.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -7929,31 +8028,36 @@ }, "string_decoder": { "version": "1.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-YuIA8DmVWmgQ2N8KM//A8BNmLZg=", "requires": { "safe-buffer": "^5.0.1" } }, "stringstream": { "version": "0.0.5", - "bundled": true, + "resolved": false, + "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=", "optional": true }, "strip-ansi": { "version": "3.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "requires": { "ansi-regex": "^2.0.0" } }, "strip-json-comments": { "version": "2.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", "optional": true }, "tar": { "version": "2.2.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=", "requires": { "block-stream": "*", "fstream": "^1.0.2", @@ -7962,7 +8066,8 @@ }, "tar-pack": { "version": "3.4.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-I74tf2cagzk3bL2wuP4/3r8xeYQ=", "optional": true, "requires": { "debug": "^2.2.0", @@ -7977,7 +8082,8 @@ }, "tough-cookie": { "version": "2.3.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-8IH3bkyFcg5sN6X6ztc3FQ2EByo=", "optional": true, "requires": { "punycode": "^1.4.1" @@ -7985,7 +8091,8 @@ }, "tunnel-agent": { "version": "0.6.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", "optional": true, "requires": { "safe-buffer": "^5.0.1" @@ -7993,26 +8100,31 @@ }, "tweetnacl": { "version": "0.14.5", - "bundled": true, + "resolved": false, + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", "optional": true }, "uid-number": { "version": "0.0.6", - "bundled": true, + "resolved": false, + "integrity": "sha1-DqEOgDXo61uOREnwbaHHMGY7qoE=", "optional": true }, "util-deprecate": { "version": "1.0.2", - "bundled": true + "resolved": false, + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, "uuid": { "version": "3.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-ZUS7ot/ajBzxfmKaOjBeK7H+5sE=", "optional": true }, "verror": { "version": "1.3.6", - "bundled": true, + "resolved": false, + "integrity": "sha1-z/XfEpRtKX0rqu+qJoniW+AcAFw=", "optional": true, "requires": { "extsprintf": "1.0.2" @@ -8020,7 +8132,8 @@ }, "wide-align": { "version": "1.1.2", - "bundled": true, + "resolved": false, + "integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==", "optional": true, "requires": { "string-width": "^1.0.2" @@ -8028,7 +8141,8 @@ }, "wrappy": { "version": "1.0.2", - "bundled": true + "resolved": false, + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" } } }, @@ -9298,9 +9412,9 @@ "integrity": "sha1-MRYKNpMK2vH8BMYHT360FGXU7Es=" }, "i18n-js": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/i18n-js/-/i18n-js-3.0.3.tgz", - "integrity": "sha512-u144MQhV/8mz4Y5wP86SQAWMwS8gpe/JavIa9hugSI4WreezGgbhJPdk2Q60KcdIltKLiNefGtHNh1N8SSmQqQ==" + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/i18n-js/-/i18n-js-3.0.11.tgz", + "integrity": "sha512-v7dG3kYJTQTyox3NqDabPDE/ZotWntyMI9kh4cYi+XlCSnsIR+KBTS2opPyObL8WndnklcLzbNU92FP/mLge3Q==" }, "iconv-lite": { "version": "0.4.19", @@ -12176,9 +12290,9 @@ } }, "js-base64": { - "version": "2.4.5", - "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.4.5.tgz", - "integrity": "sha512-aUnNwqMOXw3yvErjMPSQu6qIIzUmT1e5KcU1OZxRDU1g/am6mzBvcrmLAYwzmB59BHPrh5/tKaiF4OPhqRWESQ==" + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.4.6.tgz", + "integrity": "sha512-O9SR2NVICx6rCqh1qsU91QZ5IoNa+2T1ROJ0OQlfvATKGmnjsAvg3r0E5ufPZ4a95jdKTPXhFWiE/sOZ7a5Rtg==" }, "js-sha256": { "version": "0.9.0", @@ -12494,9 +12608,9 @@ "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==" }, "lodash-es": { - "version": "4.17.8", - "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.8.tgz", - "integrity": "sha512-I9mjAxengFAleSThFhhAhvba6fsO0hunb9/0sQ6qQihSZsJRBofv2rYH58WXaOb/O++eUmYpCLywSQ22GfU+sA==", + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.10.tgz", + "integrity": "sha512-iesFYPmxYYGTcmQK0sL8bX3TGHyM6b2qREaB4kamHfQyfPJP0xgoGxp19nsH16nsfquLdiyKyX3mQkfiSGV8Rg==", "dev": true }, "lodash._getnative": { @@ -16462,30 +16576,6 @@ "prop-types": "^15.5.10" } }, - "react-native-fetch-blob": { - "version": "0.10.8", - "resolved": "https://registry.npmjs.org/react-native-fetch-blob/-/react-native-fetch-blob-0.10.8.tgz", - "integrity": "sha1-T8JWq64MtfEOfEHyjBGz/zMNcqk=", - "requires": { - "base-64": "0.1.0", - "glob": "7.0.6" - }, - "dependencies": { - "glob": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.0.6.tgz", - "integrity": "sha1-IRuvr0nlJbjNkyYNFKsTYVKz9Xo=", - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.2", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - } - } - }, "react-native-fit-image": { "version": "1.5.4", "resolved": "https://registry.npmjs.org/react-native-fit-image/-/react-native-fit-image-1.5.4.tgz", @@ -16495,17 +16585,29 @@ } }, "react-native-i18n": { - "version": "2.0.12", - "resolved": "https://registry.npmjs.org/react-native-i18n/-/react-native-i18n-2.0.12.tgz", - "integrity": "sha512-2eTUk7BVZP5knthCmVt6y7rePFwrxXl4ym2I20e91oTYJnKM22sAjQMnLhRCYZWC4ucRBbe2pUp63uxNdTkkQw==", + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/react-native-i18n/-/react-native-i18n-2.0.14.tgz", + "integrity": "sha512-Cv38EgAfZTWjRBj0yPSb8c68qPME554d6k0dxGKM/wlHL8xV3bdvzP5F60MyNWdmTOUC4V2jFmGDvVU5VkFIpg==", "requires": { - "i18n-js": "^3.0.3" + "i18n-js": "^3.0.11" } }, - "react-native-image-picker": { - "version": "0.26.10", - "resolved": "https://registry.npmjs.org/react-native-image-picker/-/react-native-image-picker-0.26.10.tgz", - "integrity": "sha512-z6gAbru2E6SyGWm4ZTbiM9hPHZ5Tsl9kXGfRxW6YQXf9us7zybKoS7dKE1fQPsssv/OSvpPDKannJNncE+ATRA==" + "react-native-image-crop-picker": { + "version": "git+https://github.com/RocketChat/react-native-image-crop-picker.git#6b5493f070a4830d2e870e56d5cfb6a713318675", + "from": "git+https://github.com/RocketChat/react-native-image-crop-picker.git" + }, + "react-native-image-pan-zoom": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/react-native-image-pan-zoom/-/react-native-image-pan-zoom-2.1.7.tgz", + "integrity": "sha512-UwoHcn5cp/NgU8pjzod3GiIV/U1OKOp9/7G/xPaAbwsMm7AJ6aogn7vFaVdPFUc5Qor6fCsFjeNICcxiDOcPqw==" + }, + "react-native-image-zoom-viewer": { + "version": "2.2.13", + "resolved": "https://registry.npmjs.org/react-native-image-zoom-viewer/-/react-native-image-zoom-viewer-2.2.13.tgz", + "integrity": "sha512-4Kce8dttWO4NdXBLf+2CC2aP2p2Hgwj+7NVQZlmpM9f4xitQNIf+mgWT2jDnSsXdNKiwv5BykLzuNmv542wSPQ==", + "requires": { + "react-native-image-pan-zoom": "^2.1.7" + } }, "react-native-iphone-x-helper": { "version": "1.0.3", @@ -16536,8 +16638,9 @@ "integrity": "sha512-4kj/K3kt3YqKDua9j+YHAP0Y000zVS5bwd8eMw6eH701CdhVv3GP1iPf5rsFiElXJZ3CV0aK2RS9Ul0oYNeG3Q==" }, "react-native-markdown-renderer": { - "version": "git+https://github.com/RocketChat/react-native-markdown-renderer.git#cecc6d0a2c940ac7a1e1e98c624d8b9b4d37ab68", - "from": "git+https://github.com/RocketChat/react-native-markdown-renderer.git", + "version": "3.2.8", + "resolved": "https://registry.npmjs.org/react-native-markdown-renderer/-/react-native-markdown-renderer-3.2.8.tgz", + "integrity": "sha512-gDT5r3lwecNsEfpKagSaidEGfmCbpVcmV+HHLjaGYRALJoHkpOFni0rJZW1rCerOR9sjaUNGXE66U7BUrlEw0w==", "requires": { "@types/markdown-it": "^0.0.4", "@types/react-native": ">=0.50.0", @@ -16547,9 +16650,9 @@ } }, "react-native-meteor": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/react-native-meteor/-/react-native-meteor-1.3.0.tgz", - "integrity": "sha512-FgQ9O4pN1h+OaezlAMZ8h3g6aon/P6wWoYbMQGuyFzpW+hSREPjCtMVMKEJsKZ11MzIWFblgrdk3nzUI5dpdUQ==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/react-native-meteor/-/react-native-meteor-1.4.0.tgz", + "integrity": "sha512-Bm5RGTDv7LsJqqWjaR8KCv2mpeeMMPOIeZWHSx1yeTLUnEx71jVWAbHNXmEEynyH61/NVUpwDaXZKxiw9OwhFA==", "requires": { "base-64": "^0.1.0", "crypto-js": "^3.1.6", @@ -16564,9 +16667,9 @@ } }, "react-native-modal": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/react-native-modal/-/react-native-modal-6.1.0.tgz", - "integrity": "sha512-DBEJlUElTkWw6H1huHWaa1psQhnlsYxIpfNS4Cfw/fXq5rJkY1+hzHzySbXOwDyBKIAI652Grdtx+2XItZG4Bw==", + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/react-native-modal/-/react-native-modal-6.4.0.tgz", + "integrity": "sha512-X+bOV8P24NwnIrc2vhLMwowi1iUs2NA4LJv21B/dB67n5/I4ncbhIgf13v5QJ5zGSZ3wfVgRuEKEkKyn6XpYfw==", "requires": { "prop-types": "^15.6.1", "react-native-animatable": "^1.2.4" @@ -16610,9 +16713,9 @@ } }, "react-native-picker-select": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/react-native-picker-select/-/react-native-picker-select-3.1.3.tgz", - "integrity": "sha512-uEaI40PyZgJ5S29tPdvD+AKemt2MhuRvxCSqzQ99ON62F1nsOLXj1IXKqn1wlOeGqQvTKHOVh6uR7/KrtsE2vA==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/react-native-picker-select/-/react-native-picker-select-4.0.0.tgz", + "integrity": "sha512-3wxKlFyfLsTptftTrdO1cqrXEYoJZ84wEuhfHocpkClIxK4FGEzsrZiKgIiRicaF9TCDFn76dsYdLgWFVJMqwQ==", "requires": { "lodash.isequal": "^4.5.0" } @@ -16903,45 +17006,31 @@ } }, "reactotron-core-client": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/reactotron-core-client/-/reactotron-core-client-1.13.0.tgz", - "integrity": "sha512-dX2tKjGlZ9sPETLV2r8/K93acfdnGs6oi0r+0x1xdAitaNqtd9O7oiZZc+dBqFHZB3Tz1aooAlMsjD6PVFidCg==", - "dev": true, - "requires": { - "json-stringify-safe": "^5.0.1", - "ramda": "^0.24.1", - "ramdasauce": "^2.0.0" - } + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/reactotron-core-client/-/reactotron-core-client-2.0.0.tgz", + "integrity": "sha512-9t10M/48VXShmU2yqDeSPhJHaNWLNVrKE08b2YFXBHcyCaGtrrxrJzg+Gk/lGgpRCQEayQ47WA0r5T09JN/bPg==", + "dev": true }, "reactotron-react-native": { - "version": "2.0.0-beta.10", - "resolved": "https://registry.npmjs.org/reactotron-react-native/-/reactotron-react-native-2.0.0-beta.10.tgz", - "integrity": "sha512-LcG/Ut55MEuLLHw9hpvPXTpIg6XNslWR6nNhItbwCSC1XC1JfgObYmCDziZV1O58V/oZrZ7ceCDKjzQi8tC4fg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/reactotron-react-native/-/reactotron-react-native-2.0.0.tgz", + "integrity": "sha512-VlLd1vapIR6QXCv53Bn0oHmVIN8uLufHIVTKRH/OtRZa2cGA4z1KRpbZQuryuZ8mVfptZV3rjHAv/1cjzTrwpg==", "dev": true, "requires": { "mitt": "^1.1.2", "prop-types": "^15.5.10", - "reactotron-core-client": "^2.0.0-beta.10", - "rn-host-detect": "^1.1.3" - }, - "dependencies": { - "reactotron-core-client": { - "version": "2.0.0-beta.10", - "resolved": "https://registry.npmjs.org/reactotron-core-client/-/reactotron-core-client-2.0.0-beta.10.tgz", - "integrity": "sha512-mJqd3NhYWh9PjFnBd68XYNj2s++qc6L/42Z1NoQW+LDvCfJE9ufDh6G5fK4RrxknH+i0dqnR79zT162298kU1A==", - "dev": true - } + "reactotron-core-client": "^2.0.0" } }, "reactotron-redux": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/reactotron-redux/-/reactotron-redux-1.13.0.tgz", - "integrity": "sha512-8imh/blSwBrYdp+1NXR1UNtAQM4Q5DuEd/olWjYafDJOej469+SnimJvTtsriIrFk+drPa1Ny8VeGLQihAj1Sg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/reactotron-redux/-/reactotron-redux-2.0.0.tgz", + "integrity": "sha512-ZpxfBVHfCzbF50sCAJWAUz4BCRNH8BNLqLOwIyfRlcF9noQ2dbBo8TqRB6WXxN7pdToi7GhIYBlZ8saaQ+IGtQ==", "dev": true, "requires": { "ramda": "^0.24.1", "ramdasauce": "^2.0.0", - "reactotron-core-client": "^1.13.0", + "reactotron-core-client": "^2.0.0", "redux": "^3.7.1" }, "dependencies": { @@ -16960,14 +17049,14 @@ } }, "reactotron-redux-saga": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/reactotron-redux-saga/-/reactotron-redux-saga-1.13.0.tgz", - "integrity": "sha512-d+Md68OQhBGTi4LRviPKBSOrPQ5Zl4lQhje8ENn3OP8kp1E+Jw6wKYKb3ywPOnA05F0SroSL6OJIYFtDlb02zA==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/reactotron-redux-saga/-/reactotron-redux-saga-2.0.0.tgz", + "integrity": "sha512-pHOTdql7BgyRHxPWt9fSY+SfDt4E01iXFV/FXEjM59wlhh8j0qt9+mfUQlQehvaWcUbNQdIcdN7c5KKODIRVSQ==", "dev": true, "requires": { "ramda": "^0.24.1", "ramdasauce": "^2.0.0", - "reactotron-core-client": "^1.13.0", + "reactotron-core-client": "^2.0.0", "redux": "^3.7.1", "redux-saga": "^0.15.3" }, @@ -17523,11 +17612,29 @@ "inherits": "^2.0.1" } }, - "rn-host-detect": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/rn-host-detect/-/rn-host-detect-1.1.3.tgz", - "integrity": "sha1-JC124vpIXEjXUUFuZbfM5ZaWnpE=", - "dev": true + "rn-fetch-blob": { + "version": "0.10.11", + "resolved": "https://registry.npmjs.org/rn-fetch-blob/-/rn-fetch-blob-0.10.11.tgz", + "integrity": "sha512-QHF8qlDdAcS0ZjydRlh8nZDVWBQJGsshPrXgyB0z34gY654T1+z2fkmC0WWxQ4CSKyweVFvU4fYa0AE/r1nI4A==", + "requires": { + "base-64": "0.1.0", + "glob": "7.0.6" + }, + "dependencies": { + "glob": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.0.6.tgz", + "integrity": "sha1-IRuvr0nlJbjNkyYNFKsTYVKz9Xo=", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.2", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + } + } }, "run-async": { "version": "2.3.0", diff --git a/package.json b/package.json index 917e9bdc2..1127c6bbd 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,6 @@ "android": "react-native run-android", "storybook": "storybook start -p 7007", "snyk-protect": "snyk protect", - "prepare": "npm run snyk-protect; exit 0", "fabric-ios": "./scripts/fabric-ios.sh", "fabric-android": "./scripts/fabric-android.sh", "postinstall": "cp ./temp/react.gradle ./node_modules/react-native" @@ -33,7 +32,7 @@ "babel-preset-expo": "^4.0.0", "deep-equal": "^1.0.1", "ejson": "^2.1.2", - "js-base64": "^2.4.5", + "js-base64": "^2.4.6", "js-sha256": "^0.9.0", "lodash": "^4.17.10", "markdown-it-flowdock": "^0.3.7", @@ -48,19 +47,19 @@ "react-native-dialog": "^5.0.0", "react-native-fabric": "^0.5.1", "react-native-fast-image": "^4.0.14", - "react-native-fetch-blob": "^0.10.8", - "react-native-i18n": "^2.0.12", - "react-native-image-picker": "^0.26.10", + "react-native-i18n": "^2.0.14", + "react-native-image-crop-picker": "git+https://github.com/RocketChat/react-native-image-crop-picker.git", + "react-native-image-zoom-viewer": "^2.2.13", "react-native-keyboard-aware-scroll-view": "^0.6.0", "react-native-keyboard-input": "^5.2.3", "react-native-keyboard-tracking-view": "^5.4.4", - "react-native-markdown-renderer": "git+https://github.com/RocketChat/react-native-markdown-renderer.git", - "react-native-meteor": "^1.3.0", - "react-native-modal": "^6.1.0", + "react-native-markdown-renderer": "^3.2.8", + "react-native-meteor": "^1.4.0", + "react-native-modal": "^6.4.0", "react-native-navigation": "^1.1.474", "react-native-notifications": "^1.1.19", "react-native-optimized-flatlist": "^1.0.4", - "react-native-picker-select": "^3.1.3", + "react-native-picker-select": "^4.0.0", "react-native-responsive-ui": "^1.1.1", "react-native-safari-view": "^2.1.0", "react-native-scrollable-tab-view": "^0.8.0", @@ -78,6 +77,7 @@ "redux-immutable-state-invariant": "^2.1.0", "redux-saga": "^0.16.0", "regenerator-runtime": "^0.12.0", + "rn-fetch-blob": "^0.10.11", "snyk": "^1.88.1", "strip-ansi": "^4.0.0" }, @@ -103,9 +103,9 @@ "react-dom": "^16.4.1", "react-native-bundle-visualizer": "^1.3.0", "react-test-renderer": "^16.4.1", - "reactotron-react-native": "^2.0.0-beta.10", - "reactotron-redux": "^1.13.0", - "reactotron-redux-saga": "^1.13.0" + "reactotron-react-native": "^2.0.0", + "reactotron-redux": "^2.0.0", + "reactotron-redux-saga": "^2.0.0" }, "jest": { "testPathIgnorePatterns": [ -- GitLab