be-components 2.4.4 → 2.4.6
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/lib/commonjs/Components/Icons.js +60 -0
- package/lib/commonjs/Components/Icons.js.map +1 -1
- package/lib/commonjs/Components/Slider.js +38 -0
- package/lib/commonjs/Components/Slider.js.map +1 -0
- package/lib/commonjs/SocialComponents/AudioPlayer.js +384 -0
- package/lib/commonjs/SocialComponents/AudioPlayer.js.map +1 -0
- package/lib/commonjs/SocialComponents/CompanyProfile/index.js +4 -1
- package/lib/commonjs/SocialComponents/CompanyProfile/index.js.map +1 -1
- package/lib/commonjs/SocialComponents/PodcastEpisodeCard.js +40 -1
- package/lib/commonjs/SocialComponents/PodcastEpisodeCard.js.map +1 -1
- package/lib/commonjs/SocialComponents/PodcastModule/api/index.js +5 -2
- package/lib/commonjs/SocialComponents/PodcastModule/api/index.js.map +1 -1
- package/lib/commonjs/SocialComponents/PodcastModule/index.js +9 -3
- package/lib/commonjs/SocialComponents/PodcastModule/index.js.map +1 -1
- package/lib/commonjs/SocialComponents/api/index.js +62 -0
- package/lib/commonjs/SocialComponents/api/index.js.map +1 -1
- package/lib/commonjs/SocialComponents/index.js +7 -0
- package/lib/commonjs/SocialComponents/index.js.map +1 -1
- package/lib/module/Components/Icons.js +60 -0
- package/lib/module/Components/Icons.js.map +1 -1
- package/lib/module/Components/Slider.js +31 -0
- package/lib/module/Components/Slider.js.map +1 -0
- package/lib/module/SocialComponents/AudioPlayer.js +375 -0
- package/lib/module/SocialComponents/AudioPlayer.js.map +1 -0
- package/lib/module/SocialComponents/CompanyProfile/index.js +4 -1
- package/lib/module/SocialComponents/CompanyProfile/index.js.map +1 -1
- package/lib/module/SocialComponents/PodcastEpisodeCard.js +40 -1
- package/lib/module/SocialComponents/PodcastEpisodeCard.js.map +1 -1
- package/lib/module/SocialComponents/PodcastModule/api/index.js +5 -2
- package/lib/module/SocialComponents/PodcastModule/api/index.js.map +1 -1
- package/lib/module/SocialComponents/PodcastModule/index.js +9 -3
- package/lib/module/SocialComponents/PodcastModule/index.js.map +1 -1
- package/lib/module/SocialComponents/api/index.js +62 -0
- package/lib/module/SocialComponents/api/index.js.map +1 -1
- package/lib/module/SocialComponents/index.js +2 -1
- package/lib/module/SocialComponents/index.js.map +1 -1
- package/lib/typescript/src/Components/Icons.d.ts +2 -0
- package/lib/typescript/src/Components/Icons.d.ts.map +1 -1
- package/lib/typescript/src/Components/Slider.d.ts +15 -0
- package/lib/typescript/src/Components/Slider.d.ts.map +1 -0
- package/lib/typescript/src/SocialComponents/AudioPlayer.d.ts +9 -0
- package/lib/typescript/src/SocialComponents/AudioPlayer.d.ts.map +1 -0
- package/lib/typescript/src/SocialComponents/PodcastEpisodeCard.d.ts +3 -2
- package/lib/typescript/src/SocialComponents/PodcastEpisodeCard.d.ts.map +1 -1
- package/lib/typescript/src/SocialComponents/PodcastModule/api/index.d.ts +5 -2
- package/lib/typescript/src/SocialComponents/PodcastModule/api/index.d.ts.map +1 -1
- package/lib/typescript/src/SocialComponents/PodcastModule/index.d.ts.map +1 -1
- package/lib/typescript/src/SocialComponents/api/index.d.ts +15 -2
- package/lib/typescript/src/SocialComponents/api/index.d.ts.map +1 -1
- package/lib/typescript/src/SocialComponents/index.d.ts +2 -1
- package/lib/typescript/src/SocialComponents/index.d.ts.map +1 -1
- package/package.json +2 -1
- package/src/Components/Icons.tsx +33 -0
- package/src/Components/Slider.tsx +34 -0
- package/src/SocialComponents/AudioPlayer.tsx +285 -0
- package/src/SocialComponents/CompanyProfile/index.tsx +1 -1
- package/src/SocialComponents/PodcastEpisodeCard.tsx +22 -6
- package/src/SocialComponents/PodcastModule/api/index.ts +4 -4
- package/src/SocialComponents/PodcastModule/index.tsx +11 -4
- package/src/SocialComponents/api/index.ts +57 -2
- package/src/SocialComponents/index.tsx +3 -1
- package/src/types.d.ts +27 -0
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
import React, { useEffect, useRef, useState } from 'react';
|
|
2
|
+
import { View, Platform, Image, ActivityIndicator, TouchableOpacity } from 'react-native';
|
|
3
|
+
import { SocialComponentApi, SocialPodcastHelpers } from './api';
|
|
4
|
+
import type { PlayerPodcastEpisodeProps, PlayerPodcastProps, PodcastEpisodesProps } from '../types';
|
|
5
|
+
import { Button, Icons, Text } from '../Components';
|
|
6
|
+
import { view_styles } from '../constants/styles';
|
|
7
|
+
import Colors from '../constants/colors';
|
|
8
|
+
import Slider from '../Components/Slider';
|
|
9
|
+
|
|
10
|
+
type AudioPlayerProps = {
|
|
11
|
+
podcast_episode_id:string,
|
|
12
|
+
player_id?:string,
|
|
13
|
+
onClose:() => void
|
|
14
|
+
}
|
|
15
|
+
const AudioPlayer = ({podcast_episode_id, player_id, onClose}:AudioPlayerProps) => {
|
|
16
|
+
const [ audio_size, setAudioSize ] = useState({ width:50 });
|
|
17
|
+
const [ audio_data, setAudioData ] = useState<{
|
|
18
|
+
audio_loading:boolean,
|
|
19
|
+
podcast_episode?:PodcastEpisodesProps,
|
|
20
|
+
}>({
|
|
21
|
+
audio_loading:false,
|
|
22
|
+
});
|
|
23
|
+
const { audio_loading, podcast_episode } = audio_data;
|
|
24
|
+
const [ time_data, setTimeData ] = useState<{
|
|
25
|
+
duration: number,
|
|
26
|
+
loaded:boolean,
|
|
27
|
+
status: 'paused'|'playing',
|
|
28
|
+
current_time: number,
|
|
29
|
+
time_remaining:number,
|
|
30
|
+
minimum_value: number,
|
|
31
|
+
maximum_value:number
|
|
32
|
+
}>({
|
|
33
|
+
duration:0,
|
|
34
|
+
loaded:false,
|
|
35
|
+
status: 'paused',
|
|
36
|
+
current_time:0,
|
|
37
|
+
time_remaining:0,
|
|
38
|
+
minimum_value:0,
|
|
39
|
+
maximum_value: 0
|
|
40
|
+
});
|
|
41
|
+
const { loaded, status, current_time, time_remaining, maximum_value, minimum_value } = time_data;
|
|
42
|
+
|
|
43
|
+
const [ player_data, setPlayerData ] = useState<{
|
|
44
|
+
player_loading:boolean,
|
|
45
|
+
player_podcast?:PlayerPodcastProps,
|
|
46
|
+
player_podcast_episode?:PlayerPodcastEpisodeProps
|
|
47
|
+
}>({
|
|
48
|
+
player_loading: false
|
|
49
|
+
});
|
|
50
|
+
const { player_loading, player_podcast } = player_data;
|
|
51
|
+
|
|
52
|
+
const audio_ref:any = useRef(null)
|
|
53
|
+
|
|
54
|
+
useEffect(() => {
|
|
55
|
+
const handleBeforeUnload = async(event:any) => {
|
|
56
|
+
event.preventDefault();
|
|
57
|
+
event.returnValue = ''; // This is required for some browsers to show a confirmation dialog
|
|
58
|
+
// Perform any cleanup or save data here
|
|
59
|
+
if(audio_ref?.current){
|
|
60
|
+
await SocialComponentApi.pausePodcastEpisode(podcast_episode_id, audio_ref.current.currentTime);
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
if(Platform.OS == 'web'){
|
|
65
|
+
window.addEventListener('beforeunload', handleBeforeUnload);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return () => {
|
|
69
|
+
if(Platform.OS == 'web'){
|
|
70
|
+
window.removeEventListener('beforeunload', handleBeforeUnload);
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
},[])
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
useEffect(() => {
|
|
77
|
+
SocialComponentApi.setEnvironment();
|
|
78
|
+
getAudioData(podcast_episode_id);
|
|
79
|
+
},[podcast_episode_id]);
|
|
80
|
+
|
|
81
|
+
const getAudioData = async(pod_episode_id:string) => {
|
|
82
|
+
setAudioData({ ...audio_data, audio_loading:true })
|
|
83
|
+
const episode = await SocialComponentApi.getPodcastEpisodeById(pod_episode_id);
|
|
84
|
+
setAudioData({
|
|
85
|
+
...audio_data,
|
|
86
|
+
audio_loading: false,
|
|
87
|
+
podcast_episode: episode
|
|
88
|
+
})
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const getPlayerData = async(pod_episode_id:string) => {
|
|
92
|
+
setPlayerData({ ...player_data, player_loading: true });
|
|
93
|
+
const p_data = await SocialComponentApi.getPlayerPodcastEpisode(pod_episode_id);
|
|
94
|
+
setPlayerData({
|
|
95
|
+
...player_data,
|
|
96
|
+
player_loading: false,
|
|
97
|
+
player_podcast:p_data?.player_podcast,
|
|
98
|
+
player_podcast_episode:p_data?.player_podcast_episode
|
|
99
|
+
});
|
|
100
|
+
return p_data
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const startAudio = async() => {
|
|
104
|
+
if(!audio_ref?.current || !loaded){ return alert('Unable to play audio at this time') }
|
|
105
|
+
let cur_time = audio_ref.current.currentTime
|
|
106
|
+
let dur = audio_ref.current.duration
|
|
107
|
+
audio_ref?.current.play();
|
|
108
|
+
if(player_id){
|
|
109
|
+
setPlayerData({ ...player_data, player_loading: true });
|
|
110
|
+
const p_resp = await SocialComponentApi.startPodcastEpisode(podcast_episode_id);
|
|
111
|
+
setPlayerData({ ...player_data, player_loading: false, player_podcast: p_resp?.player_podcast, player_podcast_episode: p_resp?.player_podcast_episode });
|
|
112
|
+
}
|
|
113
|
+
setTimeData({
|
|
114
|
+
...time_data,
|
|
115
|
+
current_time: cur_time,
|
|
116
|
+
time_remaining: dur - cur_time,
|
|
117
|
+
duration: dur,
|
|
118
|
+
status: 'playing'
|
|
119
|
+
})
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const pauseAudio = async() => {
|
|
123
|
+
if(!audio_ref?.current || !loaded){ return alert('Unable to play audio at this time') }
|
|
124
|
+
let cur_time = audio_ref.current.currentTime
|
|
125
|
+
let dur = audio_ref.current.duration
|
|
126
|
+
audio_ref?.current.pause();
|
|
127
|
+
|
|
128
|
+
if(player_id){
|
|
129
|
+
setPlayerData({ ...player_data, player_loading: true });
|
|
130
|
+
const p_resp = await SocialComponentApi.pausePodcastEpisode(podcast_episode_id, cur_time);
|
|
131
|
+
setPlayerData({ ...player_data, player_loading: false, player_podcast, player_podcast_episode: p_resp });
|
|
132
|
+
}
|
|
133
|
+
setTimeData({
|
|
134
|
+
...time_data,
|
|
135
|
+
current_time: cur_time,
|
|
136
|
+
time_remaining: dur - cur_time,
|
|
137
|
+
duration: dur,
|
|
138
|
+
status: 'paused'
|
|
139
|
+
})
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const handleTimeChange = () => {
|
|
143
|
+
if(!loaded || player_loading || audio_loading){ return }
|
|
144
|
+
if(!audio_ref?.current){ return }//Error
|
|
145
|
+
let cur_time = audio_ref.current.currentTime
|
|
146
|
+
let dur = audio_ref.current.duration
|
|
147
|
+
setTimeData({
|
|
148
|
+
...time_data,
|
|
149
|
+
current_time: cur_time,
|
|
150
|
+
time_remaining: dur - cur_time,
|
|
151
|
+
duration: dur,
|
|
152
|
+
})
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const handleLoad = async() => {
|
|
156
|
+
if(!audio_ref?.current){ return alert('Unable to play audio') }
|
|
157
|
+
//First, lets grab the duration of the podcast episode
|
|
158
|
+
const dur = audio_ref.current.duration
|
|
159
|
+
let cur_time = 0
|
|
160
|
+
if(player_id){
|
|
161
|
+
let p_data = await getPlayerData(podcast_episode_id);
|
|
162
|
+
if(p_data?.player_podcast_episode && audio_ref?.current){
|
|
163
|
+
audio_ref.current.currentTime = p_data.player_podcast_episode.pause_timestamp
|
|
164
|
+
cur_time = p_data.player_podcast_episode.pause_timestamp
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
setTimeData({
|
|
169
|
+
...time_data,
|
|
170
|
+
current_time: cur_time,
|
|
171
|
+
minimum_value: 0,
|
|
172
|
+
maximum_value: dur,
|
|
173
|
+
time_remaining: dur - cur_time,
|
|
174
|
+
status: 'playing',
|
|
175
|
+
loaded:true
|
|
176
|
+
});
|
|
177
|
+
audio_ref.current.play()
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const handleStartTimeChange = () => {
|
|
181
|
+
if(!audio_ref?.current || !loaded){ return }
|
|
182
|
+
const cur = audio_ref.current.currentTime
|
|
183
|
+
let dur = audio_ref.current.duration
|
|
184
|
+
setTimeData({
|
|
185
|
+
...time_data,
|
|
186
|
+
current_time: cur,
|
|
187
|
+
duration: dur,
|
|
188
|
+
time_remaining: dur - cur,
|
|
189
|
+
status: 'paused'
|
|
190
|
+
})
|
|
191
|
+
audio_ref.current.pause();
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
const handleManualTimeChange = (val:number) => {
|
|
195
|
+
if(!audio_ref?.current || !loaded){ return }
|
|
196
|
+
audio_ref.current.currentTime = val
|
|
197
|
+
let dur = audio_ref.current.duration
|
|
198
|
+
setTimeData({
|
|
199
|
+
...time_data,
|
|
200
|
+
current_time: val,
|
|
201
|
+
duration: dur,
|
|
202
|
+
status: 'playing',
|
|
203
|
+
time_remaining: dur - val
|
|
204
|
+
});
|
|
205
|
+
audio_ref.current.play();
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
if(Platform.OS != 'web'){ return <></> } //Only built for web at this moment
|
|
212
|
+
|
|
213
|
+
return (
|
|
214
|
+
<View style={{ ...view_styles.section, flex:1 }} onLayout={(ev) => {
|
|
215
|
+
const { width } = ev.nativeEvent.layout
|
|
216
|
+
setAudioSize({ width })
|
|
217
|
+
}}>
|
|
218
|
+
{!podcast_episode || audio_loading ?
|
|
219
|
+
<ActivityIndicator size='large' color={Colors.brand.midnight} style={{ alignSelf:'center' }} />
|
|
220
|
+
:
|
|
221
|
+
<View style={{ ...view_styles.body_row }}>
|
|
222
|
+
<View>
|
|
223
|
+
<Image
|
|
224
|
+
source={{ uri: SocialPodcastHelpers.getEpisodeImage(podcast_episode) }}
|
|
225
|
+
style={{ width: audio_size.width * 0.1, height: audio_size.width * 0.1 }}
|
|
226
|
+
resizeMode='cover'
|
|
227
|
+
/>
|
|
228
|
+
<View style={{ position:'absolute', top:0, left:0, right:0, bottom:0, justifyContent:'center', alignItems:'center' }}>
|
|
229
|
+
{status == 'paused' ?
|
|
230
|
+
<TouchableOpacity style={{ ...view_styles.float, backgroundColor:Colors.shades.white, borderRadius:100, padding:10 }} onPress={() => startAudio() }>
|
|
231
|
+
<Icons.PlayIcon size={12} color={Colors.brand.electric} />
|
|
232
|
+
</TouchableOpacity>
|
|
233
|
+
:status == 'playing' ?
|
|
234
|
+
<TouchableOpacity style={{ ...view_styles.float, backgroundColor:Colors.shades.white, borderRadius:100, padding:10 }} onPress={() => pauseAudio() }>
|
|
235
|
+
<Icons.PauseIcon size={12} color={Colors.utility.error} />
|
|
236
|
+
</TouchableOpacity>
|
|
237
|
+
:<></>}
|
|
238
|
+
</View>
|
|
239
|
+
</View>
|
|
240
|
+
<View style={{ flex:1, ...view_styles.body_row }}>
|
|
241
|
+
<View style={{ flex:1 }}>
|
|
242
|
+
<Text size={14} color={Colors.brand.midnight} weight='bold'>{podcast_episode.title}</Text>
|
|
243
|
+
<View style={{ flexDirection:'row', alignItems:'center' }}>
|
|
244
|
+
<Text style={{ padding:5, width:50, alignSelf:'center' }} size={12} color={Colors.brand.midnight} weight='regular'>{SocialPodcastHelpers.formatTime(current_time)}</Text>
|
|
245
|
+
<Slider
|
|
246
|
+
width={audio_size.width * 0.47}
|
|
247
|
+
value={current_time}
|
|
248
|
+
minimum_value={minimum_value}
|
|
249
|
+
maximum_value={maximum_value}
|
|
250
|
+
onSlidingStart={() => handleStartTimeChange()}
|
|
251
|
+
onSlidingComplete={(val) => handleManualTimeChange(val)}
|
|
252
|
+
/>
|
|
253
|
+
<Text style={{ padding:5, width:50, alignSelf:'center' }} size={12} color={Colors.brand.midnight} weight='regular'>-{SocialPodcastHelpers.formatTime(time_remaining)}</Text>
|
|
254
|
+
</View>
|
|
255
|
+
{player_loading || audio_loading ?
|
|
256
|
+
<View style={{ position:'absolute', top:0, left:0, bottom:0, right:0, justifyContent:'center' }}>
|
|
257
|
+
<ActivityIndicator size='small' color={Colors.brand.midnight} />
|
|
258
|
+
</View>
|
|
259
|
+
:<></>}
|
|
260
|
+
</View>
|
|
261
|
+
<View style={{ marginLeft:10, flexDirection:'row', alignItems:'center' }}>
|
|
262
|
+
<Button
|
|
263
|
+
style={{ borderRadius:100, padding:5, backgroundColor:Colors.shades.shade100, ...view_styles.float }}
|
|
264
|
+
title='X'
|
|
265
|
+
title_size={12}
|
|
266
|
+
title_color={Colors.brand.midnight}
|
|
267
|
+
onPress={async() => {
|
|
268
|
+
await pauseAudio();
|
|
269
|
+
onClose();
|
|
270
|
+
}}
|
|
271
|
+
/>
|
|
272
|
+
|
|
273
|
+
</View>
|
|
274
|
+
</View>
|
|
275
|
+
</View>
|
|
276
|
+
}
|
|
277
|
+
{podcast_episode ?
|
|
278
|
+
<audio onLoad={(ev) => console.log(ev)} ref={audio_ref} onDurationChange={() => handleLoad()} onTimeUpdate={() => handleTimeChange()} src={podcast_episode.url} />
|
|
279
|
+
:<></>}
|
|
280
|
+
</View>
|
|
281
|
+
|
|
282
|
+
)
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
export default AudioPlayer
|
|
@@ -338,7 +338,7 @@ const CompanyProfile = ({ company_id, padding_insets, onSelectCompetition, onSel
|
|
|
338
338
|
<Text theme='header_2'>{company_members.length}</Text>
|
|
339
339
|
</View>
|
|
340
340
|
</View>
|
|
341
|
-
<View style={view_styles.section_body}>
|
|
341
|
+
<View style={{ ...view_styles.section_body, padding:10 }}>
|
|
342
342
|
<View style={{ ...view_styles.body_row }}>
|
|
343
343
|
<View style={{ flex:1 }}>
|
|
344
344
|
<FlatList
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { Image, View, TouchableOpacity } from 'react-native';
|
|
3
3
|
import { view_styles } from "../constants/styles";
|
|
4
|
-
import type { PodcastEpisodesProps, PodcastProps } from '../types';
|
|
4
|
+
import type { PlayerPodcastEpisodeProps, PodcastEpisodesProps, PodcastProps } from '../types';
|
|
5
5
|
import { Icons, Text } from '../Components';
|
|
6
6
|
import { SocialPodcastHelpers } from './api';
|
|
7
7
|
import Colors from '../constants/colors';
|
|
@@ -9,13 +9,14 @@ import moment from 'moment-mini';
|
|
|
9
9
|
|
|
10
10
|
type PodcastEpisodeCardProps = {
|
|
11
11
|
podcast_episode:PodcastEpisodesProps
|
|
12
|
+
player_podcast_episode?:PlayerPodcastEpisodeProps,
|
|
12
13
|
podcast?:PodcastProps,
|
|
13
14
|
width:number,
|
|
14
15
|
onShare?:(pe:PodcastEpisodesProps) => void,
|
|
15
16
|
onSelectEpisode:(pe:PodcastEpisodesProps) => void
|
|
16
17
|
}
|
|
17
18
|
|
|
18
|
-
const PodcastEpisodeCard = ({ width, podcast_episode, onSelectEpisode, onShare }: PodcastEpisodeCardProps ) => {
|
|
19
|
+
const PodcastEpisodeCard = ({ width, podcast_episode, player_podcast_episode, onSelectEpisode, onShare }: PodcastEpisodeCardProps ) => {
|
|
19
20
|
|
|
20
21
|
|
|
21
22
|
return (
|
|
@@ -31,14 +32,29 @@ const PodcastEpisodeCard = ({ width, podcast_episode, onSelectEpisode, onShare }
|
|
|
31
32
|
:<></>}
|
|
32
33
|
</View>
|
|
33
34
|
<View style={{ ...view_styles.section_body, padding:0 }}>
|
|
34
|
-
<
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
<View>
|
|
36
|
+
<Image
|
|
37
|
+
source={{ uri: SocialPodcastHelpers.getEpisodeImage(podcast_episode) }}
|
|
38
|
+
style={{ width: width, height: width * 0.666 }}
|
|
39
|
+
/>
|
|
40
|
+
<View style={{ position:'absolute', top:0, left:0, right:0, bottom:0, backgroundColor:Colors.shades.black_faded, justifyContent:'center', alignItems:'center' }}>
|
|
41
|
+
<View style={{ ...view_styles.section, borderRadius:22, padding:10 }}>
|
|
42
|
+
<View style={{ ...view_styles.body_row }}>
|
|
43
|
+
<Icons.PlayIcon size={18} color={Colors.brand.electric} />
|
|
44
|
+
{player_podcast_episode ?
|
|
45
|
+
<Text size={14} color={Colors.brand.electric} weight='semibold' style={{ marginLeft:10 }}>Resume</Text>
|
|
46
|
+
:
|
|
47
|
+
<Text size={14} color={Colors.brand.electric} weight='semibold' style={{ marginLeft:10 }}>Play</Text>
|
|
48
|
+
}
|
|
49
|
+
</View>
|
|
50
|
+
</View>
|
|
51
|
+
</View>
|
|
52
|
+
</View>
|
|
38
53
|
<View style={{ padding:10 }}>
|
|
39
54
|
<Text theme='header_2'>{podcast_episode.title}</Text>
|
|
40
55
|
</View>
|
|
41
56
|
</View>
|
|
57
|
+
|
|
42
58
|
</TouchableOpacity>
|
|
43
59
|
)
|
|
44
60
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import axios from "axios";
|
|
2
2
|
import { APIOverrides } from "../../../ApiOverrides";
|
|
3
|
-
import type { PodcastEpisodesProps, PodcastProps, PublicPlayerProps } from "../../../types";
|
|
3
|
+
import type { PlayerPodcastEpisodeProps, PodcastEpisodesProps, PodcastProps, PublicPlayerProps } from "../../../types";
|
|
4
4
|
|
|
5
5
|
let SOCIAL_SVC_API = '';
|
|
6
6
|
let AUTH_SVC_API = '';
|
|
@@ -21,13 +21,13 @@ const PodcastApi = {
|
|
|
21
21
|
return undefined
|
|
22
22
|
}
|
|
23
23
|
},
|
|
24
|
-
getPodcastEpisodesByPodcast: async(podcast_id:string, offset:number):Promise<PodcastEpisodesProps[]> => {
|
|
24
|
+
getPodcastEpisodesByPodcast: async(podcast_id:string, offset:number):Promise<{podcast_episodes:PodcastEpisodesProps[], player_podcast_episodes:PlayerPodcastEpisodeProps[]}> => {
|
|
25
25
|
try {
|
|
26
26
|
const resp = await axios.get(`${SOCIAL_SVC_API}/v1/podcasts/episodes/podcast/${podcast_id}?offset=${offset}`);
|
|
27
|
-
return resp.data
|
|
27
|
+
return resp.data
|
|
28
28
|
} catch (e) {
|
|
29
29
|
console.log(e);
|
|
30
|
-
return []
|
|
30
|
+
return { podcast_episodes: [], player_podcast_episodes: [] }
|
|
31
31
|
}
|
|
32
32
|
},
|
|
33
33
|
getPlayersByPlayerIds: async (player_ids?: string[]): Promise<PublicPlayerProps[]> => {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React, { useEffect, useState } from 'react';
|
|
2
2
|
import { View, ActivityIndicator, Image, ScrollView, TouchableOpacity, FlatList } from "react-native"
|
|
3
|
-
import type { PodcastEpisodesProps, PodcastProps, PublicPlayerProps } from '../../types';
|
|
3
|
+
import type { PlayerPodcastEpisodeProps, PodcastEpisodesProps, PodcastProps, PublicPlayerProps } from '../../types';
|
|
4
4
|
import { PodcastApi } from './api';
|
|
5
5
|
import Colors from '../../constants/colors';
|
|
6
6
|
import { SocialPodcastHelpers } from '../api';
|
|
@@ -27,16 +27,18 @@ const PodcastModule = ({ podcast_id, padding_insets, onSelectEpisode, onBack, on
|
|
|
27
27
|
episodes_loading:boolean,
|
|
28
28
|
podcast?:PodcastProps,
|
|
29
29
|
podcast_episodes:PodcastEpisodesProps[],
|
|
30
|
+
player_podcast_episodes:PlayerPodcastEpisodeProps[],
|
|
30
31
|
players:PublicPlayerProps[],
|
|
31
32
|
episodes_offset:number
|
|
32
33
|
}>({
|
|
33
34
|
loading:false,
|
|
34
35
|
episodes_loading: false,
|
|
36
|
+
player_podcast_episodes:[],
|
|
35
37
|
podcast_episodes:[],
|
|
36
38
|
players:[],
|
|
37
39
|
episodes_offset:0
|
|
38
40
|
});
|
|
39
|
-
const { loading, episodes_loading, podcast, podcast_episodes, episodes_offset, players } = pod_data;
|
|
41
|
+
const { loading, episodes_loading, podcast, podcast_episodes, episodes_offset, players, player_podcast_episodes } = pod_data;
|
|
40
42
|
|
|
41
43
|
useEffect(() => {
|
|
42
44
|
PodcastApi.setEnvironment();
|
|
@@ -47,6 +49,7 @@ const PodcastModule = ({ podcast_id, padding_insets, onSelectEpisode, onBack, on
|
|
|
47
49
|
setPodData({ ...pod_data, loading:true });
|
|
48
50
|
const pod = await PodcastApi.getPodcastById(id);
|
|
49
51
|
const pod_ep = await PodcastApi.getPodcastEpisodesByPodcast(id, offset);
|
|
52
|
+
|
|
50
53
|
const ps = await PodcastApi.getPlayersByPlayerIds(pod?.player_ids);
|
|
51
54
|
setPodData({
|
|
52
55
|
...pod_data,
|
|
@@ -54,7 +57,8 @@ const PodcastModule = ({ podcast_id, padding_insets, onSelectEpisode, onBack, on
|
|
|
54
57
|
episodes_loading: false,
|
|
55
58
|
podcast: pod,
|
|
56
59
|
players:ps,
|
|
57
|
-
podcast_episodes: pod_ep,
|
|
60
|
+
podcast_episodes: pod_ep.podcast_episodes,
|
|
61
|
+
player_podcast_episodes: pod_ep.player_podcast_episodes,
|
|
58
62
|
episodes_offset:offset
|
|
59
63
|
})
|
|
60
64
|
}
|
|
@@ -65,7 +69,8 @@ const PodcastModule = ({ podcast_id, padding_insets, onSelectEpisode, onBack, on
|
|
|
65
69
|
setPodData({
|
|
66
70
|
...pod_data,
|
|
67
71
|
episodes_loading: false,
|
|
68
|
-
podcast_episodes: pod_eps,
|
|
72
|
+
podcast_episodes: pod_eps.podcast_episodes,
|
|
73
|
+
player_podcast_episodes: pod_eps.player_podcast_episodes,
|
|
69
74
|
episodes_offset: offset
|
|
70
75
|
})
|
|
71
76
|
}
|
|
@@ -89,10 +94,12 @@ const PodcastModule = ({ podcast_id, padding_insets, onSelectEpisode, onBack, on
|
|
|
89
94
|
|
|
90
95
|
const renderEpsidoes = (data: { item:PodcastEpisodesProps, index:number }) => {
|
|
91
96
|
const ep_width = (module_size.width - 60) / 2
|
|
97
|
+
const ppe = player_podcast_episodes.find(pp => pp.podcast_episode_id == data.item.podcast_episode_id);
|
|
92
98
|
return (
|
|
93
99
|
<View>
|
|
94
100
|
<PodcastEpisodeCard
|
|
95
101
|
podcast_episode={data.item}
|
|
102
|
+
player_podcast_episode={ppe}
|
|
96
103
|
width={ep_width}
|
|
97
104
|
onShare={onShareEpisode}
|
|
98
105
|
onSelectEpisode={onSelectEpisode}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import axios from "axios";
|
|
2
2
|
import { APIOverrides } from "../../ApiOverrides";
|
|
3
|
-
import type { AthleteProps, EventProps, LeagueProps, MatchProps, OrderProps, PlayerFollowerProps, PodcastEpisodesProps, PodcastProps, PostReactionProps, TeamProps, TournamentProps } from "../../types";
|
|
3
|
+
import type { AthleteProps, EventProps, LeagueProps, MatchProps, OrderProps, PlayerFollowerProps, PlayerPodcastEpisodeProps, PlayerPodcastProps, PodcastEpisodesProps, PodcastProps, PostReactionProps, TeamProps, TournamentProps } from "../../types";
|
|
4
4
|
import Colors from "../../constants/colors";
|
|
5
5
|
import moment from "moment-mini";
|
|
6
6
|
|
|
@@ -105,6 +105,51 @@ const SocialComponentApi = {
|
|
|
105
105
|
return undefined
|
|
106
106
|
}
|
|
107
107
|
},
|
|
108
|
+
getPodcastById: async(podcast_id:string):Promise<PodcastProps | undefined> => {
|
|
109
|
+
try {
|
|
110
|
+
const resp = await axios.get(`${SOCIAL_SVC_API}/v1/podcasts/podcast/${podcast_id}`);
|
|
111
|
+
return resp.data.podcast
|
|
112
|
+
} catch (e) {
|
|
113
|
+
return undefined
|
|
114
|
+
}
|
|
115
|
+
},
|
|
116
|
+
getPodcastEpisodeById: async(podcast_episode_id:string):Promise<PodcastEpisodesProps | undefined> => {
|
|
117
|
+
try {
|
|
118
|
+
const resp = await axios.get(`${SOCIAL_SVC_API}/v1/podcasts/episodes/episode/${podcast_episode_id}`);
|
|
119
|
+
return resp.data.podcast_episode
|
|
120
|
+
} catch (e) {
|
|
121
|
+
console.log(e)
|
|
122
|
+
return undefined
|
|
123
|
+
}
|
|
124
|
+
},
|
|
125
|
+
getPlayerPodcastEpisode: async(podcast_episode_id:string):Promise<undefined | { player_podcast?:PlayerPodcastProps, player_podcast_episode?:PlayerPodcastEpisodeProps }> => {
|
|
126
|
+
try {
|
|
127
|
+
const resp = await axios.get(`${SOCIAL_SVC_API}/v1/podcasts/episode/player/${podcast_episode_id}`);
|
|
128
|
+
return resp.data
|
|
129
|
+
} catch (e) {
|
|
130
|
+
console.log(e)
|
|
131
|
+
return undefined
|
|
132
|
+
}
|
|
133
|
+
},
|
|
134
|
+
startPodcastEpisode: async(podcast_episode_id:string):Promise<undefined | { player_podcast:PlayerPodcastProps, player_podcast_episode:PlayerPodcastEpisodeProps }> => {
|
|
135
|
+
try {
|
|
136
|
+
const resp = await axios.post(`${SOCIAL_SVC_API}/v1/podcasts/episode/start`, { podcast_episode_id });
|
|
137
|
+
console.log(resp.data)
|
|
138
|
+
return resp.data
|
|
139
|
+
} catch (e) {
|
|
140
|
+
console.log(e)
|
|
141
|
+
return undefined
|
|
142
|
+
}
|
|
143
|
+
},
|
|
144
|
+
pausePodcastEpisode:async(podcast_episode_id:string, pause_timestamp:number):Promise<undefined | PlayerPodcastEpisodeProps> => {
|
|
145
|
+
try {
|
|
146
|
+
const resp = await axios.post(`${SOCIAL_SVC_API}/v1/podcasts/episode/pause`, { podcast_episode_id, pause_timestamp });
|
|
147
|
+
return resp.data.player_podcast_episode
|
|
148
|
+
} catch (e) {
|
|
149
|
+
console.log(e)
|
|
150
|
+
return undefined
|
|
151
|
+
}
|
|
152
|
+
}
|
|
108
153
|
}
|
|
109
154
|
|
|
110
155
|
|
|
@@ -194,10 +239,20 @@ const SocialPodcastHelpers = {
|
|
|
194
239
|
if(image_source && image_source !== ''){ return image_source }
|
|
195
240
|
return 'https://res.cloudinary.com/hoabts6mc/image/upload/v1728494579/default_pod_nji5sk.webp'
|
|
196
241
|
},
|
|
197
|
-
getEpisodeImage: (podcast_episode
|
|
242
|
+
getEpisodeImage: (podcast_episode?:PodcastEpisodesProps):string => {
|
|
243
|
+
if(!podcast_episode){ return 'https://res.cloudinary.com/hoabts6mc/image/upload/v1728494579/default_pod_nji5sk.webp' }
|
|
198
244
|
let image_source = podcast_episode.image_override?.url
|
|
199
245
|
if(!image_source){ image_source = podcast_episode.image?.url }
|
|
200
246
|
if(image_source && image_source != ''){ return image_source }
|
|
201
247
|
return 'https://res.cloudinary.com/hoabts6mc/image/upload/v1728494579/default_pod_nji5sk.webp'
|
|
248
|
+
},
|
|
249
|
+
formatTime: (time:number) => {
|
|
250
|
+
const minutes = Math.floor(time / 60);
|
|
251
|
+
const seconds = Math.floor(time - minutes * 60);
|
|
252
|
+
const final_time = SocialPodcastHelpers.str_pad_left(minutes, '0', 2) + ':' + SocialPodcastHelpers.str_pad_left(seconds, '0', 2);
|
|
253
|
+
return final_time
|
|
254
|
+
},
|
|
255
|
+
str_pad_left: (string:number, pad:string, length:number) => {
|
|
256
|
+
return (new Array(length + 1).join(pad) + string).slice(-length);
|
|
202
257
|
}
|
|
203
258
|
}
|
|
@@ -3,10 +3,12 @@ import PlayerList from "./PlayerList";
|
|
|
3
3
|
import PlayerProfile from "./PlayerProfile";
|
|
4
4
|
import CompanyProfile from './CompanyProfile';
|
|
5
5
|
import PodcastModule from './PodcastModule';
|
|
6
|
+
import AudioPlayer from "./AudioPlayer";
|
|
6
7
|
export {
|
|
7
8
|
PlayerCard,
|
|
8
9
|
PlayerList,
|
|
9
10
|
PlayerProfile,
|
|
10
11
|
CompanyProfile,
|
|
11
|
-
PodcastModule
|
|
12
|
+
PodcastModule,
|
|
13
|
+
AudioPlayer
|
|
12
14
|
}
|
package/src/types.d.ts
CHANGED
|
@@ -150,6 +150,33 @@ export interface CompanyProps {
|
|
|
150
150
|
last_update_datetime: any
|
|
151
151
|
}
|
|
152
152
|
|
|
153
|
+
export interface PlayerPodcastProps {
|
|
154
|
+
player_podcast_id:string,
|
|
155
|
+
player_id:string,
|
|
156
|
+
podcast_id:string,
|
|
157
|
+
subscribed:boolean,
|
|
158
|
+
last_visit_datetime:any,
|
|
159
|
+
status:'suggested'|'visited'
|
|
160
|
+
number_of_visits?:number,
|
|
161
|
+
last_visit_episode?:string,
|
|
162
|
+
create_datetime:any,
|
|
163
|
+
last_update_datetime:any
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
export interface PlayerPodcastEpisodeProps {
|
|
167
|
+
player_podcast_episode_id:string,
|
|
168
|
+
player_id:string,
|
|
169
|
+
podcast_episode_id:string,
|
|
170
|
+
last_visit_datetime:any,
|
|
171
|
+
number_of_visits: number,
|
|
172
|
+
pause_timestamp: number,
|
|
173
|
+
completed?:boolean,
|
|
174
|
+
reaction?:string,
|
|
175
|
+
status: 'inprogress'|'inactive'|'complete',
|
|
176
|
+
create_datetime:any,
|
|
177
|
+
last_update_datetime:any
|
|
178
|
+
}
|
|
179
|
+
|
|
153
180
|
export interface LocationProps {
|
|
154
181
|
location_id:string,
|
|
155
182
|
value:string,
|