API Reference

Complete API reference for the StreamLayer React Native SDK including TypeScript interfaces, enums, the StreamLayer class, StreamLayerView component props, and a full integration usage example.

API Reference


Interfaces and Enums


StreamLayerDemoEvent

Represents a demo event in the StreamLayer system.

  1. id: string – Unique identifier for the event.
  2. title?: string – (Optional) Title of the event.
  3. subtitle?: string – (Optional) Subtitle or additional description.
  4. previewUrl?: string – (Optional) URL of a preview image or video.
  5. videoUrl?: string – (Optional) URL of the main event video.
export interface StreamLayerDemoEvent {
  id: string,
  title?: string,
  subtitle?: string,
  previewUrl?: string,
  videoUrl?: string
}

StreamLayerInviteGroupType

Defines the type of group invitation in StreamLayer.

  1. Chat – Represents an invitation to a Chat group.
export enum StreamLayerInviteGroupType {
  Chat = "Chat"
}

StreamLayerInviteUser

Represents an invited user in the StreamLayer system.

  1. id?: string – (Optional) Unique user identifier.
  2. tinodeUserId?: string – (Optional) Tinode-specific user identifier (if applicable).
  3. name?: string – (Optional) Full name of the user.
  4. username?: string – (Optional) Username of the user.
  5. avatar?: string – (Optional) URL to the user’s avatar image.
export interface StreamLayerInviteUser {
  id?: string,
  tinodeUserId?: string,
  name?: string,
  username?: string,
  avatar?: string,
}

StreamLayerInvite

Represents an invitation to a StreamLayer event or group.

  1. linkId?: string – (Optional) Unique identifier for the invitation link.
  2. eventId?: string – (Optional) Identifier for the event related to this invite.
  3. externalEventId?: string – (Optional) External identifier of the event (for integration purposes).
  4. groupId?: string – (Optional) Identifier of the group the invite is associated with.
  5. externalGroupId?: string – (Optional) External identifier for the group.
  6. gamification?: boolean – (Optional) Whether gamification features are enabled for this invite.
  7. groupType?: StreamLayerInviteGroupType – (Optional) Type of the invite (e.g. Chat).
  8. user?: StreamLayerInviteUser – (Optional) User details associated with the invitation.
export interface StreamLayerInvite {
  linkId?: string,
  eventId?: string,
  externalEventId?: string,
  groupId?: string,
  externalGroupId?: string,
  gamification?: boolean,
  groupType?: StreamLayerInviteGroupType,
  user?: StreamLayerInviteUser
}

StreamLayerTheme (Enum)

Defines the available UI themes for the StreamLayer SDK.

  1. Blue – Blue theme.
  2. Green – Green theme.
export enum StreamLayerTheme {
  Blue = "Blue",
  Green = "Green"
}

StreamLayerConfiguration

Defines the configuration settings for initializing the StreamLayer SDK.

  1. sdkKey: string – Required API key to authenticate the SDK.
  2. theme?: StreamLayerTheme – (Optional) Defines the UI theme (Blue or Green).
  3. isLoggingEnabled?: boolean – (Optional) Enables or disables logging for debugging.
  4. isGlobalLeaderboardEnabled?: boolean – (Optional) Enables global leaderboard functionality.
  5. isGamesInviteEnabled?: boolean – (Optional) Enables the ability to send game invites.
export interface StreamLayerConfiguration {
  sdkKey: string,
  theme?: StreamLayerTheme,
  isLoggingEnabled?: boolean,
  isGlobalLeaderboardEnabled?: boolean,
  isGamesInviteEnabled?: boolean
}

DeepLinkParams

A dynamic object that holds key-value pairs for handling deep links.

  1. [key: string]: any; – Allows storing various deep link parameters.
export interface DeepLinkParams {
  [key: string]: any;
}

Class: StreamLayer

Provides methods for interacting with the StreamLayer SDK.

export class StreamLayer {

  static isInitialized(): Promise<boolean> {
      return StreamLayerModule.isInitialized();
  }

  static authorizationBypass(schema: string, token: string): Promise<void> {
    return StreamLayerModule.authorizationBypass(schema, token)
  }

  static useAnonymousAuth(): Promise<void> {
    return StreamLayerModule.useAnonymousAuth()
  }

  static isUserAuthorized(): Promise<boolean> {
    return StreamLayerModule.isUserAuthorized()
  }

  static logout(): Promise<void> {
    return StreamLayerModule.logout() 
  }

  static removeOverlay(): Promise<void> {
    return StreamLayerModule.removeOverlay() 
  }

  static createEventSession(id: string): Promise<void> {
    return StreamLayerModule.createEventSession(id)
  }

  static releaseEventSession(): void {
    StreamLayerModule.releaseEventSession()
  }

  static getInvite(json: Object): Promise<StreamLayerInvite> {
    return StreamLayerModule.getInvite(json);
  }

  static getDemoEvents(date: string): Promise<Array<StreamLayerDemoEvent>> {
    return StreamLayerModule.getDemoEvents(date)
  }

  static initSdk(config: StreamLayerConfiguration): Promise<void> {
    return StreamLayerModule.initSdk({...config, sdkKey: Config.SL_SDK_API_KEY })
  }

  static handleDeepLink(params: DeepLinkParams): Promise<boolean> {
    return StreamLayerModule.handleDeepLink(params);
  }

}

useAnonymousAuth(): Promise<void>

Enables anonymous authentication mode.
Returns: A Promise<void> indicating the completion of the operation.


isUserAuthorized(): Promise<boolean>

Checks whether the current user is authorized.
Returns: A Promise<boolean> resolving to true if the user is authorized, otherwise false.


logout(): Promise<void>

Logs out the current user from the SDK.
Returns: A Promise<void> indicating the completion of the operation.


removeOverlay(): Promise<void>

Removes any active StreamLayer Element from the StreamLayer UI.
Returns: A Promise<void> indicating the completion of the operation.


createEventSession(id: string): Promise<void>

Creates a new event session with the specified ID.
Parameters: id: string – The unique identifier for the event session. Returns: A Promise<void> indicating the completion of the operation.


releaseEventSession(): void

Releases the current event session, if active.
Returns: void.


getInvite(json: Object): Promise<StreamLayerInvite>

Retrieves invite details based on the provided JSON parameters.
Parameters: json: Object – Object containing the invite request parameters. Returns: A Promise<StreamLayerInvite> resolving to the invite details.


getDemoEvents(date: string): Promise<Array<StreamLayerDemoEvent>>

Fetches a list of demo events for a specific date.
Parameters: date: string – The date for which demo events should be retrieved. Returns: A Promise<Array<StreamLayerDemoEvent>> resolving to an array of demo events.


initSdk(config: StreamLayerConfiguration): Promise<void>

Initializes the StreamLayer SDK with the provided configuration.
Parameters:

config: StreamLayerConfiguration – The SDK configuration settings.

Returns: A Promise<void> indicating the completion of the initialization process.


handleDeepLink(params: DeepLinkParams): Promise<boolean>

Processes a deep link and handles navigation accordingly.
Parameters: params: DeepLinkParams – Key-value parameters from the deep link. Returns: A Promise<boolean> resolving to true if the deep link was handled successfully, otherwise false.


Class StreamLayerView


StreamLayerViewOverlay

Defines different StreamLayer Element types available in the StreamLayer view.

  1. Games: StreamLayer Element for interactive games.
  2. Twitter: StreamLayer Element that integrates Twitter feed.
  3. Statistics: StreamLayer Element displaying statistical data.
export enum StreamLayerViewOverlay {
  Games = "Games",
  Twitter = "Twitter",
  Statistics = "Statistics",
}

StreamLayerViewOverlayLandscapeMode

Specifies the placement of StreamLayer Elements in landscape mode.

  1. Start: StreamLayer Element positioned at the beginning of the screen.
  2. End: StreamLayer Element positioned at the end of the screen.
  3. Lbar: StreamLayer Element positioned in an L-bar layout.
export enum StreamLayerViewOverlayLandscapeMode {
  Start = "Start",
  End = "End",
  Lbar = "Lbar",
}

StreamLayerViewNotificationFeature

Defines the notification features available in the StreamLayer view.

  1. Games: Notifications about game events.
  2. Chat: Notifications for chat interactions.
  3. Twitter: Notifications for Twitter-related content.
export enum StreamLayerViewNotificationFeature {
  Games = "Games",
  Chat = "Chat",
  Twitter = "Twitter",
}

StreamLayerViewConfiguration

Configuration options for the StreamLayer view.

  1. viewNotificationFeatures: List of enabled notification features.
  2. isGamesPointsEnabled: Enables/disables game points display.
  3. isGamesPointsStartSide: Determines whether game points appear on the starting side.
  4. isLaunchButtonEnabled: Enables/disables the launch button.
  5. isMenuAlwaysOpened: Keeps the menu always open if true.
  6. isMenuLabelsVisible: Shows or hides menu labels.
  7. isMenuProfileEnabled: Enables/disables the profile section in the menu.
  8. isTooltipsEnabled: Enables/disables tooltips.
  9. isWhoIsWatchingViewEnabled: Enables/disables the "Who is watching?" view.
  10. isOverlayExpandable: Allows the StreamLayer Element to be expanded.
  11. overlayHeightSpace: Sets additional height space for the overlay.
  12. overlayWidth: Defines the width of the overlay.
  13. overlayLandscapeMode: Defines how the StreamLayer Element is displayed in landscape mode.
export interface StreamLayerViewConfiguration {
  viewNotificationFeatures?: StreamLayerViewNotificationFeature[]
  isGamesPointsEnabled?: boolean,
  isGamesPointsStartSide?: boolean,
  isLaunchButtonEnabled?: boolean,
  isMenuAlwaysOpened?: boolean,
  isMenuLabelsVisible?: boolean,
  isMenuProfileEnabled?: boolean,
  isTooltipsEnabled?: boolean,
  isWhoIsWatchingViewEnabled?: boolean,
  isOverlayExpandable?: boolean,
  overlayHeightSpace?: number,
  overlayWidth?: number,
  overlayLandscapeMode?: StreamLayerViewOverlayLandscapeMode
}

StreamLayerViewProps

Props for the StreamLayerView React component.

  1. style: Custom styles for the view.
  2. config: Configuration options for the view.
  3. applyWindowInsets: If true, applies window insets for better layout adaptation.
  4. playerView: A React node representing the video player inside the overlay.
  5. player: The player object controlling volume and settings.
  6. onRequestStream: Callback when a stream is requested (receives id).
  7. onLBarStateChanged: Callback triggered when the L-bar position changes (receives slideX, slideY).
  8. onRequestAudioDucking: Callback for requesting audio ducking (receives level).
  9. onDisableAudioDucking: Callback when audio ducking should be disabled.

export interface StreamLayerViewProps {
  style?: StyleProp<ViewStyle>;
  config?: StreamLayerViewConfiguration;
  applyWindowInsets?: Boolean;
  playerView?: ReactNode;
  player?: StreamLayerViewPlayer;
  onRequestStream?: (id: string) => void;
  onLBarStateChanged?: (slideX: number, slideY: number) => void;
  onRequestAudioDucking?: (level: number) => void;
  onDisableAudioDucking?: () => void;
}

StreamLayerViewPlayer
Represents a player inside the StreamLayer view.

volume: The volume level of the player.

export interface StreamLayerViewPlayer {
  volume: number;
}

Integration usage:


Variables.

State Class for LBar

This class represents the state of an LBar with two properties: slideX and slideY, which define its position.

class LBarState {
    slideX: number;
    slideY: number;

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

Player Configuration and Source

These constants define the player's configuration and source URL for playback.

const playerConfig: PlayerConfiguration = {
    license: undefined,
};

const source: SourceDescription = {
    sources: [
        {
            src: "https://cdn.theoplayer.com/video/elephants-dream/playlist-single-audio.m3u8",
            type: "application/x-mpegurl"
        },
    ],
};

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

const streamLayerViewPlayer: StreamLayerViewPlayer = {
    get volume() {
        return 0.0
    },
    set volume(value) {

    },
}
View Configuration and Insets

These variables store the safe area insets and the view configuration.

const viewConfig = getViewConfig()
const insets = useSafeAreaInsets()
Event List and Current Event

This block initializes an array of event items and finds the currently selected event.

volumeBeforeDucking (number | undefined) – Stores the player's volume level before it is temporarily reduced (ducked), ensuring it can be restored later.

isPortrait (boolean | undefined) – Tracks whether the device screen is in portrait mode, likely affecting UI layout and player positioning.

player (THEOplayer | undefined) – Holds an instance of THEOplayer, managing video playback. If undefined, the player is not yet initialized.

lbarState (LBarState) – Manages the position of the LBar UI component, storing slideX and slideY values for animations or positioning.

events (Array<StreamLayerDemoEvent> | undefined) – Holds a list of available events for selection. If undefined, no events have been loaded yet.

currentEventId (String | undefined) – Stores the ID of the currently selected event, helping to determine which event details to display.

isInitialized (boolean) – Indicates whether the component has completed its setup process, ensuring dependent logic executes only when ready.

viewRef (useRef<StreamLayerView>) – A reference to the StreamLayerView component, allowing direct interaction and modifications.

const [volumeBeforeDucking, setVolumeBeforeDucking] = useState<number | undefined>(undefined)
const [isPortrait, setPortrait] = useState<boolean>();
const [player, setPlayer] = useState<THEOplayer | undefined>(undefined);
const [lbarState, setLbarState] = useState(new LBarState(0, 0));
const [events, setEvents] = useState<Array<StreamLayerDemoEvent>>()
const [currentEventId, setCurrentEventId] = useState<String>()
const [isInitialized, setInitialized] = useState(false);
const viewRef = useRef<StreamLayerView>(null);

Event List and Selection
  1. scrollItems (Array<ReactElement>) – Holds a list of rendered event items for display.
  2. Looping through events – Each event is converted into a Pressable component, allowing user interaction.
  3. currentEvent (StreamLayerDemoEvent | undefined) – Finds the currently selected event based on currentEventId.
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>
      )
  })
}

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

Effect Hook for Initialization and Orientation Handling
  1. useEffect – Runs once on mount ([] dependency array).
  2. setPortrait(isScreenPortrait()) – Determines initial screen orientation.
  3. initialize() – Calls checkInitialized() inside a try-catch block.
  4. Dimensions.addEventListener('change', ...) – Listens for screen rotation and updates isPortrait.
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()


}, []);

View Configuration: getViewConfig()

This function is used to return a configuration object for the StreamLayerView, which defines various UI and functional settings for the StreamLayer integration in the app.

  1. viewNotificationFeatures (StreamLayerViewNotificationFeature[]):
    An array of features that should be enabled for notifications in the view. The array includes:
    1. StreamLayerViewNotificationFeature.Games: Enables the "Games" notification feature.
  2. StreamLayerViewNotificationFeature.Chat: Enables the "Chat" feature, allowing users to communicate within the stream.
  3. StreamLayerViewNotificationFeature.Twitter: Enables Twitter integration for the event or stream.
    isGamesPointsEnabled (boolean): This boolean value indicates whether game points are enabled or not. It's set to true, meaning points are enabled for the game or stream.
  4. isGamesPointsStartSide (boolean):
    Determines whether the points start from the side or not. It's set to false, meaning the points will not start from the side.
  5. isLaunchButtonEnabled (boolean):
    This value enables or disables the "Launch" button in the UI. It's set to true, meaning the button will be shown.
  6. isMenuAlwaysOpened (boolean):
    Controls whether the menu should always remain open. It's set to false, meaning the menu can be collapsed.
  7. isMenuLabelsVisible (boolean):
    This option controls whether labels in the menu are visible. It's set to true, meaning labels will be displayed.
  8. isMenuProfileEnabled (boolean):
    Controls whether the user profile option is enabled in the menu. It's set to true, meaning the profile will be enabled.
  9. isTooltipsEnabled (boolean):
    This option enables or disables tooltips in the app. It's set to true, meaning tooltips are enabled.
  10. isWhoIsWatchingViewEnabled (boolean):
    If set to true, this enables a view that shows who is watching the stream.
  11. isOverlayExpandable (boolean):
    This option allows the StreamLayer Element to be expandable. It's set to true, meaning the StreamLayer Element can expand.
  12. overlayHeightSpace (number):
    Specifies the height space for the overlay. It’s set to 300, indicating the StreamLayer Element’s height.
  13. overlayWidth (number):
    Specifies the width of the overlay. It's set to 0, meaning the StreamLayer Element has no width initially.
  14. overlayLandscapeMode (StreamLayerViewOverlayLandscapeMode):
    Defines the behavior of the StreamLayer Element in landscape mode. It’s set to
  15. StreamLayerViewOverlayLandscapeMode.Start, meaning the StreamLayer Element behavior will be defined at the start of the landscape mode.
function getViewConfig(): StreamLayerViewConfiguration {
  return {
      viewNotificationFeatures: new Array(
          StreamLayerViewNotificationFeature.Games,
          StreamLayerViewNotificationFeature.Chat,
          StreamLayerViewNotificationFeature.Twitter
      ),
      isGamesPointsEnabled: true,
      isGamesPointsStartSide: false,
      isLaunchButtonEnabled: true,
      isMenuAlwaysOpened: false,
      isMenuLabelsVisible: true,
      isMenuProfileEnabled: true,
      isTooltipsEnabled: true,
      isWhoIsWatchingViewEnabled: true,
      isOverlayExpandable: true,
      overlayHeightSpace: 300,
      overlayWidth: 0,
      overlayLandscapeMode: StreamLayerViewOverlayLandscapeMode.Start
  }
}
isScreenPortrait()
function isScreenPortrait(): boolean {
  return Dimensions.get('window').height > Dimensions.get('window').width
}
onReady(player: THEOplayer)

This function is called when the player is ready:

  1. setPlayer(player):
    Sets the player instance to the state.
  2. player.autoplay = true:
    Automatically plays the video when it’s loaded.
  3. player.source = source:
    Sets the video source, where source is assumed to be a predefined video URL or stream source.
  4. player.addEventListener(PlayerEventType.ERROR, console.log):
    Adds an error event listener to the player. If an error occurs during playback, it will be logged to the console.
const onReady = (player: THEOplayer) => {
  setPlayer(player);
  player.autoplay = true
  player.source = source;
  player.addEventListener(PlayerEventType.ERROR, console.log);
}

checkInitialized()

This asynchronous function initializes the StreamLayer SDK:

  1. StreamLayer.initSdk({ isLoggingEnabled: true, theme: StreamLayerTheme.Green }, false):
    Initializes the SDK with logging enabled and sets the theme to green.
  2. checkAuth():
    Calls checkAuth() to verify the user's authentication status.
  3. loadDemoEvents():
    Loads demo events from the StreamLayer API.
  4. StreamLayer.isInitialized():
    Checks if the SDK is initialized and stores the result in inited. It then updates the state setInitialized(inited).
const checkInitialized = async () => {
  try {
          await StreamLayer.initSdk({
              isLoggingEnabled: true,
              theme: StreamLayerTheme.Green
            },false)
          checkAuth()
          loadDemoEvents()
          const inited = await StreamLayer.isInitialized()
          setInitialized(inited)

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

This function loads demo events:

  1. It fetches events from the StreamLayer API using StreamLayer.getDemoEvents("2022-01-01").
  2. If events are successfully fetched, it updates the state with the event list using setEvents(events).
  3. If there are events, it automatically creates a session for the first event by calling createEventSession(events[0].id).
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);
  }
}

checkAuth()

This function checks if the user is authenticated:

  1. StreamLayer.isUserAuthorized():
    Checks if the user is authorized.
  2. StreamLayer.useAnonymousAuth():
    If the user is not authorized, it switches to anonymous authentication.
const checkAuth = async () => {
  try {
      const isUserAuthorized = await StreamLayer.isUserAuthorized()
      if (!isUserAuthorized) {
          await StreamLayer.useAnonymousAuth();
      }
  } catch (e) {
      console.error(e);
  }
}
createEventSession(id: string)

This function creates a new event session

  1. StreamLayer.createEventSession(id):
    Calls StreamLayer to create an event session with the given id.
  2. setCurrentEventId(id):
    Updates the currentEventId state to the newly created event's ID.
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);
  }
};

Event Listeners for UI and Audio

  1. onRequestStream(id: string) – Handles stream request events.
  2. onLBarStateChanged(slideX: number, slideY: number) – Updates LBar state when its position changes.
  3. onRequestAudioDucking(level: number) – Handles audio ducking requests.
  4. onDisableAudioDucking() – Disables audio ducking when needed.
    const onRequestStream = (id: string) => {
        console.log("onRequestStream id=" + id)
        createEventSession(id)
    }

    const onLBarStateChanged = (slideX: number, slideY: number) => {
        console.log("onLBarStateChanged slideX=" + slideX + " slideY=" + slideY)
        setLbarState(new LBarState(slideX, slideY));
    }

    const onRequestAudioDucking = (level: number) => {
        console.log("onRequestAudioDucking level=" + level)
    }

    const onDisableAudioDucking = () => {
        console.log("onDisableAudioDucking")
    }

Fully tuned example:

function App(): React.JSX.Element {

  class LBarState {
    slideX: number;
    slideY: number;

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

const playerConfig: PlayerConfiguration = {
    license: undefined,
};

const source: SourceDescription = {
    sources: [
        {
            src: "https://cdn.theoplayer.com/video/elephants-dream/playlist-single-audio.m3u8",
            type: "application/x-mpegurl"
        },
    ],
};

const insets = useSafeAreaInsets()

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

const streamLayerViewPlayer: StreamLayerViewPlayer = {
    get volume() {
        return 0.0
    },
    set volume(value) {

    },
}

const viewConfig = getViewConfig()

const [volumeBeforeDucking, setVolumeBeforeDucking] = useState<number | undefined>(undefined)
const [isPortrait, setPortrait] = useState<boolean>();
const [player, setPlayer] = useState<THEOplayer | undefined>(undefined);
const [lbarState, setLbarState] = useState(new LBarState(0, 0));
const [events, setEvents] = useState<Array<StreamLayerDemoEvent>>()
const [currentEventId, setCurrentEventId] = useState<String>()
const [isInitialized, setInitialized] = useState(false);
const viewRef = useRef<StreamLayerView>(null);

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>
      )
  })
}

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

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 getViewConfig(): StreamLayerViewConfiguration {
  return {
      viewNotificationFeatures: new Array(
          StreamLayerViewNotificationFeature.Games,
          StreamLayerViewNotificationFeature.Chat,
          StreamLayerViewNotificationFeature.Twitter
      ),
      isGamesPointsEnabled: true,
      isGamesPointsStartSide: false,
      isLaunchButtonEnabled: true,
      isMenuAlwaysOpened: false,
      isMenuLabelsVisible: true,
      isMenuProfileEnabled: true,
      isTooltipsEnabled: true,
      isWhoIsWatchingViewEnabled: true,
      isOverlayExpandable: true,
      overlayHeightSpace: 300,
      overlayWidth: 0,
      overlayLandscapeMode: StreamLayerViewOverlayLandscapeMode.Start
  }
}

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


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


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

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

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);
  }
}

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

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);
  }
};

const onRequestStream = (id: string) => {
  console.log("onRequestStream id=" + id)
  createEventSession(id)
}

const onLBarStateChanged = (slideX: number, slideY: number) => {
  console.log("onLBarStateChanged slideX=" + slideX + " slideY=" + slideY)
  setLbarState(new LBarState(slideX, slideY));
}

const onRequestAudioDucking = (level: number) => {
  console.log("onRequestAudioDucking level=" + level)
}

const onDisableAudioDucking = () => {
  console.log("onDisableAudioDucking")
}
   


 return (
        <SafeAreaView style={{...styles.container, marginTop: insets.top }}  edges={['top']}>
            {(isPortrait) &&
                <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 && 
                <StreamLayerView
                    style={StyleSheet.absoluteFillObject}
                    ref={viewRef}
                    config={viewConfig}
                    applyWindowInsets={false}
                    onRequestStream={onRequestStream}
                    onLBarStateChanged={onLBarStateChanged}
                    onRequestAudioDucking={onRequestAudioDucking}
                    onDisableAudioDucking={onDisableAudioDucking}
                    player={streamLayerViewPlayer}
                    playerView={
                        <THEOplayerView config={playerConfig} onPlayerReady={onReady}
                            style={{
                                width: Dimensions.get('screen').width - lbarState.slideX,
                                height: playerHeight-lbarState.slideY,
                                paddingTop: 0,
                            }}>
                            {player !== undefined && (
                                <UiContainer
                                    theme={DEFAULT_THEOPLAYER_THEME}
                                    player={player}
                                    center={
                                        <CenteredControlBar
                                            left={<SkipButton skip={-10} />}
                                            middle={<PlayButton />}
                                            right={<SkipButton skip={10} />}
                                        />
                                    }
                                />
                            )}
                        </THEOplayerView>
                    }
                />
            }

        </SafeAreaView>
    )


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,
    }
});

Related