diff --git a/examples/web/package.json b/examples/web/package.json index b223ec7..28ce1e9 100644 --- a/examples/web/package.json +++ b/examples/web/package.json @@ -10,7 +10,7 @@ "preview": "vite preview" }, "dependencies": { - "iot-callkit-web": "~2.1.2", + "iot-callkit-web": "2.1.3-alpha", "@vitejs/plugin-react": "^4.1.0", "antd-mobile": "~5.37.0", "antd-mobile-icons": "~0.3.0", diff --git a/examples/web/src/App.tsx b/examples/web/src/App.tsx index 1051bb6..a809f45 100644 --- a/examples/web/src/App.tsx +++ b/examples/web/src/App.tsx @@ -8,7 +8,7 @@ import defaultSettings from "../src/configs/callkit.config"; import { AuthProvider, useAuth } from "./hooks/useAuth"; import { IotEngineProvider } from "./hooks/useIotEngine"; -import { useLocalStorage } from "./hooks/useLocalStorage"; +import { useSessionStorage } from "./hooks/useSessionStorage"; import Home from "./pages/Home"; import Login from "./pages/Login"; import PersonalCenter from "./pages/PersonalCenter"; @@ -26,7 +26,7 @@ export const ProtectedRoute = ({ children }: { children: React.ReactNode }) => { }; const App = () => { - useLocalStorage("settings", defaultSettings); + useSessionStorage("settings", defaultSettings); const [version, setVersion] = useState<{ version: string | undefined; diff --git a/examples/web/src/configs/callkit.config.ts b/examples/web/src/configs/callkit.config.ts index 5dc3d37..f7700f0 100644 --- a/examples/web/src/configs/callkit.config.ts +++ b/examples/web/src/configs/callkit.config.ts @@ -1,6 +1,6 @@ export default { - appId: "5ea8ad97b4684c798966b99a965beb9a", - authKey: "59a44ef2b37745fe93c6c660f0700184", - secretKey: "65825d8c98b5461291f91726ef9cfb85", + appId: "", + authKey: "", + secretKey: "", region: ["cn"], }; diff --git a/examples/web/src/hooks/useAuth.tsx b/examples/web/src/hooks/useAuth.tsx index 1914b00..210247d 100644 --- a/examples/web/src/hooks/useAuth.tsx +++ b/examples/web/src/hooks/useAuth.tsx @@ -4,12 +4,11 @@ import { useNavigate } from "react-router-dom"; import { ACTIVE_ACCOUNT, BASE_URL_TAIL, fetchAPI, generateBasicAuth } from "../configs/server"; -import { useLocalStorage } from "./useLocalStorage"; +import { useSessionStorage } from "./useSessionStorage"; export interface AuthContextProps { user: User; login: (data: User) => Promise; - logout: () => void; } export interface User { @@ -23,12 +22,11 @@ export interface User { const AuthContext = createContext({ user: {}, login: async () => {}, - logout: () => {}, }); export const AuthProvider = ({ children }: { children: React.ReactNode }) => { - const [user, setUser] = useLocalStorage("user", null); - const [settings] = useLocalStorage("settings", null); + const [user, setUser] = useSessionStorage("user", null); + const [settings] = useSessionStorage("settings", null); const navigate = useNavigate(); useEffect(() => { @@ -38,6 +36,10 @@ export const AuthProvider = ({ children }: { children: React.ReactNode }) => { }, []); const login = async (data: User) => { + if (settings.appId === "") { + Toast.show("please input appid in setting page"); + return; + } const res = await fetchAPI({ url: `${settings.region[0]}${BASE_URL_TAIL}${ACTIVE_ACCOUNT}`, body: { @@ -72,16 +74,10 @@ export const AuthProvider = ({ children }: { children: React.ReactNode }) => { } }; - const logout = () => { - setUser(null); - navigate("/", { replace: true }); - }; - const value = useMemo( () => ({ user, login, - logout, }), [user], ); diff --git a/examples/web/src/hooks/useIotEngine.tsx b/examples/web/src/hooks/useIotEngine.tsx index ca9e72a..0854eb6 100644 --- a/examples/web/src/hooks/useIotEngine.tsx +++ b/examples/web/src/hooks/useIotEngine.tsx @@ -3,7 +3,7 @@ import getAgoraIotEngine, { InitParam } from "iot-callkit-web"; import { createContext, useContext, useEffect, useMemo, useRef } from "react"; import { useAuth } from "./useAuth"; -import { useLocalStorage } from "./useLocalStorage"; +import { useSessionStorage } from "./useSessionStorage"; export interface IotEngineContextProps { iotEngine: IAgoraIotAppSdk; @@ -16,7 +16,7 @@ const IotEngineContext = createContext({ export const IotEngineProvider = ({ children }: { children: React.ReactNode }) => { const { user } = useAuth(); - const [settings] = useLocalStorage("settings", null); + const [settings] = useSessionStorage("settings", null); const iotEngine = useRef(getAgoraIotEngine()); useEffect(() => { if (!user || !settings) { diff --git a/examples/web/src/hooks/useSessionStorage.tsx b/examples/web/src/hooks/useSessionStorage.tsx new file mode 100644 index 0000000..d2fe631 --- /dev/null +++ b/examples/web/src/hooks/useSessionStorage.tsx @@ -0,0 +1,35 @@ +import { useState } from "react"; + +export const useSessionStorage = (keyName: string, defaultValue?: any) => { + const [storedValue, setStoredValue] = useState(() => { + try { + const value = window.sessionStorage.getItem(keyName); + if (value) { + return JSON.parse(value); + } else { + window.sessionStorage.setItem(keyName, JSON.stringify(defaultValue)); + return defaultValue; + } + } catch (err) { + console.log(err); + return defaultValue; + } + }); + const setValue = (newValue: any) => { + try { + window.sessionStorage.setItem(keyName, JSON.stringify(newValue)); + } catch (err) { + console.log(err); + } + if (newValue instanceof Array) { + setStoredValue([...newValue]); + } else { + if (newValue instanceof Object) { + setStoredValue({ ...newValue }); + } else { + setStoredValue(newValue); + } + } + }; + return [storedValue, setValue]; +}; diff --git a/examples/web/src/pages/Home/index.scss b/examples/web/src/pages/Home/index.scss index d3d051c..34fcdb9 100644 --- a/examples/web/src/pages/Home/index.scss +++ b/examples/web/src/pages/Home/index.scss @@ -1,7 +1,8 @@ .home { .item { background: #333; - margin: 12px; + margin: 0 auto; + max-width: 600px; } .delete { color: #ffffff; diff --git a/examples/web/src/pages/Home/index.tsx b/examples/web/src/pages/Home/index.tsx index bf9bec8..7989a7a 100644 --- a/examples/web/src/pages/Home/index.tsx +++ b/examples/web/src/pages/Home/index.tsx @@ -9,7 +9,7 @@ import { useNavigate } from "react-router-dom"; import LogSink, { log } from "../../components/LogSink"; import { useIotEngine } from "../../hooks/useIotEngine"; -import { useLocalStorage } from "../../hooks/useLocalStorage"; +import { useSessionStorage } from "../../hooks/useSessionStorage"; import "./index.scss"; @@ -23,30 +23,48 @@ interface ConnectionObjStore { localNodeId: string; isPreview: boolean; isFullScreen: boolean; - isConnected: boolean; isAudioMute: boolean; isMicOn: boolean; } const Home = () => { const navigate = useNavigate(); - const [addPeerNodeId, setAddPeerNodeId] = useState("01HR439QSN8BM59HAR5P426TBP"); + const [addPeerNodeId, setAddPeerNodeId] = useState(""); const [isShowLogSink, setIsShowLogSink] = useState(false); - const [connectionObjStoreList, setConnectionObjStoreList] = useLocalStorage( + const [connectionObjStoreList, setConnectionObjStoreList] = useSessionStorage( "connectionObjStoreList", [], ); + const connectionObjStoreListRef = useRef(connectionObjStoreList); const { iotEngine } = useIotEngine(); - const preview = useRef(null); - const connectionCreate = (peerNodeId: string) => { const connectionMgr: IConnectionMgr = iotEngine.getConnectionMgr(); const param = new ConnectCreateParam({ mAttachMsg: "", mPeerNodeId: peerNodeId, }); - connectionMgr?.connectionCreate(param); + const connectObj = connectionMgr?.connectionCreate(param); + changeAndAddConnectObj(connectObj); + }; + + const changeAndAddConnectObj = (connectObj: IConnectionObj) => { + const nextConnectionObjStoreList = connectionObjStoreListRef.current; + if ( + !nextConnectionObjStoreList.find( + (node: IConnectionObj) => node.peerNodeId === connectObj.peerNodeId, + ) + ) { + nextConnectionObjStoreList.push({ + peerNodeId: connectObj.peerNodeId, + localNodeId: connectObj.localNodeId, + isPreview: false, + isFullScreen: false, + isAudioMute: true, + isMicOn: false, + }); + } + setConnectionObjStoreList(nextConnectionObjStoreList); }; const connectionDestroy = (peerNodeId: string) => { @@ -56,14 +74,22 @@ const Home = () => { .find(node => node.peerNodeId === peerNodeId); if (connectObj) { connectionMgr?.connectionDestroy(connectObj); - changeConnectionObjStore(connectObj.peerNodeId, "isConnected", false); + console.log(connectionMgr?.getConnectionList()); + changeConnectionObjStore(peerNodeId, "isPreview", false); + changeConnectionObjStore(peerNodeId, "isAudioMute", true); + changeConnectionObjStore(peerNodeId, "isMicOn", false); } }; const deleteConnectionObjStore = (peerNodeId: string) => { - setConnectionObjStoreList( - connectionObjStoreList.filter((node: ConnectionObjStore) => node.peerNodeId !== peerNodeId), + const nextConnectionObjStoreList = connectionObjStoreListRef.current; + const index = nextConnectionObjStoreList.findIndex( + (node: ConnectionObjStore) => node.peerNodeId === peerNodeId, ); + if (index !== -1) { + nextConnectionObjStoreList.splice(index, 1); + } + setConnectionObjStoreList(nextConnectionObjStoreList); }; useEffect(() => { @@ -89,7 +115,6 @@ const Home = () => { const eventListener = { onConnectionCreateDone: (connectObj: IConnectionObj, errCode: number) => { log.log("onConnectionCreateDone", "connectObj", connectObj, "errCode", errCode); - if (!connectObj) { Toast.show("error: connectObj is null"); return; @@ -100,34 +125,16 @@ const Home = () => { return; } connectObj.registerListener(connectionObjEventListeners); - if ( - !connectionObjStoreList.find( - (node: IConnectionObj) => node.peerNodeId === connectObj.peerNodeId, - ) - ) { - setConnectionObjStoreList([ - ...connectionObjStoreList, - { - peerNodeId: connectObj.peerNodeId, - localNodeId: connectObj.localNodeId, - isPreview: false, - isFullScreen: false, - isConnected: true, - } as ConnectionObjStore, - ]); - } else { - changeConnectionObjStore(connectObj.peerNodeId, "isConnected", true); - } + changeAndAddConnectObj(connectObj); }, onPeerDisconnected: (connectObj: IConnectionObj, errCode: number) => { log.log("onPeerDisconnected", "connectObj", connectObj, "errCode", errCode); - if (!connectObj) { Toast.show("error: connectObj is null"); return; } connectObj.unregisterListener(connectionObjEventListeners); - changeConnectionObjStore(connectObj.peerNodeId, "isConnected", false); + connectionDestroy(connectObj.peerNodeId); }, }; iotEngine.setLogLevel(LOG_LEVEL.LOG_LEVEL_DEBUG); @@ -139,16 +146,9 @@ const Home = () => { }, []); const updateConnectionObjStoreList = () => { - const connectionMgr: IConnectionMgr = iotEngine.getConnectionMgr(); - const connectionList = connectionMgr?.getConnectionList(); - - const nextConnectionObjStoreList = connectionObjStoreList; + const nextConnectionObjStoreList = connectionObjStoreListRef.current; for (let i = 0; i < nextConnectionObjStoreList.length; i++) { const node: ConnectionObjStore = nextConnectionObjStoreList[i]; - const find = connectionList?.find((connection: IConnectionObj) => { - return connection.peerNodeId === node.peerNodeId; - }); - node.isConnected = find?.getInfo().mState === ConnectStatus.CONNECTED; node.isPreview = false; node.isFullScreen = false; node.isAudioMute = true; @@ -163,14 +163,17 @@ const Home = () => { return; } connectObj.streamSubscribeStart(STREAM_ID.BROADCAST_STREAM_1, ""); - connectObj.setVideoDisplayView(STREAM_ID.BROADCAST_STREAM_1, preview.current); + connectObj.setVideoDisplayView( + STREAM_ID.BROADCAST_STREAM_1, + document.querySelector(`.grid-video-container-${peerNodeId}`) as HTMLDivElement, + ); changeConnectionObjStore(peerNodeId, "isPreview", true); }; const changeConnectionObjStore = (peerNodeId: string, key: string, value: any) => { - const nextConnectionObjStoreList = [...connectionObjStoreList]; - connectionObjStoreList.find((node: ConnectionObjStore) => { + const nextConnectionObjStoreList = connectionObjStoreListRef.current; + nextConnectionObjStoreList.find((node: ConnectionObjStore) => { if (node.peerNodeId === peerNodeId && node.hasOwnProperty(key)) { (node as any)[key] = value; } @@ -205,6 +208,7 @@ const Home = () => { }; const goStreamManager = (peerNodeId: string) => { + muteAudio(peerNodeId, false); navigate(`/stream-manager/${peerNodeId}`); }; @@ -359,8 +363,9 @@ const Home = () => {
{node.isFullScreen && (
- + { logout(); diff --git a/examples/web/src/pages/Register/index.tsx b/examples/web/src/pages/Register/index.tsx index b8b5823..2898492 100644 --- a/examples/web/src/pages/Register/index.tsx +++ b/examples/web/src/pages/Register/index.tsx @@ -2,12 +2,16 @@ import { Button, Form, Input, Modal, NavBar, Toast } from "antd-mobile"; import { useNavigate } from "react-router-dom"; import { BASE_URL_TAIL, CREATE_ACCOUNT, fetchAPI, generateBasicAuth } from "../../configs/server"; -import { useLocalStorage } from "../../hooks/useLocalStorage"; +import { useSessionStorage } from "../../hooks/useSessionStorage"; const Register = () => { const navigate = useNavigate(); - const [settings] = useLocalStorage("settings"); + const [settings] = useSessionStorage("settings"); const onFinish = async (values: { account: string }) => { + if (settings.appId === "") { + Toast.show("please input appid in setting page"); + return; + } const res = await fetchAPI({ url: `${settings.region[0]}${BASE_URL_TAIL}${CREATE_ACCOUNT}`, body: { diff --git a/examples/web/src/pages/StreamManager/index.scss b/examples/web/src/pages/StreamManager/index.scss index 52e9c33..029322d 100644 --- a/examples/web/src/pages/StreamManager/index.scss +++ b/examples/web/src/pages/StreamManager/index.scss @@ -2,6 +2,7 @@ .item { background: #333; margin: 12px; + max-width: 600px; } .delete { color: #ffffff; diff --git a/examples/web/src/pages/StreamManager/index.tsx b/examples/web/src/pages/StreamManager/index.tsx index 6cf5e0a..a9a19e6 100644 --- a/examples/web/src/pages/StreamManager/index.tsx +++ b/examples/web/src/pages/StreamManager/index.tsx @@ -26,8 +26,6 @@ const StreamManager = () => { const [connectionObj, setConnectionObj] = useState(null); const [isShowLogSink, setIsShowLogSink] = useState(false); - const [currentStreamType, _setCurrentStreamType] = useState("BROADCAST_STREAM_1"); - const { peerNodeId } = useParams(); const [streamList, setStreamList] = useState([ { @@ -152,6 +150,15 @@ const StreamManager = () => { ]); const back = () => { + for (const index in streamList) { + const stream = streamList[index]; + if (stream.isPreview) { + stopPreview(stream.value); + } + if (stream.isPlaying) { + onAudioPlay(stream.value, true); + } + } navigate("/"); }; @@ -171,14 +178,6 @@ const StreamManager = () => { "videoHeight", videoHeight, ); - - const newStreamList = streamList.map(stream => { - if (stream.type === currentStreamType) { - return { ...stream, isPreview: true }; - } - return stream; - }); - setStreamList(newStreamList); }, }; const eventListener = { @@ -201,6 +200,7 @@ const StreamManager = () => { Toast.show("error: connectObj is null"); return; } + setConnectionObj(connectObj); }, }; connectionMgr?.registerListener(eventListener); @@ -215,6 +215,15 @@ const StreamManager = () => { if (connectionObj) { connectionObj.unregisterListener(connectionObjEventListeners); } + for (const index in streamList) { + const stream = streamList[index]; + if (stream.isPreview) { + stopPreview(stream.value); + } + if (stream.isPlaying) { + onAudioPlay(stream.value, true); + } + } }; }, []); @@ -350,7 +359,12 @@ const StreamManager = () => {
{ - onAudioPlay(stream.value, stream.isPlaying); + if (stream.isPreview) { + onAudioPlay(stream.value, stream.isPlaying); + } else { + Toast.show("请先预览"); + return; + } }} > {stream.isPlaying ? "静音" : "音放"} diff --git a/examples/web/src/pages/settings/index.tsx b/examples/web/src/pages/settings/index.tsx index c38122f..1484979 100644 --- a/examples/web/src/pages/settings/index.tsx +++ b/examples/web/src/pages/settings/index.tsx @@ -1,15 +1,13 @@ import { Button, Form, Input, NavBar, Selector, Toast } from "antd-mobile"; import { useEffect } from "react"; -import { useNavigate } from "react-router-dom"; import defaultSettings from "../../configs/callkit.config"; import { Region } from "../../configs/server"; -import { useLocalStorage } from "../../hooks/useLocalStorage"; +import { useSessionStorage } from "../../hooks/useSessionStorage"; import { enumToItems } from "../../utils"; const Settings = () => { - const navigate = useNavigate(); - const [settings, setSettings] = useLocalStorage("settings"); + const [settings, setSettings] = useSessionStorage("settings"); useEffect(() => { if (!settings) { @@ -29,7 +27,7 @@ const Settings = () => { Toast.show({ content: "保存成功", }); - navigate("/"); + location.href = "/"; }; const onFinishFailed = (errorInfo: any) => {