@plusscommunities/pluss-core-app 1.2.3 → 1.4.1-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 -16
- package/src/apis/index.js +1 -0
- package/src/apis/notificationActions.js +47 -0
- package/src/components/CommentReply.js +1 -1
- package/src/components/CommentSection.js +157 -14
- package/src/components/ImageUploader.js +5 -5
- package/src/components/MediaPlayer.js +13 -12
- package/src/components/VideoPopup.js +2 -1
- package/src/components/expo-image-picker-multiple/ImageBrowser.js +3 -3
package/package.json
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@plusscommunities/pluss-core-app",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.1-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,31 +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-
|
|
26
|
-
"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",
|
|
27
32
|
"expo-video-player": "^1.6.0",
|
|
28
33
|
"js-cookie": "^2.2.1",
|
|
29
34
|
"lodash": "^4.17.4",
|
|
30
35
|
"mime-types": "^2.1.24",
|
|
31
36
|
"moment": "^2.18.1",
|
|
32
|
-
"react": "
|
|
33
|
-
"react-native": "
|
|
37
|
+
"react": "17.0.1",
|
|
38
|
+
"react-native": "0.64.3",
|
|
34
39
|
"react-native-auto-height-image": "3.1.3",
|
|
35
40
|
"react-native-elements": "^0.17.0",
|
|
36
41
|
"react-native-image-zoom-viewer": "^3.0.1",
|
|
37
42
|
"react-native-iphone-x-helper": "^1.3.1",
|
|
38
43
|
"react-native-vimeo-iframe": "^1.0.4",
|
|
39
|
-
"react-native-webview": "11.
|
|
44
|
+
"react-native-webview": "11.15.0",
|
|
40
45
|
"react-native-youtube-iframe": "^2.2.1",
|
|
41
46
|
"react-redux": "^5.0.5"
|
|
42
47
|
},
|
package/src/apis/index.js
CHANGED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { getUrl } from '../helper';
|
|
2
|
+
import { authedFunction } from '../session';
|
|
3
|
+
|
|
4
|
+
export const notificationActions = {
|
|
5
|
+
getAppNotificationSetting: () => {
|
|
6
|
+
return authedFunction({
|
|
7
|
+
method: 'GET',
|
|
8
|
+
url: getUrl('notifications', 'getState/get', {
|
|
9
|
+
type: 'app',
|
|
10
|
+
}),
|
|
11
|
+
});
|
|
12
|
+
},
|
|
13
|
+
muteApp: () => {
|
|
14
|
+
return authedFunction({
|
|
15
|
+
method: 'POST',
|
|
16
|
+
url: getUrl('notifications', 'updateState/mute'),
|
|
17
|
+
data: { type: 'app' },
|
|
18
|
+
});
|
|
19
|
+
},
|
|
20
|
+
unmuteApp: () => {
|
|
21
|
+
return authedFunction({
|
|
22
|
+
method: 'POST',
|
|
23
|
+
url: getUrl('notifications', 'updateState/unmute'),
|
|
24
|
+
data: { type: 'app' },
|
|
25
|
+
});
|
|
26
|
+
},
|
|
27
|
+
getEntityNotificationSetting: (type, id) => {
|
|
28
|
+
return authedFunction({
|
|
29
|
+
method: 'GET',
|
|
30
|
+
url: getUrl('notifications', 'getState/get', { type, id }),
|
|
31
|
+
});
|
|
32
|
+
},
|
|
33
|
+
muteEntity: (type, id) => {
|
|
34
|
+
return authedFunction({
|
|
35
|
+
method: 'POST',
|
|
36
|
+
url: getUrl('notifications', 'updateState/mute'),
|
|
37
|
+
data: { type, id },
|
|
38
|
+
});
|
|
39
|
+
},
|
|
40
|
+
unmuteEntity: (type, id) => {
|
|
41
|
+
return authedFunction({
|
|
42
|
+
method: 'POST',
|
|
43
|
+
url: getUrl('notifications', 'updateState/unmute'),
|
|
44
|
+
data: { type, id },
|
|
45
|
+
});
|
|
46
|
+
},
|
|
47
|
+
};
|
|
@@ -329,5 +329,5 @@ const mapStateToProps = state => {
|
|
|
329
329
|
return { user };
|
|
330
330
|
};
|
|
331
331
|
|
|
332
|
-
const commentReply = connect(mapStateToProps, {}, null, {
|
|
332
|
+
const commentReply = connect(mapStateToProps, {}, null, { forwardRef: true })(CommentReply);
|
|
333
333
|
export { commentReply as CommentReply };
|
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
import React, { Component } from 'react';
|
|
2
|
-
import { View, Text, TouchableOpacity, Image } from 'react-native';
|
|
2
|
+
import { View, Text, TouchableOpacity, Image, StyleSheet } from 'react-native';
|
|
3
3
|
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 } from '../helper';
|
|
7
|
+
import { getPluralS, getThumb300, get1400, getSiteSettingFromState } from '../helper';
|
|
8
8
|
import { getMainBrandingColourFromState, TEXT_DARKEST, BG_GREY, TEXT_LIGHT, LINEGREY } from '../colours';
|
|
9
|
-
import {
|
|
10
|
-
import { reactionActions } from '../apis';
|
|
9
|
+
import { reactionActions, notificationActions } from '../apis';
|
|
11
10
|
import { ConfirmPopup } from './ConfirmPopup';
|
|
12
11
|
import { ProfilePic } from './ProfilePic';
|
|
13
12
|
import { ImagePopup } from './ImagePopup';
|
|
13
|
+
import { InlineButton } from './InlineButton';
|
|
14
|
+
import { Spinner } from './Spinner';
|
|
14
15
|
|
|
15
16
|
class CommentSection extends Component {
|
|
16
17
|
constructor(props) {
|
|
@@ -23,10 +24,15 @@ class CommentSection extends Component {
|
|
|
23
24
|
commentToReport: null,
|
|
24
25
|
commentReportedStatus: null,
|
|
25
26
|
reportLoading: false,
|
|
27
|
+
processing: false,
|
|
28
|
+
muteExpiry: null,
|
|
29
|
+
muteLoaded: false,
|
|
26
30
|
};
|
|
27
31
|
}
|
|
28
32
|
|
|
29
33
|
componentDidMount() {
|
|
34
|
+
this.getNotificationSate();
|
|
35
|
+
|
|
30
36
|
if (!_.includes(this.props.user.hidden, 'viewComment')) {
|
|
31
37
|
this.getComments();
|
|
32
38
|
}
|
|
@@ -97,6 +103,64 @@ class CommentSection extends Component {
|
|
|
97
103
|
this.props.commentReply.getWrappedInstance().focusInput();
|
|
98
104
|
}
|
|
99
105
|
|
|
106
|
+
onMute = () => {
|
|
107
|
+
const { entityType, entityId } = this.props;
|
|
108
|
+
this.setState({ processing: true }, async () => {
|
|
109
|
+
try {
|
|
110
|
+
const { data } = await notificationActions.muteEntity(entityType, entityId);
|
|
111
|
+
// console.log('onMute', data);
|
|
112
|
+
const muteExpiry = moment(data.Expiry);
|
|
113
|
+
this.setState({ muteExpiry, processing: false });
|
|
114
|
+
} catch (error) {
|
|
115
|
+
console.error('onMute', error);
|
|
116
|
+
this.setState({ processing: false });
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
onUnmute = () => {
|
|
122
|
+
const { entityType, entityId } = this.props;
|
|
123
|
+
this.setState({ processing: true }, async () => {
|
|
124
|
+
try {
|
|
125
|
+
const { data } = await notificationActions.unmuteEntity(entityType, entityId);
|
|
126
|
+
// console.log('onUnmute', data);
|
|
127
|
+
this.setState({ muteExpiry: null, processing: false });
|
|
128
|
+
} catch (error) {
|
|
129
|
+
console.error('onUnmute', error);
|
|
130
|
+
this.setState({ processing: false });
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
isMuted = () => {
|
|
136
|
+
const { muteExpiry } = this.state;
|
|
137
|
+
return muteExpiry && moment() <= muteExpiry;
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
getMuteRemaining = () => {
|
|
141
|
+
const { muteExpiry } = this.state;
|
|
142
|
+
const actual = muteExpiry ? moment.duration(muteExpiry.diff(moment())).asHours() : 0;
|
|
143
|
+
return Math.abs(Math.ceil(actual));
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
getNotificationSate = () => {
|
|
147
|
+
const { processing } = this.state;
|
|
148
|
+
const { entityType, entityId, notificationsForComments } = this.props;
|
|
149
|
+
if (processing || !notificationsForComments) return;
|
|
150
|
+
|
|
151
|
+
this.setState({ processing: true }, async () => {
|
|
152
|
+
try {
|
|
153
|
+
const { data } = await notificationActions.getEntityNotificationSetting(entityType, entityId);
|
|
154
|
+
// console.log('getNotificationSate', data);
|
|
155
|
+
const muteExpiry = data ? moment(data.Expiry) : null;
|
|
156
|
+
this.setState({ muteExpiry, muteLoaded: true, processing: false });
|
|
157
|
+
} catch (error) {
|
|
158
|
+
console.error('getNotificationSate', error);
|
|
159
|
+
this.setState({ processing: false });
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
};
|
|
163
|
+
|
|
100
164
|
getAdjustedSize(size) {
|
|
101
165
|
if (this.props.scaleFont) {
|
|
102
166
|
return size + this.props.user.fontScale;
|
|
@@ -288,6 +352,47 @@ class CommentSection extends Component {
|
|
|
288
352
|
);
|
|
289
353
|
}
|
|
290
354
|
|
|
355
|
+
renderMute() {
|
|
356
|
+
const { notificationsForComments } = this.props;
|
|
357
|
+
const { muteLoaded, muteExpiry, processing } = this.state;
|
|
358
|
+
if (!notificationsForComments || !muteLoaded) return null;
|
|
359
|
+
|
|
360
|
+
if (processing)
|
|
361
|
+
return (
|
|
362
|
+
<View style={styles.muteSpinnerContainer}>
|
|
363
|
+
<Spinner size={'small'} color={this.props.colourBrandingMain} />
|
|
364
|
+
</View>
|
|
365
|
+
);
|
|
366
|
+
|
|
367
|
+
const isMuted = this.isMuted();
|
|
368
|
+
const hours = this.getMuteRemaining();
|
|
369
|
+
const mutedFor = `Muted for ${hours} hour${getPluralS(hours)}`;
|
|
370
|
+
// console.log(muteExpiry.format('DD MMM YYYY hh:mm a'));
|
|
371
|
+
|
|
372
|
+
return (
|
|
373
|
+
<View style={styles.muteContainer}>
|
|
374
|
+
{isMuted && muteExpiry ? <Text style={[{ color: this.props.colourBrandingMain }, styles.mutedForText]}>{mutedFor}</Text> : null}
|
|
375
|
+
<InlineButton
|
|
376
|
+
onPress={isMuted ? this.onUnmute : this.onMute}
|
|
377
|
+
color="#fff"
|
|
378
|
+
style={[{ borderColor: this.props.colourBrandingMain }, styles.muteButton]}
|
|
379
|
+
disabled={processing}
|
|
380
|
+
disabledOpacity
|
|
381
|
+
noText
|
|
382
|
+
>
|
|
383
|
+
<View style={styles.muteButtonInner}>
|
|
384
|
+
<Icon
|
|
385
|
+
name={isMuted ? 'bell-o' : 'bell-slash-o'}
|
|
386
|
+
type={'font-awesome'}
|
|
387
|
+
iconStyle={[{ color: this.props.colourBrandingMain }, styles.muteButtonIcon]}
|
|
388
|
+
/>
|
|
389
|
+
<Text style={[{ color: this.props.colourBrandingMain }, styles.muteButtonText]}>{isMuted ? 'Unmute' : 'Mute'}</Text>
|
|
390
|
+
</View>
|
|
391
|
+
</InlineButton>
|
|
392
|
+
</View>
|
|
393
|
+
);
|
|
394
|
+
}
|
|
395
|
+
|
|
291
396
|
renderComments() {
|
|
292
397
|
if (this.state.commentsLoading) {
|
|
293
398
|
return (
|
|
@@ -317,11 +422,14 @@ class CommentSection extends Component {
|
|
|
317
422
|
<View style={styles.commentSection}>
|
|
318
423
|
{!this.isEmpty() && (
|
|
319
424
|
<View style={styles.commentSectionTitleRow}>
|
|
320
|
-
{
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
425
|
+
<View style={{ alignItems: 'flex-end' }}>
|
|
426
|
+
{this.renderMute()}
|
|
427
|
+
{!this.props.hideAddComment && this.state.comments.length > 2 && (
|
|
428
|
+
<TouchableOpacity onPress={this.onGoToAdd.bind(this)}>
|
|
429
|
+
<Text style={[styles.goToText, { color: this.props.colourBrandingMain }]}>Add a comment</Text>
|
|
430
|
+
</TouchableOpacity>
|
|
431
|
+
)}
|
|
432
|
+
</View>
|
|
325
433
|
<Text style={[styles.commentCount, { fontSize: this.getAdjustedSize(15) }]}>
|
|
326
434
|
{this.state.comments.length}
|
|
327
435
|
{` comment${getPluralS(this.state.comments.length)}`}
|
|
@@ -374,22 +482,22 @@ class CommentSection extends Component {
|
|
|
374
482
|
}
|
|
375
483
|
}
|
|
376
484
|
|
|
377
|
-
const styles = {
|
|
485
|
+
const styles = StyleSheet.create({
|
|
378
486
|
commentSectionOuter: {
|
|
379
487
|
flex: 1,
|
|
380
488
|
paddingHorizontal: 16,
|
|
381
489
|
},
|
|
382
490
|
commentSection: {
|
|
383
491
|
flex: 1,
|
|
384
|
-
paddingVertical:
|
|
492
|
+
paddingVertical: 12,
|
|
385
493
|
borderTopColor: LINEGREY,
|
|
386
494
|
borderTopWidth: 1,
|
|
387
|
-
borderTopStyle: 'solid',
|
|
388
495
|
},
|
|
389
496
|
commentCount: {
|
|
390
497
|
fontFamily: 'sf-semibold',
|
|
391
498
|
color: TEXT_DARKEST,
|
|
392
499
|
flex: 1,
|
|
500
|
+
marginTop: 4,
|
|
393
501
|
},
|
|
394
502
|
comment: {
|
|
395
503
|
marginTop: 16,
|
|
@@ -463,14 +571,49 @@ const styles = {
|
|
|
463
571
|
reportLoadingContainer: {
|
|
464
572
|
paddingVertical: 10,
|
|
465
573
|
},
|
|
466
|
-
|
|
574
|
+
goToText: {
|
|
575
|
+
marginTop: 4,
|
|
576
|
+
},
|
|
577
|
+
muteSpinnerContainer: {
|
|
578
|
+
width: 100,
|
|
579
|
+
marginBottom: 6,
|
|
580
|
+
},
|
|
581
|
+
muteContainer: {
|
|
582
|
+
flexDirection: 'row',
|
|
583
|
+
alignItems: 'center',
|
|
584
|
+
justifyContent: 'flex-end',
|
|
585
|
+
marginBottom: 6,
|
|
586
|
+
},
|
|
587
|
+
mutedForText: {
|
|
588
|
+
fontFamily: 'sf-semibold',
|
|
589
|
+
fontSize: 13,
|
|
590
|
+
marginRight: 8,
|
|
591
|
+
},
|
|
592
|
+
muteButton: {
|
|
593
|
+
borderWidth: 1,
|
|
594
|
+
paddingHorizontal: 8,
|
|
595
|
+
},
|
|
596
|
+
muteButtonInner: {
|
|
597
|
+
flexDirection: 'row',
|
|
598
|
+
alignItems: 'center',
|
|
599
|
+
},
|
|
600
|
+
muteButtonIcon: {
|
|
601
|
+
fontSize: 14,
|
|
602
|
+
},
|
|
603
|
+
muteButtonText: {
|
|
604
|
+
fontFamily: 'sf-semibold',
|
|
605
|
+
fontSize: 14,
|
|
606
|
+
marginLeft: 6,
|
|
607
|
+
},
|
|
608
|
+
});
|
|
467
609
|
|
|
468
610
|
const mapStateToProps = state => {
|
|
469
611
|
return {
|
|
470
612
|
colourBrandingMain: getMainBrandingColourFromState(state),
|
|
471
613
|
user: state.user,
|
|
614
|
+
notificationsForComments: getSiteSettingFromState(state, 'NotificationsForComments', false),
|
|
472
615
|
};
|
|
473
616
|
};
|
|
474
617
|
|
|
475
|
-
const commentSection = connect(mapStateToProps, {}, null, {
|
|
618
|
+
const commentSection = connect(mapStateToProps, {}, null, { forwardRef: true })(CommentSection);
|
|
476
619
|
export { commentSection as CommentSection };
|
|
@@ -3,7 +3,7 @@ import { View, ScrollView, TouchableOpacity, Text, Platform, Linking, Modal, Dim
|
|
|
3
3
|
import { connect } from 'react-redux';
|
|
4
4
|
import { Icon } from 'react-native-elements';
|
|
5
5
|
import _ from 'lodash';
|
|
6
|
-
import
|
|
6
|
+
import { Camera } from 'expo-camera';
|
|
7
7
|
import * as MediaLibrary from 'expo-media-library';
|
|
8
8
|
import * as ImageManipulator from 'expo-image-manipulator';
|
|
9
9
|
import * as ImagePicker from 'expo-image-picker';
|
|
@@ -60,7 +60,7 @@ class ImageUploader extends Component {
|
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
loadLocalAlbums = async () => {
|
|
63
|
-
const hasPermission = await
|
|
63
|
+
const hasPermission = await MediaLibrary.getPermissionsAsync();
|
|
64
64
|
if (!hasPermission.granted) return;
|
|
65
65
|
|
|
66
66
|
this.setState({ loadingLocalFolders: true }, async () => {
|
|
@@ -254,8 +254,8 @@ class ImageUploader extends Component {
|
|
|
254
254
|
}
|
|
255
255
|
|
|
256
256
|
askPermissionsAsync = async () => {
|
|
257
|
-
const cameraPermission = await
|
|
258
|
-
const rollPermission = await
|
|
257
|
+
const cameraPermission = await Camera.requestCameraPermissionsAsync();
|
|
258
|
+
const rollPermission = await MediaLibrary.requestPermissionsAsync();
|
|
259
259
|
if (cameraPermission.status !== 'granted' || rollPermission.status !== 'granted') {
|
|
260
260
|
this.showWarningPopup(cameraPermission.status !== 'granted', rollPermission.status !== 'granted');
|
|
261
261
|
return false;
|
|
@@ -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);
|
|
@@ -39,7 +39,7 @@ class MediaPlayer extends Component {
|
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
componentDidMount = async () => {
|
|
42
|
-
this.setupForPlaying();
|
|
42
|
+
await this.setupForPlaying();
|
|
43
43
|
|
|
44
44
|
ScreenOrientation.lockAsync(Platform.OS === 'ios' ? ScreenOrientation.OrientationLock.DEFAULT : ScreenOrientation.OrientationLock.ALL);
|
|
45
45
|
const motionAvailalble = await DeviceMotion.isAvailableAsync();
|
|
@@ -75,25 +75,26 @@ class MediaPlayer extends Component {
|
|
|
75
75
|
|
|
76
76
|
setupForPlaying = async () => {
|
|
77
77
|
// Extract live stream info
|
|
78
|
-
const { source } = this.props;
|
|
79
|
-
const isUrlLink = source.startsWith('http');
|
|
80
|
-
const isYoutube = source.includes('youtube.com/watch?v=') || source.includes('youtu.be/');
|
|
81
|
-
const isVimeo = source.includes('vimeo.com/');
|
|
82
|
-
|
|
78
|
+
const { source, useVideoPlayer } = this.props;
|
|
79
|
+
const isUrlLink = source && source.startsWith('http');
|
|
80
|
+
const isYoutube = source && (source.includes('youtube.com/watch?v=') || source.includes('youtu.be/'));
|
|
81
|
+
const isVimeo = source && source.includes('vimeo.com/');
|
|
82
|
+
let heightFactor = 0;
|
|
83
83
|
|
|
84
84
|
if (isYoutube) {
|
|
85
85
|
const metadata = await getYoutubeMeta(this.getYoutubeVideoId(source));
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
this.setState({ heightFactor: 0.565, readyToRender: true });
|
|
86
|
+
heightFactor = metadata.height / metadata.width;
|
|
87
|
+
} else if (useVideoPlayer) {
|
|
88
|
+
heightFactor = 0;
|
|
90
89
|
} else {
|
|
91
|
-
|
|
90
|
+
heightFactor = 0.565;
|
|
92
91
|
}
|
|
92
|
+
|
|
93
|
+
this.setState({ isUrlLink, isYoutube, isVimeo, playbackLoaded: isYoutube || isVimeo, heightFactor, readyToRender: true });
|
|
93
94
|
};
|
|
94
95
|
|
|
95
96
|
getStreamPlaybackUrl = () => {
|
|
96
|
-
// return 'https://stream.mux.com/
|
|
97
|
+
// return 'https://stream.mux.com/Ym4nKktRpGuZNBBBlzhxpyRwZLpvMlPRchcu01x6Ur600.m3u8';
|
|
97
98
|
return `https://stream.mux.com/${this.props.playbackId}.m3u8`;
|
|
98
99
|
};
|
|
99
100
|
|
|
@@ -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) {
|
|
@@ -3,7 +3,7 @@ import { StyleSheet, View, FlatList, Dimensions, ActivityIndicator, Platform } f
|
|
|
3
3
|
import _ from 'lodash';
|
|
4
4
|
import * as ScreenOrientation from 'expo-screen-orientation';
|
|
5
5
|
import * as MediaLibrary from 'expo-media-library';
|
|
6
|
-
import
|
|
6
|
+
import { Camera } from 'expo-camera';
|
|
7
7
|
import { isVideo } from '../../helper';
|
|
8
8
|
import ImageTile from './ImageTile';
|
|
9
9
|
|
|
@@ -49,8 +49,8 @@ export default class ImageBrowser extends React.Component {
|
|
|
49
49
|
};
|
|
50
50
|
|
|
51
51
|
getPermissionsAsync = async () => {
|
|
52
|
-
const { status: camera } = await
|
|
53
|
-
const { status: cameraRoll } = await
|
|
52
|
+
const { status: camera } = await Camera.requestCameraPermissionsAsync();
|
|
53
|
+
const { status: cameraRoll } = await MediaLibrary.requestPermissionsAsync();
|
|
54
54
|
this.setState({
|
|
55
55
|
hasCameraPermission: camera === 'granted',
|
|
56
56
|
hasCameraRollPermission: cameraRoll === 'granted',
|