AgoraIO-Community / AgoraWebSDK-NG

The Next Generation of Agora Web SDK
https://agoraio-community.github.io/AgoraWebSDK-NG/
161 stars 74 forks source link

API difference between `react-native-agora` and web SDK #126

Closed Invertisment closed 3 years ago

Invertisment commented 3 years ago

Hi. I'm trying to create an application front-end that would share as much code between react-native and web parts. I have an issue regarding integration of the APIs. I wouldn't have this issue if I'd have two different codebases and two different projects but I want to have as much overlap as possible.

I'm trying to use both: native and web SDKs but the API is too different to do it efficiently.

For instance if I'd want to subscribe to and display some kind of video stream. But both SDKs do it in a radically different way:

react-native-agora: https://github.com/AgoraIO-Community/react-native-agora/blob/master/example/src/examples/basic/JoinChannelVideo.tsx#L162

        <RtcLocalView.SurfaceView
          style={styles.max}
          channelId={channelName}
          renderMode={VideoRenderMode.Hidden}
        />

React-native way is what I'd prefer and it plays nice with the app. It destroys the element as react would expect and probably even subscriptions could be handled this way.

agora-rtc-sdk-ng: https://github.com/AgoraIO-Community/AgoraWebSDK-NG/blob/master/Demo/basicVideoCall/basicVideoCall.js#L116

    user.videoTrack.play(`player-${uid}`);

I understand that it's very straightforward to have a web container which would be used to display some content. But there is an issue if I want to use it in a react application. There is no way to extract the video track without this callback. There is no way to display it without using the "user-joined" callback. And if there is no way to do it it's not usable in react apps in general.

Is there any way for the web SDK to specify the stream's user ID so that I'd be able to use it in the same way as in react-native-agora? I'd like to have a method for which I'd pass the channel's ID and my own container's ID and it would display the stream. Is this possible? It has to be a trivial thing to do. It's fine if the container would need to get appId and token too. It would work.

Invertisment commented 3 years ago

Also types in native sdk say that UserJoined callback is this: (uid: number, elapsed: number) => void

But types in this SDK say that user-joined callback should be this kind of type:

declare function event_user_joined(user: IAgoraRTCRemoteUser): void;

where IAgoraRTCRemoteUser is:

export declare interface IAgoraRTCRemoteUser {
    /**
     * The ID of the remote user.
     */
    uid: UID;

and export declare type UID = number | string;

So one SDK says it's strictly number and the other says it can be number | string. TypeScript is not happy about this. Should I parse the result or what? I don't know what should I do. IMO I'd use string as it's a safer type to use between programming languages but it's not allowed to be used in one of the projects. I have no idea what is the use of the numeric identifier.

I don't want to use a number because if I have a react native project then the integer may get parsed into a native integer. So if it's parsed on Android then Ints have 32bit of width: https://developer.android.com/reference/java/lang/Integer I don't know how these IDs are generated but the types don't match and I don't know a good way around it.

HAHAHA44 commented 3 years ago

Hi. I'm trying to create an application front-end that would share as much code between react-native and web parts. I have an issue regarding integration of the APIs. I wouldn't have this issue if I'd have two different codebases and two different projects but I want to have as much overlap as possible.

I'm trying to use both: native and web SDKs but the API is too different to do it efficiently.

For instance if I'd want to subscribe to and display some kind of video stream. But both SDKs do it in a radically different way:

react-native-agora: https://github.com/AgoraIO-Community/react-native-agora/blob/master/example/src/examples/basic/JoinChannelVideo.tsx#L162

        <RtcLocalView.SurfaceView
          style={styles.max}
          channelId={channelName}
          renderMode={VideoRenderMode.Hidden}
        />

React-native way is what I'd prefer and it plays nice with the app. It destroys the element as react would expect and probably even subscriptions could be handled this way.

agora-rtc-sdk-ng: https://github.com/AgoraIO-Community/AgoraWebSDK-NG/blob/master/Demo/basicVideoCall/basicVideoCall.js#L116

    user.videoTrack.play(`player-${uid}`);

I understand that it's very straightforward to have a web container which would be used to display some content. But there is an issue if I want to use it in a react application. There is no way to extract the video track without this callback. There is no way to display it without using the "user-joined" callback. And if there is no way to do it it's not usable in react apps in general.

Is there any way for the web SDK to specify the stream's user ID so that I'd be able to use it in the same way as in react-native-agora? I'd like to have a method for which I'd pass the channel's ID and my own container's ID and it would display the stream. Is this possible? It has to be a trivial thing to do. It's fine if the container would need to get appId and token too. It would work.

I think that share the code of using web sdk and react-native sdk is not a good choice. They are different product with the different design. Web sdk is design for vanilla js or ts developer to adapt to each front-end framework, and RN sdk is just for react native framework for cross-platform development. Of course you can write a glue layer to adapt to two SDKs, but I think it is better to write two projects to using two sdk, and they have the same interface for your Generic UI layer or custom layer to use.

RN SDK ----> RN SDK Access Layer  \
                                                                  \    -----> Generic Logic
                                                                    /
Web SDK ----> Web SDK Access Layer /

Access Layers have the same Interface.

Invertisment commented 3 years ago

I did it. It's not pretty and it won't be very pretty. But it works. At least I don't need to maintain two sources.