1.0.5 • Published 7 months ago

react-native-reels-list v1.0.5

Weekly downloads
-
License
ISC
Repository
github
Last release
7 months ago

react-native-reels-list

react-native-reels-list is a customizable React Native component designed to provide an intagram/tiktok like optimized video list experience. It offers a variety of features and options to ensure smooth and efficient video playback in your React Native applications.

react-native-reels-list

Features

  • Optimized video list for smooth performance
  • Customizable video height
  • Tap to mute functionality
  • Hold to pause functionality
  • Seekbar support
  • Loading indicator
  • Custom overlay components
  • Playback status updates

Installation

Install the package via npm:

npm install react-native-reels-list

or via yarn:

yarn add react-native-reels-list

Note: This package uses expo-av for video playback, expo-av is required to be installed in your project. Follow these installation instructions..

Usage

Here's an example of how to use the ReelsList component in your React Native application:

import { useCallback, useContext } from "react";
import { VIEWPORT_HEIGHT } from "@/constants";
import { useBottomTabBarHeight } from "@react-navigation/bottom-tabs";
import ReelsList, { VideoItemType } from "react-native-reels-list";
import { MuteContext } from "@/context";
import { AVPlaybackStatus } from "expo-av";

const videos = [
  { key: '1', uri: 'https://example.com/video1.mp4', thumbnail: 'https://example.com/thumbnail1.jpg', ...otherProperties},
  { key: '2', uri: 'https://example.com/video2.mp4', thumbnail: 'https://example.com/thumbnail4.jpg', ...otherProperties},
  // Add more videos as needed
];

const App = () => {
  const tabBarHeight = useBottomTabBarHeight();
  const { isMuted, handleMuteToggle } = useContext(MuteContext);
  const [currentVideoIndex, setCurrentVideoIndex] = useState(0);
  const [status, setStatus] = useState<AVPlaybackStatus | null>(null);

  const videoHeight = VIEWPORT_HEIGHT - tabBarHeight;

 const onViewableItemsChanged = useCallback(
    (info: {
      viewableItems: ViewToken<VideoItemType>[];
      changed: ViewToken<VideoItemType>[];
    }) => {
      // Update the current video index when the viewable items change
      setCurrentVideoIndex(
        (prev) => info.changed.find((item) => item.isViewable)?.index ?? prev
      );
      // If required, add your custom logic here
    },
    []
  );

  const handleGetItemLayout = useCallback(
    (data: ArrayLike<VideoItemType> | null | undefined, index: number) => {
      return {
        length: videoHeight,
        offset: videoHeight * index,
        index,
      };
    },
    [videoHeight]
  );

   const overlayComponent = useCallback(
    ({ item }: { item: VideoItemType, index:number }) => (
      // Custom overlay component for each video item. Add your custom UI with position: 'absolute' here.
      <View style={styles.overlay}>
        <Link href={`/profile/${item.username}`} asChild>
          <Pressable>
            <Text>@{item.username}</Text>
          </Pressable>
        </Link>
      </View>
    ),
    []
  );

  return (
    <ReelsList
      videoHeight={videoHeight}
      currentVideoIndex={currentVideoIndex}
      handleGetItemLayout={handleGetItemLayout}
      onViewableItemsChanged={onViewableItemsChanged}
      videos={videos}
      isMuted={isMuted}
      handleMuteToggle={handleMuteToggle}
      showSeekbar={true}
      showLoadingIndicator={true}
      holdToPause={true}
      overlayComponent={overlayComponent}
      onCurrentPlaybackStatusUpdate={(status) => setStatus(status)}
      refreshing={refreshing}
      onRefresh={() => {
        // Refresh the video list
      }}
      onEndReached={() => {
        // Fetch more videos
      }}
    />
  );
};

export default FollowingTopTab;


const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: "center",
    alignItems: "center",
  },
  overlay:{
    position: "absolute",
    bottom: 40,
    left: 8,
    zIndex: 2,
  }
});

export default App;

Props

The ReelsList component accepts the following props:

PropTypeDescriptionDefaultRequired
currentVideoIndexnumberThe index of the current video being played.-Yes
handleGetItemLayoutfunctionFunction to get the layout of each item in the list.-Yes
onViewableItemsChangedfunctionCallback function when viewable items change.-Yes
videosArray<{ key: string, uri: string, thumbnail: string, ...otherProperties }>Array of video items to be displayed in the list.-Yes
videoHeightnumberHeight of each video in the list.-Yes
isMutedbooleanFlag to mute/unmute videos.falseNo
handleMuteTogglefunctionCallback function to handle mute toggle.-No
showSeekbarbooleanFlag to show/hide the seekbar.falseNo
showLoadingIndicatorbooleanFlag to show/hide the loading indicator.falseNo
useNativeControlsbooleanFlag to use native video controls.falseNo
holdToPausebooleanFlag to enable hold-to-pause functionality.falseNo
bottomOffsetnumberOffset from the bottom of the screen for the default seekbar and buffering indicator.0No
overlayComponent({ item, index }) => ReactNodeFunction to render a custom overlay component for each video.-No
onCurrentPlaybackStatusUpdate(status: AVPlaybackStatus) => voidA function to be called regularly with the AVPlaybackStatus of the currently playing video. Helps in tracking the playback status of the video for custom UI updates.-No

Additionally, the component accepts all other FlatList props for added customizations.

Performance Metrics

DeviceMax CPU Usage*Idle CPU UsageAvg. RAM UsageInitial Load Time (Lazy Loading On)Initial Load Time (Lazy Loading Off)
Two Video Lists (Two Top Tabs)
Samsung Galaxy A22 (6 GB RAM)70%13%650 MB1-2 Seconds18 Seconds
Samsung Galaxy S22 Ultra (12 GB RAM)37%10%770 MB1-2 Seconds13 Seconds
Samsung Galaxy A21s (4 GB RAM)75%18%698 MB4-5 Seconds30-40 Seconds
One Video List (Single Top Tab)
Samsung Galaxy A22 (6 GB RAM)48%12%515 MB1-2 Seconds-
Samsung Galaxy S22 Ultra (12 GB RAM)32%10%635 MB1-2 Seconds-
Samsung Galaxy A21s (4 GB RAM)71%16%532 MB4-5 Seconds-

*Note: The maximum CPU usage values represent occasional spikes and should not be a cause for concern.

Usage Tips

  • If you are using multiple simultaneously running video lists, load the lists lazily for improved performance.
  • On lower-end devices, if you encounter java.lang.OutOfMemoryError, set android:largeHeap="true" in the Android manifest.

Contributing

Contributions are welcome! Please open an issue or submit a pull request for any improvements or bug fixes.

Author

Developed by Simranjit Singh.

Acknowledgments

Special thanks to all the contributors and the React Native community for their support and inspiration.