@plusscommunities/pluss-core-app 1.3.1 → 1.4.4-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.
- package/package.json +21 -15
- package/src/apis/index.js +2 -0
- package/src/apis/profileActions.js +13 -0
- package/src/apis/reactionActions.js +2 -1
- package/src/apis/typeActions.js +13 -0
- package/src/components/AudienceSelectorLauncher.js +61 -0
- package/src/components/AudienceSelectorPage.js +344 -0
- package/src/components/CommentReply.js +16 -12
- package/src/components/CommentSection.js +121 -28
- package/src/components/FormCardSectionOptionLauncher.js +16 -7
- package/src/components/ImageUploadProgress.js +1 -1
- package/src/components/ImageUploader.js +1 -1
- package/src/components/PlussChat.js +1 -1
- package/src/components/VideoPopup.js +2 -1
- package/src/components/index.js +2 -0
package/package.json
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@plusscommunities/pluss-core-app",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.4-beta.0",
|
|
4
4
|
"description": "Core extension package for Pluss Communities platform",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"scripts": {
|
|
7
|
+
"prepatch": "npm version prepatch --preid=beta",
|
|
7
8
|
"patch": "npm version patch",
|
|
9
|
+
"preupload": "npm publish --access public --tag beta && rm -rf node_modules",
|
|
10
|
+
"preupload:p": "npm run prepatch && npm run preupload",
|
|
8
11
|
"upload": "npm publish --access public && rm -rf node_modules",
|
|
9
12
|
"upload:p": "npm run patch && npm run upload"
|
|
10
13
|
},
|
|
@@ -12,30 +15,33 @@
|
|
|
12
15
|
"license": "ISC",
|
|
13
16
|
"dependencies": {
|
|
14
17
|
"@expo/vector-icons": "^12.0.0",
|
|
15
|
-
"
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
"expo-
|
|
21
|
-
"expo-
|
|
22
|
-
"expo-
|
|
23
|
-
"expo-
|
|
24
|
-
"expo-
|
|
25
|
-
"expo-
|
|
18
|
+
"@react-native-async-storage/async-storage": "~1.15.0",
|
|
19
|
+
"@react-native-community/netinfo": "7.1.3",
|
|
20
|
+
"@react-native-picker/picker": "2.2.1",
|
|
21
|
+
"aws-amplify": "^4.3.11",
|
|
22
|
+
"aws-amplify-react-native": "^6.0.2",
|
|
23
|
+
"expo-av": "~10.2.0",
|
|
24
|
+
"expo-constants": "~13.0.0",
|
|
25
|
+
"expo-file-system": "~13.1.0",
|
|
26
|
+
"expo-image-manipulator": "~10.2.0",
|
|
27
|
+
"expo-image-picker": "~12.0.1",
|
|
28
|
+
"expo-linear-gradient": "~11.0.0",
|
|
29
|
+
"expo-media-library": "~14.0.0",
|
|
30
|
+
"expo-screen-orientation": "~4.1.1",
|
|
31
|
+
"expo-sharing": "~10.1.0",
|
|
26
32
|
"expo-video-player": "^1.6.0",
|
|
27
33
|
"js-cookie": "^2.2.1",
|
|
28
34
|
"lodash": "^4.17.4",
|
|
29
35
|
"mime-types": "^2.1.24",
|
|
30
36
|
"moment": "^2.18.1",
|
|
31
|
-
"react": "
|
|
32
|
-
"react-native": "
|
|
37
|
+
"react": "17.0.1",
|
|
38
|
+
"react-native": "0.64.3",
|
|
33
39
|
"react-native-auto-height-image": "3.1.3",
|
|
34
40
|
"react-native-elements": "^0.17.0",
|
|
35
41
|
"react-native-image-zoom-viewer": "^3.0.1",
|
|
36
42
|
"react-native-iphone-x-helper": "^1.3.1",
|
|
37
43
|
"react-native-vimeo-iframe": "^1.0.4",
|
|
38
|
-
"react-native-webview": "11.
|
|
44
|
+
"react-native-webview": "11.15.0",
|
|
39
45
|
"react-native-youtube-iframe": "^2.2.1",
|
|
40
46
|
"react-redux": "^5.0.5"
|
|
41
47
|
},
|
package/src/apis/index.js
CHANGED
|
@@ -5,4 +5,6 @@ export * from './contactActions';
|
|
|
5
5
|
export * from './eventActions';
|
|
6
6
|
export * from './analyticsActions';
|
|
7
7
|
export * from './notificationActions';
|
|
8
|
+
export * from './typeActions';
|
|
8
9
|
export { default as userActions } from './userActions';
|
|
10
|
+
export { default as profileActions } from './profileActions';
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { getUrl } from '../helper';
|
|
2
|
+
import { authedFunction } from '../session';
|
|
3
|
+
|
|
4
|
+
const profileActions = {
|
|
5
|
+
getUserTagsBySite: site => {
|
|
6
|
+
return authedFunction({
|
|
7
|
+
method: 'GET',
|
|
8
|
+
url: getUrl('profile', 'usertags/site', { site }),
|
|
9
|
+
});
|
|
10
|
+
},
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export default profileActions;
|
|
@@ -26,13 +26,14 @@ export const reactionActions = {
|
|
|
26
26
|
},
|
|
27
27
|
});
|
|
28
28
|
},
|
|
29
|
-
addComment: (entityId, entityType, entityName, site, comment, image) => {
|
|
29
|
+
addComment: (entityId, entityType, entityName, site, comment, image, parentId) => {
|
|
30
30
|
const data = {
|
|
31
31
|
entityId,
|
|
32
32
|
entityType,
|
|
33
33
|
entityName,
|
|
34
34
|
site,
|
|
35
35
|
comment,
|
|
36
|
+
parentId,
|
|
36
37
|
};
|
|
37
38
|
if (!_.isEmpty(image)) data.image = image;
|
|
38
39
|
return authedFunction({
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { getUrl } from '../helper';
|
|
2
|
+
import { authedFunction } from '../session';
|
|
3
|
+
|
|
4
|
+
export const typeActions = {
|
|
5
|
+
getUserTypes: site => {
|
|
6
|
+
const url = getUrl('types', 'getusertypes');
|
|
7
|
+
return authedFunction({
|
|
8
|
+
method: 'POST',
|
|
9
|
+
url,
|
|
10
|
+
data: { site },
|
|
11
|
+
});
|
|
12
|
+
},
|
|
13
|
+
};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import React, { PureComponent } from 'react';
|
|
2
|
+
import { StyleSheet } from 'react-native';
|
|
3
|
+
import { connect } from 'react-redux';
|
|
4
|
+
import { FormCardSectionOptionLauncher } from './FormCardSectionOptionLauncher';
|
|
5
|
+
import { getMainBrandingColourFromState, TEXT_DARK } from '../colours';
|
|
6
|
+
import { Services } from '../config';
|
|
7
|
+
|
|
8
|
+
class AudienceSelectorLauncher extends PureComponent {
|
|
9
|
+
onPressAudience = () => {
|
|
10
|
+
const { user, audienceType, audienceTypeSelection } = this.props;
|
|
11
|
+
|
|
12
|
+
Services.navigation.navigate('audienceSelectorPage', {
|
|
13
|
+
site: user.site,
|
|
14
|
+
audienceType: audienceType || 'Custom',
|
|
15
|
+
audienceTypeSelection: audienceTypeSelection || [],
|
|
16
|
+
onChange: (audienceType, audienceTypeSelection) => {
|
|
17
|
+
if (this.props.onChange) this.props.onChange(audienceType, audienceTypeSelection);
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
render() {
|
|
23
|
+
const { style, textStyle, audienceTypeSelection } = this.props;
|
|
24
|
+
const selected =
|
|
25
|
+
audienceTypeSelection && audienceTypeSelection.length > 0
|
|
26
|
+
? `Current selection: ${audienceTypeSelection.map(i => i.Title).join(', ')}`
|
|
27
|
+
: '';
|
|
28
|
+
|
|
29
|
+
return (
|
|
30
|
+
<FormCardSectionOptionLauncher
|
|
31
|
+
sectionStyle={[styles.audienceSection, style]}
|
|
32
|
+
textStyle={[styles.audienceText, textStyle]}
|
|
33
|
+
onPress={this.onPressAudience}
|
|
34
|
+
title="Audience"
|
|
35
|
+
description={selected}
|
|
36
|
+
value={selected ? 'Custom' : 'All Users'}
|
|
37
|
+
/>
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const styles = StyleSheet.create({
|
|
43
|
+
audienceSection: {
|
|
44
|
+
paddingHorizontal: 0,
|
|
45
|
+
},
|
|
46
|
+
audienceText: {
|
|
47
|
+
fontFamily: 'sf-semibold',
|
|
48
|
+
fontSize: 16,
|
|
49
|
+
color: TEXT_DARK,
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
const mapStateToProps = state => {
|
|
54
|
+
return {
|
|
55
|
+
user: state.user,
|
|
56
|
+
colourBrandingMain: getMainBrandingColourFromState(state),
|
|
57
|
+
};
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
const audienceSelectorLauncher = connect(mapStateToProps, {})(AudienceSelectorLauncher);
|
|
61
|
+
export { audienceSelectorLauncher as AudienceSelectorLauncher };
|
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
import React, { Component } from 'react';
|
|
2
|
+
import { connect } from 'react-redux';
|
|
3
|
+
import _ from 'lodash';
|
|
4
|
+
import { TouchableOpacity, View, ScrollView, Text, StyleSheet } from 'react-native';
|
|
5
|
+
import { Icon } from 'react-native-elements';
|
|
6
|
+
import { Services } from '../config';
|
|
7
|
+
import { FormCard } from './FormCard';
|
|
8
|
+
import { FormCardSection } from './FormCardSection';
|
|
9
|
+
import { InlineButton } from './InlineButton';
|
|
10
|
+
import Header from './Header';
|
|
11
|
+
import { Spinner } from './Spinner';
|
|
12
|
+
import { TEXT_DARK, COLOUR_GREEN, BG_GREY, INACTIVE_BUTTON, TEXT_LIGHT, getMainBrandingColourFromState } from '../colours';
|
|
13
|
+
import { typeActions, profileActions } from '../apis';
|
|
14
|
+
|
|
15
|
+
class AudienceSelectorPage extends Component {
|
|
16
|
+
constructor(props) {
|
|
17
|
+
super(props);
|
|
18
|
+
|
|
19
|
+
this.state = {
|
|
20
|
+
loading: false,
|
|
21
|
+
categories: [
|
|
22
|
+
{
|
|
23
|
+
name: 'All Primary Users',
|
|
24
|
+
key: 'resident',
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
name: 'All Staff Users',
|
|
28
|
+
key: 'staff',
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
name: 'All Linked Users',
|
|
32
|
+
key: 'family',
|
|
33
|
+
},
|
|
34
|
+
],
|
|
35
|
+
types: [],
|
|
36
|
+
tags: [],
|
|
37
|
+
combinedList: [],
|
|
38
|
+
seeAll: false,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
componentDidMount = async () => {
|
|
43
|
+
try {
|
|
44
|
+
this.setState({ loading: true });
|
|
45
|
+
await this.getUserTypes();
|
|
46
|
+
await this.getUserTags();
|
|
47
|
+
this.setState({ loading: false, combinedList: this.getAvailableAudienceTags() });
|
|
48
|
+
} catch (error) {
|
|
49
|
+
console.error('loading types error', error);
|
|
50
|
+
this.setState({ loading: false });
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
getUserTypes = async () => {
|
|
55
|
+
const { data } = await typeActions.getUserTypes(this.props.site);
|
|
56
|
+
data.forEach(e => {
|
|
57
|
+
e.name = e.category ? `(${e.category[0].toUpperCase() + e.category.substring(1)}) ${e.displayName}` : e.displayName;
|
|
58
|
+
e.key = e.typeName;
|
|
59
|
+
});
|
|
60
|
+
// console.log('getUserTypes', data);
|
|
61
|
+
this.setState({ types: data });
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
getUserTags = async () => {
|
|
65
|
+
const { data } = await profileActions.getUserTagsBySite(this.props.site);
|
|
66
|
+
data.forEach(e => {
|
|
67
|
+
e.name = e.Title;
|
|
68
|
+
e.key = e.Id;
|
|
69
|
+
});
|
|
70
|
+
// console.log('getUserTags', data);
|
|
71
|
+
this.setState({ tags: data });
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
getAvailableAudienceTags = () => {
|
|
75
|
+
const { categories, types, tags } = this.state;
|
|
76
|
+
const { audienceTypeSelection } = this.props;
|
|
77
|
+
|
|
78
|
+
const categoryTags = categories.map(c => {
|
|
79
|
+
const Id = `category_${c.key}`;
|
|
80
|
+
return {
|
|
81
|
+
AudienceType: 'Category',
|
|
82
|
+
AudienceTypeSelection: c.key,
|
|
83
|
+
Id,
|
|
84
|
+
Title: c.name,
|
|
85
|
+
Selected: audienceTypeSelection.some(i => i.Id === Id),
|
|
86
|
+
};
|
|
87
|
+
});
|
|
88
|
+
const userTypeTags = types.map(t => {
|
|
89
|
+
const Id = `userType_${t.typeName}`;
|
|
90
|
+
return {
|
|
91
|
+
AudienceType: 'UserType',
|
|
92
|
+
AudienceTypeSelection: t.typeName,
|
|
93
|
+
Id,
|
|
94
|
+
Title: `User Type: ${t.displayName}`,
|
|
95
|
+
Selected: audienceTypeSelection.some(i => i.Id === Id),
|
|
96
|
+
};
|
|
97
|
+
});
|
|
98
|
+
const userTagTags = tags.map(t => {
|
|
99
|
+
const Id = `userTag_${t.Id}`;
|
|
100
|
+
return {
|
|
101
|
+
AudienceType: 'UserTags',
|
|
102
|
+
AudienceTypeSelection: t.Id,
|
|
103
|
+
Id,
|
|
104
|
+
Title: `User Tag: ${t.Title}`,
|
|
105
|
+
Selected: audienceTypeSelection.some(i => i.Id === Id),
|
|
106
|
+
};
|
|
107
|
+
});
|
|
108
|
+
return [...categoryTags, ...userTypeTags, ...userTagTags];
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
onPressBack = () => {
|
|
112
|
+
Services.navigation.goBack();
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
onSelectAll = () => {
|
|
116
|
+
const newList = [...this.state.combinedList];
|
|
117
|
+
newList.forEach(i => (i.Selected = false));
|
|
118
|
+
this.setState({ combinedList: newList });
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
onSeeAll = () => {
|
|
122
|
+
this.setState({ seeAll: !this.state.seeAll });
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
onToggleAudienceOption = option => {
|
|
126
|
+
const newList = [...this.state.combinedList];
|
|
127
|
+
const selected = newList.find(i => i.Id === option.Id);
|
|
128
|
+
if (selected) {
|
|
129
|
+
selected.Selected = !selected.Selected;
|
|
130
|
+
this.setState({ combinedList: newList });
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
onDone = () => {
|
|
135
|
+
if (this.props.onChange) {
|
|
136
|
+
const { combinedList } = this.state;
|
|
137
|
+
const selected = combinedList.filter(i => i.Selected);
|
|
138
|
+
if (selected && selected.length > 0) {
|
|
139
|
+
this.props.onChange('Custom', selected);
|
|
140
|
+
} else {
|
|
141
|
+
this.props.onChange(null, null);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
Services.navigation.goBack();
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
renderOption(label, selected, onSelect, key = null, hasUnderline = true) {
|
|
148
|
+
return (
|
|
149
|
+
<TouchableOpacity key={key} onPress={onSelect}>
|
|
150
|
+
<FormCardSection hasUnderline={hasUnderline} hasContent>
|
|
151
|
+
<View style={styles.labelContainer}>
|
|
152
|
+
<Text style={styles.labelText}>{label}</Text>
|
|
153
|
+
<Icon
|
|
154
|
+
name="check-circle"
|
|
155
|
+
type="font-awesome"
|
|
156
|
+
iconStyle={[{ color: INACTIVE_BUTTON, fontSize: 20 }, selected && { color: COLOUR_GREEN }]}
|
|
157
|
+
/>
|
|
158
|
+
</View>
|
|
159
|
+
</FormCardSection>
|
|
160
|
+
</TouchableOpacity>
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
renderSelectAll() {
|
|
165
|
+
const { combinedList, loading } = this.state;
|
|
166
|
+
const allSelected = !combinedList.find(i => i.Selected);
|
|
167
|
+
if (loading) return null;
|
|
168
|
+
|
|
169
|
+
return (
|
|
170
|
+
<FormCard style={styles.selectAllContainer}>{this.renderOption('All Users', allSelected, this.onSelectAll, null, false)}</FormCard>
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
renderSelection() {
|
|
175
|
+
const { loading, combinedList, seeAll } = this.state;
|
|
176
|
+
if (loading) return null;
|
|
177
|
+
|
|
178
|
+
const selectedText = combinedList
|
|
179
|
+
.filter(i => i.Selected)
|
|
180
|
+
.map(i => i.Title)
|
|
181
|
+
.join(', ');
|
|
182
|
+
const hasSelected = !_.isEmpty(selectedText);
|
|
183
|
+
|
|
184
|
+
return (
|
|
185
|
+
<View style={styles.selectionContainer}>
|
|
186
|
+
<View style={styles.selectionContainerInner}>
|
|
187
|
+
<Text style={styles.selectionTitle}>or select from below</Text>
|
|
188
|
+
{hasSelected ? (
|
|
189
|
+
<TouchableOpacity onPress={this.onSeeAll}>
|
|
190
|
+
<Text style={styles.seeAllButton}>{seeAll ? 'See less' : 'See all'}</Text>
|
|
191
|
+
</TouchableOpacity>
|
|
192
|
+
) : null}
|
|
193
|
+
</View>
|
|
194
|
+
{hasSelected ? (
|
|
195
|
+
<Text style={styles.selectionText} numberOfLines={seeAll ? null : 1}>{`Current selection: ${selectedText}`}</Text>
|
|
196
|
+
) : null}
|
|
197
|
+
</View>
|
|
198
|
+
);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
renderTips() {
|
|
202
|
+
return (
|
|
203
|
+
<View style={styles.tipContainer}>
|
|
204
|
+
<Text style={styles.tipText}>
|
|
205
|
+
<Text style={{ fontFamily: 'sf-semibold' }}>Tip: </Text>
|
|
206
|
+
Group your users using User Tags from your website Community Manager
|
|
207
|
+
</Text>
|
|
208
|
+
</View>
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
renderAvailableAudiences() {
|
|
213
|
+
const { loading, combinedList } = this.state;
|
|
214
|
+
|
|
215
|
+
return (
|
|
216
|
+
<ScrollView style={styles.availableScrollContainer} contentContainerStyle={styles.availabelScrollContent}>
|
|
217
|
+
<FormCard>
|
|
218
|
+
{combinedList.map((option, index) => {
|
|
219
|
+
const notLast = index < combinedList.length - 1;
|
|
220
|
+
return this.renderOption(option.Title, option.Selected, () => this.onToggleAudienceOption(option), index, notLast);
|
|
221
|
+
})}
|
|
222
|
+
</FormCard>
|
|
223
|
+
{loading ? <Spinner /> : null}
|
|
224
|
+
{this.renderTips()}
|
|
225
|
+
</ScrollView>
|
|
226
|
+
);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
renderButtons() {
|
|
230
|
+
const { loading } = this.state;
|
|
231
|
+
|
|
232
|
+
return (
|
|
233
|
+
<View style={styles.doneButtonContainer}>
|
|
234
|
+
<InlineButton
|
|
235
|
+
color={loading ? INACTIVE_BUTTON : this.props.colourBrandingMain}
|
|
236
|
+
onPress={this.onDone}
|
|
237
|
+
touchableStyle={styles.doneButton}
|
|
238
|
+
fillTouchable
|
|
239
|
+
large
|
|
240
|
+
disabled={loading}
|
|
241
|
+
>
|
|
242
|
+
Done
|
|
243
|
+
</InlineButton>
|
|
244
|
+
</View>
|
|
245
|
+
);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
render() {
|
|
249
|
+
return (
|
|
250
|
+
<View style={styles.container}>
|
|
251
|
+
<Header leftIcon="angle-left" onPressLeft={this.onPressBack} text={'Select Audience'} />
|
|
252
|
+
{this.renderSelectAll()}
|
|
253
|
+
{this.renderSelection()}
|
|
254
|
+
{this.renderAvailableAudiences()}
|
|
255
|
+
{this.renderButtons()}
|
|
256
|
+
</View>
|
|
257
|
+
);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
const styles = StyleSheet.create({
|
|
262
|
+
container: {
|
|
263
|
+
flex: 1,
|
|
264
|
+
position: 'relative',
|
|
265
|
+
backgroundColor: BG_GREY,
|
|
266
|
+
},
|
|
267
|
+
selectAllContainer: {
|
|
268
|
+
marginTop: 20,
|
|
269
|
+
},
|
|
270
|
+
selectionContainer: {
|
|
271
|
+
padding: 20,
|
|
272
|
+
},
|
|
273
|
+
selectionContainerInner: {
|
|
274
|
+
flexDirection: 'row',
|
|
275
|
+
justifyContent: 'space-between',
|
|
276
|
+
},
|
|
277
|
+
selectionTitle: {
|
|
278
|
+
fontFamily: 'sf-bold',
|
|
279
|
+
fontSize: 14,
|
|
280
|
+
color: TEXT_DARK,
|
|
281
|
+
},
|
|
282
|
+
selectionText: {
|
|
283
|
+
fontFamily: 'sf-bold',
|
|
284
|
+
fontSize: 14,
|
|
285
|
+
color: TEXT_DARK,
|
|
286
|
+
marginTop: 10,
|
|
287
|
+
},
|
|
288
|
+
seeAllButton: {
|
|
289
|
+
marginLeft: 10,
|
|
290
|
+
fontFamily: 'sf-bold',
|
|
291
|
+
fontSize: 14,
|
|
292
|
+
color: TEXT_LIGHT,
|
|
293
|
+
},
|
|
294
|
+
availableScrollContainer: {
|
|
295
|
+
flex: 1,
|
|
296
|
+
},
|
|
297
|
+
availabelScrollContent: {
|
|
298
|
+
flexGrow: 1,
|
|
299
|
+
justifyContent: 'space-between',
|
|
300
|
+
flexDirection: 'column',
|
|
301
|
+
},
|
|
302
|
+
tipContainer: {
|
|
303
|
+
padding: 10,
|
|
304
|
+
},
|
|
305
|
+
tipText: {
|
|
306
|
+
fontSize: 14,
|
|
307
|
+
fontFamily: 'sf-regular',
|
|
308
|
+
color: TEXT_DARK,
|
|
309
|
+
},
|
|
310
|
+
labelContainer: {
|
|
311
|
+
flexDirection: 'row',
|
|
312
|
+
justifyContent: 'space-between',
|
|
313
|
+
},
|
|
314
|
+
labelText: {
|
|
315
|
+
fontFamily: 'sf-medium',
|
|
316
|
+
fontSize: 16,
|
|
317
|
+
color: TEXT_DARK,
|
|
318
|
+
},
|
|
319
|
+
description: {
|
|
320
|
+
marginTop: 5,
|
|
321
|
+
fontSize: 14,
|
|
322
|
+
fontFamily: 'sf-regular',
|
|
323
|
+
color: TEXT_DARK,
|
|
324
|
+
},
|
|
325
|
+
doneButtonContainer: {
|
|
326
|
+
backgroundColor: '#fff',
|
|
327
|
+
marginTop: 1,
|
|
328
|
+
flexDirection: 'row',
|
|
329
|
+
paddingTop: 10,
|
|
330
|
+
paddingBottom: 20,
|
|
331
|
+
},
|
|
332
|
+
doneButton: {
|
|
333
|
+
flex: 1,
|
|
334
|
+
marginHorizontal: 6,
|
|
335
|
+
},
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
const mapStateToProps = state => {
|
|
339
|
+
return {
|
|
340
|
+
colourBrandingMain: getMainBrandingColourFromState(state),
|
|
341
|
+
};
|
|
342
|
+
};
|
|
343
|
+
|
|
344
|
+
export default connect(mapStateToProps, {})(AudienceSelectorPage);
|
|
@@ -2,6 +2,7 @@ import React, { Component } from 'react';
|
|
|
2
2
|
import { connect } from 'react-redux';
|
|
3
3
|
import { Keyboard, TextInput, View, ImageBackground, TouchableOpacity, Dimensions } from 'react-native';
|
|
4
4
|
import { Icon } from 'react-native-elements';
|
|
5
|
+
import { getBottomSpace } from 'react-native-iphone-x-helper';
|
|
5
6
|
import _ from 'lodash';
|
|
6
7
|
import { getApiError } from '../session';
|
|
7
8
|
import { getShadowStyle } from '../helper';
|
|
@@ -26,9 +27,9 @@ class CommentReply extends Component {
|
|
|
26
27
|
}
|
|
27
28
|
|
|
28
29
|
componentDidMount() {
|
|
29
|
-
if (this.props.commentSection) {
|
|
30
|
+
if (this.props.commentSection && this.props.commentSection.current) {
|
|
30
31
|
this.setState({
|
|
31
|
-
commentsLoading: this.props.commentSection.getWrappedInstance().isLoading(),
|
|
32
|
+
commentsLoading: this.props.commentSection.current.getWrappedInstance().isLoading(),
|
|
32
33
|
});
|
|
33
34
|
}
|
|
34
35
|
}
|
|
@@ -39,7 +40,7 @@ class CommentReply extends Component {
|
|
|
39
40
|
});
|
|
40
41
|
setTimeout(() => {
|
|
41
42
|
if (!this.props.noScroll) {
|
|
42
|
-
this.props.scrollView
|
|
43
|
+
this.props.scrollView?.current?.scrollToEnd({ animated: true });
|
|
43
44
|
}
|
|
44
45
|
}, 500);
|
|
45
46
|
};
|
|
@@ -81,7 +82,7 @@ class CommentReply extends Component {
|
|
|
81
82
|
addComment() {
|
|
82
83
|
setTimeout(() => {
|
|
83
84
|
if (!this.props.noScroll) {
|
|
84
|
-
this.props.scrollView
|
|
85
|
+
this.props.scrollView?.current?.scrollToEnd({ animated: true });
|
|
85
86
|
}
|
|
86
87
|
}, 500);
|
|
87
88
|
const text = this.state.commentInput;
|
|
@@ -93,20 +94,20 @@ class CommentReply extends Component {
|
|
|
93
94
|
});
|
|
94
95
|
Keyboard.dismiss();
|
|
95
96
|
if (this.props.commentSection) {
|
|
96
|
-
this.props.commentSection
|
|
97
|
+
this.props.commentSection?.current?.getWrappedInstance().startedAddingComment();
|
|
97
98
|
}
|
|
98
99
|
reactionActions
|
|
99
|
-
.addComment(this.props.entityId, this.props.entityType, this.props.entityName, this.props.site, text, image)
|
|
100
|
+
.addComment(this.props.entityId, this.props.entityType, this.props.entityName, this.props.site, text, image, this.props.threadId)
|
|
100
101
|
.then(res => {
|
|
101
102
|
if (this.props.commentSection) {
|
|
102
|
-
this.props.commentSection
|
|
103
|
+
this.props.commentSection?.current?.getWrappedInstance().commentAdded(res.data);
|
|
103
104
|
}
|
|
104
105
|
this.setState({
|
|
105
106
|
addingComment: false,
|
|
106
107
|
});
|
|
107
108
|
setTimeout(() => {
|
|
108
109
|
if (!this.props.noScroll) {
|
|
109
|
-
this.props.scrollView
|
|
110
|
+
this.props.scrollView?.current?.scrollToEnd({ animated: true });
|
|
110
111
|
}
|
|
111
112
|
}, 500);
|
|
112
113
|
})
|
|
@@ -125,7 +126,7 @@ class CommentReply extends Component {
|
|
|
125
126
|
if (this.state.uploadingCommentImage || !_.isEmpty(this.state.commentImageInput)) {
|
|
126
127
|
return;
|
|
127
128
|
}
|
|
128
|
-
this.commentImageUploader.
|
|
129
|
+
this.commentImageUploader.showUploadMenu();
|
|
129
130
|
}
|
|
130
131
|
|
|
131
132
|
renderImageAttachment() {
|
|
@@ -181,9 +182,11 @@ class CommentReply extends Component {
|
|
|
181
182
|
|
|
182
183
|
render() {
|
|
183
184
|
if (_.includes(this.props.user.hidden, 'addComment')) {
|
|
185
|
+
console.log('no way');
|
|
184
186
|
return null;
|
|
185
187
|
}
|
|
186
188
|
if (this.state.commentsLoading) {
|
|
189
|
+
console.log('still loading');
|
|
187
190
|
return null;
|
|
188
191
|
}
|
|
189
192
|
return (
|
|
@@ -202,12 +205,12 @@ class CommentReply extends Component {
|
|
|
202
205
|
value={this.state.commentInput}
|
|
203
206
|
onFocus={() => {
|
|
204
207
|
if (!this.props.noScroll) {
|
|
205
|
-
this.props.scrollView
|
|
208
|
+
this.props.scrollView?.current?.scrollToEnd({ animated: true });
|
|
206
209
|
}
|
|
207
210
|
}}
|
|
208
211
|
onChangeText={value => {
|
|
209
212
|
if (!this.props.noScroll) {
|
|
210
|
-
this.props.scrollView
|
|
213
|
+
this.props.scrollView?.current?.scrollToEnd({ animated: false });
|
|
211
214
|
}
|
|
212
215
|
this.setState({
|
|
213
216
|
commentInput: value,
|
|
@@ -290,6 +293,7 @@ const styles = {
|
|
|
290
293
|
backgroundColor: '#fff',
|
|
291
294
|
paddingVertical: 8,
|
|
292
295
|
paddingHorizontal: 8,
|
|
296
|
+
paddingBottom: 8 + getBottomSpace(),
|
|
293
297
|
flexGrow: 1,
|
|
294
298
|
},
|
|
295
299
|
inputText: {
|
|
@@ -329,5 +333,5 @@ const mapStateToProps = state => {
|
|
|
329
333
|
return { user };
|
|
330
334
|
};
|
|
331
335
|
|
|
332
|
-
const commentReply = connect(mapStateToProps, {}, null, {
|
|
336
|
+
const commentReply = connect(mapStateToProps, {}, null, { forwardRef: true })(CommentReply);
|
|
333
337
|
export { commentReply as CommentReply };
|
|
@@ -4,10 +4,15 @@ import _ from 'lodash';
|
|
|
4
4
|
import moment from 'moment';
|
|
5
5
|
import { connect } from 'react-redux';
|
|
6
6
|
import { Icon } from 'react-native-elements';
|
|
7
|
-
import { getPluralS, getThumb300, get1400, getSiteSettingFromState } from '../helper';
|
|
7
|
+
import { getPluralS, getThumb300, get1400, getSiteSettingFromState, getFirstName, getPluralOptions } from '../helper';
|
|
8
8
|
import { getMainBrandingColourFromState, TEXT_DARKEST, BG_GREY, TEXT_LIGHT, LINEGREY } from '../colours';
|
|
9
9
|
import { reactionActions, notificationActions } from '../apis';
|
|
10
|
-
import { ConfirmPopup
|
|
10
|
+
import { ConfirmPopup } from './ConfirmPopup';
|
|
11
|
+
import { ProfilePic } from './ProfilePic';
|
|
12
|
+
import { ImagePopup } from './ImagePopup';
|
|
13
|
+
import { InlineButton } from './InlineButton';
|
|
14
|
+
import { Spinner } from './Spinner';
|
|
15
|
+
import { Services } from '../config';
|
|
11
16
|
|
|
12
17
|
class CommentSection extends Component {
|
|
13
18
|
constructor(props) {
|
|
@@ -96,9 +101,13 @@ class CommentSection extends Component {
|
|
|
96
101
|
}
|
|
97
102
|
|
|
98
103
|
onGoToAdd() {
|
|
99
|
-
this.props.commentReply.
|
|
104
|
+
this.props.commentReply.focusInput();
|
|
100
105
|
}
|
|
101
106
|
|
|
107
|
+
onOpenThread = comment => {
|
|
108
|
+
Services.navigation.navigate('thread', { ...this.props, threadId: comment.Id });
|
|
109
|
+
};
|
|
110
|
+
|
|
102
111
|
onMute = () => {
|
|
103
112
|
const { entityType, entityId } = this.props;
|
|
104
113
|
this.setState({ processing: true }, async () => {
|
|
@@ -170,9 +179,8 @@ class CommentSection extends Component {
|
|
|
170
179
|
commentsLoadStarted: true,
|
|
171
180
|
commentsLoading: true,
|
|
172
181
|
});
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
}
|
|
182
|
+
this.props.commentReply?.current?.getWrappedInstance().loadingStarted();
|
|
183
|
+
|
|
176
184
|
this.loadComments();
|
|
177
185
|
}
|
|
178
186
|
}
|
|
@@ -191,9 +199,17 @@ class CommentSection extends Component {
|
|
|
191
199
|
this.setState(
|
|
192
200
|
{
|
|
193
201
|
comments: _.sortBy(
|
|
194
|
-
_.uniqBy(
|
|
195
|
-
|
|
196
|
-
|
|
202
|
+
_.uniqBy(
|
|
203
|
+
_.filter(_.concat(this.state.comments, res.data), c => {
|
|
204
|
+
if (!this.props.threadId) {
|
|
205
|
+
return true;
|
|
206
|
+
}
|
|
207
|
+
return c.Id === this.props.threadId || c.ParentId === this.props.threadId;
|
|
208
|
+
}),
|
|
209
|
+
c => {
|
|
210
|
+
return c.Id;
|
|
211
|
+
},
|
|
212
|
+
),
|
|
197
213
|
'Timestamp',
|
|
198
214
|
),
|
|
199
215
|
commentsLoading: false,
|
|
@@ -204,9 +220,9 @@ class CommentSection extends Component {
|
|
|
204
220
|
}
|
|
205
221
|
},
|
|
206
222
|
);
|
|
207
|
-
if (this.props.commentReply) {
|
|
208
|
-
|
|
209
|
-
}
|
|
223
|
+
//if (this.props.commentReply) {
|
|
224
|
+
this.props.commentReply?.current?.getWrappedInstance().loadingCompleted();
|
|
225
|
+
//}
|
|
210
226
|
if (this.props.live) {
|
|
211
227
|
this.loadTimer = setTimeout(() => {
|
|
212
228
|
this.loadComments();
|
|
@@ -310,6 +326,55 @@ class CommentSection extends Component {
|
|
|
310
326
|
);
|
|
311
327
|
}
|
|
312
328
|
|
|
329
|
+
renderReplyText = c => {
|
|
330
|
+
if (this.props.threadId || this.props.hideReplyButton) {
|
|
331
|
+
return null;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
const threadComments = _.filter(this.state.comments, innerC => {
|
|
335
|
+
return innerC.ParentId === c.Id;
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
let content = null;
|
|
339
|
+
|
|
340
|
+
if (_.isEmpty(threadComments)) {
|
|
341
|
+
// no replies
|
|
342
|
+
content = (
|
|
343
|
+
<Text style={[styles.commentRepliesText, { color: this.props.colourBrandingMain }]}>{`Reply to ${getFirstName(
|
|
344
|
+
c.User ? c.User.displayName : 'comment',
|
|
345
|
+
)}`}</Text>
|
|
346
|
+
);
|
|
347
|
+
} else {
|
|
348
|
+
// existing replies
|
|
349
|
+
const profilePics = _.take(
|
|
350
|
+
_.uniqBy(threadComments, c => c.UserId),
|
|
351
|
+
3,
|
|
352
|
+
);
|
|
353
|
+
content = (
|
|
354
|
+
<View style={styles.multiReplyContainer}>
|
|
355
|
+
{profilePics.map((c, i) => {
|
|
356
|
+
return <ProfilePic style={{ marginRight: -10 }} Diameter={20} ProfilePic={c.User.profilePic} />;
|
|
357
|
+
})}
|
|
358
|
+
<Text style={[styles.commentRepliesText, { marginLeft: 20, color: this.props.colourBrandingMain }]}>{`${
|
|
359
|
+
threadComments.length
|
|
360
|
+
} repl${getPluralOptions(threadComments.length, 'y', 'ies')}`}</Text>
|
|
361
|
+
</View>
|
|
362
|
+
);
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
return (
|
|
366
|
+
<View style={styles.commentReplies}>
|
|
367
|
+
<TouchableOpacity
|
|
368
|
+
onPress={() => {
|
|
369
|
+
this.onOpenThread(c);
|
|
370
|
+
}}
|
|
371
|
+
>
|
|
372
|
+
{content}
|
|
373
|
+
</TouchableOpacity>
|
|
374
|
+
</View>
|
|
375
|
+
);
|
|
376
|
+
};
|
|
377
|
+
|
|
313
378
|
renderComment(c) {
|
|
314
379
|
return (
|
|
315
380
|
<View style={styles.comment} key={c.Id}>
|
|
@@ -323,27 +388,32 @@ class CommentSection extends Component {
|
|
|
323
388
|
<Icon name="trash" type="font-awesome" iconStyle={styles.commentButtonIcon} />
|
|
324
389
|
</View>
|
|
325
390
|
</TouchableOpacity>
|
|
326
|
-
) :
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
)
|
|
391
|
+
) : null
|
|
392
|
+
// (
|
|
393
|
+
// !this.props.disableFlag && (
|
|
394
|
+
// <TouchableOpacity onPress={this.onPressReportComment.bind(this, c)}>
|
|
395
|
+
// <View style={[styles.commentButtonContainer, { backgroundColor: this.props.colourBrandingMain }]}>
|
|
396
|
+
// <Icon name="flag" type="font-awesome" iconStyle={styles.commentButtonIcon} />
|
|
397
|
+
// </View>
|
|
398
|
+
// </TouchableOpacity>
|
|
399
|
+
// )
|
|
400
|
+
// )
|
|
401
|
+
}
|
|
335
402
|
<Text style={[styles.commentName, { fontSize: this.getAdjustedSize(13) }]}>{c.User.displayName}</Text>
|
|
336
403
|
</View>
|
|
337
404
|
{!_.isEmpty(c.Comment) && <Text style={[styles.commentText, { fontSize: this.getAdjustedSize(13) }]}>{c.Comment}</Text>}
|
|
338
405
|
{this.renderCommentImage(c)}
|
|
339
406
|
</View>
|
|
340
407
|
</View>
|
|
341
|
-
<
|
|
342
|
-
{
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
408
|
+
<View style={styles.commentBottom}>
|
|
409
|
+
<Text style={[styles.commentTime, { fontSize: this.getAdjustedSize(13) }]}>
|
|
410
|
+
{moment
|
|
411
|
+
.utc(c.Timestamp)
|
|
412
|
+
.local()
|
|
413
|
+
.format('D MMM • h:mma')}
|
|
414
|
+
</Text>
|
|
415
|
+
{this.renderReplyText(c)}
|
|
416
|
+
</View>
|
|
347
417
|
</View>
|
|
348
418
|
);
|
|
349
419
|
}
|
|
@@ -414,6 +484,11 @@ class CommentSection extends Component {
|
|
|
414
484
|
if (this.props.reverseOrder) {
|
|
415
485
|
source = source.reverse();
|
|
416
486
|
}
|
|
487
|
+
if (!this.props.showReplies && !this.props.threadId) {
|
|
488
|
+
source = _.filter(source, c => {
|
|
489
|
+
return !c.ParentId;
|
|
490
|
+
});
|
|
491
|
+
}
|
|
417
492
|
return (
|
|
418
493
|
<View style={styles.commentSection}>
|
|
419
494
|
{!this.isEmpty() && (
|
|
@@ -535,12 +610,30 @@ const styles = StyleSheet.create({
|
|
|
535
610
|
fontFamily: 'sf-regular',
|
|
536
611
|
color: TEXT_DARKEST,
|
|
537
612
|
},
|
|
613
|
+
commentBottom: {
|
|
614
|
+
flexDirection: 'row-reverse',
|
|
615
|
+
justifyContent: 'space-between',
|
|
616
|
+
alignItems: 'center',
|
|
617
|
+
},
|
|
538
618
|
commentTime: {
|
|
539
619
|
fontFamily: 'sf-regular',
|
|
540
620
|
marginTop: 4,
|
|
541
621
|
color: TEXT_LIGHT,
|
|
542
622
|
textAlign: 'right',
|
|
543
623
|
},
|
|
624
|
+
commentReplies: {
|
|
625
|
+
flex: 1,
|
|
626
|
+
paddingLeft: 48,
|
|
627
|
+
},
|
|
628
|
+
commentRepliesText: {
|
|
629
|
+
fontFamily: 'sf-semibold',
|
|
630
|
+
fontSize: 15,
|
|
631
|
+
},
|
|
632
|
+
multiReplyContainer: {
|
|
633
|
+
flexDirection: 'row',
|
|
634
|
+
alignItems: 'center',
|
|
635
|
+
paddingVertical: 4,
|
|
636
|
+
},
|
|
544
637
|
commentImageContainer: {
|
|
545
638
|
marginTop: 8,
|
|
546
639
|
width: 60,
|
|
@@ -611,5 +704,5 @@ const mapStateToProps = state => {
|
|
|
611
704
|
};
|
|
612
705
|
};
|
|
613
706
|
|
|
614
|
-
const commentSection = connect(mapStateToProps, {}, null, {
|
|
707
|
+
const commentSection = connect(mapStateToProps, {}, null, { forwardRef: true })(CommentSection);
|
|
615
708
|
export { commentSection as CommentSection };
|
|
@@ -2,23 +2,26 @@ import React, { PureComponent } from 'react';
|
|
|
2
2
|
import { View, Text, TouchableOpacity } from 'react-native';
|
|
3
3
|
import { Icon } from 'react-native-elements';
|
|
4
4
|
import { connect } from 'react-redux';
|
|
5
|
-
import { TEXT_DARK, getMainBrandingColourFromState } from '../colours';
|
|
5
|
+
import { TEXT_DARK, TEXT_LIGHT, getMainBrandingColourFromState } from '../colours';
|
|
6
6
|
import { FormCardSection } from './FormCardSection';
|
|
7
7
|
|
|
8
8
|
class FormCardSectionOptionLauncher extends PureComponent {
|
|
9
9
|
render() {
|
|
10
|
+
const { onPress, sectionStyle, textStyle, title, description, value, icon, colourBrandingMain } = this.props;
|
|
11
|
+
|
|
10
12
|
return (
|
|
11
|
-
<TouchableOpacity onPress={
|
|
12
|
-
<FormCardSection hasContent sectionStyle={
|
|
13
|
+
<TouchableOpacity onPress={onPress}>
|
|
14
|
+
<FormCardSection hasContent sectionStyle={sectionStyle}>
|
|
13
15
|
<View style={styles.container}>
|
|
14
|
-
<Text style={[styles.text, { marginRight: 16, flex: 1 },
|
|
15
|
-
<Text style={[styles.text, { marginRight: 16 }]}>{
|
|
16
|
+
<Text style={[styles.text, { marginRight: 16, flex: 1 }, textStyle]}>{title}</Text>
|
|
17
|
+
<Text style={[styles.text, { marginRight: 16 }]}>{value}</Text>
|
|
16
18
|
<Icon
|
|
17
|
-
name={
|
|
19
|
+
name={icon ? icon : 'angle-right'}
|
|
18
20
|
type="font-awesome"
|
|
19
|
-
iconStyle={[styles.text, { fontSize: 20, color:
|
|
21
|
+
iconStyle={[styles.text, { fontSize: 20, color: colourBrandingMain }]}
|
|
20
22
|
/>
|
|
21
23
|
</View>
|
|
24
|
+
{description ? <Text style={styles.description}>{description}</Text> : null}
|
|
22
25
|
</FormCardSection>
|
|
23
26
|
</TouchableOpacity>
|
|
24
27
|
);
|
|
@@ -36,6 +39,12 @@ const styles = {
|
|
|
36
39
|
fontSize: 17,
|
|
37
40
|
color: TEXT_DARK,
|
|
38
41
|
},
|
|
42
|
+
description: {
|
|
43
|
+
fontFamily: 'sf-regular',
|
|
44
|
+
fontSize: 15,
|
|
45
|
+
color: TEXT_LIGHT,
|
|
46
|
+
marginTop: 8,
|
|
47
|
+
},
|
|
39
48
|
};
|
|
40
49
|
|
|
41
50
|
const mapStateToProps = state => {
|
|
@@ -5,7 +5,7 @@ import { Spinner } from './Spinner';
|
|
|
5
5
|
|
|
6
6
|
class ImageUploadProgress extends Component {
|
|
7
7
|
onRetryUpload = (imageUri, uploadUri) => {
|
|
8
|
-
this.props.uploader.
|
|
8
|
+
this.props.uploader.retryUpload(imageUri, uploadUri);
|
|
9
9
|
};
|
|
10
10
|
|
|
11
11
|
render() {
|
|
@@ -786,4 +786,4 @@ const mapStateToProps = state => {
|
|
|
786
786
|
};
|
|
787
787
|
};
|
|
788
788
|
|
|
789
|
-
export default connect(mapStateToProps, { stockImagesLoaded, imageLibraryLoaded }, null, {
|
|
789
|
+
export default connect(mapStateToProps, { stockImagesLoaded, imageLibraryLoaded }, null, { forwardRef: true })(ImageUploader);
|
|
@@ -3,7 +3,8 @@ import { Platform, View, Modal, TouchableOpacity, StyleSheet } from 'react-nativ
|
|
|
3
3
|
import * as ScreenOrientation from 'expo-screen-orientation';
|
|
4
4
|
import { StatusBarHeight, getCompressed, imageExists } from '../helper';
|
|
5
5
|
import { Pl60Icon } from '../fonts';
|
|
6
|
-
import { SharingTools
|
|
6
|
+
import { SharingTools } from './SharingTools';
|
|
7
|
+
import { MediaPlayer } from './MediaPlayer';
|
|
7
8
|
|
|
8
9
|
class VideoPopup extends Component {
|
|
9
10
|
constructor(props) {
|
package/src/components/index.js
CHANGED
|
@@ -36,6 +36,7 @@ export * from './FontScalePopup';
|
|
|
36
36
|
export * from './FontScaleButton';
|
|
37
37
|
export * from './UserListPopup';
|
|
38
38
|
export * from './Reactions';
|
|
39
|
+
export * from './AudienceSelectorLauncher';
|
|
39
40
|
export { default as EmptyStateWidget } from './EmptyStateWidget';
|
|
40
41
|
export { default as EmptyStateMain } from './EmptyStateMain';
|
|
41
42
|
export { default as LoadingStateWidget } from './LoadingStateWidget';
|
|
@@ -48,3 +49,4 @@ export { default as PlussChat } from './PlussChat';
|
|
|
48
49
|
export { default as PositionedImage } from './PositionedImage';
|
|
49
50
|
export { default as FormattedText } from './FormattedText';
|
|
50
51
|
export { default as MediaPlayer } from './MediaPlayer';
|
|
52
|
+
export { default as AudienceSelectorPage } from './AudienceSelectorPage';
|