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.
Files changed (62) hide show
  1. package/lib/commonjs/Components/Icons.js +60 -0
  2. package/lib/commonjs/Components/Icons.js.map +1 -1
  3. package/lib/commonjs/Components/Slider.js +38 -0
  4. package/lib/commonjs/Components/Slider.js.map +1 -0
  5. package/lib/commonjs/SocialComponents/AudioPlayer.js +384 -0
  6. package/lib/commonjs/SocialComponents/AudioPlayer.js.map +1 -0
  7. package/lib/commonjs/SocialComponents/CompanyProfile/index.js +4 -1
  8. package/lib/commonjs/SocialComponents/CompanyProfile/index.js.map +1 -1
  9. package/lib/commonjs/SocialComponents/PodcastEpisodeCard.js +40 -1
  10. package/lib/commonjs/SocialComponents/PodcastEpisodeCard.js.map +1 -1
  11. package/lib/commonjs/SocialComponents/PodcastModule/api/index.js +5 -2
  12. package/lib/commonjs/SocialComponents/PodcastModule/api/index.js.map +1 -1
  13. package/lib/commonjs/SocialComponents/PodcastModule/index.js +9 -3
  14. package/lib/commonjs/SocialComponents/PodcastModule/index.js.map +1 -1
  15. package/lib/commonjs/SocialComponents/api/index.js +62 -0
  16. package/lib/commonjs/SocialComponents/api/index.js.map +1 -1
  17. package/lib/commonjs/SocialComponents/index.js +7 -0
  18. package/lib/commonjs/SocialComponents/index.js.map +1 -1
  19. package/lib/module/Components/Icons.js +60 -0
  20. package/lib/module/Components/Icons.js.map +1 -1
  21. package/lib/module/Components/Slider.js +31 -0
  22. package/lib/module/Components/Slider.js.map +1 -0
  23. package/lib/module/SocialComponents/AudioPlayer.js +375 -0
  24. package/lib/module/SocialComponents/AudioPlayer.js.map +1 -0
  25. package/lib/module/SocialComponents/CompanyProfile/index.js +4 -1
  26. package/lib/module/SocialComponents/CompanyProfile/index.js.map +1 -1
  27. package/lib/module/SocialComponents/PodcastEpisodeCard.js +40 -1
  28. package/lib/module/SocialComponents/PodcastEpisodeCard.js.map +1 -1
  29. package/lib/module/SocialComponents/PodcastModule/api/index.js +5 -2
  30. package/lib/module/SocialComponents/PodcastModule/api/index.js.map +1 -1
  31. package/lib/module/SocialComponents/PodcastModule/index.js +9 -3
  32. package/lib/module/SocialComponents/PodcastModule/index.js.map +1 -1
  33. package/lib/module/SocialComponents/api/index.js +62 -0
  34. package/lib/module/SocialComponents/api/index.js.map +1 -1
  35. package/lib/module/SocialComponents/index.js +2 -1
  36. package/lib/module/SocialComponents/index.js.map +1 -1
  37. package/lib/typescript/src/Components/Icons.d.ts +2 -0
  38. package/lib/typescript/src/Components/Icons.d.ts.map +1 -1
  39. package/lib/typescript/src/Components/Slider.d.ts +15 -0
  40. package/lib/typescript/src/Components/Slider.d.ts.map +1 -0
  41. package/lib/typescript/src/SocialComponents/AudioPlayer.d.ts +9 -0
  42. package/lib/typescript/src/SocialComponents/AudioPlayer.d.ts.map +1 -0
  43. package/lib/typescript/src/SocialComponents/PodcastEpisodeCard.d.ts +3 -2
  44. package/lib/typescript/src/SocialComponents/PodcastEpisodeCard.d.ts.map +1 -1
  45. package/lib/typescript/src/SocialComponents/PodcastModule/api/index.d.ts +5 -2
  46. package/lib/typescript/src/SocialComponents/PodcastModule/api/index.d.ts.map +1 -1
  47. package/lib/typescript/src/SocialComponents/PodcastModule/index.d.ts.map +1 -1
  48. package/lib/typescript/src/SocialComponents/api/index.d.ts +15 -2
  49. package/lib/typescript/src/SocialComponents/api/index.d.ts.map +1 -1
  50. package/lib/typescript/src/SocialComponents/index.d.ts +2 -1
  51. package/lib/typescript/src/SocialComponents/index.d.ts.map +1 -1
  52. package/package.json +2 -1
  53. package/src/Components/Icons.tsx +33 -0
  54. package/src/Components/Slider.tsx +34 -0
  55. package/src/SocialComponents/AudioPlayer.tsx +285 -0
  56. package/src/SocialComponents/CompanyProfile/index.tsx +1 -1
  57. package/src/SocialComponents/PodcastEpisodeCard.tsx +22 -6
  58. package/src/SocialComponents/PodcastModule/api/index.ts +4 -4
  59. package/src/SocialComponents/PodcastModule/index.tsx +11 -4
  60. package/src/SocialComponents/api/index.ts +57 -2
  61. package/src/SocialComponents/index.tsx +3 -1
  62. 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
- <Image
35
- source={{ uri: SocialPodcastHelpers.getEpisodeImage(podcast_episode) }}
36
- style={{ width: width, height: width * 0.666 }}
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.podcast_episodes
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:PodcastEpisodesProps):string => {
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,