feat: add signaling api & adapt electron

This commit is contained in:
Bloomingg
2024-05-22 17:45:17 +08:00
parent fbcae7866b
commit 3a386be4d0
18 changed files with 1475 additions and 47 deletions

1
.npmrc Normal file
View File

@@ -0,0 +1 @@
ELECTRON_MIRROR="https://npmmirror.com/mirrors/electron/"

Binary file not shown.

Binary file not shown.

725
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "@openim/node-client-sdk",
"version": "1.0.6",
"version": "1.0.9",
"description": "open im sdk for node",
"source": "src/index.ts",
"main": "lib/index.js",
@@ -51,6 +51,7 @@
"@typescript-eslint/eslint-plugin": "^4.22.0",
"@typescript-eslint/parser": "^4.22.0",
"conventional-changelog-conventionalcommits": "^5.0.0",
"electron": "^29.2.0",
"eslint": "^7.25.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-node": "^11.1.0",
@@ -58,7 +59,7 @@
"husky": "^6.0.0",
"jest": "^27.2.0",
"lint-staged": "^10.5.4",
"open-im-sdk-wasm": "^3.5.3-alpha.2",
"open-im-sdk-wasm": "^3.5.3-alpha.3",
"prettier": "^2.2.1",
"rollup": "^2.79.1",
"rollup-plugin-typescript2": "^0.36.0",
@@ -79,6 +80,7 @@
"uuid": "^9.0.0"
},
"peerDependencies": {
"open-im-sdk-wasm": "^3.5.3-alpha.1"
"electron": ">=12.0.0",
"open-im-sdk-wasm": "^3.5.3-alpha.5"
}
}

View File

@@ -27,12 +27,31 @@ export default [
output: [
{
file: 'lib/render.js',
format: 'esm',
sourcemap: false
},
{
file: 'lib/render.cjs.js',
format: 'cjs',
exports: 'auto',
sourcemap: false
},
],
plugins: [
typescript(),
]
},
{
input: 'src/preload.ts',
output: [
{
file: 'lib/preload.js',
format: 'cjs',
exports: 'auto',
sourcemap: false
},
{
file: 'lib/render.es.js',
file: 'lib/preload.es.js',
format: 'esm',
sourcemap: false
}

View File

@@ -55,6 +55,20 @@ export enum NativeEvent {
UPLOAD_FILE_CALLBACK_UPLOAD_PART_COMPLETE,
UPLOAD_FILE_CALLBACK_UPLOAD_COMPLETE,
UPLOAD_FILE_CALLBACK_COMPLETE,
CONVERSATION_USER_INPUT_STATUS_CHANGED,
RECV_ONLINE_ONLY_MESSAGE,
RECV_NEW_INVITATION,
INVITEE_ACCEPTED,
INVITEE_ACCEPTED_BY_OTHER_DEVICE,
INVITEE_REJECTED,
INVITEE_REJECTED_BY_OTHER_DEVICE,
INVITATION_CANCELLED,
INVITATION_TIMEOUT,
HANG_UP,
ROOM_PARTICIPANT_CONNECTED,
ROOM_PARTICIPANT_DISCONNECTED,
STREAM_CHANGE,
RECEIVE_CUSTOM_SIGNAL,
}
export const eventMapping: Record<NativeEvent, CbEvents> = {
@@ -117,4 +131,21 @@ export const eventMapping: Record<NativeEvent, CbEvents> = {
[NativeEvent.UPLOAD_FILE_CALLBACK_UPLOAD_ID]: CbEvents.UnUsedEvent,
[NativeEvent.UPLOAD_FILE_CALLBACK_UPLOAD_PART_COMPLETE]: CbEvents.UnUsedEvent,
[NativeEvent.UPLOAD_FILE_CALLBACK_UPLOAD_COMPLETE]: CbEvents.UnUsedEvent,
[NativeEvent.CONVERSATION_USER_INPUT_STATUS_CHANGED]: CbEvents.UnUsedEvent,
[NativeEvent.RECV_ONLINE_ONLY_MESSAGE]: CbEvents.UnUsedEvent,
[NativeEvent.RECV_NEW_INVITATION]: CbEvents.OnReceiveNewInvitation,
[NativeEvent.INVITEE_ACCEPTED]: CbEvents.OnInviteeAccepted,
[NativeEvent.INVITEE_ACCEPTED_BY_OTHER_DEVICE]:
CbEvents.OnInviteeAcceptedByOtherDevice,
[NativeEvent.INVITEE_REJECTED]: CbEvents.OnInviteeRejected,
[NativeEvent.INVITEE_REJECTED_BY_OTHER_DEVICE]:
CbEvents.OnInviteeRejectedByOtherDevice,
[NativeEvent.INVITATION_CANCELLED]: CbEvents.OnInvitationCancelled,
[NativeEvent.INVITATION_TIMEOUT]: CbEvents.OnInvitationTimeout,
[NativeEvent.HANG_UP]: CbEvents.OnHangUp,
[NativeEvent.ROOM_PARTICIPANT_CONNECTED]: CbEvents.OnRoomParticipantConnected,
[NativeEvent.ROOM_PARTICIPANT_DISCONNECTED]:
CbEvents.OnRoomParticipantDisconnected,
[NativeEvent.STREAM_CHANGE]: CbEvents.OnStreamChange,
[NativeEvent.RECEIVE_CUSTOM_SIGNAL]: CbEvents.OnReceiveCustomSignal,
};

View File

@@ -19,7 +19,12 @@ import { SelfUserInfo } from 'open-im-sdk-wasm/lib/types/entity';
import {
SetConversationExParams,
SetFriendExParams,
UploadFileParams,
} from 'open-im-sdk-wasm/lib/types/params';
import {
type SignalingModuleApi,
setupSignalingModule,
} from './modules/signaling';
function isObject(value: unknown) {
return Object.prototype.toString.call(value) === '[object Object]';
@@ -32,7 +37,8 @@ class OpenIMSDK
FriendModuleApi,
GroupModuleApi,
ConversationModuleApi,
MessageModuleApi
MessageModuleApi,
SignalingModuleApi
{
libOpenIMSDK = {} as LibOpenIMSDK;
baseCallbackProto: koffi.IKoffiCType;
@@ -70,8 +76,8 @@ class OpenIMSDK
this.listenerCallback = koffi.register(
(event: NativeEvent, data: string) => {
const cbEvent = eventMapping[event];
if (!cbEvent) return;
this.emit(cbEvent, this.generateEventResponse(data));
console.log(`listener callback - Event: ${cbEvent}, Data: ${data}`);
},
koffi.pointer(listenerCallbackProto)
);
@@ -118,6 +124,12 @@ class OpenIMSDK
'void',
['listenerCallback *']
);
this.libOpenIMSDK.set_signaling_listener = this.lib.func(
'__stdcall',
'set_signaling_listener',
'void',
['listenerCallback *']
);
this.libOpenIMSDK.init_sdk = this.lib.func(
'__stdcall',
'init_sdk',
@@ -338,6 +350,18 @@ class OpenIMSDK
'void',
['baseCallback *', 'str', 'str', 'int']
);
this.libOpenIMSDK.send_group_message_read_receipt = this.lib.func(
'__stdcall',
'send_group_message_read_receipt',
'void',
['baseCallback *', 'str', 'str', 'str']
);
this.libOpenIMSDK.get_group_message_reader_list = this.lib.func(
'__stdcall',
'get_group_message_reader_list',
'void',
['baseCallback *', 'str', 'str', 'str', 'int', 'int', 'int']
);
this.libOpenIMSDK.hide_conversation = this.lib.func(
'__stdcall',
'hide_conversation',
@@ -408,13 +432,13 @@ class OpenIMSDK
'__stdcall',
'send_message',
'void',
['sendMessageCallback *', 'str', 'str', 'str', 'str', 'str']
['sendMessageCallback *', 'str', 'str', 'str', 'str', 'str', 'int']
);
this.libOpenIMSDK.send_message_not_oss = this.lib.func(
'__stdcall',
'send_message_not_oss',
'void',
['sendMessageCallback *', 'str', 'str', 'str', 'str', 'str']
['sendMessageCallback *', 'str', 'str', 'str', 'str', 'str', 'int']
);
this.libOpenIMSDK.find_message_list = this.lib.func(
'__stdcall',
@@ -823,12 +847,131 @@ class OpenIMSDK
'int',
['baseCallback *', 'str', 'str']
);
this.libOpenIMSDK.signaling_invite_in_group = this.lib.func(
'__stdcall',
'signaling_invite_in_group',
'void',
['baseCallback *', 'str', 'str']
);
this.libOpenIMSDK.signaling_invite = this.lib.func(
'__stdcall',
'signaling_invite',
'void',
['baseCallback *', 'str', 'str']
);
this.libOpenIMSDK.signaling_accept = this.lib.func(
'__stdcall',
'signaling_accept',
'void',
['baseCallback *', 'str', 'str']
);
this.libOpenIMSDK.signaling_reject = this.lib.func(
'__stdcall',
'signaling_reject',
'void',
['baseCallback *', 'str', 'str']
);
this.libOpenIMSDK.signaling_cancel = this.lib.func(
'__stdcall',
'signaling_cancel',
'void',
['baseCallback *', 'str', 'str']
);
this.libOpenIMSDK.signaling_hung_up = this.lib.func(
'__stdcall',
'signaling_hung_up',
'void',
['baseCallback *', 'str', 'str']
);
this.libOpenIMSDK.signaling_get_room_by_group_id = this.lib.func(
'__stdcall',
'signaling_get_room_by_group_id',
'void',
['baseCallback *', 'str', 'str']
);
this.libOpenIMSDK.signaling_get_token_by_room_id = this.lib.func(
'__stdcall',
'signaling_get_token_by_room_id',
'void',
['baseCallback *', 'str', 'str']
);
this.libOpenIMSDK.get_signaling_invitation_info_start_app = this.lib.func(
'__stdcall',
'get_signaling_invitation_info_start_app',
'void',
['baseCallback *', 'str']
);
this.libOpenIMSDK.signaling_create_meeting = this.lib.func(
'__stdcall',
'signaling_create_meeting',
'void',
['baseCallback *', 'str', 'str']
);
this.libOpenIMSDK.signaling_join_meeting = this.lib.func(
'__stdcall',
'signaling_join_meeting',
'void',
['baseCallback *', 'str', 'str']
);
this.libOpenIMSDK.signaling_update_meeting_info = this.lib.func(
'__stdcall',
'signaling_update_meeting_info',
'void',
['baseCallback *', 'str', 'str']
);
this.libOpenIMSDK.signaling_close_room = this.lib.func(
'__stdcall',
'signaling_close_room',
'void',
['baseCallback *', 'str', 'str']
);
this.libOpenIMSDK.signaling_get_meetings = this.lib.func(
'__stdcall',
'signaling_get_meetings',
'void',
['baseCallback *', 'str']
);
this.libOpenIMSDK.signaling_operate_stream = this.lib.func(
'__stdcall',
'signaling_operate_stream',
'void',
['baseCallback *', 'str', 'str', 'str', 'str', 'int', 'int']
);
this.libOpenIMSDK.signaling_send_custom_signal = this.lib.func(
'__stdcall',
'signaling_send_custom_signal',
'void',
['baseCallback *', 'str', 'str', 'str']
);
this.libOpenIMSDK.upload_file = this.lib.func(
'__stdcall',
'upload_file',
'void',
['baseCallback *', 'str', 'str', 'listenerCallback *']
);
Object.assign(this, setupUserModule(this));
Object.assign(this, setupFriendModule(this));
Object.assign(this, setupGroupModule(this));
Object.assign(this, setupConversationModule(this));
Object.assign(this, setupMessageModule(this));
Object.assign(this, setupSignalingModule(this));
}
generateEventResponse = (data: unknown, operationID = ''): BaseResponse => {
@@ -862,10 +1005,6 @@ class OpenIMSDK
) => {
const registerBaseCallback = koffi.register(
(operationID: string, errCode: number, errMsg: string, data: string) => {
console.log(
`base callback - operationID: ${operationID}, errCode: ${errCode}, errMsg: ${errMsg}, data: ${data}`
);
let realData;
try {
realData = JSON.parse(data);
@@ -891,6 +1030,7 @@ class OpenIMSDK
};
sendMessageCallbackWrap = <T>(
clientMsgID: string,
resolve: (response: BaseResponse<T>) => void,
reject: (response: BaseResponse<T>) => void
) => {
@@ -902,10 +1042,6 @@ class OpenIMSDK
data: string,
progress: number
) => {
console.log(
`send message callback - operationID: ${operationID}, errCode: ${errCode}, errMsg: ${errMsg}, data: ${data}, progress: ${progress}`
);
let realData;
try {
realData = JSON.parse(data);
@@ -922,7 +1058,13 @@ class OpenIMSDK
// eslint-disable-next-line
this.emit(
CbEvents.OnProgress,
this.generateEventResponse(progress, operationID)
this.generateEventResponse(
{
clientMsgID,
progress,
},
operationID
)
);
return;
}
@@ -969,6 +1111,7 @@ class OpenIMSDK
this.libOpenIMSDK.set_advanced_msg_listener(this.listenerCallback);
this.libOpenIMSDK.set_batch_msg_listener(this.listenerCallback);
this.libOpenIMSDK.set_custom_business_listener(this.listenerCallback);
this.libOpenIMSDK.set_signaling_listener(this.listenerCallback);
};
initSDK = (param: InitConfig, opid = uuidV4()) =>
@@ -1030,6 +1173,16 @@ class OpenIMSDK
);
});
uploadFile = (params: UploadFileParams, opid = uuidV4()) =>
new Promise<BaseResponse<{ url: string }>>((resolve, reject) => {
this.libOpenIMSDK.upload_file(
this.baseCallbackWrap(resolve, reject),
opid,
JSON.stringify(params),
this.listenerCallback
);
});
// implements user api
getSelfUserInfo!: UserModuleApi['getSelfUserInfo'];
setSelfInfo!: UserModuleApi['setSelfInfo'];
@@ -1083,6 +1236,7 @@ class OpenIMSDK
transferGroupOwner!: GroupModuleApi['transferGroupOwner'];
dismissGroup!: GroupModuleApi['dismissGroup'];
quitGroup!: GroupModuleApi['quitGroup'];
isJoinGroup!: GroupModuleApi['isJoinGroup'];
// implements conversation api
getAllConversationList!: ConversationModuleApi['getAllConversationList'];
@@ -1106,6 +1260,8 @@ class OpenIMSDK
hideAllConversation!: ConversationModuleApi['hideAllConversation'];
clearConversationAndDeleteAllMsg!: ConversationModuleApi['clearConversationAndDeleteAllMsg'];
deleteConversationAndDeleteAllMsg!: ConversationModuleApi['deleteConversationAndDeleteAllMsg'];
setConversationMsgDestructTime!: ConversationModuleApi['setConversationMsgDestructTime'];
setConversationIsMsgDestruct!: ConversationModuleApi['setConversationIsMsgDestruct'];
// implements message api
createTextMessage!: MessageModuleApi['createTextMessage'];
@@ -1144,6 +1300,25 @@ class OpenIMSDK
insertGroupMessageToLocalStorage!: MessageModuleApi['insertGroupMessageToLocalStorage'];
insertSingleMessageToLocalStorage!: MessageModuleApi['insertSingleMessageToLocalStorage'];
setMessageLocalEx!: MessageModuleApi['setMessageLocalEx'];
sendGroupMessageReadReceipt!: MessageModuleApi['sendGroupMessageReadReceipt'];
getGroupMessageReaderList!: MessageModuleApi['getGroupMessageReaderList'];
// implements signaling api
signalingInviteInGroup!: SignalingModuleApi['signalingInviteInGroup'];
signalingInvite!: SignalingModuleApi['signalingInvite'];
signalingAccept!: SignalingModuleApi['signalingAccept'];
signalingReject!: SignalingModuleApi['signalingReject'];
signalingCancel!: SignalingModuleApi['signalingCancel'];
signalingHungUp!: SignalingModuleApi['signalingHungUp'];
signalingGetRoomByGroupID!: SignalingModuleApi['signalingGetRoomByGroupID'];
signalingGetTokenByRoomID!: SignalingModuleApi['signalingGetTokenByRoomID'];
signalingSendCustomSignal!: SignalingModuleApi['signalingSendCustomSignal'];
signalingCreateMeeting!: SignalingModuleApi['signalingCreateMeeting'];
signalingJoinMeeting!: SignalingModuleApi['signalingJoinMeeting'];
signalingUpdateMeetingInfo!: SignalingModuleApi['signalingUpdateMeetingInfo'];
signalingCloseRoom!: SignalingModuleApi['signalingCloseRoom'];
signalingGetMeetings!: SignalingModuleApi['signalingGetMeetings'];
signalingOperateStream!: SignalingModuleApi['signalingOperateStream'];
}
export default OpenIMSDK;

View File

@@ -10,6 +10,8 @@ import {
SetConversationPrivateStateParams,
SetBurnDurationParams,
SetConversationExParams,
SetConversationMsgDestructTimeParams,
SetConversationMsgDestructParams,
} from 'open-im-sdk-wasm/lib/types/params';
import { ConversationItem } from 'open-im-sdk-wasm/lib/types/entity';
@@ -189,6 +191,30 @@ export function setupConversationModule(openIMSDK: OpenIMSDK) {
conversationID
);
}),
setConversationMsgDestructTime: (
params: SetConversationMsgDestructTimeParams,
opid = uuidV4()
) =>
new Promise<BaseResponse<void>>((resolve, reject) => {
openIMSDK.libOpenIMSDK.set_conversation_msg_destruct_time(
openIMSDK.baseCallbackWrap<void>(resolve, reject),
opid,
params.conversationID,
params.msgDestructTime
);
}),
setConversationIsMsgDestruct: (
params: SetConversationMsgDestructParams,
opid = uuidV4()
) =>
new Promise<BaseResponse<void>>((resolve, reject) => {
openIMSDK.libOpenIMSDK.set_conversation_is_msg_destruct(
openIMSDK.baseCallbackWrap<void>(resolve, reject),
opid,
params.conversationID,
params.isMsgDestruct ? 1 : 0
);
}),
};
}
@@ -258,4 +284,12 @@ export interface ConversationModuleApi {
conversationID: string,
opid?: string
) => Promise<BaseResponse<void>>;
setConversationMsgDestructTime: (
params: SetConversationMsgDestructTimeParams,
opid?: string
) => Promise<BaseResponse<void>>;
setConversationIsMsgDestruct: (
params: SetConversationMsgDestructParams,
opid?: string
) => Promise<BaseResponse<void>>;
}

View File

@@ -265,6 +265,15 @@ export function setupGroupModule(openIMSDK: OpenIMSDK) {
groupID
);
}),
isJoinGroup: (groupID: string, opid = uuidV4()) =>
new Promise<BaseResponse<void>>((resolve, reject) => {
openIMSDK.libOpenIMSDK.is_join_group(
openIMSDK.baseCallbackWrap<void>(resolve, reject),
opid,
groupID
);
}),
};
}
@@ -350,4 +359,5 @@ export interface GroupModuleApi {
) => Promise<BaseResponse<void>>;
dismissGroup: (groupID: string, opid?: string) => Promise<BaseResponse<void>>;
quitGroup: (groupID: string, opid?: string) => Promise<BaseResponse<void>>;
isJoinGroup: (groupID: string, opid?: string) => Promise<BaseResponse<void>>;
}

View File

@@ -26,6 +26,8 @@ import {
VideoMsgParamsByURL,
FileMsgParamsByURL,
SoundMsgParamsByURL,
SendGroupReadReceiptParams,
GetGroupMessageReaderParams,
} from 'open-im-sdk-wasm/lib/types/params';
import {
VideoMsgByPathParams,
@@ -258,13 +260,17 @@ export function setupMessageModule(openIMSDK: OpenIMSDK) {
iOSBadgeCount: true,
};
openIMSDK.libOpenIMSDK.send_message(
openIMSDK.sendMessageCallbackWrap<MessageItem>(resolve, reject),
openIMSDK.sendMessageCallbackWrap<MessageItem>(
params.message.clientMsgID,
resolve,
reject
),
opid,
JSON.stringify(params.message),
params.recvID,
params.groupID,
JSON.stringify(offlinePushInfo),
params.isOnlineOnly ?? false
Number(!!params.isOnlineOnly)
);
}),
@@ -278,13 +284,17 @@ export function setupMessageModule(openIMSDK: OpenIMSDK) {
iOSBadgeCount: true,
};
openIMSDK.libOpenIMSDK.send_message_not_oss(
openIMSDK.sendMessageCallbackWrap<MessageItem>(resolve, reject),
openIMSDK.sendMessageCallbackWrap<MessageItem>(
params.message.clientMsgID,
resolve,
reject
),
opid,
JSON.stringify(params.message),
params.recvID,
params.groupID,
JSON.stringify(offlinePushInfo),
params.isOnlineOnly ?? false
Number(!!params.isOnlineOnly)
);
}),
@@ -423,6 +433,33 @@ export function setupMessageModule(openIMSDK: OpenIMSDK) {
params.localEx
);
}),
sendGroupMessageReadReceipt: (
params: SendGroupReadReceiptParams,
opid = uuidV4()
) =>
new Promise<BaseResponse<void>>((resolve, reject) => {
openIMSDK.libOpenIMSDK.send_group_message_read_receipt(
openIMSDK.baseCallbackWrap<void>(resolve, reject),
opid,
params.conversationID,
JSON.stringify(params.clientMsgIDList)
);
}),
getGroupMessageReaderList: (
params: GetGroupMessageReaderParams,
opid = uuidV4()
) =>
new Promise<BaseResponse<string[]>>((resolve, reject) => {
openIMSDK.libOpenIMSDK.get_group_message_reader_list(
openIMSDK.baseCallbackWrap<string[]>(resolve, reject),
opid,
params.conversationID,
params.clientMsgID,
params.filter,
params.offset,
params.count
);
}),
};
}
@@ -565,4 +602,12 @@ export interface MessageModuleApi {
params: SetMessageLocalExParams,
opid?: string
) => Promise<BaseResponse<void>>;
sendGroupMessageReadReceipt: (
params: SendGroupReadReceiptParams,
opid?: string
) => Promise<BaseResponse<void>>;
getGroupMessageReaderList: (
params: GetGroupMessageReaderParams,
opid?: string
) => Promise<BaseResponse<string[]>>;
}

View File

@@ -0,0 +1,220 @@
import { v4 as uuidV4 } from 'uuid';
import OpenIMSDK from '..';
import { BaseResponse } from '@/types/entity';
import {
CreateMeetingParams,
CustomSignalParams,
MeetingOperateStreamParams,
RtcActionParams,
SignalingInviteParams,
UpdateMeetingParams,
} from 'open-im-sdk-wasm/lib/types/params';
import {
RtcInviteResults,
CallingRoomData,
MeetingRecord,
} from 'open-im-sdk-wasm/lib/types/entity';
export function setupSignalingModule(openIMSDK: OpenIMSDK) {
return {
signalingInviteInGroup: (params: SignalingInviteParams, opid = uuidV4()) =>
new Promise<BaseResponse<RtcInviteResults>>((resolve, reject) => {
openIMSDK.libOpenIMSDK.signaling_invite_in_group(
openIMSDK.baseCallbackWrap<RtcInviteResults>(resolve, reject),
opid,
JSON.stringify(params)
);
}),
signalingInvite: (params: SignalingInviteParams, opid = uuidV4()) =>
new Promise<BaseResponse<RtcInviteResults>>((resolve, reject) => {
openIMSDK.libOpenIMSDK.signaling_invite(
openIMSDK.baseCallbackWrap<RtcInviteResults>(resolve, reject),
opid,
JSON.stringify(params)
);
}),
signalingCancel: (params: RtcActionParams, opid = uuidV4()) =>
new Promise<BaseResponse<void>>((resolve, reject) => {
openIMSDK.libOpenIMSDK.signaling_cancel(
openIMSDK.baseCallbackWrap<void>(resolve, reject),
opid,
JSON.stringify(params)
);
}),
signalingAccept: (params: RtcActionParams, opid = uuidV4()) =>
new Promise<BaseResponse<RtcInviteResults>>((resolve, reject) => {
openIMSDK.libOpenIMSDK.signaling_accept(
openIMSDK.baseCallbackWrap<RtcInviteResults>(resolve, reject),
opid,
JSON.stringify(params)
);
}),
signalingReject: (params: RtcActionParams, opid = uuidV4()) =>
new Promise<BaseResponse<void>>((resolve, reject) => {
openIMSDK.libOpenIMSDK.signaling_reject(
openIMSDK.baseCallbackWrap<void>(resolve, reject),
opid,
JSON.stringify(params)
);
}),
signalingHungUp: (params: RtcActionParams, opid = uuidV4()) =>
new Promise<BaseResponse<void>>((resolve, reject) => {
openIMSDK.libOpenIMSDK.signaling_hung_up(
openIMSDK.baseCallbackWrap<void>(resolve, reject),
opid,
JSON.stringify(params)
);
}),
signalingGetRoomByGroupID: (groupID: string, opid = uuidV4()) =>
new Promise<BaseResponse<CallingRoomData>>((resolve, reject) => {
openIMSDK.libOpenIMSDK.signaling_get_room_by_group_id(
openIMSDK.baseCallbackWrap<CallingRoomData>(resolve, reject),
opid,
groupID
);
}),
signalingGetTokenByRoomID: (roomID: string, opid = uuidV4()) =>
new Promise<BaseResponse<RtcInviteResults>>((resolve, reject) => {
openIMSDK.libOpenIMSDK.signaling_get_token_by_room_id(
openIMSDK.baseCallbackWrap<RtcInviteResults>(resolve, reject),
opid,
roomID
);
}),
signalingSendCustomSignal: (params: CustomSignalParams, opid = uuidV4()) =>
new Promise<BaseResponse<void>>((resolve, reject) => {
openIMSDK.libOpenIMSDK.signaling_send_custom_signal(
openIMSDK.baseCallbackWrap<void>(resolve, reject),
opid,
JSON.stringify(params.customInfo),
params.roomID
);
}),
signalingCreateMeeting: (params: CreateMeetingParams, opid = uuidV4()) =>
new Promise<BaseResponse<RtcInviteResults>>((resolve, reject) => {
openIMSDK.libOpenIMSDK.signaling_create_meeting(
openIMSDK.baseCallbackWrap<RtcInviteResults>(resolve, reject),
opid,
JSON.stringify(params)
);
}),
signalingJoinMeeting: (roomID: string, opid = uuidV4()) =>
new Promise<BaseResponse<RtcInviteResults>>((resolve, reject) => {
openIMSDK.libOpenIMSDK.signaling_join_meeting(
openIMSDK.baseCallbackWrap<RtcInviteResults>(resolve, reject),
opid,
JSON.stringify({
roomID,
})
);
}),
signalingUpdateMeetingInfo: (
params: Partial<UpdateMeetingParams> & { roomID: string },
opid = uuidV4()
) =>
new Promise<BaseResponse<void>>((resolve, reject) => {
openIMSDK.libOpenIMSDK.signaling_update_meeting_info(
openIMSDK.baseCallbackWrap<void>(resolve, reject),
opid,
JSON.stringify(params)
);
}),
signalingCloseRoom: (roomID: string, opid = uuidV4()) =>
new Promise<BaseResponse<void>>((resolve, reject) => {
openIMSDK.libOpenIMSDK.signaling_close_room(
openIMSDK.baseCallbackWrap<void>(resolve, reject),
opid,
roomID
);
}),
signalingGetMeetings: (opid = uuidV4()) =>
new Promise<BaseResponse<{ meetingInfoList: MeetingRecord[] }>>(
(resolve, reject) => {
openIMSDK.libOpenIMSDK.signaling_get_meetings(
openIMSDK.baseCallbackWrap<{ meetingInfoList: MeetingRecord[] }>(
resolve,
reject
),
opid
);
}
),
signalingOperateStream: (
params: MeetingOperateStreamParams,
opid = uuidV4()
) =>
new Promise<BaseResponse<void>>((resolve, reject) => {
openIMSDK.libOpenIMSDK.signaling_operate_stream(
openIMSDK.baseCallbackWrap<void>(resolve, reject),
opid,
params.streamType,
params.roomID,
params.userID ?? '',
params.mute ? 1 : 0,
params.muteAll ? 1 : 0
);
}),
};
}
export interface SignalingModuleApi {
signalingInviteInGroup: (
params: SignalingInviteParams,
opid?: string
) => Promise<BaseResponse<RtcInviteResults>>;
signalingInvite: (
params: SignalingInviteParams,
opid?: string
) => Promise<BaseResponse<RtcInviteResults>>;
signalingCancel: (
params: RtcActionParams,
opid?: string
) => Promise<BaseResponse<void>>;
signalingAccept: (
params: RtcActionParams,
opid?: string
) => Promise<BaseResponse<RtcInviteResults>>;
signalingReject: (
params: RtcActionParams,
opid?: string
) => Promise<BaseResponse<void>>;
signalingHungUp: (
params: RtcActionParams,
opid?: string
) => Promise<BaseResponse<void>>;
signalingGetRoomByGroupID: (
groupID: string,
opid?: string
) => Promise<BaseResponse<CallingRoomData>>;
signalingGetTokenByRoomID: (
roomID: string,
opid?: string
) => Promise<BaseResponse<RtcInviteResults>>;
signalingSendCustomSignal: (
params: CustomSignalParams,
opid?: string
) => Promise<BaseResponse<void>>;
signalingCreateMeeting: (
params: CreateMeetingParams,
opid?: string
) => Promise<BaseResponse<RtcInviteResults>>;
signalingJoinMeeting: (
meetingID: string,
opid?: string
) => Promise<BaseResponse<RtcInviteResults>>;
signalingUpdateMeetingInfo: (
params: Partial<UpdateMeetingParams> & { roomID: string },
opid?: string
) => Promise<BaseResponse<void>>;
signalingCloseRoom: (
roomID: string,
opid?: string
) => Promise<BaseResponse<void>>;
signalingGetMeetings: (
opid?: string
) => Promise<BaseResponse<{ meetingInfoList: MeetingRecord[] }>>;
signalingOperateStream: (
params: MeetingOperateStreamParams,
opid?: string
) => Promise<BaseResponse<void>>;
}

View File

@@ -1,3 +1,3 @@
import OpenIMSDK from './core';
import OpenIMSDKMain from './main';
export default OpenIMSDK;
export default OpenIMSDKMain;

41
src/main.ts Normal file
View File

@@ -0,0 +1,41 @@
import { ipcMain, WebContents } from 'electron';
import { CbEvents } from 'open-im-sdk-wasm';
import OpenIMSDK from './core';
class OpenIMSDKMain {
private sdk: OpenIMSDK;
private webContents: WebContents[] = [];
constructor(path: string, webContent?: WebContents) {
this.sdk = new OpenIMSDK(path, this.emitProxy);
if (webContent) {
this.webContents = [webContent];
}
this.initMethodsHandler();
}
private initMethodsHandler = () => {
ipcMain.handle('openim-sdk-ipc-methods', async (_, method, ...args) => {
try {
// @ts-ignore
// eslint-disable-next-line
return await this.sdk[method](...args);
} catch (error) {
return error;
}
});
};
private emitProxy = (event: CbEvents, data: any) => {
this.webContents.forEach(webContent => {
if (!webContent.isDestroyed()) {
webContent.send('openim-sdk-ipc-event', event, data);
}
});
};
public addWebContent(webContent: WebContents) {
this.webContents.push(webContent);
}
}
export default OpenIMSDKMain;

11
src/preload.ts Normal file
View File

@@ -0,0 +1,11 @@
import { contextBridge, ipcRenderer } from 'electron';
contextBridge.exposeInMainWorld('openIMRenderApi', {
subscribe: (channel: string, callback: (...args: any[]) => void) => {
const subscription = (_: unknown, ...args: any[]) => callback(...args);
ipcRenderer.on(channel, subscription);
return () => ipcRenderer.removeListener(channel, subscription);
},
imMethodsInvoke: (method: string, ...args: any[]) =>
ipcRenderer.invoke('openim-sdk-ipc-methods', method, ...args),
});

View File

@@ -93,6 +93,7 @@ type CreateElectronOptions = {
};
let wasmSDK: IMSDKInterface | undefined;
let instance: IMSDKInterface | undefined;
const sdkEmitter = new Emitter();
// eslint-disable-next-line
@@ -109,38 +110,49 @@ export function getWithRenderProcess({
wasmConfig,
invoke,
}: CreateElectronOptions) {
const interalInvoke = invoke ?? window.openIMRenderApi?.imMethodsInvoke;
const subscribeCallback = (event: keyof EmitterEvents, data: any) =>
sdkEmitter.emit(event, data);
if (instance) {
return {
instance,
subscribeCallback,
};
}
if (!interalInvoke && !wasmSDK) {
createWasmSDK(wasmConfig);
}
window.openIMRenderApi?.subscribe('openim-sdk-ipc-event', subscribeCallback);
const sdkProxyHandler: ProxyHandler<IMSDKInterface> = {
get(_, prop: keyof IMSDKInterface) {
return async (...args: any[]) => {
try {
if (!invoke) {
if (!interalInvoke) {
if (!wasmSDK) {
await createWasmSDK(wasmConfig);
if (!wasmSDK) throw new Error('WASM SDK is not available');
const cachedMethod = methodCache.get(wasmSDK[prop]);
}
const cachedMethod = methodCache.get(wasmSDK![prop]);
if (cachedMethod) {
// eslint-disable-next-line
return cachedMethod(...args);
}
// @ts-ignore
const method = async (...args: any[]) => wasmSDK![prop](...args);
methodCache.set(wasmSDK[prop], method);
methodCache.set(wasmSDK![prop], method);
return method(...args);
}
if (!subscribeCallback) {
console.warn('No subscribeCallback method provided');
}
if (prop === 'on' || prop === 'off') {
// @ts-ignore
return sdkEmitter[prop](...args);
}
const result = await invoke(prop, ...args);
if (result?.errCode) {
const result = await interalInvoke(prop, ...args);
if (result?.errCode !== 0 && prop !== 'initSDK') {
throw result;
}
return result;
@@ -152,8 +164,7 @@ export function getWithRenderProcess({
},
};
return {
subscribeCallback,
proxy: new Proxy({} as IMSDKInterface, sdkProxyHandler),
};
instance = new Proxy({} as IMSDKInterface, sdkProxyHandler);
return { instance, subscribeCallback };
}

15
src/types/global.d.ts vendored Normal file
View File

@@ -0,0 +1,15 @@
import { WsResponse } from 'open-im-sdk-wasm/lib/types/entity';
export interface IOpenIMRenderAPI {
subscribe: (
channel: string,
callback: (...args: any[]) => void
) => () => void;
imMethodsInvoke: (method: string, ...args: any[]) => Promise<WsResponse>;
}
declare global {
interface Window {
openIMRenderApi?: IOpenIMRenderAPI;
}
}

View File

@@ -15,6 +15,7 @@ declare module 'libOpenIMSDK' {
set_user_listener(cCallback: CB_I_S): void;
set_friend_listener(cCallback: CB_I_S): void;
set_custom_business_listener(cCallback: CB_I_S): void;
set_signaling_listener(cCallback: CB_I_S): void;
init_sdk(cCallback: CB_I_S, operationID: string, config: string): number;
un_init_sdk(operationID: string): void;
login(
@@ -169,6 +170,21 @@ declare module 'libOpenIMSDK' {
conversationID: string,
isMsgDestruct: number
): void;
send_group_message_read_receipt(
cCallback: CB_S_I_S_S,
operationID: string,
conversationID: string,
clientMsgIDList: string
): void;
get_group_message_reader_list(
cCallback: CB_S_I_S_S,
operationID: string,
conversationID: string,
clientMsgID: string,
filter: number,
offset: number,
count: number
): void;
hide_conversation(
cCallback: CB_S_I_S_S,
operationID: string,
@@ -237,7 +253,7 @@ declare module 'libOpenIMSDK' {
recvID: string,
groupID: string,
offlinePushInfo: string,
isOnlineOnly: boolean
isOnlineOnly: number
): void;
send_message_not_oss(
cCallback: CB_S_I_S_S_I,
@@ -246,7 +262,7 @@ declare module 'libOpenIMSDK' {
recvID: string,
groupID: string,
offlinePushInfo: string,
isOnlineOnly: boolean
isOnlineOnly: number
): void;
find_message_list(
cCallback: CB_S_I_S_S,
@@ -631,6 +647,92 @@ declare module 'libOpenIMSDK' {
operationID: string,
cGroupID: string
): void;
signaling_invite_in_group(
cCallback: CB_S_I_S_S,
operationID: string,
cSignalInviteInGroupReq: string
): void;
signaling_invite(
cCallback: CB_S_I_S_S,
operationID: string,
cSignalInviteReq: string
): void;
signaling_accept(
cCallback: CB_S_I_S_S,
operationID: string,
cSignalAcceptReq: string
): void;
signaling_reject(
cCallback: CB_S_I_S_S,
operationID: string,
cSignalRejectReq: string
): void;
signaling_cancel(
cCallback: CB_S_I_S_S,
operationID: string,
cSignalCancelReq: string
): void;
signaling_hung_up(
cCallback: CB_S_I_S_S,
operationID: string,
cSignalHungUpReq: string
): void;
signaling_get_room_by_group_id(
cCallback: CB_S_I_S_S,
operationID: string,
cGroupID: string
): void;
signaling_get_token_by_room_id(
cCallback: CB_S_I_S_S,
operationID: string,
cRoomID: string
): void;
get_signaling_invitation_info_start_app(
cCallback: CB_S_I_S_S,
operationID: string
): void;
signaling_create_meeting(
cCallback: CB_S_I_S_S,
operationID: string,
cSignalingCreateMeetingReq: string
): void;
signaling_join_meeting(
cCallback: CB_S_I_S_S,
operationID: string,
cSignalingJoinMeetingReq: string
): void;
signaling_update_meeting_info(
cCallback: CB_S_I_S_S,
operationID: string,
cSignalingUpdateMeetingInfoReq: string
): void;
signaling_close_room(
cCallback: CB_S_I_S_S,
operationID: string,
cRoomID: string
): void;
signaling_get_meetings(cCallback: CB_S_I_S_S, operationID: string): void;
signaling_operate_stream(
cCallback: CB_S_I_S_S,
operationID: string,
cStreamType: string,
cRoomID: string,
cUserID: string,
mute: number,
muteAll: number
): void;
signaling_send_custom_signal(
cCallback: CB_S_I_S_S,
operationID: string,
cCustomInfo: string,
cRoomID: string
): void;
upload_file(
cCallback: CB_S_I_S_S,
operationID: string,
cFileInfo: string,
pCallback: CB_I_S
): void;
}
const lib: LibOpenIMSDK;
export default lib;