123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379 |
- <template>
- <view class="web_view_wrap">
- <web-view
- allow="microphone;camera;midi;encrypted-media;"
- :src="hybridUrl"
- @message="handleMessage"
- >
- </web-view>
- </view>
- </template>
- <script>
- import IMSDK, { IMMethods, SessionType } from "openim-uniapp-polyfill";
- import {
- CustomMessageStatus,
- CustomType,
- GroupMemberListTypes,
- PageEvents,
- } from "../../../constant";
- import {
- gotoAppPermissionSetting,
- judgeIosPermission,
- requestAndroidPermission,
- } from "../../../util/permission";
- import beCalledRing from "../../../static/audio/beCalled.mp3";
- import callingRing from "../../../static/audio/calling.wav";
- let currentWebview;
- let innerAudioContext;
- const RtcMessageTypes = {
- Accept: "accept",
- Refuse: "refuse",
- Cancel: "cancel",
- Hung: "hung",
- Disconnect: "disconnect",
- ConnectFailed: "connectFailed",
- Invite: "invite",
- };
- export default {
- data() {
- return {
- callState: {
- isGroup: true,
- isVideo: true,
- isCalled: true,
- },
- invitationData: {},
- connectData: {},
- hybridUrl: "/hybrid/html/h5/index.html",
- };
- },
- onLoad(options) {
- const data = JSON.parse(options.invitationData);
- this.invitationData = data.invitation;
- this.callState.isGroup =
- this.invitationData.sessionType !== SessionType.Single;
- this.callState.isVideo = this.invitationData.mediaType === "video";
- this.callState.isCalled = JSON.parse(options.isCalled);
- if (options.connectData) {
- this.connectData = JSON.parse(options.connectData);
- }
- const connectDataStr =
- this.callState.isGroup && options.connectData
- ? `&connectData=${options.connectData}`
- : "";
- const participantStr = data.participant
- ? `&participantInfo=${JSON.stringify(data.participant)}`
- : "";
- const invitedMemberStr = options.memberList
- ? `&invitedMemberInfo=${options.memberList}`
- : "";
- this.hybridUrl =
- this.hybridUrl +
- `?isCalled=${options.isCalled}&isGroup=${
- this.callState.isGroup
- }&isVideo=${this.callState.isVideo}&totalMember=${
- data.invitation.inviteeUserIDList.length + 1
- }&statusBarHeight=${uni.getWindowInfo().statusBarHeight}` +
- connectDataStr +
- participantStr +
- invitedMemberStr;
- console.log(this.hybridUrl);
- this.setRTCListener();
- this.backPlayRing(this.callState.isCalled ? beCalledRing : callingRing);
- },
- onReady() {
- this.checkRecordPermission();
- setTimeout(() => {
- currentWebview = this.$scope.$getAppWebview().children()[0];
- currentWebview.setStyle({
- top: uni.getWindowInfo().statusBarHeight,
- });
- });
- },
- onUnload() {
- this.disposeRTCListener();
- innerAudioContext?.destroy();
- console.log("destroy");
- },
- methods: {
- backPlayRing(audioSrc) {
- if (this.callState.isGroup && !this.callState.isCalled) {
- return;
- }
- innerAudioContext = uni.createInnerAudioContext();
- innerAudioContext.autoplay = true;
- innerAudioContext.src = audioSrc;
- innerAudioContext.loop = true;
- },
- handleMessage({ detail: { data } }) {
- const type = data[0].type;
- switch (type) {
- case RtcMessageTypes.Accept:
- this.acceptInvite();
- innerAudioContext.stop();
- break;
- case RtcMessageTypes.Refuse:
- this.refuseInvite();
- innerAudioContext.stop();
- break;
- case RtcMessageTypes.Cancel:
- this.cancelInvite();
- innerAudioContext.stop();
- break;
- case RtcMessageTypes.Hung:
- this.insertRtcMessage(CustomMessageStatus.Success, data[0].duration);
- uni.navigateBack();
- break;
- case RtcMessageTypes.Disconnect:
- this.insertRtcMessage(CustomMessageStatus.Success, data[0].duration);
- uni.navigateBack();
- break;
- case RtcMessageTypes.ConnectFailed:
- uni.$u.toast("连接失败!");
- uni.navigateBack();
- break;
- case RtcMessageTypes.Invite:
- uni.$u.route("/pages_im/pages/conversation/groupMemberList/index", {
- type: GroupMemberListTypes.CallInvite,
- groupID: this.invitationData.groupID,
- callMediaType: this.invitationData.mediaType,
- });
- break;
- default:
- break;
- }
- },
- sendRtcInvite(mediaType, userIDList) {
- const invitation = {
- ...this.invitationData,
- inviteeUserIDList: userIDList,
- };
- IMSDK.asyncApi(IMSDK.IMMethods.SignalingInviteInGroup, IMSDK.uuid(), {
- invitation,
- })
- .then(({ data }) => {
- console.log(data);
- uni.$u.toast("邀请成功!");
- })
- .catch((err) => {
- console.log(err);
- uni.$u.toast("邀请失败!");
- });
- },
- async checkRecordPermission() {
- if (uni.$u.os() === "ios") {
- const iosFlag = judgeIosPermission("record");
- const iosFlag2 = judgeIosPermission("camera");
- if (iosFlag === 0 || !iosFlag2) {
- uni.$u.toast("您已禁止访问麦克风或摄像头,请前往开启");
- setTimeout(() => gotoAppPermissionSetting(), 250);
- return false;
- }
- } else {
- const androidFlag = await requestAndroidPermission(
- "android.permission.RECORD_AUDIO",
- );
- const androidFlag2 = await requestAndroidPermission(
- "android.permission.CAMERA",
- );
- if (androidFlag === -1 || androidFlag2 === -1) {
- uni.$u.toast("您已禁止访问麦克风或摄像头,请前往开启");
- setTimeout(() => gotoAppPermissionSetting(), 250);
- return false;
- }
- }
- return true;
- },
- async acceptInvite() {
- const options = {
- opUserID: this.$store.getters.storeCurrentUserID,
- invitation: this.invitationData,
- };
- IMSDK.asyncApi(
- IMSDK.IMMethods.SignalingAccept,
- IMSDK.uuid(),
- options,
- ).then(({ data }) => {
- console.log(data);
- console.log(currentWebview);
- currentWebview.evalJS(`acceptCallback(${JSON.stringify(data)})`);
- });
- },
- refuseInvite() {
- const options = {
- opUserID: this.$store.getters.storeCurrentUserID,
- invitation: this.invitationData,
- };
- IMSDK.asyncApi(
- IMSDK.IMMethods.SignalingReject,
- IMSDK.uuid(),
- options,
- ).finally(() => {
- this.insertRtcMessage(CustomMessageStatus.Refuse);
- uni.navigateBack();
- });
- },
- cancelInvite() {
- const options = {
- opUserID: this.$store.getters.storeCurrentUserID,
- invitation: this.invitationData,
- };
- IMSDK.asyncApi(
- IMSDK.IMMethods.SignalingCancel,
- IMSDK.uuid(),
- options,
- ).finally(() => {
- this.insertRtcMessage(CustomMessageStatus.Cancel);
- uni.navigateBack();
- });
- },
- async insertRtcMessage(status, timeStr) {
- const customData = {
- customType: CustomType.Call,
- data: {
- duration: timeStr ?? "",
- type: this.callState.isVideo
- ? CustomType.VideoCall
- : CustomType.VoiceCall,
- status,
- },
- };
- const message = await IMSDK.asyncApi(
- IMMethods.CreateCustomMessage,
- IMSDK.uuid(),
- {
- data: JSON.stringify(customData),
- extension: "",
- description: "RTC",
- },
- );
- const sourceID =
- this.invitationData.groupID || this.invitationData.inviteeUserIDList[0];
- const funcName = this.callState.isGroup
- ? IMSDK.IMMethods.InsertGroupMessageToLocalStorage
- : IMSDK.IMMethods.InsertSingleMessageToLocalStorage;
- IMSDK.asyncApi(funcName, IMSDK.uuid(), {
- message,
- groupID: sourceID,
- sendID: this.invitationData.inviterUserID,
- })
- .then(({ data }) => {
- if (this.inCurrentConversation(data)) {
- data.isAppend = true;
- this.$store.dispatch("message/pushNewMessage", data);
- setTimeout(() => uni.$emit(PageEvents.ScrollToBottom, true));
- }
- })
- .catch((err) => {
- console.log(err);
- });
- },
- inCurrentConversation(newServerMsg) {
- if (this.callState.isGroup) {
- return (
- newServerMsg.groupID ===
- this.$store.getters.storeCurrentConversation.groupID
- );
- }
- return (
- newServerMsg.sendID ===
- this.$store.getters.storeCurrentConversation.userID ||
- newServerMsg.recvID ===
- this.$store.getters.storeCurrentConversation.userID
- );
- },
- acceptHandler() {
- console.log("acceptHandler");
- innerAudioContext.stop();
- currentWebview.evalJS(
- `acceptCallback(${JSON.stringify(this.connectData)})`,
- );
- },
- refusedHandler({ data }) {
- console.log(data);
- uni.$u.toast("对方已拒绝!");
- this.insertRtcMessage(CustomMessageStatus.Refused);
- uni.navigateBack();
- },
- accessByOtherDeviceHandler({ data }) {
- console.log(data);
- uni.$u.toast("已在其他设备上处理!");
- this.insertRtcMessage(CustomMessageStatus.AccessByOther);
- uni.navigateBack();
- },
- canceledHandler({ data }) {
- console.log(data);
- const canceledData = JSON.parse(data);
- if (canceledData.opUserID === this.invitationData.inviterUserID) {
- uni.$u.toast("对方已取消!");
- this.insertRtcMessage(CustomMessageStatus.Canceled);
- uni.navigateBack();
- }
- },
- timeOutHandler({ data }) {
- console.log(data);
- uni.$u.toast("对方未接听!");
- this.insertRtcMessage(CustomMessageStatus.Timeout);
- uni.navigateBack();
- },
- setRTCListener() {
- IMSDK.subscribe(IMSDK.IMEvents.OnInviteeAccepted, this.acceptHandler);
- IMSDK.subscribe(IMSDK.IMEvents.OnInviteeRejected, this.refusedHandler);
- IMSDK.subscribe(
- IMSDK.IMEvents.OnInviteeAcceptedByOtherDevice,
- this.accessByOtherDeviceHandler,
- );
- IMSDK.subscribe(
- IMSDK.IMEvents.OnInviteeRejectedByOtherDevice,
- this.accessByOtherDeviceHandler,
- );
- IMSDK.subscribe(
- IMSDK.IMEvents.OnInvitationCancelled,
- this.canceledHandler,
- );
- IMSDK.subscribe(IMSDK.IMEvents.OnInvitationTimeout, this.timeOutHandler);
- },
- disposeRTCListener() {
- IMSDK.unsubscribe(IMSDK.IMEvents.OnInviteeAccepted, this.acceptHandler);
- IMSDK.unsubscribe(IMSDK.IMEvents.OnInviteeRejected, this.refusedHandler);
- IMSDK.unsubscribe(
- IMSDK.IMEvents.OnInviteeAcceptedByOtherDevice,
- this.accessByOtherDeviceHandler,
- );
- IMSDK.unsubscribe(
- IMSDK.IMEvents.OnInviteeRejectedByOtherDevice,
- this.accessByOtherDeviceHandler,
- );
- IMSDK.unsubscribe(
- IMSDK.IMEvents.OnInvitationCancelled,
- this.canceledHandler,
- );
- IMSDK.unsubscribe(
- IMSDK.IMEvents.OnInvitationTimeout,
- this.timeOutHandler,
- );
- },
- },
- onBackPress(options) {
- if (options.from === "navigateBack" || !currentWebview) {
- if (currentWebview) {
- currentWebview.evalJS(`tryDisconnectAgin()`);
- }
- return false;
- }
- currentWebview.evalJS(`backConfirm()`);
- return true;
- },
- };
- </script>
- <style lang="scss" scoped>
- .web_view_wrap {
- margin-top: var(--status-bar-height);
- }
- </style>
|