react-native-streamlayer-new-arch

0.4.2 • Public • Published

React Native Integration Guide

We also support EXPO projects.

Background

The React Native SDK should be integrated if the client host app is built using React. Please ensure you are familiar with the Architecture Overview before proceeding with this integration.

Prerequisites

System Requirements

iOS Requirements
  • Xcode 15.3
  • Swift 5.9
  • iOS 15+
Android Requirements
  • Android Studio 4.0+
  • Kotlin 1.7+ or Java 8+
  • Minimum SDK version 21

Obtain an SDK API Key

You will need an SDK API Key to integrate StreamLayer into your application. If you do not already have one, please follow the instructions below.

Provide us with your email address to create a new organization for you on our platform, including setting up a personal dashboard for your account. You will then receive an invitation email with a link to the admin panel and your authentication credentials. After gaining access to the admin panel, you can generate an API key in the development section of the admin panel. This API key authenticates your application with our servers and is required for all interactions.

Integration Example

You can find a complete StreamLayer SDK integration example in our repo.
Or you can follow our video guide:

<iframe width="560" height="315" src="https://www.youtube.com/embed/fnke6UbZlwQ" frameborder="0" allowfullscreen />

Installation

Install the necessary packages with the following command:

npm

npm install react-native-streamlayer-new-arch

yarn

yarn add react-native-streamlayer-new-arch

Native iOS Configuration

Update Cocoapods Dependencies

Navigate to the ios directory and install the dependencies:

cd ios && pod install && cd ..

Upgrade minimum Ios Target

Update the minimum iOS version in the Podfile.

platform :ios, '15.0'

Add imports

import { 
    StreamLayer, 
    StreamLayerView, 
    StreamLayerViewPlayer, 
    StreamLayerViewOverlayLandscapeMode, 
    StreamLayerViewConfiguration, 
    StreamLayerViewNotificationFeature, 
    StreamLayerDemoEvent, 
    StreamLayerTheme 
} from 'react-native-streamlayer';

Add variables

The LBarState class represents the state of an interactive bar overlay in the StreamLayer integration. It tracks the horizontal (slideX) and vertical (slideY) positions of the overlay component. Instances of this class are used to store and update UI state when the L-bar position changes.

  class LBarState {
    slideX: number;
    slideY: number;

    constructor(slideX: number, slideY: number) {
        this.slideX = slideX
        this.slideY = slideY
    }
}

Player Height Calculation

The playerHeight variable determines the height of the player UI. If the screen is in portrait mode, a fixed height of 300px is assigned. Otherwise, the height is dynamically adjusted to match the full screen height using Dimensions.get('screen').height.

const playerHeight = isScreenPortrait() ? 300 : Dimensions.get('screen').height;

StreamLayer Player Configuration

This object acts as a placeholder for the StreamLayerViewPlayer. The volume property is defined with a getter and setter but is currently set to 0.0. The setter can be extended to implement volume control when required.

const streamLayerViewPlayer: StreamLayerViewPlayer = {
    get volume() {
        return 0.0
    },
    set volume(value) {
        // Custom logic for setting volume if needed
    },
}

View Configuration

The viewConfig object is obtained from getViewConfig(), which contains custom configurations for the StreamLayerView component. This includes settings for overlays, layout adjustments, and rendering preferences.

const viewConfig = getViewConfig()

State Variables

/// Stores the player's volume before applying audio ducking, used to restore it later.
const [volumeBeforeDucking, setVolumeBeforeDucking] = useState<number | undefined>(undefined)

/// Tracks the screen orientation to adjust UI layout accordingly.
const [isPortrait, setPortrait] = useState<boolean>(); 

/// Holds the current state of the L-bar overlay.
const [lbarState, setLbarState] = useState(new LBarState(0, 0));

/// Stores the list of available StreamLayerDemoEvent instances.
const [events, setEvents] = useState<Array<StreamLayerDemoEvent>>()

/// Stores the ID of the currently active event.
const [currentEventId, setCurrentEventId] = useState<String>()

/// Tracks whether the StreamLayerView has been initialized
const [isInitialized, setInitialized] = useState(false);

View Reference

A useRef hook is used to store a reference to the StreamLayerView. This allows direct interaction with the view without causing unnecessary re-renders.

const viewRef = useRef<StreamLayerView>(null);

Generating Scrollable Event List

The scrollItems array is dynamically populated with Pressable components representing events.

var scrollItems = new Array<ReactElement>();

if (events !== undefined) {
    events.forEach((event) => {
        scrollItems.push(
            <Pressable key={event.id} onPress={() => createEventSession(event.id)}>
                <View style={styles.eventRow}>
                    {event.previewUrl !== undefined && (
                        <Image source={{ uri: event.previewUrl }}
                            style={styles.eventRowImage} />
                    )}
                    <Text style={styles.eventRowTitle} numberOfLines={1} ellipsizeMode='tail'>
                        {event.title}
                    </Text>
                </View>
            </Pressable>
        );
    });
}

Finding the Current Event

This logic retrieves the currently selected event by matching currentEventId against the events list. If no match is found, currentEvent remains undefined.

var currentEvent: StreamLayerDemoEvent | undefined;
if (events !== undefined && currentEventId !== undefined) {
  currentEvent = events.find((event) => {
      return event.id == currentEventId
  })
}

Add methods

Initialization and Orientation Handling

The useEffect hook is responsible for initializing the StreamLayer SDK and tracking screen orientation changes. When the component mounts, it determines if the device is in portrait mode and initializes StreamLayer. Additionally, it listens for screen dimension changes to update the portrait state dynamically. When the component unmounts, the event listener is removed to prevent memory leaks.

useEffect(() => {
        
  setPortrait(isScreenPortrait())
  const initialize = async () => {

      try {
          checkInitialized();
      } catch (error) {
          console.error("Error initializing:", error);
      }
  };

  initialize();

  const subscription = Dimensions.addEventListener('change', ({ window, screen }) => {
      setPortrait(window.height > window.width)
  });


  return () => subscription?.remove()


}, []);


function isScreenPortrait(): boolean {
  return Dimensions.get('window').height > Dimensions.get('window').width
}

StreamLayer View Configuration

The getViewConfig function returns an object that configures the StreamLayer UI. It defines which notification features are enabled, whether points for games should be displayed, and settings for UI elements like the launch button, tooltips, and profile visibility. The overlay settings control the behavior of the expandable StreamLayer overlay.

function getViewConfig(): StreamLayerViewConfiguration {
  return {
      viewNotificationFeatures: new Array(
          StreamLayerViewNotificationFeature.Games,
          StreamLayerViewNotificationFeature.Chat,
          StreamLayerViewNotificationFeature.WatchParty,
          StreamLayerViewNotificationFeature.Twitter
      ),
      isGamesPointsEnabled: true,
      isGamesPointsStartSide: false,
      isLaunchButtonEnabled: true,
      isMenuAlwaysOpened: false,
      isMenuLabelsVisible: true,
      isMenuProfileEnabled: true,
      isTooltipsEnabled: true,
      isWatchPartyReturnButtonEnabled: true,
      isWhoIsWatchingViewEnabled: true,
      isOverlayExpandable: true,
      overlayHeightSpace: 300,
      overlayWidth: 0,
      overlayLandscapeMode: StreamLayerViewOverlayLandscapeMode.Start
  }
}

Player Setup

When the THEOplayer instance is ready, the onReady function sets up the player with autoplay enabled and assigns a media source. Additionally, it listens for error events to handle any issues that might occur during playback.

const onReady = (player: THEOplayer) => {
  setPlayer(player);
  player.autoplay = true
  player.source = source;
  player.addEventListener(PlayerEventType.ERROR, console.log);
}

StreamLayer SDK Initialization and Authentication

The checkInitialized function initializes the StreamLayer SDK, enabling logging and applying a theme. It then verifies whether the SDK has been successfully initialized and updates the state accordingly.

const checkInitialized = async () => {
  try {
          await StreamLayer.initSdk({
                isLoggingEnabled: true,
                theme: StreamLayerTheme.Green,
                sdkKey: "YOUR SDK KEY",
            },false)
          checkAuth()
          loadDemoEvents()
          const inited = await StreamLayer.isInitialized()
          setInitialized(inited)

  } catch (e) {
      console.error(e);
  }
}

To ensure authentication, the checkAuth function checks if the user is authorized. If not, it triggers anonymous authentication to allow access without requiring login credentials.

const checkAuth = async () => {
  try {
      const isUserAuthorized = await StreamLayer.isUserAuthorized()
      if (!isUserAuthorized) {
          await StreamLayer.useAnonymousAuth();
      }
  } catch (e) {
      console.error(e);
  }
}

The loadDemoEvents function fetches a list of demo events from the StreamLayer API based on a specific date. If events exist, the first event is used to create a session.

const loadDemoEvents = async () => {
  try {
      const events = await StreamLayer.getDemoEvents("2022-01-01")
      setEvents(events)
      if (events !== undefined && events !== null && events.length > 0) {
          createEventSession(events[0].id)
      }
  } catch (e) {
      console.error("PlayerScreen loadDemoEvents error", e);
  }
}

The createEventSession function creates a new session for an event using its ID, ensuring that event-based interactions are properly initialized.

const createEventSession = async (id: string) => {
  try {
      await StreamLayer.createEventSession(id);
      console.log(`Created a new event with id ${id}`);
      setCurrentEventId(id)
  } catch (e) {
      console.error(e);
  }
};

Add functions for view event listener

   /// Initializes an event session for that stream.

   const onRequestStream = (id: string) => {
      createEventSession(id)
   }

   /// Updates the local state for the LBar UI component whenever its position changes.

   const onLBarStateChanged = (slideX: number, slideY: number) => {
      setLbarState(new LBarState(slideX, slideY));
   }

   /// Handles audio ducking requests from StreamLayer.

   const onRequestAudioDucking = (level: number) => {
      /// Add your handlers
   }

   /// Handles the event when audio ducking needs to be disabled.

   const onDisableAudioDucking = () => {
      /// Add your handlers
   }

Add Views for StreamLayer and StreamLayer Events

The following component sets up the main StreamLayer view within the app. It integrates StreamLayer’s event system, applying UI adjustments based on the user's interaction.

    return (

        <SafeAreaView style={{...styles.container, marginTop: insets.top }}  edges={['top']}>
        
            {(isPortrait) &&
               /// Displays the event title and scrollable event list when the screen is in portrait mode.
                <View style={{ flex: 1, marginTop: playerHeight  - insets.top }}>
                    {currentEvent !== undefined && (
                        <Text style={styles.eventTitle}>{currentEvent.title}</Text>
                    )}
                    <ScrollView style={{ flex: 1 }}>
                        {scrollItems}
                    </ScrollView>
                </View>
            }
             
            {isInitialized && 
               /// StreamLayer overlat that takes your component and scales it down when the l-bar arrives
                <StreamLayerView
                    style={StyleSheet.absoluteFillObject}
                    ref={viewRef}
                    config={viewConfig}
                    applyWindowInsets={false}
                    onRequestStream={onRequestStream}
                    onLBarStateChanged={onLBarStateChanged}
                    onRequestAudioDucking={onRequestAudioDucking}
                    onDisableAudioDucking={onDisableAudioDucking}
                    player={streamLayerViewPlayer}
                    playerView={
                           <View>
                      			/// YOUR VIEW SCALES DOWN WHEN THE L-Bar ARRIVES
                      		</View>
                    }
                />
            }

        </SafeAreaView>
    )

Styles

const styles = StyleSheet.create({
    container: {
        flex: 1,
        backgroundColor: 'gray',
    },
    eventTitle: {
        color: 'white',
        fontSize: 24,
        margin: 4
    },
    eventRowTitle: {
        flex: 1,
        color: 'white',
        fontSize: 16,
        margin: 4
    },
    eventRow: {
        flexDirection: 'row',
        margin: 4,
        padding: 4,
        height: 58,
        justifyContent: 'flex-start',
        alignItems: 'center',
        borderWidth: 1,
        borderColor: 'black',
    },
    eventRowImage: {
        width: 100,
        height: 50
    },
    overlay: {
        paddingTop: 500,
        backgroundColor: '#00000000',
        flex: 1,
    }
});

Package Sidebar

Install

npm i react-native-streamlayer-new-arch

Weekly Downloads

15

Version

0.4.2

License

MIT

Unpacked Size

402 kB

Total Files

169

Last publish

Collaborators

  • joseph_yakovlev