From a0e4a70dd1be8407327d9a758d9a97e99754062a Mon Sep 17 00:00:00 2001 From: gxz Date: Mon, 20 Nov 2023 16:34:24 +0800 Subject: [PATCH 1/7] ci: ci config --- .github/workflows/build.yml | 25 +++++++++++++---------- .github/workflows/dep.yml | 37 +++++++++++++++++++++++++++++++++- .github/workflows/doc.yml | 2 +- .github/workflows/gitleaks.yml | 4 ++-- .github/workflows/publish.yml | 2 +- .github/workflows/terra.yml | 4 ++-- .github/workflows/typedoc.yml | 2 +- 7 files changed, 57 insertions(+), 19 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9690027..44e599f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -18,7 +18,7 @@ jobs: turbo_cache_hit: 0 steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Setup uses: ./.github/actions/setup @@ -66,6 +66,7 @@ jobs: run: | sed "s/localAppId = '\(.*\)'/localAppId = '${{ secrets.APP_ID }}'/g" agora.config.ts > tmp mv tmp agora.config.ts + cat agora.config.ts working-directory: example/src/config - name: Build example for Android @@ -78,6 +79,7 @@ jobs: name: AgoraRtmNgExample path: | example/android/app/build/outputs/apk/release/*.apk + if-no-files-found: error build-ios: if: ${{ contains(github.event.pull_request.labels.*.name, 'ci:dep-update') }} @@ -87,15 +89,14 @@ jobs: turbo_cache_hit: 0 steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Setup uses: ./.github/actions/setup - - name: Setup cocoapods + - name: Setup fastlane run: | - gem install cocoapods -v 1.13.0 - gem install activesupport -v 7.0.8 + brew install fastlane - name: Cache turborepo for iOS uses: actions/cache@v3 @@ -174,6 +175,7 @@ jobs: name: AgoraRtmNgExample path: | example/ios/*.ipa + if-no-files-found: error - name: Upload dSYM uses: actions/upload-artifact@v3 @@ -181,10 +183,11 @@ jobs: name: AgoraRtmNgExampleSymbol path: | example/ios/*.dSYM.zip + if-no-files-found: error - # notification: - # runs-on: ubuntu-latest - # needs: [ build-android, build-ios ] - # steps: - # - run: | - # curl -X POST "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=${{ secrets.WECHAT_KEY }}" -d '{"msgtype":"text","text":{"content":"ReactNative:\n${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"}}' + notification: + runs-on: ubuntu-latest + needs: [build-android, build-ios] + steps: + - run: | + curl -X POST "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=${{ secrets.WECHAT_KEY }}" -d '{"msgtype":"text","text":{"content":"[RTM]ReactNative Example:\n${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}\nDownload Link:\nhttps://nightly.link/${{ github.repository }}/actions/runs/${{ github.run_id }}"}}' diff --git a/.github/workflows/dep.yml b/.github/workflows/dep.yml index 2243a22..c7d8998 100644 --- a/.github/workflows/dep.yml +++ b/.github/workflows/dep.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Setup uses: ./.github/actions/setup @@ -46,3 +46,38 @@ jobs: Dependencies content: ${{ steps.dep.outputs.matches }} + + update-pod: + runs-on: macos-latest + needs: update-dependencies + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + ref: ${{ github.ref_name }}-dep-update + token: ${{ secrets.GH_TOKEN }} + + - name: Setup + uses: ./.github/actions/setup + + - name: Cache cocoapods + id: cocoapods-cache + uses: actions/cache@v3 + with: + path: | + **/ios/Pods + key: ${{ runner.os }}-cocoapods-0-${{ hashFiles('example/ios/Podfile.lock') }} + restore-keys: | + ${{ runner.os }}-cocoapods-0- + - name: Update Podfile.lock + run: | + pod update + working-directory: example/ios + + - name: Commit changes + run: | + git config --global user.email "${{ secrets.GIT_EMAIL }}" + git config --global user.name "${{ secrets.GIT_USERNAME }}" + git add example + git commit -m "chore(example): update Podfile.lock by new dependencies" + git push diff --git a/.github/workflows/doc.yml b/.github/workflows/doc.yml index ff17564..ef14899 100644 --- a/.github/workflows/doc.yml +++ b/.github/workflows/doc.yml @@ -8,7 +8,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Setup uses: ./.github/actions/setup diff --git a/.github/workflows/gitleaks.yml b/.github/workflows/gitleaks.yml index dc9efd4..b1192e0 100644 --- a/.github/workflows/gitleaks.yml +++ b/.github/workflows/gitleaks.yml @@ -5,14 +5,14 @@ on: push: workflow_dispatch: schedule: - - cron: "0 4 * * *" # run once a day at 4 AM + - cron: '0 4 * * *' # run once a day at 4 AM jobs: scan: name: gitleaks runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 - uses: gitleaks/gitleaks-action@v2 diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index e72eccf..1642253 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -19,7 +19,7 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 token: ${{ secrets.GH_TOKEN }} diff --git a/.github/workflows/terra.yml b/.github/workflows/terra.yml index f1f982a..04fc93c 100644 --- a/.github/workflows/terra.yml +++ b/.github/workflows/terra.yml @@ -6,14 +6,14 @@ on: terra-ref: description: The terra repo ref required: true - default: "main" + default: 'main' jobs: generate-codes: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Setup uses: ./.github/actions/setup diff --git a/.github/workflows/typedoc.yml b/.github/workflows/typedoc.yml index 9bb7ac2..c22d0da 100644 --- a/.github/workflows/typedoc.yml +++ b/.github/workflows/typedoc.yml @@ -13,7 +13,7 @@ jobs: environment: github-pages steps: - name: Checkout 🛎️ - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Setup uses: ./.github/actions/setup - name: Build TypeDoc From fb8ef64c8412fb205dc446903e157a3edbe7f2dd Mon Sep 17 00:00:00 2001 From: gxz Date: Mon, 20 Nov 2023 16:46:35 +0800 Subject: [PATCH 2/7] ci: fix --- .github/workflows/build.yml | 1 - example/src/config/agora.config.ts | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 44e599f..584bc9a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -66,7 +66,6 @@ jobs: run: | sed "s/localAppId = '\(.*\)'/localAppId = '${{ secrets.APP_ID }}'/g" agora.config.ts > tmp mv tmp agora.config.ts - cat agora.config.ts working-directory: example/src/config - name: Build example for Android diff --git a/example/src/config/agora.config.ts b/example/src/config/agora.config.ts index d79769b..2bf90e3 100644 --- a/example/src/config/agora.config.ts +++ b/example/src/config/agora.config.ts @@ -2,6 +2,7 @@ let env: any = ''; let localAppId = ''; try { env = require('./env_local').default; + console.log('appID', localAppId); } catch (error) { console.warn(error); } From ee41dca015beddf5ce4929927f9242a6b65dfaf1 Mon Sep 17 00:00:00 2001 From: gxz Date: Mon, 20 Nov 2023 16:48:12 +0800 Subject: [PATCH 3/7] ci: fix --- example/src/basic/Login/index.tsx | 1 + example/src/config/agora.config.ts | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/example/src/basic/Login/index.tsx b/example/src/basic/Login/index.tsx index f917024..2ac90f2 100644 --- a/example/src/basic/Login/index.tsx +++ b/example/src/basic/Login/index.tsx @@ -18,6 +18,7 @@ import { import Config from '../../config/agora.config'; import { useRtmClient } from '../../hooks/useRtmClient'; import * as log from '../../utils/log'; +console.log(Config); export default function Login() { const [uid, setUid] = useState(Config.uid); diff --git a/example/src/config/agora.config.ts b/example/src/config/agora.config.ts index 2bf90e3..4c4b26e 100644 --- a/example/src/config/agora.config.ts +++ b/example/src/config/agora.config.ts @@ -6,7 +6,7 @@ try { } catch (error) { console.warn(error); } - +console.log(env); const config = { // Get your own App ID at https://dashboard.agora.io/ appId: localAppId || env.appId, From d341fd9a2b85f37a33c4fb8d76d314b9c036be1a Mon Sep 17 00:00:00 2001 From: gxz Date: Mon, 20 Nov 2023 16:55:51 +0800 Subject: [PATCH 4/7] ci: fix --- example/src/basic/Login/index.tsx | 2 +- example/src/config/agora.config.ts | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/example/src/basic/Login/index.tsx b/example/src/basic/Login/index.tsx index 2ac90f2..fb94c42 100644 --- a/example/src/basic/Login/index.tsx +++ b/example/src/basic/Login/index.tsx @@ -18,7 +18,7 @@ import { import Config from '../../config/agora.config'; import { useRtmClient } from '../../hooks/useRtmClient'; import * as log from '../../utils/log'; -console.log(Config); +log.alert(JSON.stringify(Config)); export default function Login() { const [uid, setUid] = useState(Config.uid); diff --git a/example/src/config/agora.config.ts b/example/src/config/agora.config.ts index 4c4b26e..9bc1ef2 100644 --- a/example/src/config/agora.config.ts +++ b/example/src/config/agora.config.ts @@ -1,12 +1,15 @@ +import * as log from '../utils/log'; + let env: any = ''; let localAppId = ''; try { env = require('./env_local').default; - console.log('appID', localAppId); } catch (error) { console.warn(error); } -console.log(env); +log.alert(JSON.stringify(env)); +log.alert(localAppId); + const config = { // Get your own App ID at https://dashboard.agora.io/ appId: localAppId || env.appId, From dcb23d595310c343e75a4f151f45f96b779b3a1c Mon Sep 17 00:00:00 2001 From: gxz Date: Mon, 20 Nov 2023 17:16:43 +0800 Subject: [PATCH 5/7] ci: fix --- .github/workflows/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 584bc9a..c0912c7 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -64,7 +64,7 @@ jobs: - name: Modify APP ID run: | - sed "s/localAppId = '\(.*\)'/localAppId = '${{ secrets.APP_ID }}'/g" agora.config.ts > tmp + sed "s/localAppId = '\(.*\)'/localAppId = '33'/g" agora.config.ts > tmp mv tmp agora.config.ts working-directory: example/src/config @@ -81,7 +81,7 @@ jobs: if-no-files-found: error build-ios: - if: ${{ contains(github.event.pull_request.labels.*.name, 'ci:dep-update') }} + # if: ${{ contains(github.event.pull_request.labels.*.name, 'ci:dep-update') }} runs-on: macos-latest env: TURBO_CACHE_DIR: .turbo/ios From 8b866f9979117504b89186b401dd73bb66c0617a Mon Sep 17 00:00:00 2001 From: gxz Date: Mon, 20 Nov 2023 17:18:37 +0800 Subject: [PATCH 6/7] ci: fix --- .github/workflows/build.yml | 2 +- example/src/basic/Login/index.tsx | 1 - example/src/config/agora.config.ts | 4 ---- 3 files changed, 1 insertion(+), 6 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c0912c7..db0d69d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -64,7 +64,7 @@ jobs: - name: Modify APP ID run: | - sed "s/localAppId = '\(.*\)'/localAppId = '33'/g" agora.config.ts > tmp + sed "s/localAppId = '\(.*\)'/localAppId = '${{ secrets.APP_ID }}'/g" agora.config.ts > tmp mv tmp agora.config.ts working-directory: example/src/config diff --git a/example/src/basic/Login/index.tsx b/example/src/basic/Login/index.tsx index fb94c42..f917024 100644 --- a/example/src/basic/Login/index.tsx +++ b/example/src/basic/Login/index.tsx @@ -18,7 +18,6 @@ import { import Config from '../../config/agora.config'; import { useRtmClient } from '../../hooks/useRtmClient'; import * as log from '../../utils/log'; -log.alert(JSON.stringify(Config)); export default function Login() { const [uid, setUid] = useState(Config.uid); diff --git a/example/src/config/agora.config.ts b/example/src/config/agora.config.ts index 9bc1ef2..d79769b 100644 --- a/example/src/config/agora.config.ts +++ b/example/src/config/agora.config.ts @@ -1,5 +1,3 @@ -import * as log from '../utils/log'; - let env: any = ''; let localAppId = ''; try { @@ -7,8 +5,6 @@ try { } catch (error) { console.warn(error); } -log.alert(JSON.stringify(env)); -log.alert(localAppId); const config = { // Get your own App ID at https://dashboard.agora.io/ From 4f71b1f0db0727510e0951783e4196cb964669cc Mon Sep 17 00:00:00 2001 From: gxz Date: Tue, 21 Nov 2023 14:12:22 +0800 Subject: [PATCH 7/7] feat(example): Presence --- example/src/advanced/Presence/index.tsx | 394 ++++++++++++------ example/src/advanced/index.ts | 5 + example/src/basic/Login/index.tsx | 7 +- .../src/basic/createStreamChannel/index.tsx | 6 +- example/src/components/BaseComponent.tsx | 12 +- example/src/components/ui/index.tsx | 14 +- .../config/impl_special_return_list.json | 28 ++ scripts/terra/config/param_type_list.json | 1 + scripts/terra/impl.ts | 8 + .../templates/impl/file_content.mustache | 2 +- src/IAgoraRtmClient.ts | 2 +- src/impl/IAgoraRtmClientImpl.ts | 6 +- src/impl/IAgoraRtmLockImpl.ts | 12 +- src/impl/IAgoraRtmPresenceImpl.ts | 10 +- src/impl/IAgoraRtmStorageImpl.ts | 18 +- src/impl/IAgoraStreamChannelImpl.ts | 8 +- src/internal/RtmClientInternal.ts | 6 + src/internal/RtmPresence.ts | 7 + 18 files changed, 386 insertions(+), 160 deletions(-) create mode 100644 scripts/terra/config/impl_special_return_list.json create mode 100644 src/internal/RtmPresence.ts diff --git a/example/src/advanced/Presence/index.tsx b/example/src/advanced/Presence/index.tsx index ff3fba8..801b15f 100644 --- a/example/src/advanced/Presence/index.tsx +++ b/example/src/advanced/Presence/index.tsx @@ -1,35 +1,43 @@ -import { Buffer } from 'buffer'; - import { - MessageEvent, + ChannelInfo, PresenceEvent, - PublishOptions, + PresenceOptions, + RTM_CHANNEL_TYPE, RTM_CONNECTION_CHANGE_REASON, RTM_CONNECTION_STATE, RTM_ERROR_CODE, - RTM_MESSAGE_TYPE, - StorageEvent, + StateItem, + UserState, } from 'agora-react-native-rtm'; -import React, { useCallback, useEffect, useState } from 'react'; -import { GiftedChat } from 'react-native-gifted-chat'; +import React, { useCallback, useEffect, useRef, useState } from 'react'; + +import { ScrollView } from 'react-native'; import BaseComponent from '../../components/BaseComponent'; -import { AgoraButton, AgoraStyle, AgoraView } from '../../components/ui'; +import { + AgoraButton, + AgoraDropdown, + AgoraStyle, + AgoraTextInput, +} from '../../components/ui'; import Config from '../../config/agora.config'; import { useRtmClient } from '../../hooks/useRtmClient'; +import { arrayToItems } from '../../utils'; import * as log from '../../utils/log'; -export default function PublishMessage() { +export default function Presence() { const [loginSuccess, setLoginSuccess] = useState(false); const [subscribeSuccess, setSubscribeSuccess] = useState(false); - const [publishMessageByBuffer, setPublishMessageByBuffer] = useState(false); + const whoNowRequestId = useRef(); + const whereNowRequestId = useRef(); + const setStateRequestId = useRef(); + const getStateRequestId = useRef(); + const removeStateRequestId = useRef(); const [cName, setCName] = useState(Config.channelName); const [uid, setUid] = useState(Config.uid); - const [messages, setMessages] = useState([]); - - const onStorageEvent = useCallback((event: StorageEvent) => { - log.log('onStorageEvent', 'event', event); - }, []); + const [searchUid, setSearchUid] = useState(Config.uid); + const [feeling, setFeeling] = useState('happy'); + const [location, setLocation] = useState('tokyo'); const onSubscribeResult = useCallback( (requestId: number, channelName: string, errorCode: RTM_ERROR_CODE) => { @@ -47,101 +55,133 @@ export default function PublishMessage() { [] ); - const onPresenceEvent = useCallback((event: PresenceEvent) => { - log.log('onPresenceEvent', 'event', event); - }, []); - - const onPublishResult = useCallback( - (requestId: number, errorCode: RTM_ERROR_CODE) => { + const onWhoNowResult = useCallback( + ( + requestId: number, + userStateList: UserState[], + count: number, + nextPage: string, + errorCode: RTM_ERROR_CODE + ) => { log.log( - 'onPublishResult', + 'onWhoNowResult', 'requestId', requestId, + 'userStateList', + userStateList, + 'count', + count, + 'nextPage', + nextPage, 'errorCode', errorCode ); + if ( + requestId === whoNowRequestId.current && + errorCode === RTM_ERROR_CODE.RTM_ERROR_OK + ) { + log.alert( + `channel: ${cName} status`, + `${JSON.stringify(userStateList)}` + ); + } }, - [] + [cName] ); - const onMessageEvent = useCallback( - (event: MessageEvent) => { - log.log('onMessageEvent', 'event', event); - setMessages((prevState) => - GiftedChat.append(prevState, [ - { - _id: +new Date(), - text: event.message, - user: { - _id: +new Date(), - name: event.publisher || uid.slice(-1), - }, - createdAt: new Date(), - }, - ]) + const onWhereNowResult = useCallback( + ( + requestId: number, + channels: ChannelInfo[], + count: number, + errorCode: RTM_ERROR_CODE + ) => { + log.log( + 'onWhereNowResult', + 'requestId', + requestId, + 'channels', + channels, + 'count', + count, + 'errorCode', + errorCode ); + if ( + requestId === whereNowRequestId.current && + errorCode === RTM_ERROR_CODE.RTM_ERROR_OK + ) { + log.alert(`${searchUid} is at`, `${JSON.stringify(channels)}`); + } }, - [uid] + [searchUid] ); - /** - * Step 1: getRtmClient and initialize rtm client from BaseComponent - */ - const client = useRtmClient(); - - /** - * Step 2 : publish message to message channel - */ - const publish = useCallback( - (msg: string, msgs: any) => { - let result: number | undefined; - if (publishMessageByBuffer) { - result = client.publishWithBuffer( - cName, - Buffer.from(msg), - msg.length, - new PublishOptions({ - type: RTM_MESSAGE_TYPE.RTM_MESSAGE_TYPE_BINARY, - }) - ); - } else { - result = client.publish( - cName, - msg, - msg.length, - new PublishOptions({ - type: RTM_MESSAGE_TYPE.RTM_MESSAGE_TYPE_STRING, - }) - ); - } - - if (result !== RTM_ERROR_CODE.RTM_ERROR_OK) { - log.error('CHANNEL_INVALID_MESSAGE', result); - } else { - setMessages((previousMessages) => - GiftedChat.append(previousMessages, msgs) - ); + const onPresenceSetStateResult = useCallback( + (requestId: number, errorCode: RTM_ERROR_CODE) => { + log.log( + 'onPresenceSetStateResult', + 'requestId', + requestId, + 'errorCode', + errorCode + ); + if ( + requestId === setStateRequestId.current && + errorCode === RTM_ERROR_CODE.RTM_ERROR_OK + ) { + // log.alert(`${uid} state:`, `${JSON.stringify(state)}`); + // setUserState(state); } }, - [cName, client, publishMessageByBuffer] + [] ); - const onSend = useCallback( - (msgs = []) => { - if (!loginSuccess) { - log.error('please login first'); - return; + const onPresenceGetStateResult = useCallback( + (requestId: number, state: UserState, errorCode: RTM_ERROR_CODE) => { + log.log( + 'onPresenceGetStateResult', + 'requestId', + requestId, + 'state', + state, + 'errorCode', + errorCode + ); + if ( + requestId === getStateRequestId.current && + errorCode === RTM_ERROR_CODE.RTM_ERROR_OK + ) { + log.alert(`${uid} state:`, `${JSON.stringify(state)}`); } + }, + [uid] + ); - msgs.forEach((message: any) => { - publish(message.text, msgs); - }); + const onPresenceRemoveStateResult = useCallback( + (requestId: number, errorCode: RTM_ERROR_CODE) => { + log.log( + 'onPresenceRemoveStateResult', + 'requestId', + requestId, + 'errorCode', + errorCode + ); }, - [loginSuccess, publish] + [] ); + const onPresenceEvent = useCallback((event: PresenceEvent) => { + log.log('onPresenceEvent', 'event', event); + }, []); + + /** + * Step 1: getRtmClient and initialize rtm client from BaseComponent + */ + const client = useRtmClient(); + /** - * Step 3(optional) : subscribe message channel + * Step 1-1(optional) : subscribe message channel */ const subscribe = () => { client.subscribe(Config.channelName, { @@ -152,35 +192,119 @@ export default function PublishMessage() { }; /** - * Step 4 : unsubscribe message channel + * Step 1-1 : unsubscribe message channel */ const unsubscribe = () => { client.unsubscribe(Config.channelName); setSubscribeSuccess(false); }; + /** + * Step 2 : whoNow + */ + const whoNow = () => { + whoNowRequestId.current = client + .getPresence() + .whoNow( + cName, + RTM_CHANNEL_TYPE.RTM_CHANNEL_TYPE_MESSAGE, + new PresenceOptions({ includeState: true, includeUserId: true }) + ); + }; + + /** + * Step 3 : whereNow + */ + const whereNow = () => { + whereNowRequestId.current = client.getPresence().whereNow(searchUid); + }; + + /** + * Step 4 : setState + */ + const setState = () => { + setStateRequestId.current = client + .getPresence() + .setState( + cName, + RTM_CHANNEL_TYPE.RTM_CHANNEL_TYPE_MESSAGE, + [ + new StateItem({ key: 'feeling', value: feeling }), + new StateItem({ key: 'location', value: location }), + ], + 1 + ); + }; + + /** + * Step 5 : getState + */ + const getState = () => { + getStateRequestId.current = client + .getPresence() + .getState(cName, RTM_CHANNEL_TYPE.RTM_CHANNEL_TYPE_MESSAGE, uid); + }; + + /** + * Step 6 : removeState + */ + const removeState = () => { + removeStateRequestId.current = client + .getPresence() + .removeState( + cName, + RTM_CHANNEL_TYPE.RTM_CHANNEL_TYPE_MESSAGE, + ['feeling', 'location'], + 1 + ); + }; + useEffect(() => { - client.addEventListener('onStorageEvent', onStorageEvent); client.addEventListener('onSubscribeResult', onSubscribeResult); + client.addEventListener('onWhoNowResult', onWhoNowResult); + client.addEventListener('onWhereNowResult', onWhereNowResult); + client.addEventListener( + 'onPresenceSetStateResult', + onPresenceSetStateResult + ); + client.addEventListener( + 'onPresenceGetStateResult', + onPresenceGetStateResult + ); + client.addEventListener( + 'onPresenceRemoveStateResult', + onPresenceRemoveStateResult + ); client.addEventListener('onPresenceEvent', onPresenceEvent); - client.addEventListener('onMessageEvent', onMessageEvent); - client.addEventListener('onPublishResult', onPublishResult); return () => { - client.removeEventListener('onStorageEvent', onStorageEvent); client.removeEventListener('onSubscribeResult', onSubscribeResult); + client.removeEventListener('onWhoNowResult', onWhoNowResult); + client.removeEventListener('onWhereNowResult', onWhereNowResult); + client.removeEventListener( + 'onPresenceSetStateResult', + onPresenceSetStateResult + ); + client.removeEventListener( + 'onPresenceGetStateResult', + onPresenceGetStateResult + ); + client.removeEventListener( + 'onPresenceRemoveStateResult', + onPresenceRemoveStateResult + ); client.removeEventListener('onPresenceEvent', onPresenceEvent); - client.removeEventListener('onMessageEvent', onMessageEvent); - client.removeEventListener('onPublishResult', onPublishResult); }; }, [ client, uid, - onStorageEvent, onSubscribeResult, + onWhoNowResult, + onWhereNowResult, + onPresenceSetStateResult, + onPresenceGetStateResult, + onPresenceRemoveStateResult, onPresenceEvent, - onMessageEvent, - onPublishResult, ]); const onConnectionStateChanged = useCallback( @@ -230,7 +354,7 @@ export default function PublishMessage() { return ( <> - + setCName(v)} onUidChanged={(v) => setUid(v)} @@ -242,23 +366,61 @@ export default function PublishMessage() { subscribeSuccess ? unsubscribe() : subscribe(); }} /> - - { - setPublishMessageByBuffer((v) => !v); - }} - /> - onSend(v)} - user={{ - _id: uid, - }} - /> + { + whoNow(); + }} + /> + { + setSearchUid(text); + }} + label="what uid you want to find" + value={searchUid} + /> + { + whereNow(); + }} + /> + + { + setLocation(value); + }} + /> + { + setFeeling(text); + }} + label="How do you feel now?" + value={feeling} + /> + { + setState(); + }} + /> + { + getState(); + }} + /> + { + removeState(); + }} + /> + ); } diff --git a/example/src/advanced/index.ts b/example/src/advanced/index.ts index c21a584..06ba9ce 100644 --- a/example/src/advanced/index.ts +++ b/example/src/advanced/index.ts @@ -1,3 +1,4 @@ +import Presence from './Presence'; import PublishMessage from './publishMessage'; import PublishTopicMessage from './publishTopicMessage'; @@ -12,6 +13,10 @@ const Advanced = { name: 'PublishTopicMessage', component: PublishTopicMessage, }, + { + name: 'Presence', + component: Presence, + }, ], }; export default Advanced; diff --git a/example/src/basic/Login/index.tsx b/example/src/basic/Login/index.tsx index f917024..c2b409b 100644 --- a/example/src/basic/Login/index.tsx +++ b/example/src/basic/Login/index.tsx @@ -6,14 +6,13 @@ import { } from 'agora-react-native-rtm'; import React, { useCallback, useEffect, useState } from 'react'; -import { KeyboardAvoidingView, Platform } from 'react-native'; +import { KeyboardAvoidingView, Platform, ScrollView } from 'react-native'; import { AgoraButton, AgoraStyle, AgoraText, AgoraTextInput, - AgoraView, } from '../../components/ui'; import Config from '../../config/agora.config'; import { useRtmClient } from '../../hooks/useRtmClient'; @@ -110,7 +109,7 @@ export default function Login() { style={AgoraStyle.fullSize} behavior={Platform.OS === 'ios' ? 'padding' : 'height'} > - + {loginSuccess ? ( {`current login userId:\n${uid}`} ) : ( @@ -129,7 +128,7 @@ export default function Login() { loginSuccess ? logout() : login(); }} /> - + ); } diff --git a/example/src/basic/createStreamChannel/index.tsx b/example/src/basic/createStreamChannel/index.tsx index 7e74830..28f2372 100644 --- a/example/src/basic/createStreamChannel/index.tsx +++ b/example/src/basic/createStreamChannel/index.tsx @@ -7,7 +7,7 @@ import { } from 'agora-react-native-rtm'; import React, { useCallback, useEffect, useState } from 'react'; -import { KeyboardAvoidingView, Platform } from 'react-native'; +import { KeyboardAvoidingView, Platform, ScrollView } from 'react-native'; import BaseComponent from '../../components/BaseComponent'; import { AgoraButton, AgoraStyle, AgoraView } from '../../components/ui'; @@ -178,7 +178,7 @@ export default function CreateStreamChannel() { style={AgoraStyle.fullSize} behavior={Platform.OS === 'ios' ? 'padding' : 'height'} > - + setCName(v)} onUidChanged={(v) => setUid(v)} @@ -208,7 +208,7 @@ export default function CreateStreamChannel() { } }} /> - + ); } diff --git a/example/src/components/BaseComponent.tsx b/example/src/components/BaseComponent.tsx index 5c916dd..b1e55ee 100644 --- a/example/src/components/BaseComponent.tsx +++ b/example/src/components/BaseComponent.tsx @@ -1,4 +1,4 @@ -import { RTM_ERROR_CODE } from 'agora-react-native-rtm'; +import { RTM_ERROR_CODE, RtmConfig } from 'agora-react-native-rtm'; import React, { useCallback, useEffect, useState } from 'react'; import Config from '../config/agora.config'; @@ -37,10 +37,12 @@ export default function BaseComponent({ if (!uid || uid.length === 0) { return; } - client.initialize({ - userId: uid, - appId: Config.appId, - }); + client.initialize( + new RtmConfig({ + userId: uid, + appId: Config.appId, + }) + ); return () => { setLoginSuccess(false); diff --git a/example/src/components/ui/index.tsx b/example/src/components/ui/index.tsx index 597b6b4..e5b656b 100644 --- a/example/src/components/ui/index.tsx +++ b/example/src/components/ui/index.tsx @@ -66,7 +66,7 @@ export const AgoraButton = (props: ButtonProps) => { export const AgoraDivider = (props: DividerProps) => { return ( <> - + ); }; @@ -197,7 +197,8 @@ export const AgoraCard = ( export interface AgoraDropdownItem extends Item {} export const AgoraDropdown = ( - props: PickerSelectProps & PickerProps & { title: string } + props: PickerSelectProps & + PickerProps & { title: string; titleStyle?: TextProps['style'] } ) => { const [value, setValue] = useState(props.value); @@ -207,7 +208,7 @@ export const AgoraDropdown = ( return ( - + ": "$1", "^util::(.*)": "$1", "^agora::(.*)": "$1", diff --git a/scripts/terra/impl.ts b/scripts/terra/impl.ts index b59a854..cdb0045 100644 --- a/scripts/terra/impl.ts +++ b/scripts/terra/impl.ts @@ -12,6 +12,7 @@ import { isMatch, } from './utils'; +const implSpecialReturnList = require('./config/impl_special_return_list.json'); const paramOptionalList = require('./config/param_optional_list.json'); interface CXXFileUserData { @@ -31,6 +32,7 @@ interface ClazzMethodUserData { hasParameters: boolean; bindingFunctionName?: string; bindingIrisKey?: string; + returnParamName?: string; } export function impl(parseResult: ParseResult) { @@ -65,6 +67,12 @@ export function impl(parseResult: ParseResult) { bindingFunctionName: `getApiTypeFrom${ method.name.charAt(0).toUpperCase() + method.name.slice(1) }`, + returnParamName: + method.parameters.filter((param) => { + return param.name === implSpecialReturnList[method.fullName]; + }).length > 0 + ? implSpecialReturnList[method.fullName] + : 'result', bindingIrisKey: `${node.asClazz().name.slice(1)}_${method.name}`, }; method.user_data = clazzMethodUserData; diff --git a/scripts/terra/templates/impl/file_content.mustache b/scripts/terra/templates/impl/file_content.mustache index ed718f8..4abd191 100644 --- a/scripts/terra/templates/impl/file_content.mustache +++ b/scripts/terra/templates/impl/file_content.mustache @@ -43,7 +43,7 @@ export class {{name}}Impl implements {{name}}{ {{/user_data.hasParameters}} }; const jsonResults = callIrisApi.call(this, apiType, jsonParams); - return jsonResults.result; + return jsonResults.{{user_data.returnParamName}}; } protected {{user_data.bindingFunctionName}}(): string { diff --git a/src/IAgoraRtmClient.ts b/src/IAgoraRtmClient.ts index 111467a..ad79f5c 100644 --- a/src/IAgoraRtmClient.ts +++ b/src/IAgoraRtmClient.ts @@ -415,7 +415,7 @@ export abstract class IRtmClient { abstract logout(): number; abstract getStorage(): IRtmStorage[]; abstract getLock(): IRtmLock[]; - abstract getPresence(): IRtmPresence[]; + abstract getPresence(): IRtmPresence; abstract renewToken(token: string): number; abstract publish( channelName: string, diff --git a/src/impl/IAgoraRtmClientImpl.ts b/src/impl/IAgoraRtmClientImpl.ts index 7f9c04f..67af63e 100644 --- a/src/impl/IAgoraRtmClientImpl.ts +++ b/src/impl/IAgoraRtmClientImpl.ts @@ -436,7 +436,7 @@ export class IRtmClientImpl implements IRtmClient { return 'RtmClient_getLock'; } - getPresence(): IRtmPresence[] { + getPresence(): IRtmPresence { const apiType = this.getApiTypeFromGetPresence(); const jsonParams = {}; const jsonResults = callIrisApi.call(this, apiType, jsonParams); @@ -490,7 +490,7 @@ export class IRtmClientImpl implements IRtmClient { }, }; const jsonResults = callIrisApi.call(this, apiType, jsonParams); - return jsonResults.result; + return jsonResults.requestId; } protected getApiTypeFromPublish(): string { @@ -516,7 +516,7 @@ export class IRtmClientImpl implements IRtmClient { }, }; const jsonResults = callIrisApi.call(this, apiType, jsonParams); - return jsonResults.result; + return jsonResults.requestId; } protected getApiTypeFromSubscribe(): string { diff --git a/src/impl/IAgoraRtmLockImpl.ts b/src/impl/IAgoraRtmLockImpl.ts index 1ce1506..909aaee 100644 --- a/src/impl/IAgoraRtmLockImpl.ts +++ b/src/impl/IAgoraRtmLockImpl.ts @@ -31,7 +31,7 @@ export class IRtmLockImpl implements IRtmLock { }, }; const jsonResults = callIrisApi.call(this, apiType, jsonParams); - return jsonResults.result; + return jsonResults.requestId; } protected getApiTypeFromSetLock(): string { @@ -57,7 +57,7 @@ export class IRtmLockImpl implements IRtmLock { }, }; const jsonResults = callIrisApi.call(this, apiType, jsonParams); - return jsonResults.result; + return jsonResults.requestId; } protected getApiTypeFromGetLocks(): string { @@ -86,7 +86,7 @@ export class IRtmLockImpl implements IRtmLock { }, }; const jsonResults = callIrisApi.call(this, apiType, jsonParams); - return jsonResults.result; + return jsonResults.requestId; } protected getApiTypeFromRemoveLock(): string { @@ -118,7 +118,7 @@ export class IRtmLockImpl implements IRtmLock { }, }; const jsonResults = callIrisApi.call(this, apiType, jsonParams); - return jsonResults.result; + return jsonResults.requestId; } protected getApiTypeFromAcquireLock(): string { @@ -147,7 +147,7 @@ export class IRtmLockImpl implements IRtmLock { }, }; const jsonResults = callIrisApi.call(this, apiType, jsonParams); - return jsonResults.result; + return jsonResults.requestId; } protected getApiTypeFromReleaseLock(): string { @@ -179,7 +179,7 @@ export class IRtmLockImpl implements IRtmLock { }, }; const jsonResults = callIrisApi.call(this, apiType, jsonParams); - return jsonResults.result; + return jsonResults.requestId; } protected getApiTypeFromRevokeLock(): string { diff --git a/src/impl/IAgoraRtmPresenceImpl.ts b/src/impl/IAgoraRtmPresenceImpl.ts index 1077fd3..c268a11 100644 --- a/src/impl/IAgoraRtmPresenceImpl.ts +++ b/src/impl/IAgoraRtmPresenceImpl.ts @@ -33,7 +33,7 @@ export class IRtmPresenceImpl implements IRtmPresence { }, }; const jsonResults = callIrisApi.call(this, apiType, jsonParams); - return jsonResults.result; + return jsonResults.requestId; } protected getApiTypeFromWhoNow(): string { @@ -53,7 +53,7 @@ export class IRtmPresenceImpl implements IRtmPresence { }, }; const jsonResults = callIrisApi.call(this, apiType, jsonParams); - return jsonResults.result; + return jsonResults.requestId; } protected getApiTypeFromWhereNow(): string { @@ -85,7 +85,7 @@ export class IRtmPresenceImpl implements IRtmPresence { }, }; const jsonResults = callIrisApi.call(this, apiType, jsonParams); - return jsonResults.result; + return jsonResults.requestId; } protected getApiTypeFromSetState(): string { @@ -117,7 +117,7 @@ export class IRtmPresenceImpl implements IRtmPresence { }, }; const jsonResults = callIrisApi.call(this, apiType, jsonParams); - return jsonResults.result; + return jsonResults.requestId; } protected getApiTypeFromRemoveState(): string { @@ -146,7 +146,7 @@ export class IRtmPresenceImpl implements IRtmPresence { }, }; const jsonResults = callIrisApi.call(this, apiType, jsonParams); - return jsonResults.result; + return jsonResults.requestId; } protected getApiTypeFromGetState(): string { diff --git a/src/impl/IAgoraRtmStorageImpl.ts b/src/impl/IAgoraRtmStorageImpl.ts index f19fda0..89885e2 100644 --- a/src/impl/IAgoraRtmStorageImpl.ts +++ b/src/impl/IAgoraRtmStorageImpl.ts @@ -142,7 +142,7 @@ export class IRtmStorageImpl implements IRtmStorage { }, }; const jsonResults = callIrisApi.call(this, apiType, jsonParams); - return jsonResults.result; + return jsonResults.requestId; } protected getApiTypeFromSetChannelMetadata(): string { @@ -177,7 +177,7 @@ export class IRtmStorageImpl implements IRtmStorage { }, }; const jsonResults = callIrisApi.call(this, apiType, jsonParams); - return jsonResults.result; + return jsonResults.requestId; } protected getApiTypeFromUpdateChannelMetadata(): string { @@ -212,7 +212,7 @@ export class IRtmStorageImpl implements IRtmStorage { }, }; const jsonResults = callIrisApi.call(this, apiType, jsonParams); - return jsonResults.result; + return jsonResults.requestId; } protected getApiTypeFromRemoveChannelMetadata(): string { @@ -238,7 +238,7 @@ export class IRtmStorageImpl implements IRtmStorage { }, }; const jsonResults = callIrisApi.call(this, apiType, jsonParams); - return jsonResults.result; + return jsonResults.requestId; } protected getApiTypeFromGetChannelMetadata(): string { @@ -267,7 +267,7 @@ export class IRtmStorageImpl implements IRtmStorage { }, }; const jsonResults = callIrisApi.call(this, apiType, jsonParams); - return jsonResults.result; + return jsonResults.requestId; } protected getApiTypeFromSetUserMetadata(): string { @@ -296,7 +296,7 @@ export class IRtmStorageImpl implements IRtmStorage { }, }; const jsonResults = callIrisApi.call(this, apiType, jsonParams); - return jsonResults.result; + return jsonResults.requestId; } protected getApiTypeFromUpdateUserMetadata(): string { @@ -325,7 +325,7 @@ export class IRtmStorageImpl implements IRtmStorage { }, }; const jsonResults = callIrisApi.call(this, apiType, jsonParams); - return jsonResults.result; + return jsonResults.requestId; } protected getApiTypeFromRemoveUserMetadata(): string { @@ -345,7 +345,7 @@ export class IRtmStorageImpl implements IRtmStorage { }, }; const jsonResults = callIrisApi.call(this, apiType, jsonParams); - return jsonResults.result; + return jsonResults.requestId; } protected getApiTypeFromGetUserMetadata(): string { @@ -365,7 +365,7 @@ export class IRtmStorageImpl implements IRtmStorage { }, }; const jsonResults = callIrisApi.call(this, apiType, jsonParams); - return jsonResults.result; + return jsonResults.requestId; } protected getApiTypeFromSubscribeUserMetadata(): string { diff --git a/src/impl/IAgoraStreamChannelImpl.ts b/src/impl/IAgoraStreamChannelImpl.ts index b840b29..9ea103e 100644 --- a/src/impl/IAgoraStreamChannelImpl.ts +++ b/src/impl/IAgoraStreamChannelImpl.ts @@ -24,7 +24,7 @@ export class IStreamChannelImpl implements IStreamChannel { }, }; const jsonResults = callIrisApi.call(this, apiType, jsonParams); - return jsonResults.result; + return jsonResults.requestId; } protected getApiTypeFromJoin(): string { @@ -60,7 +60,7 @@ export class IStreamChannelImpl implements IStreamChannel { }, }; const jsonResults = callIrisApi.call(this, apiType, jsonParams); - return jsonResults.result; + return jsonResults.requestId; } protected getApiTypeFromLeave(): string { @@ -97,7 +97,7 @@ export class IStreamChannelImpl implements IStreamChannel { }, }; const jsonResults = callIrisApi.call(this, apiType, jsonParams); - return jsonResults.result; + return jsonResults.requestId; } protected getApiTypeFromJoinTopic(): string { @@ -146,7 +146,7 @@ export class IStreamChannelImpl implements IStreamChannel { }, }; const jsonResults = callIrisApi.call(this, apiType, jsonParams); - return jsonResults.result; + return jsonResults.requestId; } protected getApiTypeFromLeaveTopic(): string { diff --git a/src/internal/RtmClientInternal.ts b/src/internal/RtmClientInternal.ts index 9ec5e8b..b6c6b24 100644 --- a/src/internal/RtmClientInternal.ts +++ b/src/internal/RtmClientInternal.ts @@ -1,7 +1,9 @@ import { IRtmEventHandler } from '../IAgoraRtmClient'; +import { IRtmPresence } from '../IAgoraRtmPresence'; import { IStreamChannel } from '../IAgoraStreamChannel'; import { IRtmClientEvent } from '../extensions/IAgoraRtmClientExtension'; import { IRtmClientImpl } from '../impl/IAgoraRtmClientImpl'; +import { IRtmPresenceImpl } from '../impl/IAgoraRtmPresenceImpl'; import { DeviceEventEmitter, @@ -22,6 +24,10 @@ export class RtmClientInternal extends IRtmClientImpl { return new StreamChannelInternal(channelName); } + override getPresence(): IRtmPresence { + return new IRtmPresenceImpl(); + } + override release(): number { RtmClientInternal._event_handlers = []; this.removeAllListeners(); diff --git a/src/internal/RtmPresence.ts b/src/internal/RtmPresence.ts new file mode 100644 index 0000000..74a5e43 --- /dev/null +++ b/src/internal/RtmPresence.ts @@ -0,0 +1,7 @@ +import { IRtmPresenceImpl } from '../impl/IAgoraRtmPresenceImpl'; + +export class RtmPresenceInternal extends IRtmPresenceImpl { + constructor() { + super(); + } +}