@plusscommunities/pluss-core-app 6.1.9 → 6.1.10-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,236 @@
1
+ function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
2
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
3
+ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
4
+ import React, { Component } from 'react';
5
+ import { View, TouchableOpacity, Text, StyleSheet, ActivityIndicator } from 'react-native';
6
+ import { Icon } from 'react-native-elements';
7
+ import * as DocumentPicker from 'expo-document-picker';
8
+ import { connect } from 'react-redux';
9
+ import Config from '../config';
10
+ import { fileActions } from '../apis';
11
+ import { getValueOrDefault } from '../helper';
12
+ import { TEXT_DARK, getMainBrandingColourFromState } from '../colours';
13
+ const DEFAULT_DOCUMENT_NAME = 'document';
14
+ class DocumentUploader extends Component {
15
+ constructor(...args) {
16
+ super(...args);
17
+ _defineProperty(this, "state", {
18
+ isUploading: false,
19
+ uploadProgress: 0
20
+ });
21
+ _defineProperty(this, "pickDocument", async () => {
22
+ const {
23
+ allowedTypes,
24
+ multiple
25
+ } = this.props;
26
+ try {
27
+ const result = await DocumentPicker.getDocumentAsync({
28
+ type: allowedTypes,
29
+ copyToCacheDirectory: true,
30
+ multiple: multiple || false
31
+ });
32
+ // console.log('pickDocument', JSON.stringify(result, null, 2));
33
+
34
+ if (!result.canceled) {
35
+ await this.handleDocumentPicked(result);
36
+ }
37
+ } catch (error) {
38
+ console.log('Document picker error:', error);
39
+ this.props.onUploadFailed(null, error.message);
40
+ }
41
+ });
42
+ _defineProperty(this, "handleDocumentPicked", async documentResult => {
43
+ const {
44
+ assets
45
+ } = documentResult;
46
+ const {
47
+ userId
48
+ } = this.props;
49
+ try {
50
+ this.setState({
51
+ isUploading: true,
52
+ uploadProgress: 0
53
+ });
54
+
55
+ // Process each asset in parallel
56
+ const uploadPromises = assets.map(async asset => {
57
+ const {
58
+ name,
59
+ uri
60
+ } = asset;
61
+
62
+ // Generate a unique filename if not provided
63
+ const [file, fileExt] = name.split('.');
64
+ const fileName = `${getValueOrDefault(this.props.fileName, DEFAULT_DOCUMENT_NAME)}_${Date.now()}.${fileExt}`;
65
+ const uploadUri = fileActions.getUploadUrl(userId, fileName);
66
+ // console.log('handleDocumentPicked', JSON.stringify({ uploadUri, uri, name, fileName }, null, 2));
67
+
68
+ try {
69
+ // Notify parent component that upload has started for this file
70
+ this.props.onUploadStarted(uploadUri, uri, file, fileExt.toUpperCase());
71
+ const res = await fileActions.uploadUserMediaWithProgress(uri, uploadUri, progress => {
72
+ if (this.props.onUploadProgress) this.props.onUploadProgress(progress);
73
+ });
74
+ const fileUrl = Config.env.baseUploadsUrl + res.key;
75
+ this.props.onUploadSuccess(fileUrl, uploadUri);
76
+ console.log('Upload success', fileUrl);
77
+ return {
78
+ success: true,
79
+ url: fileUrl,
80
+ uploadUri
81
+ };
82
+ } catch (error) {
83
+ console.error(`Upload failed for ${name}:`, error);
84
+ this.props.onUploadFailed(uploadUri, error.message);
85
+ return {
86
+ success: false,
87
+ error,
88
+ uploadUri
89
+ };
90
+ }
91
+ });
92
+
93
+ // Wait for all uploads to complete
94
+ const results = await Promise.all(uploadPromises);
95
+ return results;
96
+ } catch (error) {
97
+ console.error('Document upload error:', error);
98
+ return [];
99
+ } finally {
100
+ this.setState({
101
+ isUploading: false,
102
+ uploadProgress: 0
103
+ });
104
+ }
105
+ });
106
+ _defineProperty(this, "renderUploadButton", () => {
107
+ const {
108
+ buttonTitle,
109
+ buttonStyle,
110
+ buttonTextStyle,
111
+ disabled
112
+ } = this.props;
113
+ const {
114
+ isUploading
115
+ } = this.state;
116
+ const mainColor = getMainBrandingColourFromState(this.props);
117
+ return /*#__PURE__*/React.createElement(TouchableOpacity, {
118
+ style: [styles.uploadButton, {
119
+ borderColor: mainColor
120
+ }, buttonStyle],
121
+ onPress: this.pickDocument,
122
+ disabled: isUploading || disabled,
123
+ activeOpacity: 0.7
124
+ }, isUploading ? /*#__PURE__*/React.createElement(ActivityIndicator, {
125
+ color: mainColor
126
+ }) : /*#__PURE__*/React.createElement(View, {
127
+ style: styles.buttonContent
128
+ }, /*#__PURE__*/React.createElement(Icon, {
129
+ name: "attachment",
130
+ type: "entypo",
131
+ color: mainColor,
132
+ size: 18,
133
+ style: styles.icon
134
+ }), /*#__PURE__*/React.createElement(Text, {
135
+ style: [styles.buttonText, {
136
+ color: mainColor
137
+ }, buttonTextStyle]
138
+ }, buttonTitle)));
139
+ });
140
+ _defineProperty(this, "renderProgress", () => {
141
+ const {
142
+ uploadProgress
143
+ } = this.state;
144
+ if (uploadProgress <= 0 || uploadProgress >= 1) return null;
145
+ return /*#__PURE__*/React.createElement(View, {
146
+ style: styles.progressContainer
147
+ }, /*#__PURE__*/React.createElement(View, {
148
+ style: styles.progressBar
149
+ }, /*#__PURE__*/React.createElement(View, {
150
+ style: [styles.progressFill, {
151
+ width: `${uploadProgress * 100}%`
152
+ }]
153
+ })), /*#__PURE__*/React.createElement(Text, {
154
+ style: styles.progressText
155
+ }, Math.round(uploadProgress * 100), "%"));
156
+ });
157
+ }
158
+ render() {
159
+ return /*#__PURE__*/React.createElement(View, {
160
+ style: styles.container
161
+ }, this.renderUploadButton(), this.renderProgress());
162
+ }
163
+ }
164
+ _defineProperty(DocumentUploader, "defaultProps", {
165
+ allowedTypes: ['application/pdf'],
166
+ buttonTitle: 'Upload Document',
167
+ buttonStyle: {},
168
+ buttonTextStyle: {},
169
+ onUploadStarted: () => {},
170
+ onUploadSuccess: () => {},
171
+ onUploadFailed: () => {},
172
+ onUploadProgress: null,
173
+ userId: null,
174
+ fileName: null,
175
+ disabled: false
176
+ });
177
+ const styles = StyleSheet.create({
178
+ container: {
179
+ marginVertical: 10
180
+ },
181
+ uploadButton: {
182
+ flexDirection: 'row',
183
+ alignItems: 'center',
184
+ justifyContent: 'center',
185
+ paddingVertical: 8,
186
+ paddingHorizontal: 16,
187
+ borderRadius: 6,
188
+ backgroundColor: '#fff',
189
+ borderWidth: 1,
190
+ borderColor: '#007AFF'
191
+ },
192
+ buttonContent: {
193
+ flexDirection: 'row',
194
+ alignItems: 'center'
195
+ },
196
+ buttonText: {
197
+ color: '#fff',
198
+ fontSize: 16,
199
+ fontWeight: '500',
200
+ marginLeft: 8
201
+ },
202
+ icon: {
203
+ marginRight: 8
204
+ },
205
+ progressContainer: {
206
+ marginTop: 8,
207
+ alignItems: 'center'
208
+ },
209
+ progressBar: {
210
+ height: 4,
211
+ width: '100%',
212
+ backgroundColor: '#E0E0E0',
213
+ borderRadius: 2,
214
+ overflow: 'hidden'
215
+ },
216
+ progressFill: {
217
+ height: '100%',
218
+ backgroundColor: '#4CAF50'
219
+ },
220
+ progressText: {
221
+ marginTop: 4,
222
+ fontSize: 12,
223
+ color: TEXT_DARK
224
+ }
225
+ });
226
+ const mapStateToProps = state => {
227
+ const {
228
+ user
229
+ } = state;
230
+ return {
231
+ user,
232
+ colourBrandingMain: getMainBrandingColourFromState(state)
233
+ };
234
+ };
235
+ export default connect(mapStateToProps)(DocumentUploader);
236
+ //# sourceMappingURL=DocumentUploader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["React","Component","View","TouchableOpacity","Text","StyleSheet","ActivityIndicator","Icon","DocumentPicker","connect","Config","fileActions","getValueOrDefault","TEXT_DARK","getMainBrandingColourFromState","DEFAULT_DOCUMENT_NAME","DocumentUploader","constructor","args","_defineProperty","isUploading","uploadProgress","allowedTypes","multiple","props","result","getDocumentAsync","type","copyToCacheDirectory","canceled","handleDocumentPicked","error","console","log","onUploadFailed","message","documentResult","assets","userId","setState","uploadPromises","map","asset","name","uri","file","fileExt","split","fileName","Date","now","uploadUri","getUploadUrl","onUploadStarted","toUpperCase","res","uploadUserMediaWithProgress","progress","onUploadProgress","fileUrl","env","baseUploadsUrl","key","onUploadSuccess","success","url","results","Promise","all","buttonTitle","buttonStyle","buttonTextStyle","disabled","state","mainColor","createElement","style","styles","uploadButton","borderColor","onPress","pickDocument","activeOpacity","color","buttonContent","size","icon","buttonText","progressContainer","progressBar","progressFill","width","progressText","Math","round","render","container","renderUploadButton","renderProgress","create","marginVertical","flexDirection","alignItems","justifyContent","paddingVertical","paddingHorizontal","borderRadius","backgroundColor","borderWidth","fontSize","fontWeight","marginLeft","marginRight","marginTop","height","overflow","mapStateToProps","user","colourBrandingMain"],"sources":["DocumentUploader.js"],"sourcesContent":["import React, { Component } from 'react';\nimport { View, TouchableOpacity, Text, StyleSheet, ActivityIndicator } from 'react-native';\nimport { Icon } from 'react-native-elements';\nimport * as DocumentPicker from 'expo-document-picker';\nimport { connect } from 'react-redux';\nimport Config from '../config';\nimport { fileActions } from '../apis';\nimport { getValueOrDefault } from '../helper';\nimport { TEXT_DARK, getMainBrandingColourFromState } from '../colours';\n\nconst DEFAULT_DOCUMENT_NAME = 'document';\n\nclass DocumentUploader extends Component {\n static defaultProps = {\n allowedTypes: ['application/pdf'],\n buttonTitle: 'Upload Document',\n buttonStyle: {},\n buttonTextStyle: {},\n onUploadStarted: () => {},\n onUploadSuccess: () => {},\n onUploadFailed: () => {},\n onUploadProgress: null,\n userId: null,\n fileName: null,\n disabled: false,\n };\n\n state = {\n isUploading: false,\n uploadProgress: 0,\n };\n\n pickDocument = async () => {\n const { allowedTypes, multiple } = this.props;\n\n try {\n const result = await DocumentPicker.getDocumentAsync({\n type: allowedTypes,\n copyToCacheDirectory: true,\n multiple: multiple || false,\n });\n // console.log('pickDocument', JSON.stringify(result, null, 2));\n\n if (!result.canceled) {\n await this.handleDocumentPicked(result);\n }\n } catch (error) {\n console.log('Document picker error:', error);\n this.props.onUploadFailed(null, error.message);\n }\n };\n\n handleDocumentPicked = async documentResult => {\n const { assets } = documentResult;\n const { userId } = this.props;\n\n try {\n this.setState({ isUploading: true, uploadProgress: 0 });\n\n // Process each asset in parallel\n const uploadPromises = assets.map(async asset => {\n const { name, uri } = asset;\n\n // Generate a unique filename if not provided\n const [file, fileExt] = name.split('.');\n const fileName = `${getValueOrDefault(this.props.fileName, DEFAULT_DOCUMENT_NAME)}_${Date.now()}.${fileExt}`;\n const uploadUri = fileActions.getUploadUrl(userId, fileName);\n // console.log('handleDocumentPicked', JSON.stringify({ uploadUri, uri, name, fileName }, null, 2));\n\n try {\n // Notify parent component that upload has started for this file\n this.props.onUploadStarted(uploadUri, uri, file, fileExt.toUpperCase());\n\n const res = await fileActions.uploadUserMediaWithProgress(uri, uploadUri, progress => {\n if (this.props.onUploadProgress) this.props.onUploadProgress(progress);\n });\n\n const fileUrl = Config.env.baseUploadsUrl + res.key;\n this.props.onUploadSuccess(fileUrl, uploadUri);\n console.log('Upload success', fileUrl);\n return { success: true, url: fileUrl, uploadUri };\n } catch (error) {\n console.error(`Upload failed for ${name}:`, error);\n this.props.onUploadFailed(uploadUri, error.message);\n return { success: false, error, uploadUri };\n }\n });\n\n // Wait for all uploads to complete\n const results = await Promise.all(uploadPromises);\n return results;\n } catch (error) {\n console.error('Document upload error:', error);\n return [];\n } finally {\n this.setState({ isUploading: false, uploadProgress: 0 });\n }\n };\n\n renderUploadButton = () => {\n const { buttonTitle, buttonStyle, buttonTextStyle, disabled } = this.props;\n const { isUploading } = this.state;\n const mainColor = getMainBrandingColourFromState(this.props);\n\n return (\n <TouchableOpacity\n style={[styles.uploadButton, { borderColor: mainColor }, buttonStyle]}\n onPress={this.pickDocument}\n disabled={isUploading || disabled}\n activeOpacity={0.7}\n >\n {isUploading ? (\n <ActivityIndicator color={mainColor} />\n ) : (\n <View style={styles.buttonContent}>\n <Icon name=\"attachment\" type=\"entypo\" color={mainColor} size={18} style={styles.icon} />\n <Text style={[styles.buttonText, { color: mainColor }, buttonTextStyle]}>{buttonTitle}</Text>\n </View>\n )}\n </TouchableOpacity>\n );\n };\n\n renderProgress = () => {\n const { uploadProgress } = this.state;\n if (uploadProgress <= 0 || uploadProgress >= 1) return null;\n\n return (\n <View style={styles.progressContainer}>\n <View style={styles.progressBar}>\n <View style={[styles.progressFill, { width: `${uploadProgress * 100}%` }]} />\n </View>\n <Text style={styles.progressText}>{Math.round(uploadProgress * 100)}%</Text>\n </View>\n );\n };\n\n render() {\n return (\n <View style={styles.container}>\n {this.renderUploadButton()}\n {this.renderProgress()}\n </View>\n );\n }\n}\n\nconst styles = StyleSheet.create({\n container: {\n marginVertical: 10,\n },\n uploadButton: {\n flexDirection: 'row',\n alignItems: 'center',\n justifyContent: 'center',\n paddingVertical: 8,\n paddingHorizontal: 16,\n borderRadius: 6,\n backgroundColor: '#fff',\n borderWidth: 1,\n borderColor: '#007AFF',\n },\n buttonContent: {\n flexDirection: 'row',\n alignItems: 'center',\n },\n buttonText: {\n color: '#fff',\n fontSize: 16,\n fontWeight: '500',\n marginLeft: 8,\n },\n icon: {\n marginRight: 8,\n },\n progressContainer: {\n marginTop: 8,\n alignItems: 'center',\n },\n progressBar: {\n height: 4,\n width: '100%',\n backgroundColor: '#E0E0E0',\n borderRadius: 2,\n overflow: 'hidden',\n },\n progressFill: {\n height: '100%',\n backgroundColor: '#4CAF50',\n },\n progressText: {\n marginTop: 4,\n fontSize: 12,\n color: TEXT_DARK,\n },\n});\n\nconst mapStateToProps = state => {\n const { user } = state;\n return {\n user,\n colourBrandingMain: getMainBrandingColourFromState(state),\n };\n};\n\nexport default connect(mapStateToProps)(DocumentUploader);\n"],"mappings":";;;AAAA,OAAOA,KAAK,IAAIC,SAAS,QAAQ,OAAO;AACxC,SAASC,IAAI,EAAEC,gBAAgB,EAAEC,IAAI,EAAEC,UAAU,EAAEC,iBAAiB,QAAQ,cAAc;AAC1F,SAASC,IAAI,QAAQ,uBAAuB;AAC5C,OAAO,KAAKC,cAAc,MAAM,sBAAsB;AACtD,SAASC,OAAO,QAAQ,aAAa;AACrC,OAAOC,MAAM,MAAM,WAAW;AAC9B,SAASC,WAAW,QAAQ,SAAS;AACrC,SAASC,iBAAiB,QAAQ,WAAW;AAC7C,SAASC,SAAS,EAAEC,8BAA8B,QAAQ,YAAY;AAEtE,MAAMC,qBAAqB,GAAG,UAAU;AAExC,MAAMC,gBAAgB,SAASf,SAAS,CAAC;EAAAgB,YAAA,GAAAC,IAAA;IAAA,SAAAA,IAAA;IAAAC,eAAA,gBAe/B;MACNC,WAAW,EAAE,KAAK;MAClBC,cAAc,EAAE;IAClB,CAAC;IAAAF,eAAA,uBAEc,YAAY;MACzB,MAAM;QAAEG,YAAY;QAAEC;MAAS,CAAC,GAAG,IAAI,CAACC,KAAK;MAE7C,IAAI;QACF,MAAMC,MAAM,GAAG,MAAMjB,cAAc,CAACkB,gBAAgB,CAAC;UACnDC,IAAI,EAAEL,YAAY;UAClBM,oBAAoB,EAAE,IAAI;UAC1BL,QAAQ,EAAEA,QAAQ,IAAI;QACxB,CAAC,CAAC;QACF;;QAEA,IAAI,CAACE,MAAM,CAACI,QAAQ,EAAE;UACpB,MAAM,IAAI,CAACC,oBAAoB,CAACL,MAAM,CAAC;QACzC;MACF,CAAC,CAAC,OAAOM,KAAK,EAAE;QACdC,OAAO,CAACC,GAAG,CAAC,wBAAwB,EAAEF,KAAK,CAAC;QAC5C,IAAI,CAACP,KAAK,CAACU,cAAc,CAAC,IAAI,EAAEH,KAAK,CAACI,OAAO,CAAC;MAChD;IACF,CAAC;IAAAhB,eAAA,+BAEsB,MAAMiB,cAAc,IAAI;MAC7C,MAAM;QAAEC;MAAO,CAAC,GAAGD,cAAc;MACjC,MAAM;QAAEE;MAAO,CAAC,GAAG,IAAI,CAACd,KAAK;MAE7B,IAAI;QACF,IAAI,CAACe,QAAQ,CAAC;UAAEnB,WAAW,EAAE,IAAI;UAAEC,cAAc,EAAE;QAAE,CAAC,CAAC;;QAEvD;QACA,MAAMmB,cAAc,GAAGH,MAAM,CAACI,GAAG,CAAC,MAAMC,KAAK,IAAI;UAC/C,MAAM;YAAEC,IAAI;YAAEC;UAAI,CAAC,GAAGF,KAAK;;UAE3B;UACA,MAAM,CAACG,IAAI,EAAEC,OAAO,CAAC,GAAGH,IAAI,CAACI,KAAK,CAAC,GAAG,CAAC;UACvC,MAAMC,QAAQ,GAAG,GAAGpC,iBAAiB,CAAC,IAAI,CAACY,KAAK,CAACwB,QAAQ,EAAEjC,qBAAqB,CAAC,IAAIkC,IAAI,CAACC,GAAG,CAAC,CAAC,IAAIJ,OAAO,EAAE;UAC5G,MAAMK,SAAS,GAAGxC,WAAW,CAACyC,YAAY,CAACd,MAAM,EAAEU,QAAQ,CAAC;UAC5D;;UAEA,IAAI;YACF;YACA,IAAI,CAACxB,KAAK,CAAC6B,eAAe,CAACF,SAAS,EAAEP,GAAG,EAAEC,IAAI,EAAEC,OAAO,CAACQ,WAAW,CAAC,CAAC,CAAC;YAEvE,MAAMC,GAAG,GAAG,MAAM5C,WAAW,CAAC6C,2BAA2B,CAACZ,GAAG,EAAEO,SAAS,EAAEM,QAAQ,IAAI;cACpF,IAAI,IAAI,CAACjC,KAAK,CAACkC,gBAAgB,EAAE,IAAI,CAAClC,KAAK,CAACkC,gBAAgB,CAACD,QAAQ,CAAC;YACxE,CAAC,CAAC;YAEF,MAAME,OAAO,GAAGjD,MAAM,CAACkD,GAAG,CAACC,cAAc,GAAGN,GAAG,CAACO,GAAG;YACnD,IAAI,CAACtC,KAAK,CAACuC,eAAe,CAACJ,OAAO,EAAER,SAAS,CAAC;YAC9CnB,OAAO,CAACC,GAAG,CAAC,gBAAgB,EAAE0B,OAAO,CAAC;YACtC,OAAO;cAAEK,OAAO,EAAE,IAAI;cAAEC,GAAG,EAAEN,OAAO;cAAER;YAAU,CAAC;UACnD,CAAC,CAAC,OAAOpB,KAAK,EAAE;YACdC,OAAO,CAACD,KAAK,CAAC,qBAAqBY,IAAI,GAAG,EAAEZ,KAAK,CAAC;YAClD,IAAI,CAACP,KAAK,CAACU,cAAc,CAACiB,SAAS,EAAEpB,KAAK,CAACI,OAAO,CAAC;YACnD,OAAO;cAAE6B,OAAO,EAAE,KAAK;cAAEjC,KAAK;cAAEoB;YAAU,CAAC;UAC7C;QACF,CAAC,CAAC;;QAEF;QACA,MAAMe,OAAO,GAAG,MAAMC,OAAO,CAACC,GAAG,CAAC5B,cAAc,CAAC;QACjD,OAAO0B,OAAO;MAChB,CAAC,CAAC,OAAOnC,KAAK,EAAE;QACdC,OAAO,CAACD,KAAK,CAAC,wBAAwB,EAAEA,KAAK,CAAC;QAC9C,OAAO,EAAE;MACX,CAAC,SAAS;QACR,IAAI,CAACQ,QAAQ,CAAC;UAAEnB,WAAW,EAAE,KAAK;UAAEC,cAAc,EAAE;QAAE,CAAC,CAAC;MAC1D;IACF,CAAC;IAAAF,eAAA,6BAEoB,MAAM;MACzB,MAAM;QAAEkD,WAAW;QAAEC,WAAW;QAAEC,eAAe;QAAEC;MAAS,CAAC,GAAG,IAAI,CAAChD,KAAK;MAC1E,MAAM;QAAEJ;MAAY,CAAC,GAAG,IAAI,CAACqD,KAAK;MAClC,MAAMC,SAAS,GAAG5D,8BAA8B,CAAC,IAAI,CAACU,KAAK,CAAC;MAE5D,oBACExB,KAAA,CAAA2E,aAAA,CAACxE,gBAAgB;QACfyE,KAAK,EAAE,CAACC,MAAM,CAACC,YAAY,EAAE;UAAEC,WAAW,EAAEL;QAAU,CAAC,EAAEJ,WAAW,CAAE;QACtEU,OAAO,EAAE,IAAI,CAACC,YAAa;QAC3BT,QAAQ,EAAEpD,WAAW,IAAIoD,QAAS;QAClCU,aAAa,EAAE;MAAI,GAElB9D,WAAW,gBACVpB,KAAA,CAAA2E,aAAA,CAACrE,iBAAiB;QAAC6E,KAAK,EAAET;MAAU,CAAE,CAAC,gBAEvC1E,KAAA,CAAA2E,aAAA,CAACzE,IAAI;QAAC0E,KAAK,EAAEC,MAAM,CAACO;MAAc,gBAChCpF,KAAA,CAAA2E,aAAA,CAACpE,IAAI;QAACoC,IAAI,EAAC,YAAY;QAAChB,IAAI,EAAC,QAAQ;QAACwD,KAAK,EAAET,SAAU;QAACW,IAAI,EAAE,EAAG;QAACT,KAAK,EAAEC,MAAM,CAACS;MAAK,CAAE,CAAC,eACxFtF,KAAA,CAAA2E,aAAA,CAACvE,IAAI;QAACwE,KAAK,EAAE,CAACC,MAAM,CAACU,UAAU,EAAE;UAAEJ,KAAK,EAAET;QAAU,CAAC,EAAEH,eAAe;MAAE,GAAEF,WAAkB,CACxF,CAEQ,CAAC;IAEvB,CAAC;IAAAlD,eAAA,yBAEgB,MAAM;MACrB,MAAM;QAAEE;MAAe,CAAC,GAAG,IAAI,CAACoD,KAAK;MACrC,IAAIpD,cAAc,IAAI,CAAC,IAAIA,cAAc,IAAI,CAAC,EAAE,OAAO,IAAI;MAE3D,oBACErB,KAAA,CAAA2E,aAAA,CAACzE,IAAI;QAAC0E,KAAK,EAAEC,MAAM,CAACW;MAAkB,gBACpCxF,KAAA,CAAA2E,aAAA,CAACzE,IAAI;QAAC0E,KAAK,EAAEC,MAAM,CAACY;MAAY,gBAC9BzF,KAAA,CAAA2E,aAAA,CAACzE,IAAI;QAAC0E,KAAK,EAAE,CAACC,MAAM,CAACa,YAAY,EAAE;UAAEC,KAAK,EAAE,GAAGtE,cAAc,GAAG,GAAG;QAAI,CAAC;MAAE,CAAE,CACxE,CAAC,eACPrB,KAAA,CAAA2E,aAAA,CAACvE,IAAI;QAACwE,KAAK,EAAEC,MAAM,CAACe;MAAa,GAAEC,IAAI,CAACC,KAAK,CAACzE,cAAc,GAAG,GAAG,CAAC,EAAC,GAAO,CACvE,CAAC;IAEX,CAAC;EAAA;EAED0E,MAAMA,CAAA,EAAG;IACP,oBACE/F,KAAA,CAAA2E,aAAA,CAACzE,IAAI;MAAC0E,KAAK,EAAEC,MAAM,CAACmB;IAAU,GAC3B,IAAI,CAACC,kBAAkB,CAAC,CAAC,EACzB,IAAI,CAACC,cAAc,CAAC,CACjB,CAAC;EAEX;AACF;AAAC/E,eAAA,CArIKH,gBAAgB,kBACE;EACpBM,YAAY,EAAE,CAAC,iBAAiB,CAAC;EACjC+C,WAAW,EAAE,iBAAiB;EAC9BC,WAAW,EAAE,CAAC,CAAC;EACfC,eAAe,EAAE,CAAC,CAAC;EACnBlB,eAAe,EAAEA,CAAA,KAAM,CAAC,CAAC;EACzBU,eAAe,EAAEA,CAAA,KAAM,CAAC,CAAC;EACzB7B,cAAc,EAAEA,CAAA,KAAM,CAAC,CAAC;EACxBwB,gBAAgB,EAAE,IAAI;EACtBpB,MAAM,EAAE,IAAI;EACZU,QAAQ,EAAE,IAAI;EACdwB,QAAQ,EAAE;AACZ,CAAC;AA0HH,MAAMK,MAAM,GAAGxE,UAAU,CAAC8F,MAAM,CAAC;EAC/BH,SAAS,EAAE;IACTI,cAAc,EAAE;EAClB,CAAC;EACDtB,YAAY,EAAE;IACZuB,aAAa,EAAE,KAAK;IACpBC,UAAU,EAAE,QAAQ;IACpBC,cAAc,EAAE,QAAQ;IACxBC,eAAe,EAAE,CAAC;IAClBC,iBAAiB,EAAE,EAAE;IACrBC,YAAY,EAAE,CAAC;IACfC,eAAe,EAAE,MAAM;IACvBC,WAAW,EAAE,CAAC;IACd7B,WAAW,EAAE;EACf,CAAC;EACDK,aAAa,EAAE;IACbiB,aAAa,EAAE,KAAK;IACpBC,UAAU,EAAE;EACd,CAAC;EACDf,UAAU,EAAE;IACVJ,KAAK,EAAE,MAAM;IACb0B,QAAQ,EAAE,EAAE;IACZC,UAAU,EAAE,KAAK;IACjBC,UAAU,EAAE;EACd,CAAC;EACDzB,IAAI,EAAE;IACJ0B,WAAW,EAAE;EACf,CAAC;EACDxB,iBAAiB,EAAE;IACjByB,SAAS,EAAE,CAAC;IACZX,UAAU,EAAE;EACd,CAAC;EACDb,WAAW,EAAE;IACXyB,MAAM,EAAE,CAAC;IACTvB,KAAK,EAAE,MAAM;IACbgB,eAAe,EAAE,SAAS;IAC1BD,YAAY,EAAE,CAAC;IACfS,QAAQ,EAAE;EACZ,CAAC;EACDzB,YAAY,EAAE;IACZwB,MAAM,EAAE,MAAM;IACdP,eAAe,EAAE;EACnB,CAAC;EACDf,YAAY,EAAE;IACZqB,SAAS,EAAE,CAAC;IACZJ,QAAQ,EAAE,EAAE;IACZ1B,KAAK,EAAEtE;EACT;AACF,CAAC,CAAC;AAEF,MAAMuG,eAAe,GAAG3C,KAAK,IAAI;EAC/B,MAAM;IAAE4C;EAAK,CAAC,GAAG5C,KAAK;EACtB,OAAO;IACL4C,IAAI;IACJC,kBAAkB,EAAExG,8BAA8B,CAAC2D,KAAK;EAC1D,CAAC;AACH,CAAC;AAED,eAAehE,OAAO,CAAC2G,eAAe,CAAC,CAACpG,gBAAgB,CAAC","ignoreList":[]}
@@ -47,6 +47,7 @@ export { default as LoadingStateWidget } from './LoadingStateWidget';
47
47
  export { default as Header } from './Header';
48
48
  export { default as LoadingIndicator } from './LoadingIndicator';
49
49
  export { default as ImageUploader } from './ImageUploader';
50
+ export { default as DocumentUploader } from './DocumentUploader';
50
51
  export { default as ImageUploadProgress } from './ImageUploadProgress';
51
52
  export { default as UserListing } from './UserListing';
52
53
  export { default as PlussChat } from './PlussChat';
@@ -1 +1 @@
1
- {"version":3,"names":["default","EmptyStateWidget","EmptyStateMain","LoadingStateWidget","Header","LoadingIndicator","ImageUploader","ImageUploadProgress","UserListing","PlussChat","PositionedImage","FormattedText","MediaPlayer","AudienceSelectorPage"],"sources":["index.js"],"sourcesContent":["export * from './InlineButton';\nexport * from './AddToCalendarButton';\nexport * from './Forbidden';\nexport * from './FormCard';\nexport * from './FormCardSection';\nexport * from './FormCardSectionOptionLauncher';\nexport * from './ProfilePic';\nexport * from './Spinner';\nexport * from './LoadingCircles';\nexport * from './Popup';\nexport * from './ImagePopup';\nexport * from './VideoPopup';\nexport * from './SharingTools';\nexport * from './MiddlePopup';\nexport * from './ConfirmPopup';\nexport * from './ConfirmationPopup';\nexport * from './CommentSection';\nexport * from './CommentReply';\nexport * from './PopupMenu';\nexport * from './AddButton';\nexport * from './Attachment';\nexport * from './GenericInputSection';\nexport * from './GenericInput';\nexport * from './RadioButton';\nexport * from './PDFPopup';\nexport * from './TextStyle';\nexport * from './TickIcon';\nexport * from './Toggle';\nexport * from './Input';\nexport * from './StickyFooter';\nexport * from './CategoryTabs';\nexport * from './DropDownMenu';\nexport * from './DropDownItem';\nexport * from './BackButton';\nexport * from './Reaction';\nexport * from './TouchableSearchBar';\nexport * from './WarningPopup';\nexport * from './FontScalePopup';\nexport * from './FontScaleButton';\nexport * from './UserListPopup';\nexport * from './Reactions';\nexport * from './AudienceSelectorLauncher';\nexport * from './CalendarPopup';\nexport { default as EmptyStateWidget } from './EmptyStateWidget';\nexport { default as EmptyStateMain } from './EmptyStateMain';\nexport { default as LoadingStateWidget } from './LoadingStateWidget';\nexport { default as Header } from './Header';\nexport { default as LoadingIndicator } from './LoadingIndicator';\nexport { default as ImageUploader } from './ImageUploader';\nexport { default as ImageUploadProgress } from './ImageUploadProgress';\nexport { default as UserListing } from './UserListing';\nexport { default as PlussChat } from './PlussChat';\nexport { default as PositionedImage } from './PositionedImage';\nexport * from './AutoOffsetImage';\nexport { default as FormattedText } from './FormattedText';\nexport { default as MediaPlayer } from './MediaPlayer';\nexport { default as AudienceSelectorPage } from './AudienceSelectorPage';\n"],"mappings":"AAAA,cAAc,gBAAgB;AAC9B,cAAc,uBAAuB;AACrC,cAAc,aAAa;AAC3B,cAAc,YAAY;AAC1B,cAAc,mBAAmB;AACjC,cAAc,iCAAiC;AAC/C,cAAc,cAAc;AAC5B,cAAc,WAAW;AACzB,cAAc,kBAAkB;AAChC,cAAc,SAAS;AACvB,cAAc,cAAc;AAC5B,cAAc,cAAc;AAC5B,cAAc,gBAAgB;AAC9B,cAAc,eAAe;AAC7B,cAAc,gBAAgB;AAC9B,cAAc,qBAAqB;AACnC,cAAc,kBAAkB;AAChC,cAAc,gBAAgB;AAC9B,cAAc,aAAa;AAC3B,cAAc,aAAa;AAC3B,cAAc,cAAc;AAC5B,cAAc,uBAAuB;AACrC,cAAc,gBAAgB;AAC9B,cAAc,eAAe;AAC7B,cAAc,YAAY;AAC1B,cAAc,aAAa;AAC3B,cAAc,YAAY;AAC1B,cAAc,UAAU;AACxB,cAAc,SAAS;AACvB,cAAc,gBAAgB;AAC9B,cAAc,gBAAgB;AAC9B,cAAc,gBAAgB;AAC9B,cAAc,gBAAgB;AAC9B,cAAc,cAAc;AAC5B,cAAc,YAAY;AAC1B,cAAc,sBAAsB;AACpC,cAAc,gBAAgB;AAC9B,cAAc,kBAAkB;AAChC,cAAc,mBAAmB;AACjC,cAAc,iBAAiB;AAC/B,cAAc,aAAa;AAC3B,cAAc,4BAA4B;AAC1C,cAAc,iBAAiB;AAC/B,SAASA,OAAO,IAAIC,gBAAgB,QAAQ,oBAAoB;AAChE,SAASD,OAAO,IAAIE,cAAc,QAAQ,kBAAkB;AAC5D,SAASF,OAAO,IAAIG,kBAAkB,QAAQ,sBAAsB;AACpE,SAASH,OAAO,IAAII,MAAM,QAAQ,UAAU;AAC5C,SAASJ,OAAO,IAAIK,gBAAgB,QAAQ,oBAAoB;AAChE,SAASL,OAAO,IAAIM,aAAa,QAAQ,iBAAiB;AAC1D,SAASN,OAAO,IAAIO,mBAAmB,QAAQ,uBAAuB;AACtE,SAASP,OAAO,IAAIQ,WAAW,QAAQ,eAAe;AACtD,SAASR,OAAO,IAAIS,SAAS,QAAQ,aAAa;AAClD,SAAST,OAAO,IAAIU,eAAe,QAAQ,mBAAmB;AAC9D,cAAc,mBAAmB;AACjC,SAASV,OAAO,IAAIW,aAAa,QAAQ,iBAAiB;AAC1D,SAASX,OAAO,IAAIY,WAAW,QAAQ,eAAe;AACtD,SAASZ,OAAO,IAAIa,oBAAoB,QAAQ,wBAAwB","ignoreList":[]}
1
+ {"version":3,"names":["default","EmptyStateWidget","EmptyStateMain","LoadingStateWidget","Header","LoadingIndicator","ImageUploader","DocumentUploader","ImageUploadProgress","UserListing","PlussChat","PositionedImage","FormattedText","MediaPlayer","AudienceSelectorPage"],"sources":["index.js"],"sourcesContent":["export * from './InlineButton';\nexport * from './AddToCalendarButton';\nexport * from './Forbidden';\nexport * from './FormCard';\nexport * from './FormCardSection';\nexport * from './FormCardSectionOptionLauncher';\nexport * from './ProfilePic';\nexport * from './Spinner';\nexport * from './LoadingCircles';\nexport * from './Popup';\nexport * from './ImagePopup';\nexport * from './VideoPopup';\nexport * from './SharingTools';\nexport * from './MiddlePopup';\nexport * from './ConfirmPopup';\nexport * from './ConfirmationPopup';\nexport * from './CommentSection';\nexport * from './CommentReply';\nexport * from './PopupMenu';\nexport * from './AddButton';\nexport * from './Attachment';\nexport * from './GenericInputSection';\nexport * from './GenericInput';\nexport * from './RadioButton';\nexport * from './PDFPopup';\nexport * from './TextStyle';\nexport * from './TickIcon';\nexport * from './Toggle';\nexport * from './Input';\nexport * from './StickyFooter';\nexport * from './CategoryTabs';\nexport * from './DropDownMenu';\nexport * from './DropDownItem';\nexport * from './BackButton';\nexport * from './Reaction';\nexport * from './TouchableSearchBar';\nexport * from './WarningPopup';\nexport * from './FontScalePopup';\nexport * from './FontScaleButton';\nexport * from './UserListPopup';\nexport * from './Reactions';\nexport * from './AudienceSelectorLauncher';\nexport * from './CalendarPopup';\nexport { default as EmptyStateWidget } from './EmptyStateWidget';\nexport { default as EmptyStateMain } from './EmptyStateMain';\nexport { default as LoadingStateWidget } from './LoadingStateWidget';\nexport { default as Header } from './Header';\nexport { default as LoadingIndicator } from './LoadingIndicator';\nexport { default as ImageUploader } from './ImageUploader';\nexport { default as DocumentUploader } from './DocumentUploader';\nexport { default as ImageUploadProgress } from './ImageUploadProgress';\nexport { default as UserListing } from './UserListing';\nexport { default as PlussChat } from './PlussChat';\nexport { default as PositionedImage } from './PositionedImage';\nexport * from './AutoOffsetImage';\nexport { default as FormattedText } from './FormattedText';\nexport { default as MediaPlayer } from './MediaPlayer';\nexport { default as AudienceSelectorPage } from './AudienceSelectorPage';\n"],"mappings":"AAAA,cAAc,gBAAgB;AAC9B,cAAc,uBAAuB;AACrC,cAAc,aAAa;AAC3B,cAAc,YAAY;AAC1B,cAAc,mBAAmB;AACjC,cAAc,iCAAiC;AAC/C,cAAc,cAAc;AAC5B,cAAc,WAAW;AACzB,cAAc,kBAAkB;AAChC,cAAc,SAAS;AACvB,cAAc,cAAc;AAC5B,cAAc,cAAc;AAC5B,cAAc,gBAAgB;AAC9B,cAAc,eAAe;AAC7B,cAAc,gBAAgB;AAC9B,cAAc,qBAAqB;AACnC,cAAc,kBAAkB;AAChC,cAAc,gBAAgB;AAC9B,cAAc,aAAa;AAC3B,cAAc,aAAa;AAC3B,cAAc,cAAc;AAC5B,cAAc,uBAAuB;AACrC,cAAc,gBAAgB;AAC9B,cAAc,eAAe;AAC7B,cAAc,YAAY;AAC1B,cAAc,aAAa;AAC3B,cAAc,YAAY;AAC1B,cAAc,UAAU;AACxB,cAAc,SAAS;AACvB,cAAc,gBAAgB;AAC9B,cAAc,gBAAgB;AAC9B,cAAc,gBAAgB;AAC9B,cAAc,gBAAgB;AAC9B,cAAc,cAAc;AAC5B,cAAc,YAAY;AAC1B,cAAc,sBAAsB;AACpC,cAAc,gBAAgB;AAC9B,cAAc,kBAAkB;AAChC,cAAc,mBAAmB;AACjC,cAAc,iBAAiB;AAC/B,cAAc,aAAa;AAC3B,cAAc,4BAA4B;AAC1C,cAAc,iBAAiB;AAC/B,SAASA,OAAO,IAAIC,gBAAgB,QAAQ,oBAAoB;AAChE,SAASD,OAAO,IAAIE,cAAc,QAAQ,kBAAkB;AAC5D,SAASF,OAAO,IAAIG,kBAAkB,QAAQ,sBAAsB;AACpE,SAASH,OAAO,IAAII,MAAM,QAAQ,UAAU;AAC5C,SAASJ,OAAO,IAAIK,gBAAgB,QAAQ,oBAAoB;AAChE,SAASL,OAAO,IAAIM,aAAa,QAAQ,iBAAiB;AAC1D,SAASN,OAAO,IAAIO,gBAAgB,QAAQ,oBAAoB;AAChE,SAASP,OAAO,IAAIQ,mBAAmB,QAAQ,uBAAuB;AACtE,SAASR,OAAO,IAAIS,WAAW,QAAQ,eAAe;AACtD,SAAST,OAAO,IAAIU,SAAS,QAAQ,aAAa;AAClD,SAASV,OAAO,IAAIW,eAAe,QAAQ,mBAAmB;AAC9D,cAAc,mBAAmB;AACjC,SAASX,OAAO,IAAIY,aAAa,QAAQ,iBAAiB;AAC1D,SAASZ,OAAO,IAAIa,WAAW,QAAQ,eAAe;AACtD,SAASb,OAAO,IAAIc,oBAAoB,QAAQ,wBAAwB","ignoreList":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plusscommunities/pluss-core-app",
3
- "version": "6.1.9",
3
+ "version": "6.1.10-beta.0",
4
4
  "description": "Core extension package for Pluss Communities platform",
5
5
  "main": "dist/module/index.js",
6
6
  "module": "dist/module/index.js",
@@ -31,6 +31,7 @@
31
31
  "expo-av": "~13.10.6",
32
32
  "expo-calendar": "~12.2.1",
33
33
  "expo-constants": "~15.4.6",
34
+ "expo-document-picker": "~11.10.1",
34
35
  "expo-file-system": "~16.0.9",
35
36
  "expo-image-manipulator": "~11.8.0",
36
37
  "expo-image-picker": "~14.7.1",
@@ -0,0 +1,206 @@
1
+ import React, { Component } from 'react';
2
+ import { View, TouchableOpacity, Text, StyleSheet, ActivityIndicator } from 'react-native';
3
+ import { Icon } from 'react-native-elements';
4
+ import * as DocumentPicker from 'expo-document-picker';
5
+ import { connect } from 'react-redux';
6
+ import Config from '../config';
7
+ import { fileActions } from '../apis';
8
+ import { getValueOrDefault } from '../helper';
9
+ import { TEXT_DARK, getMainBrandingColourFromState } from '../colours';
10
+
11
+ const DEFAULT_DOCUMENT_NAME = 'document';
12
+
13
+ class DocumentUploader extends Component {
14
+ static defaultProps = {
15
+ allowedTypes: ['application/pdf'],
16
+ buttonTitle: 'Upload Document',
17
+ buttonStyle: {},
18
+ buttonTextStyle: {},
19
+ onUploadStarted: () => {},
20
+ onUploadSuccess: () => {},
21
+ onUploadFailed: () => {},
22
+ onUploadProgress: null,
23
+ userId: null,
24
+ fileName: null,
25
+ disabled: false,
26
+ };
27
+
28
+ state = {
29
+ isUploading: false,
30
+ uploadProgress: 0,
31
+ };
32
+
33
+ pickDocument = async () => {
34
+ const { allowedTypes, multiple } = this.props;
35
+
36
+ try {
37
+ const result = await DocumentPicker.getDocumentAsync({
38
+ type: allowedTypes,
39
+ copyToCacheDirectory: true,
40
+ multiple: multiple || false,
41
+ });
42
+ // console.log('pickDocument', JSON.stringify(result, null, 2));
43
+
44
+ if (!result.canceled) {
45
+ await this.handleDocumentPicked(result);
46
+ }
47
+ } catch (error) {
48
+ console.log('Document picker error:', error);
49
+ this.props.onUploadFailed(null, error.message);
50
+ }
51
+ };
52
+
53
+ handleDocumentPicked = async documentResult => {
54
+ const { assets } = documentResult;
55
+ const { userId } = this.props;
56
+
57
+ try {
58
+ this.setState({ isUploading: true, uploadProgress: 0 });
59
+
60
+ // Process each asset in parallel
61
+ const uploadPromises = assets.map(async asset => {
62
+ const { name, uri } = asset;
63
+
64
+ // Generate a unique filename if not provided
65
+ const [file, fileExt] = name.split('.');
66
+ const fileName = `${getValueOrDefault(this.props.fileName, DEFAULT_DOCUMENT_NAME)}_${Date.now()}.${fileExt}`;
67
+ const uploadUri = fileActions.getUploadUrl(userId, fileName);
68
+ // console.log('handleDocumentPicked', JSON.stringify({ uploadUri, uri, name, fileName }, null, 2));
69
+
70
+ try {
71
+ // Notify parent component that upload has started for this file
72
+ this.props.onUploadStarted(uploadUri, uri, file, fileExt.toUpperCase());
73
+
74
+ const res = await fileActions.uploadUserMediaWithProgress(uri, uploadUri, progress => {
75
+ if (this.props.onUploadProgress) this.props.onUploadProgress(progress);
76
+ });
77
+
78
+ const fileUrl = Config.env.baseUploadsUrl + res.key;
79
+ this.props.onUploadSuccess(fileUrl, uploadUri);
80
+ console.log('Upload success', fileUrl);
81
+ return { success: true, url: fileUrl, uploadUri };
82
+ } catch (error) {
83
+ console.error(`Upload failed for ${name}:`, error);
84
+ this.props.onUploadFailed(uploadUri, error.message);
85
+ return { success: false, error, uploadUri };
86
+ }
87
+ });
88
+
89
+ // Wait for all uploads to complete
90
+ const results = await Promise.all(uploadPromises);
91
+ return results;
92
+ } catch (error) {
93
+ console.error('Document upload error:', error);
94
+ return [];
95
+ } finally {
96
+ this.setState({ isUploading: false, uploadProgress: 0 });
97
+ }
98
+ };
99
+
100
+ renderUploadButton = () => {
101
+ const { buttonTitle, buttonStyle, buttonTextStyle, disabled } = this.props;
102
+ const { isUploading } = this.state;
103
+ const mainColor = getMainBrandingColourFromState(this.props);
104
+
105
+ return (
106
+ <TouchableOpacity
107
+ style={[styles.uploadButton, { borderColor: mainColor }, buttonStyle]}
108
+ onPress={this.pickDocument}
109
+ disabled={isUploading || disabled}
110
+ activeOpacity={0.7}
111
+ >
112
+ {isUploading ? (
113
+ <ActivityIndicator color={mainColor} />
114
+ ) : (
115
+ <View style={styles.buttonContent}>
116
+ <Icon name="attachment" type="entypo" color={mainColor} size={18} style={styles.icon} />
117
+ <Text style={[styles.buttonText, { color: mainColor }, buttonTextStyle]}>{buttonTitle}</Text>
118
+ </View>
119
+ )}
120
+ </TouchableOpacity>
121
+ );
122
+ };
123
+
124
+ renderProgress = () => {
125
+ const { uploadProgress } = this.state;
126
+ if (uploadProgress <= 0 || uploadProgress >= 1) return null;
127
+
128
+ return (
129
+ <View style={styles.progressContainer}>
130
+ <View style={styles.progressBar}>
131
+ <View style={[styles.progressFill, { width: `${uploadProgress * 100}%` }]} />
132
+ </View>
133
+ <Text style={styles.progressText}>{Math.round(uploadProgress * 100)}%</Text>
134
+ </View>
135
+ );
136
+ };
137
+
138
+ render() {
139
+ return (
140
+ <View style={styles.container}>
141
+ {this.renderUploadButton()}
142
+ {this.renderProgress()}
143
+ </View>
144
+ );
145
+ }
146
+ }
147
+
148
+ const styles = StyleSheet.create({
149
+ container: {
150
+ marginVertical: 10,
151
+ },
152
+ uploadButton: {
153
+ flexDirection: 'row',
154
+ alignItems: 'center',
155
+ justifyContent: 'center',
156
+ paddingVertical: 8,
157
+ paddingHorizontal: 16,
158
+ borderRadius: 6,
159
+ backgroundColor: '#fff',
160
+ borderWidth: 1,
161
+ borderColor: '#007AFF',
162
+ },
163
+ buttonContent: {
164
+ flexDirection: 'row',
165
+ alignItems: 'center',
166
+ },
167
+ buttonText: {
168
+ color: '#fff',
169
+ fontSize: 16,
170
+ fontWeight: '500',
171
+ marginLeft: 8,
172
+ },
173
+ icon: {
174
+ marginRight: 8,
175
+ },
176
+ progressContainer: {
177
+ marginTop: 8,
178
+ alignItems: 'center',
179
+ },
180
+ progressBar: {
181
+ height: 4,
182
+ width: '100%',
183
+ backgroundColor: '#E0E0E0',
184
+ borderRadius: 2,
185
+ overflow: 'hidden',
186
+ },
187
+ progressFill: {
188
+ height: '100%',
189
+ backgroundColor: '#4CAF50',
190
+ },
191
+ progressText: {
192
+ marginTop: 4,
193
+ fontSize: 12,
194
+ color: TEXT_DARK,
195
+ },
196
+ });
197
+
198
+ const mapStateToProps = state => {
199
+ const { user } = state;
200
+ return {
201
+ user,
202
+ colourBrandingMain: getMainBrandingColourFromState(state),
203
+ };
204
+ };
205
+
206
+ export default connect(mapStateToProps)(DocumentUploader);
@@ -47,6 +47,7 @@ export { default as LoadingStateWidget } from './LoadingStateWidget';
47
47
  export { default as Header } from './Header';
48
48
  export { default as LoadingIndicator } from './LoadingIndicator';
49
49
  export { default as ImageUploader } from './ImageUploader';
50
+ export { default as DocumentUploader } from './DocumentUploader';
50
51
  export { default as ImageUploadProgress } from './ImageUploadProgress';
51
52
  export { default as UserListing } from './UserListing';
52
53
  export { default as PlussChat } from './PlussChat';