feat: bump up fabric example react-native iOS (#3951)
* feat: 🔥 version bump react native for ios FabricExample * feat: ✨ copied newly created basic example TS files
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
import {Picker} from '@react-native-picker/picker';
|
||||
import {Text} from 'react-native';
|
||||
import {AudioTrack, SelectedTrack} from 'react-native-video';
|
||||
import styles from '../styles';
|
||||
import React from 'react';
|
||||
|
||||
export interface AudioTrackSelectorType {
|
||||
audioTracks: Array<AudioTrack>;
|
||||
selectedAudioTrack: SelectedTrack | undefined;
|
||||
onValueChange: (arg0: string) => void;
|
||||
}
|
||||
|
||||
const AudioTrackSelector = ({
|
||||
audioTracks,
|
||||
selectedAudioTrack,
|
||||
onValueChange,
|
||||
}: AudioTrackSelectorType) => {
|
||||
return (
|
||||
<>
|
||||
<Text style={styles.controlOption}>AudioTrack</Text>
|
||||
<Picker
|
||||
style={styles.picker}
|
||||
itemStyle={styles.pickerItem}
|
||||
selectedValue={selectedAudioTrack?.value}
|
||||
onValueChange={itemValue => {
|
||||
if (itemValue !== 'empty') {
|
||||
console.log('on audio value change ' + itemValue);
|
||||
onValueChange(`${itemValue}`);
|
||||
}
|
||||
}}>
|
||||
{audioTracks?.length <= 0 ? (
|
||||
<Picker.Item label={'empty'} value={'empty'} key={'empty'} />
|
||||
) : (
|
||||
<Picker.Item label={'none'} value={'none'} key={'none'} />
|
||||
)}
|
||||
{audioTracks.map(track => {
|
||||
if (!track) {
|
||||
return;
|
||||
}
|
||||
return (
|
||||
<Picker.Item
|
||||
label={`${track.language} - ${track.title} - ${track.selected}`}
|
||||
value={`${track.index}`}
|
||||
key={`${track.index}`}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</Picker>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default AudioTrackSelector;
|
||||
154
examples/FabricExample/src/components/Seeker.tsx
Normal file
154
examples/FabricExample/src/components/Seeker.tsx
Normal file
@@ -0,0 +1,154 @@
|
||||
import React, {useCallback, useEffect, useState} from 'react';
|
||||
import {PanResponder, View} from 'react-native';
|
||||
import styles from '../styles';
|
||||
|
||||
interface SeekerProps {
|
||||
currentTime: number;
|
||||
duration: number;
|
||||
isLoading: boolean;
|
||||
isUISeeking: boolean;
|
||||
videoSeek: (arg0: number) => void;
|
||||
}
|
||||
|
||||
const Seeker = ({
|
||||
currentTime,
|
||||
duration,
|
||||
isLoading,
|
||||
isUISeeking,
|
||||
videoSeek,
|
||||
}: SeekerProps) => {
|
||||
const [seeking, setSeeking] = useState(false);
|
||||
const [seekerPosition, setSeekerPosition] = useState(0);
|
||||
const [seekerWidth, setSeekerWidth] = useState(0);
|
||||
|
||||
/**
|
||||
* Set the position of the seekbar's components
|
||||
* (both fill and handle) according to the
|
||||
* position supplied.
|
||||
*
|
||||
* @param {float} position position in px of seeker handle}
|
||||
*/
|
||||
const updateSeekerPosition = useCallback(
|
||||
(position = 0) => {
|
||||
if (position <= 0) {
|
||||
position = 0;
|
||||
} else if (position >= seekerWidth) {
|
||||
position = seekerWidth;
|
||||
}
|
||||
setSeekerPosition(position);
|
||||
},
|
||||
[seekerWidth],
|
||||
);
|
||||
|
||||
/**
|
||||
* Return the time that the video should be at
|
||||
* based on where the seeker handle is.
|
||||
*
|
||||
* @return {float} time in ms based on seekerPosition.
|
||||
*/
|
||||
const calculateTimeFromSeekerPosition = () => {
|
||||
const percent = seekerPosition / seekerWidth;
|
||||
return duration * percent;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get our seekbar responder going
|
||||
*/
|
||||
|
||||
const seekPanResponder = PanResponder.create({
|
||||
// Ask to be the responder.
|
||||
onStartShouldSetPanResponder: (_evt, _gestureState) => true,
|
||||
onMoveShouldSetPanResponder: (_evt, _gestureState) => true,
|
||||
|
||||
/**
|
||||
* When we start the pan tell the machine that we're
|
||||
* seeking. This stops it from updating the seekbar
|
||||
* position in the onProgress listener.
|
||||
*/
|
||||
onPanResponderGrant: (evt, _gestureState) => {
|
||||
const position = evt.nativeEvent.locationX;
|
||||
updateSeekerPosition(position);
|
||||
setSeeking(true);
|
||||
},
|
||||
|
||||
/**
|
||||
* When panning, update the seekbar position, duh.
|
||||
*/
|
||||
onPanResponderMove: (evt, _gestureState) => {
|
||||
const position = evt.nativeEvent.locationX;
|
||||
updateSeekerPosition(position);
|
||||
},
|
||||
|
||||
/**
|
||||
* On release we update the time and seek to it in the video.
|
||||
* If you seek to the end of the video we fire the
|
||||
* onEnd callback
|
||||
*/
|
||||
onPanResponderRelease: (_evt, _gestureState) => {
|
||||
const time = calculateTimeFromSeekerPosition();
|
||||
if (time >= duration && !isLoading) {
|
||||
// FIXME ...
|
||||
// state.paused = true;
|
||||
// this.onEnd();
|
||||
} else {
|
||||
videoSeek(time);
|
||||
setSeeking(false);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (!isLoading && !seeking && !isUISeeking) {
|
||||
const percent = currentTime / duration;
|
||||
const position = seekerWidth * percent;
|
||||
updateSeekerPosition(position);
|
||||
}
|
||||
}, [
|
||||
currentTime,
|
||||
duration,
|
||||
isLoading,
|
||||
seekerWidth,
|
||||
seeking,
|
||||
isUISeeking,
|
||||
updateSeekerPosition,
|
||||
]);
|
||||
|
||||
if (!seekPanResponder) {
|
||||
return null;
|
||||
}
|
||||
const seekerStyle = [
|
||||
styles.seekbarFill,
|
||||
{
|
||||
width: seekerPosition > 0 ? seekerPosition : 0,
|
||||
backgroundColor: '#FFF',
|
||||
},
|
||||
];
|
||||
|
||||
const seekerPositionStyle = [
|
||||
styles.seekbarHandle,
|
||||
{
|
||||
left: seekerPosition > 0 ? seekerPosition : 0,
|
||||
},
|
||||
];
|
||||
|
||||
const seekerPointerStyle = [styles.seekbarCircle, {backgroundColor: '#FFF'}];
|
||||
|
||||
return (
|
||||
<View
|
||||
style={styles.seekbarContainer}
|
||||
{...seekPanResponder.panHandlers}
|
||||
{...styles.generalControls}>
|
||||
<View
|
||||
style={styles.seekbarTrack}
|
||||
onLayout={event => setSeekerWidth(event.nativeEvent.layout.width)}
|
||||
pointerEvents={'none'}>
|
||||
<View style={seekerStyle} pointerEvents={'none'} />
|
||||
</View>
|
||||
<View style={seekerPositionStyle} pointerEvents={'none'}>
|
||||
<View style={seekerPointerStyle} pointerEvents={'none'} />
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
export default Seeker;
|
||||
64
examples/FabricExample/src/components/TextTracksSelector.tsx
Normal file
64
examples/FabricExample/src/components/TextTracksSelector.tsx
Normal file
@@ -0,0 +1,64 @@
|
||||
import {Picker} from '@react-native-picker/picker';
|
||||
import {Text} from 'react-native';
|
||||
import {TextTrack, SelectedTrack} from 'react-native-video';
|
||||
import styles from '../styles';
|
||||
import React from 'react';
|
||||
|
||||
export interface TextTrackSelectorType {
|
||||
textTracks: Array<TextTrack>;
|
||||
selectedTextTrack: SelectedTrack | undefined;
|
||||
onValueChange: (arg0: string) => void;
|
||||
textTracksSelectionBy: string;
|
||||
}
|
||||
|
||||
const TextTrackSelector = ({
|
||||
textTracks,
|
||||
selectedTextTrack,
|
||||
onValueChange,
|
||||
textTracksSelectionBy,
|
||||
}: TextTrackSelectorType) => {
|
||||
return (
|
||||
<>
|
||||
<Text style={styles.controlOption}>TextTrack</Text>
|
||||
<Picker
|
||||
style={styles.picker}
|
||||
itemStyle={styles.pickerItem}
|
||||
selectedValue={`${selectedTextTrack?.value}`}
|
||||
onValueChange={itemValue => {
|
||||
if (itemValue !== 'empty') {
|
||||
onValueChange(itemValue);
|
||||
}
|
||||
}}>
|
||||
{textTracks?.length <= 0 ? (
|
||||
<Picker.Item label={'empty'} value={'empty'} key={'empty'} />
|
||||
) : (
|
||||
<Picker.Item label={'none'} value={'none'} key={'none'} />
|
||||
)}
|
||||
{textTracks.map(track => {
|
||||
if (!track) {
|
||||
return;
|
||||
}
|
||||
if (textTracksSelectionBy === 'index') {
|
||||
return (
|
||||
<Picker.Item
|
||||
label={`${track.index}`}
|
||||
value={track.index}
|
||||
key={track.index}
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<Picker.Item
|
||||
label={track.language}
|
||||
value={track.language}
|
||||
key={track.language}
|
||||
/>
|
||||
);
|
||||
}
|
||||
})}
|
||||
</Picker>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default TextTrackSelector;
|
||||
@@ -0,0 +1,64 @@
|
||||
import {Picker} from '@react-native-picker/picker';
|
||||
import {Text} from 'react-native';
|
||||
import {
|
||||
SelectedVideoTrack,
|
||||
SelectedVideoTrackType,
|
||||
VideoTrack,
|
||||
} from 'react-native-video';
|
||||
import styles from '../styles';
|
||||
import React from 'react';
|
||||
|
||||
export interface VideoTrackSelectorType {
|
||||
videoTracks: Array<VideoTrack>;
|
||||
selectedVideoTrack: SelectedVideoTrack | undefined;
|
||||
onValueChange: (arg0: string) => void;
|
||||
}
|
||||
|
||||
const VideoTrackSelector = ({
|
||||
videoTracks,
|
||||
selectedVideoTrack,
|
||||
onValueChange,
|
||||
}: VideoTrackSelectorType) => {
|
||||
return (
|
||||
<>
|
||||
<Text style={styles.controlOption}>VideoTrack</Text>
|
||||
<Picker
|
||||
style={styles.picker}
|
||||
itemStyle={styles.pickerItem}
|
||||
selectedValue={
|
||||
selectedVideoTrack === undefined ||
|
||||
selectedVideoTrack?.type === SelectedVideoTrackType.AUTO
|
||||
? 'auto'
|
||||
: `${selectedVideoTrack?.value}`
|
||||
}
|
||||
onValueChange={itemValue => {
|
||||
if (itemValue !== 'empty') {
|
||||
onValueChange(itemValue);
|
||||
}
|
||||
}}>
|
||||
<Picker.Item label={'auto'} value={'auto'} key={'auto'} />
|
||||
{videoTracks?.length <= 0 || videoTracks?.length <= 0 ? (
|
||||
<Picker.Item label={'empty'} value={'empty'} key={'empty'} />
|
||||
) : (
|
||||
<Picker.Item label={'none'} value={'none'} key={'none'} />
|
||||
)}
|
||||
{videoTracks?.map(track => {
|
||||
if (!track) {
|
||||
return;
|
||||
}
|
||||
return (
|
||||
<Picker.Item
|
||||
label={`${track.width}x${track.height} ${Math.floor(
|
||||
(track.bitrate || 0) / 8 / 1024,
|
||||
)} Kbps`}
|
||||
value={`${track.index}`}
|
||||
key={track.index}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</Picker>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default VideoTrackSelector;
|
||||
Reference in New Issue
Block a user