Skip to content

Commit ac3e188

Browse files
feat(UNT-T27088): external url support
1 parent 2da83a6 commit ac3e188

File tree

9 files changed

+216
-55
lines changed

9 files changed

+216
-55
lines changed

README.md

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,31 @@ const ref = useRef<IWaveformRef>(null);
8888
<Waveform
8989
mode="static"
9090
ref={ref}
91-
path={item}
91+
path={path}
92+
candleSpace={2}
93+
candleWidth={4}
94+
scrubColor="white"
95+
onPlayerStateChange={playerState=>console.log(playerState)}
96+
onPanStateChange={isMoving=>console.log(isMoving)}
97+
/>;
98+
```
99+
100+
When you want to show a waveform for a external audio URL, you need to use `static` mode for the waveform and set isExternalUrl to true.
101+
102+
Check the example below for more information.
103+
104+
```tsx
105+
import { Waveform, type IWaveformRef } from '@simform_solutions/react-native-audio-waveform';
106+
107+
const url = 'https://dl.espressif.com/dl/audio/gs-16b-2c-44100hz.mp3'; // URL to the audio file for which you want to show waveform
108+
const ref = useRef<IWaveformRef>(null);
109+
<Waveform
110+
mode="static"
111+
ref={ref}
112+
path={url}
113+
isExternalUrl={true}
114+
onDownloadStateChange={state=>console.log(state)}
115+
onDownloadProgressChange={progress=>console.log(progress)}
92116
candleSpace={2}
93117
candleWidth={4}
94118
scrubColor="white"
@@ -127,6 +151,9 @@ You can check out the full example at [Example](./example/src/App.tsx).
127151
| mode\* | - ||| 'live' or 'static' | Type of waveform. It can be either `static` for the resource file or `live` if you want to record audio |
128152
| ref\* | - ||| IWaveformRef | Type of ref provided to waveform component. If waveform mode is `static`, some methods from ref will throw error and same for `live`.<br> Check [IWaveformRef](#iwaveformref-methods) for more details about which methods these refs provides. |
129153
| path\* | - ||| string | Used for `static` type. It is the resource path of an audio source file. |
154+
| volume | 3 ||| number | Used for `static` type. It is a volume level for the media player, ranging from 1 to 10. |
155+
| isExternalUrl | false ||| boolean | Used for `static` type. If the resource path of an audio file is a URL, then pass true; otherwise, pass false. |
156+
| downloadExternalAudio | true ||| boolean | Used for `static` type. Indicates whether the external media should be downloaded. |
130157
| candleSpace | 2 ||| number | Space between two candlesticks of waveform |
131158
| candleWidth | 5 ||| number | Width of single candlestick of waveform |
132159
| candleHeightScale | 3 ||| number | Scaling height of candlestick of waveform |
@@ -138,6 +165,8 @@ You can check out the full example at [Example](./example/src/App.tsx).
138165
| onRecorderStateChange | - ||| ( recorderState : RecorderState ) => void | callback function which returns the recorder state whenever the recorder state changes. Check RecorderState for more details |
139166
| onCurrentProgressChange | - ||| ( currentProgress : number, songDuration: number ) => void | callback function, which returns current progress of audio and total song duration. |
140167
| onChangeWaveformLoadState | - ||| ( state : boolean ) => void | callback function which returns the loading state of waveform candlestick. |
168+
| onDownloadStateChange | - ||| ( state : boolean ) => void | A callback function that returns the loading state of a file download from an external URL. |
169+
| onDownloadProgressChange | - ||| ( currentProgress : number ) => void | Used when isExternalUrl is true; a callback function that returns the current progress of a file download from an external URL |
141170
| onError | - ||| ( error : Error ) => void | callback function which returns the error for static audio waveform |
142171

143172
##### Know more about [ViewStyle](https://reactnative.dev/docs/view-style-props), [PlayerState](#playerstate), and [RecorderState](#recorderstate)

example/src/App.tsx

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
Pressable,
1414
ScrollView,
1515
StatusBar,
16+
TouchableOpacity,
1617
View,
1718
} from 'react-native';
1819
import {
@@ -41,16 +42,20 @@ const ListItem = React.memo(
4142
currentPlaying,
4243
setCurrentPlaying,
4344
onPanStateChange,
45+
isExternalUrl = false,
4446
}: {
4547
item: ListItem;
4648
currentPlaying: string;
4749
setCurrentPlaying: Dispatch<SetStateAction<string>>;
4850
onPanStateChange: (value: boolean) => void;
51+
isExternalUrl?: boolean;
4952
}) => {
5053
const ref = useRef<IWaveformRef>(null);
5154
const [playerState, setPlayerState] = useState(PlayerState.stopped);
5255
const styles = stylesheet({ currentUser: item.fromCurrentUser });
5356
const [isLoading, setIsLoading] = useState(true);
57+
const [downloadExternalAudio, setDownloadExternalAudio] = useState(false);
58+
const [isAudioDownloaded, setIsAudioDownloaded] = useState(false);
5459

5560
const handleButtonAction = () => {
5661
if (playerState === PlayerState.stopped) {
@@ -69,7 +74,16 @@ const ListItem = React.memo(
6974
}, [currentPlaying]);
7075

7176
return (
72-
<View key={item.path} style={[styles.listItemContainer]}>
77+
<View
78+
key={item.path}
79+
style={[
80+
styles.listItemContainer,
81+
item.fromCurrentUser &&
82+
isExternalUrl &&
83+
!downloadExternalAudio && {
84+
flexDirection: 'row-reverse',
85+
},
86+
]}>
7387
<View style={styles.listItemWidth}>
7488
<ImageBackground
7589
source={
@@ -82,7 +96,8 @@ const ListItem = React.memo(
8296
disabled={isLoading}
8397
onPress={handleButtonAction}
8498
style={styles.playBackControlPressable}>
85-
{isLoading ? (
99+
{(isLoading && (!isExternalUrl || isAudioDownloaded)) ||
100+
(isExternalUrl && downloadExternalAudio && !isAudioDownloaded) ? (
86101
<ActivityIndicator color={'#FF0000'} />
87102
) : (
88103
<Image
@@ -107,6 +122,7 @@ const ListItem = React.memo(
107122
scrubColor={Colors.white}
108123
waveColor={Colors.gray}
109124
candleHeightScale={4}
125+
downloadExternalAudio={downloadExternalAudio}
110126
onPlayerStateChange={state => {
111127
setPlayerState(state);
112128
if (
@@ -116,10 +132,20 @@ const ListItem = React.memo(
116132
setCurrentPlaying('');
117133
}
118134
}}
135+
isExternalUrl={isExternalUrl}
119136
onPanStateChange={onPanStateChange}
120137
onError={error => {
121138
console.log(error, 'we are in example');
122139
}}
140+
onDownloadStateChange={state => {
141+
console.log('Download State', state);
142+
}}
143+
onDownloadProgressChange={progress => {
144+
console.log('Download Progress', `${progress}%`);
145+
if (progress === 100) {
146+
setIsAudioDownloaded(true);
147+
}
148+
}}
123149
onCurrentProgressChange={(currentProgress, songDuration) => {
124150
console.log(
125151
'currentProgress ',
@@ -134,6 +160,15 @@ const ListItem = React.memo(
134160
/>
135161
</ImageBackground>
136162
</View>
163+
{isExternalUrl && !downloadExternalAudio ? (
164+
<TouchableOpacity onPress={() => setDownloadExternalAudio(true)}>
165+
<Image
166+
source={Icons.download}
167+
style={styles.downloadIcon}
168+
resizeMode="contain"
169+
/>
170+
</TouchableOpacity>
171+
) : null}
137172
</View>
138173
);
139174
}
@@ -241,6 +276,7 @@ const AppContainer = () => {
241276
currentPlaying={currentPlaying}
242277
setCurrentPlaying={setCurrentPlaying}
243278
item={item}
279+
isExternalUrl={item.isExternalUrl}
244280
onPanStateChange={value => setShouldScroll(!value)}
245281
/>
246282
))}
8.4 KB
Loading

example/src/assets/icons/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@ export const Icons = {
33
stop: require('./stop.png'),
44
simform: require('./simform.png'),
55
mic: require('./mic.png'),
6+
download: require('./download.png'),
67
};

example/src/constants/Audios.ts

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { globalMetrics } from '../../src/theme';
55
export interface ListItem {
66
fromCurrentUser: boolean;
77
path: string;
8+
isExternalUrl?: boolean;
89
}
910

1011
/**
@@ -54,15 +55,28 @@ const audioAssetArray = [
5455
'file_example_mp3_15s.mp3',
5556
];
5657

58+
const externalAudioAssetArray = [
59+
'https://codeskulptor-demos.commondatastorage.googleapis.com/GalaxyInvaders/theme_01.mp3',
60+
'https://codeskulptor-demos.commondatastorage.googleapis.com/pang/paza-moduless.mp3',
61+
];
62+
5763
copyFilesToAndroidResources();
5864

5965
/**
6066
* List of file objects with information about the files.
6167
* @type {ListItem[]}
6268
*/
63-
export const audioListArray: ListItem[] = audioAssetArray.map(
69+
const audioList: ListItem[] = audioAssetArray.map((value, index) => ({
70+
fromCurrentUser: index % 2 !== 0,
71+
path: `${filePath}/${value}`,
72+
}));
73+
74+
const externalAudioList: ListItem[] = externalAudioAssetArray.map(
6475
(value, index) => ({
6576
fromCurrentUser: index % 2 !== 0,
66-
path: `${filePath}/${value}`,
77+
path: value,
78+
isExternalUrl: true,
6779
})
6880
);
81+
82+
export const audioListArray: ListItem[] = [...audioList, ...externalAudioList];

example/src/styles.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,12 @@ const styles = (params: StyleSheetParams = {}) =>
3737
},
3838
listItemContainer: {
3939
marginTop: scale(16),
40-
alignItems: params.currentUser ? 'flex-end' : 'flex-start',
40+
flexDirection: 'row',
41+
justifyContent: params.currentUser ? 'flex-end' : 'flex-start',
42+
alignItems: 'center',
4143
},
4244
listItemWidth: {
43-
width: '90%',
45+
width: '89%',
4446
},
4547
buttonImage: {
4648
height: '100%',
@@ -90,6 +92,13 @@ const styles = (params: StyleSheetParams = {}) =>
9092
loadingText: {
9193
color: Colors.black,
9294
},
95+
downloadIcon: {
96+
width: 20,
97+
height: 20,
98+
tintColor: Colors.pink,
99+
marginLeft: 10,
100+
marginRight: 10,
101+
},
93102
});
94103

95104
export default styles;

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@
110110
]
111111
},
112112
"dependencies": {
113-
"lodash": "^4.17.21"
113+
"lodash": "^4.17.21",
114+
"rn-fetch-blob": "^0.12.0"
114115
}
115-
}
116+
}

0 commit comments

Comments
 (0)