├── .gitignore ├── App.vue ├── LICENSE ├── README-AV.md ├── README.md ├── api ├── appServerApi.js ├── appServerError.js ├── conferenceApi.js ├── organizationServerApi.js └── organizationServerError.js ├── assets ├── images │ ├── icon.png │ └── user-fallback.png └── lang │ ├── en.json │ ├── zh-CN.json │ └── zh-TW.json ├── common ├── forward.js ├── permission.js ├── picker.js └── stringify-object.js ├── components ├── chunLei-popups │ └── chunLei-popups.vue ├── main-action-menu │ └── main-action-menu.vue └── uni-list │ ├── uni-list.vue │ ├── uni-refresh.vue │ └── uni-refresh.wxs ├── config.js ├── emoji ├── emoji.js ├── twemoji.js └── universal-emoji-parser.js ├── global.css ├── index.html ├── main.js ├── manifest.json ├── package-lock.json ├── package.json ├── pages.json ├── pages ├── SplashPage.vue ├── common │ └── LoadingView.vue ├── contact │ ├── ChannelListPage.vue │ ├── ContactListPage.vue │ ├── FriendRequestDetailPage.vue │ ├── FriendRequestListView.vue │ ├── GroupDetailView.vue │ ├── GroupListPage.vue │ ├── GroupListView.vue │ ├── NewFriendListPage.vue │ ├── OrganizationListView.vue │ ├── OrganizationTreePage.vue │ ├── SearchUserPage.vue │ └── UserDetailPage.vue ├── conversation │ ├── ConversationPage.vue │ ├── GroupConversationInfoPage.vue │ ├── MessageInputView.vue │ ├── MessageMultiSelectActionView.vue │ ├── SingleConversationInfoPage.vue │ ├── emojiStickerConfig.js │ └── message │ │ ├── ArticlesMessageContentView.vue │ │ ├── AudioInputView.vue │ │ ├── CompositeMessagePage.vue │ │ ├── ContextableNotificationMessageContentContainerView.vue │ │ ├── DeleteMessageDialogView.vue │ │ ├── MessageContentContainerView.vue │ │ ├── MessageReceiptDetailView.vue │ │ ├── NormalInMessageContentContainerView.vue │ │ ├── NormalOutMessageContentContainerView.vue │ │ ├── NotificationMessageContentView.vue │ │ ├── PreviewMessageView.vue │ │ ├── PreviewQuotedMessageView.vue │ │ ├── PttAudioInputView.vue │ │ ├── QuoteMessageView.vue │ │ ├── RecallNotificationMessageContentView.vue │ │ ├── RichNotificationMessageContentView.vue │ │ ├── content │ │ ├── AudioMessageContentViewAMR.vue │ │ ├── AudioMessageContentViewAPP.vue │ │ ├── CallStartMessageContentView.vue │ │ ├── CompositeMessageContentView.vue │ │ ├── ConferenceInviteMessageContentView.vue │ │ ├── FileMessageContentView.vue │ │ ├── ImageMessageContentView.vue │ │ ├── StickerMessageContentView.vue │ │ ├── StreamingTextMessageContentView.vue │ │ ├── TestCustomMessageContentView.vue │ │ ├── TextMessageContentView.vue │ │ ├── UnknownMessageContentView.vue │ │ ├── UnsupportMessageContentView.vue │ │ ├── UserCardMessageContentView.vue │ │ └── VideoMessageContentView.vue │ │ └── forward │ │ ├── ForwardMessageByCreateConversationView.vue │ │ ├── ForwardMessageByPickConversationView.vue │ │ ├── ForwardMessagePage.vue │ │ ├── ForwardMessageView.vue │ │ └── ForwardType.js ├── conversationList │ ├── ConversationItemView.vue │ └── ConversationListPage.vue ├── discovery │ ├── ChatroomListPage.vue │ └── DiscoveryPage.vue ├── login │ ├── LoginPage.vue │ └── login.css ├── me │ └── MePage.vue ├── misc │ ├── ApiTestPage.nvue │ ├── ApiTestPage.vue │ ├── PreviewVideoPage.vue │ └── WebViewPage.vue ├── pick │ ├── CheckableOrganizationTreeView.vue │ ├── PickSingleUserPage.vue │ ├── PickUserPage.vue │ └── PickerConversationPage.vue ├── search │ ├── SearchConversationMessagePage.vue │ ├── SearchPortalPage.vue │ └── SearchResultView.vue ├── test │ ├── testPage.vue │ └── testWebrtc.vue ├── user │ ├── CheckableUserListView.vue │ └── UserListView.vue ├── util │ ├── clipboard.js │ ├── draft.js │ ├── helper.js │ ├── imageUtil.js │ └── storageHelper.js ├── voip │ ├── Multi.nvue │ ├── Single.nvue │ ├── conference │ │ ├── ChooseConferenceLayoutView.vue │ │ ├── ConferenceApplyUnmuteAudioListView.vue │ │ ├── ConferenceApplyUnmuteVideoListView.vue │ │ ├── ConferenceConversationFloatingView.vue │ │ ├── ConferenceHandUpListView.vue │ │ ├── ConferenceInfoPage.vue │ │ ├── ConferenceManagePage.vue │ │ ├── ConferencePage.nvue │ │ ├── ConferenceParticipantListView.vue │ │ ├── ConferenceParticipantVideoView.nvue │ │ ├── ConferencePortalPage.vue │ │ ├── ConferenceSimpleInfoView.vue │ │ ├── CreateConferencePage.vue │ │ ├── JoinConferencePage.vue │ │ ├── OrderConferencePage.vue │ │ └── conferenceManager.js │ └── voipUtil.js └── workspace │ ├── WorkspacePage.nvue │ ├── WorkspaceWebViewPage.nvue │ ├── bridge.js │ ├── bridgeClientImpl.uni.js │ └── bridgeServerImpl.js ├── pstore.js ├── screenshots ├── uniapp_contact_tab.jpeg ├── uniapp_conversation.jpeg ├── uniapp_conversation_list.jpeg └── uniapp_user_profile.jpeg ├── static ├── audios │ ├── audido_msg_send_success.mp3 │ ├── audio_msg_play_completion.mp3 │ ├── incoming_call_ring.mp3 │ ├── outgoing_call_ring.mp3 │ ├── ptt_begin.mp3 │ └── ptt_end.mp3 ├── iconfonts │ ├── customicons.css │ ├── customicons.ttf │ ├── icomoon │ │ ├── fonts │ │ │ └── icomoon.ttf │ │ └── style.css │ └── wx_iconfont.ttf ├── image │ ├── av │ │ ├── add.png │ │ ├── av_book_conference.png │ │ ├── av_camera.png │ │ ├── av_camera_hover.png │ │ ├── av_conference_audio.png │ │ ├── av_conference_audio_mute.png │ │ ├── av_conference_end_call.png │ │ ├── av_conference_handup.png │ │ ├── av_conference_handup_hover.png │ │ ├── av_conference_members.png │ │ ├── av_conference_screen_sharing.png │ │ ├── av_conference_screen_sharing_hover.png │ │ ├── av_conference_video.png │ │ ├── av_conference_video_mute.png │ │ ├── av_float_audio.png │ │ ├── av_handfree.png │ │ ├── av_handfree_hover.png │ │ ├── av_hang_up.png │ │ ├── av_hang_up_hover.png │ │ ├── av_join_conference.png │ │ ├── av_minimize.png │ │ ├── av_mute.png │ │ ├── av_mute_hover.png │ │ ├── av_phone.png │ │ ├── av_share.png │ │ ├── av_start_conference.png │ │ ├── av_video_answer.png │ │ ├── av_video_answer_hover.png │ │ └── ic_conference.png │ ├── chat │ │ ├── extra.png │ │ ├── extra │ │ │ ├── choose_picture.png │ │ │ ├── close_chat.png │ │ │ └── take_photos.png │ │ ├── popu_blue.png │ │ ├── popu_white.png │ │ ├── send_fail.png │ │ └── voice │ │ │ ├── attention.png │ │ │ ├── keyboard.png │ │ │ ├── recall.png │ │ │ ├── speak.png │ │ │ ├── voice.png │ │ │ ├── voice_mine.png │ │ │ └── voice_other.png │ ├── filetypes │ │ ├── ai.png │ │ ├── apk.png │ │ ├── archive.png │ │ ├── audio.png │ │ ├── excel.png │ │ ├── exe.png │ │ ├── image.png │ │ ├── ipa.png │ │ ├── pdf.png │ │ ├── ppt.png │ │ ├── psd.png │ │ ├── unknow.png │ │ ├── video.png │ │ └── word.png │ ├── icon │ │ ├── ic_channel.png │ │ ├── ic_channel_1.png │ │ ├── ic_chatroom.png │ │ ├── ic_conference.png │ │ ├── ic_dev_docs.png │ │ ├── ic_group_chat.png │ │ ├── ic_new_friend.png │ │ ├── ic_organization.png │ │ └── ic_robot.png │ ├── logo.png │ └── tabbar │ │ ├── contact_normal.png │ │ ├── contact_press.png │ │ ├── discovery_normal.png │ │ ├── discovery_press.png │ │ ├── me_normal.png │ │ ├── me_press.png │ │ ├── message_normal.png │ │ ├── message_press.png │ │ ├── work_normal.png │ │ └── work_press.png └── js │ └── bridgeClientImpl.js ├── store.js ├── uni.scss ├── uni_modules ├── uni-popup │ ├── changelog.md │ ├── components │ │ ├── uni-popup-dialog │ │ │ ├── keypress.js │ │ │ └── uni-popup-dialog.vue │ │ ├── uni-popup-message │ │ │ └── uni-popup-message.vue │ │ ├── uni-popup-share │ │ │ └── uni-popup-share.vue │ │ └── uni-popup │ │ │ ├── i18n │ │ │ ├── en.json │ │ │ ├── index.js │ │ │ ├── zh-Hans.json │ │ │ └── zh-Hant.json │ │ │ ├── keypress.js │ │ │ ├── popup.js │ │ │ └── uni-popup.vue │ ├── package.json │ └── readme.md ├── uni-scss │ ├── changelog.md │ ├── index.scss │ ├── package.json │ ├── readme.md │ ├── styles │ │ ├── index.scss │ │ ├── setting │ │ │ ├── _border.scss │ │ │ ├── _color.scss │ │ │ ├── _radius.scss │ │ │ ├── _space.scss │ │ │ ├── _styles.scss │ │ │ ├── _text.scss │ │ │ └── _variables.scss │ │ └── tools │ │ │ └── functions.scss │ ├── theme.scss │ └── variables.scss └── uni-transition │ ├── changelog.md │ ├── components │ └── uni-transition │ │ ├── createAnimation.js │ │ └── uni-transition.vue │ ├── package.json │ └── readme.md ├── vite.config.js ├── wfc.css ├── wfc ├── av │ ├── engine │ │ ├── avengineCallback.js │ │ ├── avengineKit.js │ │ ├── callEndReason.js │ │ ├── callSession.js │ │ ├── callSessionCallback.js │ │ ├── callState.js │ │ ├── participantProfile.js │ │ ├── videoProfile.js │ │ └── videoType.js │ ├── messages │ │ ├── addParticipantsMessageContent.js │ │ ├── callAnswerMessageContent.js │ │ ├── callAnswerTMessageContent.js │ │ ├── callByeMessageContent.js │ │ ├── callModifyMessageContent.js │ │ ├── callSignalMessageContent.js │ │ ├── callStartMessageContent.js │ │ ├── conferenceChangeModeContent.js │ │ ├── conferenceCommandMessageContent.js │ │ ├── conferenceInviteMessageContent.js │ │ ├── conferenceKickoffMemberMessageContent.js │ │ ├── joinCallRequestMessageContent.js │ │ ├── multiCallOngoingMessageContent.js │ │ └── muteVideoMessageContent.js │ └── model │ │ └── conferenceInfo.js ├── client │ ├── connectionStatus.js │ ├── errorCode.js │ ├── messageConfig.js │ ├── userSettingScope.js │ ├── wfc.js │ └── wfcEvent.js ├── messages │ ├── ModifyChannelInfoType.js │ ├── articlesMessageContent.js │ ├── cardMessageContent.js │ ├── channelMenuEventMessageContent.js │ ├── compositeMessageContent.js │ ├── deleteMessageContent.js │ ├── enterChannelChatMessageContent.js │ ├── fileMessageContent.js │ ├── imageMessageContent.js │ ├── leaveChannelChatMessageContent.js │ ├── linkMessageContent.js │ ├── locationMessageContent.js │ ├── markUnreadMessageContent.js │ ├── mediaMessageContent.js │ ├── message.js │ ├── messageContent.js │ ├── messageContentMediaType.js │ ├── messageContentType.js │ ├── messagePayload.js │ ├── messageStatus.js │ ├── notification │ │ ├── addGroupMemberNotification.js │ │ ├── allowGroupMemberNotification.js │ │ ├── changeGroupNameNotification.js │ │ ├── changeGroupPortraitNotification.js │ │ ├── chatRoomWelcomeNotificationContent.js │ │ ├── createGroupNotification.js │ │ ├── dismissGroupNotification.js │ │ ├── friendAddedNotification.js │ │ ├── friendGreetingNotification.js │ │ ├── groupJoinTypeNotificationContent.js │ │ ├── groupMuteNotificationContent.js │ │ ├── groupNotification.js │ │ ├── groupPrivateChatNotificationContent.js │ │ ├── groupSetManagerNotificationContent.js │ │ ├── kickoffGroupMemberNotification.js │ │ ├── kickoffGroupMemberVisiableNotification.js │ │ ├── modifyGroupAliasNotification.js │ │ ├── modifyGroupExtraNotification.js │ │ ├── modifyGroupMemberExtraNotification.js │ │ ├── muteGroupMemberNotification.js │ │ ├── notificationMessageContent.js │ │ ├── quitGroupNotification.js │ │ ├── quitGroupVisiableNotification.js │ │ ├── recallMessageNotification.js │ │ ├── richNotificationMessageContent.js │ │ ├── startSecretChatNotification.js │ │ ├── templateNotification.js │ │ ├── tipNotification.js │ │ └── transferGroupOwnerNotification.js │ ├── pcLoginRequestMessageContent.js │ ├── persistFlag.js │ ├── ptextMessageContent.js │ ├── soundMessageContent.js │ ├── stickerMessageContent.js │ ├── streamingTextGeneratedMessageContent.js │ ├── streamingTextGeneratingMessageContent.js │ ├── textMessageContent.js │ ├── typingMessageContent.js │ ├── unknownMessageContent.js │ ├── unsupportMessageConten.js │ └── videoMessageContent.js ├── model │ ├── NullChannelInfo.js │ ├── channelInfo.js │ ├── channelMenu.js │ ├── chatRoomInfo.js │ ├── chatRoomMemberInfo.js │ ├── conversation.js │ ├── conversationInfo.js │ ├── conversationSearchResult.js │ ├── conversationType.js │ ├── favItem.js │ ├── fileRecord.js │ ├── friend.js │ ├── friendRequest.js │ ├── groupInfo.js │ ├── groupMember.js │ ├── groupMemberType.js │ ├── groupSearchResult.js │ ├── groupType.js │ ├── internal │ │ └── friendInfo.js │ ├── mention.js │ ├── modifyGroupInfoType.js │ ├── modifyMyInfoEntry.js │ ├── modifyMyInfoType.js │ ├── nullGroupInfo.js │ ├── nullUserInfo.js │ ├── pcsession.js │ ├── quoteInfo.js │ ├── readEntry.js │ ├── searchType.js │ ├── secretChatInfo.js │ ├── secretChatState.js │ ├── unreadCount.js │ ├── userClientState.js │ ├── userCustomState.js │ ├── userInfo.js │ ├── userOnlineState.js │ └── userSettingEntry.js ├── proto │ └── proto.min.js ├── ptt │ ├── messages │ │ └── pttSoundMessageContent.js │ ├── pttClient.js │ ├── pttEndReason.js │ ├── pttErrorCode.js │ ├── pttEventType.js │ └── talkingCallback.js └── util │ ├── base64.min.js │ └── longUtil.js ├── wfcScheme.js └── wfc_custom_message ├── README.md ├── customMessageConfig.js ├── customMessageContentType.js ├── testCustomMessageContent.js └── testCustomNotificationMessageContent.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | unpackage/resources/__UNI__* 3 | unpackage 4 | .hbuilderx 5 | .idea 6 | nativeplugins 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 野火IM 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README-AV.md: -------------------------------------------------------------------------------- 1 | # 音视频SDK使用说明 2 | 3 | 默认使用的是免费版多人音视频,可以更换音视频高级版,支持更高质量的音视频通话和会议功能。关于免费音视频和音视频高级版的区别,请参考[野火音视频简介](https://docs.wildfirechat.cn/blogs/野火音视频简介.html)和[野火音视频使用说明](https://docs.wildfirechat.cn/webrtc/)。 4 | 5 | 6 | ## 音视频高级版的使用说明 7 | 音视频高级版包括专业版IM服务,[janus服务](https://gitee.com/wfchat/wf-janus)和客户端音视频高级版SDK。在服务端部署专业版IM服务和janus服务后,客户端需要替换野火发给客户的SDK,替换以后就可以发起音视频通话了。音视频高级版不需要turn服务,不用部署和配置turn服务。 8 | 9 | 替换方法:下载[【官方】野火实时音视频RTC插件](https://ext.dcloud.net.cn/plugin?id=15619),然后替换野火音视频高级版SDK,android平台是```avenginekit.aar```,iOS平台是```WFAVEngineKit.xcframework```。然后使用本地插件。 -------------------------------------------------------------------------------- /api/appServerError.js: -------------------------------------------------------------------------------- 1 | export default class AppServerError extends Error { 2 | errorCode; 3 | 4 | constructor(errorCode, message) { 5 | super(message); 6 | this.errorCode = errorCode; 7 | } 8 | 9 | toString() { 10 | return this.errorCode + '-' + this.message; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /api/organizationServerError.js: -------------------------------------------------------------------------------- 1 | export default class OrganizationServerError extends Error { 2 | errorCode; 3 | 4 | constructor(errorCode, message) { 5 | super(message); 6 | this.errorCode = errorCode; 7 | } 8 | 9 | toString() { 10 | return this.errorCode + '-' + this.message; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /assets/images/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/assets/images/icon.png -------------------------------------------------------------------------------- /assets/images/user-fallback.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/assets/images/user-fallback.png -------------------------------------------------------------------------------- /common/forward.js: -------------------------------------------------------------------------------- 1 | import store from "../store"; 2 | 3 | export default { 4 | install(app, options) { 5 | app.config.globalProperties.$forward = function (options) { 6 | uni.navigateTo({ 7 | url: '/pages/conversation/message/forward/ForwardMessagePage', 8 | events: { 9 | // pickedUsers: users => { 10 | // options.successCB && options.successCB(users); 11 | // } 12 | }, 13 | 14 | success: (res) => { 15 | console.log('navigate success', res); 16 | res.eventChannel.emit('forwardOptions', { 17 | forwardType: options.forwardType, 18 | messages: options.messages, 19 | }); 20 | }, 21 | fail: (err) => { 22 | console.log('navigate error', err) 23 | }, 24 | complete: () => { 25 | console.log('navigate complete'); 26 | } 27 | }) 28 | }; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /common/picker.js: -------------------------------------------------------------------------------- 1 | import store from "../store"; 2 | 3 | export default { 4 | install(app, options) { 5 | app.config.globalProperties.$pickUsers = function (options) { 6 | uni.navigateTo({ 7 | url: '/pages/pick/PickUserPage', 8 | events: { 9 | pickedUsers: users => { 10 | options.successCB && options.successCB(users); 11 | } 12 | }, 13 | 14 | success: (res) => { 15 | res.eventChannel.emit('pickOptions', { 16 | users: options.users ? options.users : store.state.contact.favContactList.concat(store.state.contact.friendList), 17 | initialCheckedUsers: options.initialCheckedUsers, 18 | uncheckableUsers: options.uncheckableUsers, 19 | showCategoryLabel: options.showCategoryLabel !== false, 20 | confirmTitle: options.confirmTitle ? options.confirmTitle : '确定', 21 | }); 22 | } 23 | }) 24 | }; 25 | 26 | app.config.globalProperties.$pickUser = function (options) { 27 | uni.navigateTo({ 28 | url: '/pages/pick/PickSingleUserPage', 29 | events: { 30 | pickedUser: user => { 31 | options.successCB && options.successCB(user); 32 | } 33 | }, 34 | 35 | success: (res) => { 36 | res.eventChannel.emit('pickOptions', { 37 | users: options.users ? options.users : store.state.contact.favContactList.concat(store.state.contact.friendList), 38 | showCategoryLabel: options.showCategoryLabel !== false, 39 | confirmTitle: options.confirmTitle ? options.confirmTitle : '确定', 40 | }); 41 | } 42 | }) 43 | }; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /components/uni-list/uni-refresh.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 59 | 60 | -------------------------------------------------------------------------------- /emoji/emoji.js: -------------------------------------------------------------------------------- 1 | import anchorme from "anchorme"; 2 | import twemoji from "twemoji"; 3 | import Config from "../config"; 4 | 5 | const emoji = []; 6 | 7 | 8 | function parser(text) { 9 | var decodeText = anchorme({ 10 | input: text, 11 | options: { 12 | attributes: { 13 | target: "_blank", 14 | } 15 | 16 | } 17 | }); 18 | 19 | // (text.match(/\[[\w\s\u4E00-\u9FCC\u3400-\u4DB5\uFA0E\uFA0F\uFA11\uFA13\uFA14\uFA1F\uFA21\uFA23\uFA24\uFA27-\uFA29\ud840-\ud868\udc00-\udfff\ud869[\udc00-\uded6\udf00-\udfff\ud86a-\ud86c\udc00-\udfff\ud86d[\udc00-\udf34\udf40-\udfff\ud86e\udc00-\udc1d]+\]/g) || []).map(e => { 20 | // var className = getEmojiClassName(e); 21 | // 22 | // if (!className) { 23 | // // Invalid emoji 24 | // return; 25 | // } 26 | // text = decodeText = text.split(`${e}`).join(``); 27 | // }); 28 | 29 | let emoji = twemoji.parse(decodeText); 30 | emoji = emoji.replace(/src="https:\/\/twemoji\.maxcdn\.com\/v\/[0-9.]+\//g, 'src="' + Config.emojiBaseUrl()) 31 | return emoji; 32 | } 33 | 34 | function normalize(text = '') { 35 | var matchs = text.match(/<\/span>/g) || []; 36 | var decodeText = text; 37 | 38 | try { 39 | matchs.map(e => { 40 | // Decode utf16 to emoji 41 | var emojiCode = e.match(/emoji([0-9a-fA-F]+)/)[1].substr(0, 5); 42 | var emoji = String.fromCodePoint(parseInt(emojiCode, 16)); 43 | text = decodeText = text.split(e).join(emoji); 44 | }); 45 | } catch (ex) { 46 | console.error('Failed decode %s: %o', text, ex); 47 | } 48 | return decodeText; 49 | } 50 | 51 | export {emoji, parser, normalize}; 52 | -------------------------------------------------------------------------------- /emoji/universal-emoji-parser.js: -------------------------------------------------------------------------------- 1 | import twemoji from './twemoji' 2 | import emojilib from 'emojilib' 3 | 4 | /** 5 | * Parse text with emoji support 6 | * @return {string} 7 | */ 8 | const uEmojiParser = { 9 | getEmojiObjectByCode(emojiCode) { 10 | emojiCode = emojiCode.replace(/:/g, '') 11 | if (emojilib.lib[emojiCode] && typeof emojilib.lib[emojiCode] === 'object' && emojilib.lib[emojiCode].char) { 12 | return emojilib.lib[emojiCode] 13 | } else { 14 | let emojiKey = Object.keys(emojilib.lib).find(emojiKey => emojilib.lib[emojiKey].keywords.includes(emojiCode)) 15 | if (!!emojiKey) { 16 | return emojilib.lib[emojiKey] 17 | } 18 | } 19 | 20 | return undefined 21 | }, 22 | parse(text) { 23 | if (typeof text !== 'string') { 24 | throw new Error('The text parameter should be a string.'); 25 | } 26 | 27 | const emojisRegExp = /:(\w+):/g 28 | const emojisList = text.match(emojisRegExp) 29 | if (emojisList) { 30 | emojisList.forEach((emojiCode) => { 31 | const emoji = this.getEmojiObjectByCode(emojiCode) 32 | if (emoji) { 33 | const regEx = new RegExp(emojiCode) 34 | text = text.replace(regEx, emoji.char) 35 | } 36 | }) 37 | } 38 | return twemoji.parse(text) 39 | } 40 | } 41 | 42 | module.exports = uEmojiParser -------------------------------------------------------------------------------- /global.css: -------------------------------------------------------------------------------- 1 | * { 2 | margin: 0; 3 | padding: 0; 4 | box-sizing: border-box; 5 | -webkit-app-region: no-drag; 6 | } 7 | 8 | img.emoji { 9 | height: 1em !important; 10 | width: 1em !important; 11 | margin: 0 .05em 0 .1em; 12 | vertical-align: -0.1em; 13 | user-select: none; 14 | } 15 | 16 | .single-line { 17 | max-width: 100%; 18 | text-overflow: ellipsis; 19 | overflow: hidden; 20 | white-space: nowrap; 21 | } 22 | 23 | ul, 24 | ol { 25 | list-style: none; 26 | } 27 | 28 | div, 29 | button, 30 | img, 31 | video { 32 | outline: none; 33 | } 34 | 35 | p, 36 | div { 37 | word-break: break-all; 38 | user-select: none; 39 | } 40 | 41 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 野火IM 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "uni-chat", 3 | "version": "1.0.0", 4 | "main": "main.js", 5 | "author": "wfc", 6 | "license": "MIT", 7 | "dependencies": { 8 | "anchorme": "^2.1.2", 9 | "base64-arraybuffer": "^1.0.2", 10 | "emojilib": "^3.0.6", 11 | "events": "^3.3.0", 12 | "long": "^5.2.0", 13 | "mitt": "^3.0.1", 14 | "pinia": "^2.0.33", 15 | "pinyin": "^4.0.0-alpha.0", 16 | "resize-image": "^0.1.0", 17 | "segmentit": "^2.0.3", 18 | "twemoji": "^14.0.2", 19 | "universal-emoji-parser": "1.0.125", 20 | "vue": "^3.2.8", 21 | "vue-i18n": "^9.9.1" 22 | }, 23 | "devDependencies": { 24 | "@vitejs/plugin-vue": "^1.6.0", 25 | "@vue/compiler-sfc": "^3.2.6", 26 | "vite": "^2.5.2" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /pages/SplashPage.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 40 | 41 | -------------------------------------------------------------------------------- /pages/contact/ChannelListPage.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | {{ channel.name }} 7 | 8 | 9 | 10 | 11 | 12 | 13 | 35 | 36 | 62 | -------------------------------------------------------------------------------- /pages/contact/GroupDetailView.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {{ $t('group.name', [sharedContactState.currentGroup.name]) }} 6 | 7 | {{ $t('group.chat') }} 8 | 9 | 10 | 11 | 34 | 35 | 80 | -------------------------------------------------------------------------------- /pages/contact/GroupListPage.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 38 | 39 | 42 | -------------------------------------------------------------------------------- /pages/contact/GroupListView.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {{ group.name }} 6 | 7 | 8 | 9 | 10 | 11 | 33 | 34 | 58 | -------------------------------------------------------------------------------- /pages/contact/NewFriendListPage.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 49 | 50 | 57 | -------------------------------------------------------------------------------- /pages/conversation/message/DeleteMessageDialogView.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 删除消息 8 | 删除此条消息? 9 | 10 | 11 | 删除本地消息 12 | 13 | 14 | 删除远程消息 15 | 16 | 17 | 18 | 19 | 20 | 39 | 40 | 43 | -------------------------------------------------------------------------------- /pages/conversation/message/NotificationMessageContentView.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | {{ message.messageContent.digest(message) }} 4 | 5 | 6 | 7 | 22 | 23 | 36 | -------------------------------------------------------------------------------- /pages/conversation/message/PreviewMessageView.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | {{ $t('message.sender') }} 10 | 2021/2/3 11:44 11 | 12 | 13 | 14 | {{ $t('message.content') }} 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 48 | 49 | 52 | -------------------------------------------------------------------------------- /pages/conversation/message/PreviewQuotedMessageView.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 27 | 28 | 49 | -------------------------------------------------------------------------------- /pages/conversation/message/RecallNotificationMessageContentView.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | {{ message.messageContent.digest(message) }} 4 | 重新编辑 5 | 6 | 7 | 8 | 43 | 44 | 64 | -------------------------------------------------------------------------------- /pages/conversation/message/content/CallStartMessageContentView.vue: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 46 | 47 | 74 | -------------------------------------------------------------------------------- /pages/conversation/message/content/StickerMessageContentView.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 7 | 8 | 9 | 10 | 37 | 38 | 64 | -------------------------------------------------------------------------------- /pages/conversation/message/content/UnknownMessageContentView.vue: -------------------------------------------------------------------------------- 1 | 2 | 4 | {{ $t('message.unsupport_message_desc') }} 5 | 6 | 7 | 8 | 25 | 26 | 46 | -------------------------------------------------------------------------------- /pages/conversation/message/content/UnsupportMessageContentView.vue: -------------------------------------------------------------------------------- 1 | 2 | 4 | {{ message.messageContent.digest(message) }} 5 | 6 | 7 | 8 | 25 | 26 | 46 | -------------------------------------------------------------------------------- /pages/conversation/message/forward/ForwardType.js: -------------------------------------------------------------------------------- 1 | export default class ForwardType { 2 | /** 3 | * 普通转发 4 | * @type {number} 5 | */ 6 | static NORMAL = 0; 7 | /** 8 | * 逐条转发 9 | * @type {number} 10 | */ 11 | static ONE_BY_ONE = 1; 12 | /** 13 | * 合并转发 14 | * @type {number} 15 | */ 16 | static COMPOSITE = 2; 17 | } 18 | -------------------------------------------------------------------------------- /pages/discovery/ChatroomListPage.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 野火聊天室1 5 | 6 | 7 | 野火聊天室1 8 | 9 | 10 | 野火聊天室2 11 | 12 | 13 | 14 | 15 | 16 | 37 | 38 | 78 | -------------------------------------------------------------------------------- /pages/login/login.css: -------------------------------------------------------------------------------- 1 | /* pages/login/login.wxss */ 2 | .page-body { 3 | padding: 20rpx; 4 | } 5 | 6 | .page-section{ 7 | margin-top: 20rpx; 8 | } 9 | 10 | button {margin: 10px;} 11 | .other-button-hover { 12 | background-color: #3B62E0; 13 | } 14 | .button-hover { 15 | background-color: #3B62E0; 16 | } -------------------------------------------------------------------------------- /pages/misc/PreviewVideoPage.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 25 | 26 | -------------------------------------------------------------------------------- /pages/misc/WebViewPage.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 20 | 21 | -------------------------------------------------------------------------------- /pages/pick/PickerConversationPage.vue: -------------------------------------------------------------------------------- 1 | 2 | $END$ 3 | 4 | 5 | 10 | 11 | -------------------------------------------------------------------------------- /pages/test/testPage.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 退出 4 | 5 | 6 | 7 | 8 | 32 | 33 | -------------------------------------------------------------------------------- /pages/test/testWebrtc.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 19 | 20 | -------------------------------------------------------------------------------- /pages/util/clipboard.js: -------------------------------------------------------------------------------- 1 | const createImage = (options) => { 2 | options = options || {}; 3 | const img = document.createElement("img"); 4 | if (options.src) { 5 | img.src = options.src; 6 | } 7 | return img; 8 | }; 9 | 10 | export const copyToClipboard = async (blob) => { 11 | try { 12 | await navigator.clipboard.write([ 13 | // eslint-disable-next-line no-undef 14 | new ClipboardItem({ 15 | [blob.type]: blob 16 | }) 17 | ]); 18 | console.log("content copied"); 19 | } catch (error) { 20 | console.error(error); 21 | } 22 | }; 23 | 24 | const convertToPng = (imgBlob) => { 25 | const canvas = document.createElement("canvas"); 26 | const ctx = canvas.getContext("2d"); 27 | const imageEl = createImage({src: window.URL.createObjectURL(imgBlob)}); 28 | imageEl.onload = (e) => { 29 | canvas.width = e.target.width; 30 | canvas.height = e.target.height; 31 | ctx.drawImage(e.target, 0, 0, e.target.width, e.target.height); 32 | canvas.toBlob(copyToClipboard, "image/png", 1); 33 | }; 34 | }; 35 | 36 | export const copyImg = async (src) => { 37 | const img = await fetch(src); 38 | const imgBlob = await img.blob(); 39 | const extension = src.split(".").pop(); 40 | const supportedToBeConverted = ["jpeg", "jpg", "gif"]; 41 | if (supportedToBeConverted.indexOf(extension.toLowerCase())) { 42 | return convertToPng(imgBlob); 43 | } else if (extension.toLowerCase() === "png") { 44 | return copyToClipboard(imgBlob); 45 | } 46 | console.error("Format unsupported"); 47 | }; 48 | 49 | 50 | export const copyText = (text) => { 51 | const blob = new Blob([text], {type: 'text/plain'}) 52 | copyToClipboard(blob) 53 | } 54 | 55 | -------------------------------------------------------------------------------- /pages/util/draft.js: -------------------------------------------------------------------------------- 1 | import wfc from "../../wfc/client/wfc"; 2 | import {_patchToJavaLong, _reverseToJsLongString, stringValue} from "../../wfc/util/longUtil"; 3 | import store from "@/store"; 4 | 5 | export default class Draft { 6 | 7 | static setConversationDraft(conversation, draftText, quoteInfo, mentions = null) { 8 | if (!draftText && !quoteInfo) { 9 | wfc.setConversationDraft(conversation, ''); 10 | return; 11 | } 12 | let obj = { 13 | content: draftText, 14 | mentions: mentions, 15 | quoteInfo: quoteInfo, 16 | } 17 | let jsonStr = JSON.stringify(obj, (key, value) => { 18 | if (key === 'messageUid') { 19 | return stringValue(value); 20 | } 21 | return value; 22 | }); 23 | jsonStr = _patchToJavaLong(jsonStr, "messageUid") 24 | wfc.setConversationDraft(conversation, jsonStr); 25 | } 26 | 27 | static getConversationDraftEx(conversationInfo) { 28 | let obj = { 29 | text: '', 30 | quotedMessage: null 31 | } 32 | if (!conversationInfo || !conversationInfo.draft) { 33 | return obj; 34 | } 35 | // 兼容处理 36 | if (!conversationInfo.draft.startsWith("{")) { 37 | obj.text = conversationInfo.draft; 38 | return obj; 39 | } 40 | let draftStr = conversationInfo.draft; 41 | draftStr = _reverseToJsLongString(draftStr, 'messageUid'); 42 | let draft = JSON.parse(draftStr); 43 | obj.text = draft.content; 44 | obj.text = obj.text ? obj.text : ''; 45 | if (draft.quoteInfo) { 46 | let msg = store.getMessageByUid(draft.quoteInfo.messageUid); 47 | obj.quotedMessage = msg; 48 | } 49 | return obj; 50 | } 51 | 52 | static getConversationDraft(conversation) { 53 | let conversationInfo = wfc.getConversationInfo(conversation); 54 | return this.getConversationDraftEx(conversationInfo); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /pages/util/storageHelper.js: -------------------------------------------------------------------------------- 1 | export function removeItem(key) { 2 | uni.removeStorageSync(key) 3 | } 4 | 5 | export function getItem(key) { 6 | return uni.getStorageSync(key); 7 | } 8 | 9 | export function setItem(key, value) { 10 | uni.setStorageSync(key, value); 11 | } 12 | 13 | export function clear() { 14 | uni.clearStorageSync(); 15 | } 16 | -------------------------------------------------------------------------------- /pages/voip/voipUtil.js: -------------------------------------------------------------------------------- 1 | import permission from "../../common/permission"; 2 | 3 | async function checkVoipPermissions(audioOnly) { 4 | // #ifdef APP-PLUS 5 | let iosPermissions = ['record']; 6 | let androidPermissions = ['android.permission.RECORD_AUDIO']; 7 | if (!audioOnly) { 8 | iosPermissions.push('camera'); 9 | androidPermissions.push('android.permission.CAMERA'); 10 | } 11 | let status = permission.isIOS ? await permission.requestIOS(iosPermissions) : 12 | await permission.requestAndroid(androidPermissions) 13 | if (status !== 1) { 14 | uni.showModal({ 15 | content: "需要相关权限", 16 | confirmText: "设置", 17 | success: (res) => { 18 | if (res.confirm) { 19 | permission.gotoAppSetting(); 20 | } 21 | } 22 | }) 23 | return false; 24 | } else { 25 | return true; 26 | } 27 | // #endif 28 | return true; 29 | } 30 | 31 | export default checkVoipPermissions -------------------------------------------------------------------------------- /pages/workspace/WorkspacePage.nvue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 41 | 42 | -------------------------------------------------------------------------------- /pages/workspace/WorkspaceWebViewPage.nvue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 44 | 45 | -------------------------------------------------------------------------------- /pages/workspace/bridge.js: -------------------------------------------------------------------------------- 1 | let eventListeners = {}; 2 | let requestId = 0; 3 | 4 | function init() { 5 | 6 | } 7 | 8 | function call(handlerName, args, callback) { 9 | 10 | } 11 | 12 | function register(handlerName, callback) { 13 | eventListeners[handlerName] = callback; 14 | } 15 | 16 | // init(); 17 | -------------------------------------------------------------------------------- /screenshots/uniapp_contact_tab.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/screenshots/uniapp_contact_tab.jpeg -------------------------------------------------------------------------------- /screenshots/uniapp_conversation.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/screenshots/uniapp_conversation.jpeg -------------------------------------------------------------------------------- /screenshots/uniapp_conversation_list.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/screenshots/uniapp_conversation_list.jpeg -------------------------------------------------------------------------------- /screenshots/uniapp_user_profile.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/screenshots/uniapp_user_profile.jpeg -------------------------------------------------------------------------------- /static/audios/audido_msg_send_success.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/audios/audido_msg_send_success.mp3 -------------------------------------------------------------------------------- /static/audios/audio_msg_play_completion.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/audios/audio_msg_play_completion.mp3 -------------------------------------------------------------------------------- /static/audios/incoming_call_ring.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/audios/incoming_call_ring.mp3 -------------------------------------------------------------------------------- /static/audios/outgoing_call_ring.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/audios/outgoing_call_ring.mp3 -------------------------------------------------------------------------------- /static/audios/ptt_begin.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/audios/ptt_begin.mp3 -------------------------------------------------------------------------------- /static/audios/ptt_end.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/audios/ptt_end.mp3 -------------------------------------------------------------------------------- /static/iconfonts/customicons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/iconfonts/customicons.ttf -------------------------------------------------------------------------------- /static/iconfonts/icomoon/fonts/icomoon.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/iconfonts/icomoon/fonts/icomoon.ttf -------------------------------------------------------------------------------- /static/iconfonts/wx_iconfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/iconfonts/wx_iconfont.ttf -------------------------------------------------------------------------------- /static/image/av/add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/av/add.png -------------------------------------------------------------------------------- /static/image/av/av_book_conference.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/av/av_book_conference.png -------------------------------------------------------------------------------- /static/image/av/av_camera.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/av/av_camera.png -------------------------------------------------------------------------------- /static/image/av/av_camera_hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/av/av_camera_hover.png -------------------------------------------------------------------------------- /static/image/av/av_conference_audio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/av/av_conference_audio.png -------------------------------------------------------------------------------- /static/image/av/av_conference_audio_mute.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/av/av_conference_audio_mute.png -------------------------------------------------------------------------------- /static/image/av/av_conference_end_call.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/av/av_conference_end_call.png -------------------------------------------------------------------------------- /static/image/av/av_conference_handup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/av/av_conference_handup.png -------------------------------------------------------------------------------- /static/image/av/av_conference_handup_hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/av/av_conference_handup_hover.png -------------------------------------------------------------------------------- /static/image/av/av_conference_members.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/av/av_conference_members.png -------------------------------------------------------------------------------- /static/image/av/av_conference_screen_sharing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/av/av_conference_screen_sharing.png -------------------------------------------------------------------------------- /static/image/av/av_conference_screen_sharing_hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/av/av_conference_screen_sharing_hover.png -------------------------------------------------------------------------------- /static/image/av/av_conference_video.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/av/av_conference_video.png -------------------------------------------------------------------------------- /static/image/av/av_conference_video_mute.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/av/av_conference_video_mute.png -------------------------------------------------------------------------------- /static/image/av/av_float_audio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/av/av_float_audio.png -------------------------------------------------------------------------------- /static/image/av/av_handfree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/av/av_handfree.png -------------------------------------------------------------------------------- /static/image/av/av_handfree_hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/av/av_handfree_hover.png -------------------------------------------------------------------------------- /static/image/av/av_hang_up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/av/av_hang_up.png -------------------------------------------------------------------------------- /static/image/av/av_hang_up_hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/av/av_hang_up_hover.png -------------------------------------------------------------------------------- /static/image/av/av_join_conference.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/av/av_join_conference.png -------------------------------------------------------------------------------- /static/image/av/av_minimize.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/av/av_minimize.png -------------------------------------------------------------------------------- /static/image/av/av_mute.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/av/av_mute.png -------------------------------------------------------------------------------- /static/image/av/av_mute_hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/av/av_mute_hover.png -------------------------------------------------------------------------------- /static/image/av/av_phone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/av/av_phone.png -------------------------------------------------------------------------------- /static/image/av/av_share.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/av/av_share.png -------------------------------------------------------------------------------- /static/image/av/av_start_conference.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/av/av_start_conference.png -------------------------------------------------------------------------------- /static/image/av/av_video_answer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/av/av_video_answer.png -------------------------------------------------------------------------------- /static/image/av/av_video_answer_hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/av/av_video_answer_hover.png -------------------------------------------------------------------------------- /static/image/av/ic_conference.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/av/ic_conference.png -------------------------------------------------------------------------------- /static/image/chat/extra.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/chat/extra.png -------------------------------------------------------------------------------- /static/image/chat/extra/choose_picture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/chat/extra/choose_picture.png -------------------------------------------------------------------------------- /static/image/chat/extra/close_chat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/chat/extra/close_chat.png -------------------------------------------------------------------------------- /static/image/chat/extra/take_photos.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/chat/extra/take_photos.png -------------------------------------------------------------------------------- /static/image/chat/popu_blue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/chat/popu_blue.png -------------------------------------------------------------------------------- /static/image/chat/popu_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/chat/popu_white.png -------------------------------------------------------------------------------- /static/image/chat/send_fail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/chat/send_fail.png -------------------------------------------------------------------------------- /static/image/chat/voice/attention.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/chat/voice/attention.png -------------------------------------------------------------------------------- /static/image/chat/voice/keyboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/chat/voice/keyboard.png -------------------------------------------------------------------------------- /static/image/chat/voice/recall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/chat/voice/recall.png -------------------------------------------------------------------------------- /static/image/chat/voice/speak.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/chat/voice/speak.png -------------------------------------------------------------------------------- /static/image/chat/voice/voice.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/chat/voice/voice.png -------------------------------------------------------------------------------- /static/image/chat/voice/voice_mine.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/chat/voice/voice_mine.png -------------------------------------------------------------------------------- /static/image/chat/voice/voice_other.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/chat/voice/voice_other.png -------------------------------------------------------------------------------- /static/image/filetypes/ai.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/filetypes/ai.png -------------------------------------------------------------------------------- /static/image/filetypes/apk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/filetypes/apk.png -------------------------------------------------------------------------------- /static/image/filetypes/archive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/filetypes/archive.png -------------------------------------------------------------------------------- /static/image/filetypes/audio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/filetypes/audio.png -------------------------------------------------------------------------------- /static/image/filetypes/excel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/filetypes/excel.png -------------------------------------------------------------------------------- /static/image/filetypes/exe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/filetypes/exe.png -------------------------------------------------------------------------------- /static/image/filetypes/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/filetypes/image.png -------------------------------------------------------------------------------- /static/image/filetypes/ipa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/filetypes/ipa.png -------------------------------------------------------------------------------- /static/image/filetypes/pdf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/filetypes/pdf.png -------------------------------------------------------------------------------- /static/image/filetypes/ppt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/filetypes/ppt.png -------------------------------------------------------------------------------- /static/image/filetypes/psd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/filetypes/psd.png -------------------------------------------------------------------------------- /static/image/filetypes/unknow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/filetypes/unknow.png -------------------------------------------------------------------------------- /static/image/filetypes/video.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/filetypes/video.png -------------------------------------------------------------------------------- /static/image/filetypes/word.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/filetypes/word.png -------------------------------------------------------------------------------- /static/image/icon/ic_channel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/icon/ic_channel.png -------------------------------------------------------------------------------- /static/image/icon/ic_channel_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/icon/ic_channel_1.png -------------------------------------------------------------------------------- /static/image/icon/ic_chatroom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/icon/ic_chatroom.png -------------------------------------------------------------------------------- /static/image/icon/ic_conference.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/icon/ic_conference.png -------------------------------------------------------------------------------- /static/image/icon/ic_dev_docs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/icon/ic_dev_docs.png -------------------------------------------------------------------------------- /static/image/icon/ic_group_chat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/icon/ic_group_chat.png -------------------------------------------------------------------------------- /static/image/icon/ic_new_friend.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/icon/ic_new_friend.png -------------------------------------------------------------------------------- /static/image/icon/ic_organization.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/icon/ic_organization.png -------------------------------------------------------------------------------- /static/image/icon/ic_robot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/icon/ic_robot.png -------------------------------------------------------------------------------- /static/image/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/logo.png -------------------------------------------------------------------------------- /static/image/tabbar/contact_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/tabbar/contact_normal.png -------------------------------------------------------------------------------- /static/image/tabbar/contact_press.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/tabbar/contact_press.png -------------------------------------------------------------------------------- /static/image/tabbar/discovery_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/tabbar/discovery_normal.png -------------------------------------------------------------------------------- /static/image/tabbar/discovery_press.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/tabbar/discovery_press.png -------------------------------------------------------------------------------- /static/image/tabbar/me_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/tabbar/me_normal.png -------------------------------------------------------------------------------- /static/image/tabbar/me_press.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/tabbar/me_press.png -------------------------------------------------------------------------------- /static/image/tabbar/message_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/tabbar/message_normal.png -------------------------------------------------------------------------------- /static/image/tabbar/message_press.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/tabbar/message_press.png -------------------------------------------------------------------------------- /static/image/tabbar/work_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/tabbar/work_normal.png -------------------------------------------------------------------------------- /static/image/tabbar/work_press.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wildfirechat/uni-chat/f06d809a95bb15250ab9eac92b7508c21d05e644/static/image/tabbar/work_press.png -------------------------------------------------------------------------------- /static/js/bridgeClientImpl.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 大概流程 3 | * 采用类 client-server 模式实现开放平台 js sdk,有两部分相关代码: 4 | * 1. client 运行在工作台所加载的 webview 里面 5 | * 2. server 直接运行在工作台页面里面,也就是主窗口的渲染进程 6 | * 3. client 和 server 之间的交互,通过 websocket 进行中转 7 | * 8 | */ 9 | let callbackMap = new Map(); 10 | let eventListeners = {}; 11 | let requestId = 0; 12 | let client; 13 | 14 | function init() { 15 | window.__messageFromUni = (data) => { 16 | console.log('__messageFromUni', data) 17 | let obj; 18 | try { 19 | obj = JSON.parse(data); 20 | } catch (e) { 21 | console.error('parse ws data error', e); 22 | return; 23 | } 24 | if (obj.type === 'wf-op-event') { 25 | handleOpEvent(obj.handlerName, obj.args); 26 | } else if (obj.type === 'wf-op-response') { 27 | handleOpResponse(obj.requestId, obj.args) 28 | } 29 | } 30 | 31 | window.__wf_bridge_ = { 32 | call: call, 33 | register: register, 34 | } 35 | console.log('bridgeClientImpl init') 36 | } 37 | 38 | function call(handlerName, args, callback) { 39 | let reqId = 0; 40 | if (callback && typeof callback === 'function') { 41 | reqId = requestId++; 42 | callbackMap.set(reqId, callback) 43 | } 44 | let appUrl = location.href; 45 | let obj = {type: 'wf-op-request', requestId: reqId, appUrl, handlerName, args}; 46 | console.log('wf-op-request', obj) 47 | uni.postMessage({data: {obj: JSON.stringify(obj)}}) 48 | // uni.send(JSON.stringify(obj)); 49 | } 50 | 51 | function handleOpResponse(requestId, args) { 52 | console.log('handle op response', requestId, args) 53 | let cb = callbackMap.get(requestId); 54 | if (cb) { 55 | cb(args); 56 | callbackMap.delete(requestId); 57 | } 58 | } 59 | 60 | function handleOpEvent(handlerName, args) { 61 | eventListeners[handlerName] && eventListeners[handlerName](args); 62 | 63 | } 64 | 65 | function register(handlerName, callback) { 66 | eventListeners[handlerName] = callback; 67 | } 68 | 69 | init(); -------------------------------------------------------------------------------- /uni.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * 这里是uni-app内置的常用样式变量 3 | * 4 | * uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量 5 | * 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App 6 | * 7 | */ 8 | 9 | /** 10 | * 如果你是App开发者(插件使用者),你可以通过修改这些变量来定制自己的插件主题,实现自定义主题功能 11 | * 12 | * 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件 13 | */ 14 | 15 | /* 颜色变量 */ 16 | 17 | /* 行为相关颜色 */ 18 | $uni-color-primary: #007aff; 19 | $uni-color-success: #4cd964; 20 | $uni-color-warning: #f0ad4e; 21 | $uni-color-error: #dd524d; 22 | 23 | /* 文字基本颜色 */ 24 | $uni-text-color:#333;//基本色 25 | $uni-text-color-inverse:#fff;//反色 26 | $uni-text-color-grey:#999;//辅助灰色,如加载更多的提示信息 27 | $uni-text-color-placeholder: #808080; 28 | $uni-text-color-disable:#c0c0c0; 29 | 30 | /* 背景颜色 */ 31 | $uni-bg-color:#f3f3f3; 32 | $uni-bg-color-grey:#f8f8f8; 33 | $uni-bg-color-hover:#f1f1f1;//点击状态颜色 34 | $uni-bg-color-mask:rgba(0, 0, 0, 0.4);//遮罩颜色 35 | 36 | /* 边框颜色 */ 37 | $uni-border-color:#c8c7cc; 38 | 39 | /* 尺寸变量 */ 40 | 41 | /* 文字尺寸 */ 42 | $uni-font-size-sm:24rpx; 43 | $uni-font-size-base:28rpx; 44 | $uni-font-size-lg:32rpx; 45 | 46 | /* 图片尺寸 */ 47 | $uni-img-size-sm:40rpx; 48 | $uni-img-size-base:52rpx; 49 | $uni-img-size-lg:80rpx; 50 | 51 | /* Border Radius */ 52 | $uni-border-radius-sm: 4rpx; 53 | $uni-border-radius-base: 6rpx; 54 | $uni-border-radius-lg: 12rpx; 55 | $uni-border-radius-circle: 50%; 56 | 57 | /* 水平间距 */ 58 | $uni-spacing-row-sm: 10px; 59 | $uni-spacing-row-base: 20rpx; 60 | $uni-spacing-row-lg: 30rpx; 61 | 62 | /* 垂直间距 */ 63 | $uni-spacing-col-sm: 8rpx; 64 | $uni-spacing-col-base: 16rpx; 65 | $uni-spacing-col-lg: 24rpx; 66 | 67 | /* 透明度 */ 68 | $uni-opacity-disabled: 0.3; // 组件禁用态的透明度 69 | 70 | /* 文章场景相关 */ 71 | $uni-color-title: #2C405A; // 文章标题颜色 72 | $uni-font-size-title:40rpx; 73 | $uni-color-subtitle: #555555; // 二级标题颜色 74 | $uni-font-size-subtitle:36rpx; 75 | $uni-color-paragraph: #3F536E; // 文章段落颜色 76 | $uni-font-size-paragraph:30rpx; -------------------------------------------------------------------------------- /uni_modules/uni-popup/components/uni-popup-dialog/keypress.js: -------------------------------------------------------------------------------- 1 | // #ifdef H5 2 | export default { 3 | name: 'Keypress', 4 | props: { 5 | disable: { 6 | type: Boolean, 7 | default: false 8 | } 9 | }, 10 | mounted () { 11 | const keyNames = { 12 | esc: ['Esc', 'Escape'], 13 | tab: 'Tab', 14 | enter: 'Enter', 15 | space: [' ', 'Spacebar'], 16 | up: ['Up', 'ArrowUp'], 17 | left: ['Left', 'ArrowLeft'], 18 | right: ['Right', 'ArrowRight'], 19 | down: ['Down', 'ArrowDown'], 20 | delete: ['Backspace', 'Delete', 'Del'] 21 | } 22 | const listener = ($event) => { 23 | if (this.disable) { 24 | return 25 | } 26 | const keyName = Object.keys(keyNames).find(key => { 27 | const keyName = $event.key 28 | const value = keyNames[key] 29 | return value === keyName || (Array.isArray(value) && value.includes(keyName)) 30 | }) 31 | if (keyName) { 32 | // 避免和其他按键事件冲突 33 | setTimeout(() => { 34 | this.$emit(keyName, {}) 35 | }, 0) 36 | } 37 | } 38 | document.addEventListener('keyup', listener) 39 | this.$once('hook:beforeUnmount', () => { 40 | document.removeEventListener('keyup', listener) 41 | }) 42 | }, 43 | render: () => {} 44 | } 45 | // #endif 46 | -------------------------------------------------------------------------------- /uni_modules/uni-popup/components/uni-popup/i18n/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "uni-popup.cancel": "cancel", 3 | "uni-popup.ok": "ok", 4 | "uni-popup.placeholder": "pleace enter", 5 | "uni-popup.title": "Hint", 6 | "uni-popup.shareTitle": "Share to" 7 | } 8 | -------------------------------------------------------------------------------- /uni_modules/uni-popup/components/uni-popup/i18n/index.js: -------------------------------------------------------------------------------- 1 | import en from './en.json' 2 | import zhHans from './zh-Hans.json' 3 | import zhHant from './zh-Hant.json' 4 | export default { 5 | en, 6 | 'zh-Hans': zhHans, 7 | 'zh-Hant': zhHant 8 | } 9 | -------------------------------------------------------------------------------- /uni_modules/uni-popup/components/uni-popup/i18n/zh-Hans.json: -------------------------------------------------------------------------------- 1 | { 2 | "uni-popup.cancel": "取消", 3 | "uni-popup.ok": "确定", 4 | "uni-popup.placeholder": "请输入", 5 | "uni-popup.title": "提示", 6 | "uni-popup.shareTitle": "分享到" 7 | } 8 | -------------------------------------------------------------------------------- /uni_modules/uni-popup/components/uni-popup/i18n/zh-Hant.json: -------------------------------------------------------------------------------- 1 | { 2 | "uni-popup.cancel": "取消", 3 | "uni-popup.ok": "確定", 4 | "uni-popup.placeholder": "請輸入", 5 | "uni-popup.title": "提示", 6 | "uni-popup.shareTitle": "分享到" 7 | } 8 | -------------------------------------------------------------------------------- /uni_modules/uni-popup/components/uni-popup/keypress.js: -------------------------------------------------------------------------------- 1 | // #ifdef H5 2 | export default { 3 | name: 'Keypress', 4 | props: { 5 | disable: { 6 | type: Boolean, 7 | default: false 8 | } 9 | }, 10 | mounted () { 11 | const keyNames = { 12 | esc: ['Esc', 'Escape'], 13 | tab: 'Tab', 14 | enter: 'Enter', 15 | space: [' ', 'Spacebar'], 16 | up: ['Up', 'ArrowUp'], 17 | left: ['Left', 'ArrowLeft'], 18 | right: ['Right', 'ArrowRight'], 19 | down: ['Down', 'ArrowDown'], 20 | delete: ['Backspace', 'Delete', 'Del'] 21 | } 22 | const listener = ($event) => { 23 | if (this.disable) { 24 | return 25 | } 26 | const keyName = Object.keys(keyNames).find(key => { 27 | const keyName = $event.key 28 | const value = keyNames[key] 29 | return value === keyName || (Array.isArray(value) && value.includes(keyName)) 30 | }) 31 | if (keyName) { 32 | // 避免和其他按键事件冲突 33 | setTimeout(() => { 34 | this.$emit(keyName, {}) 35 | }, 0) 36 | } 37 | } 38 | document.addEventListener('keyup', listener) 39 | // this.$once('hook:beforeUnmount', () => { 40 | // document.removeEventListener('keyup', listener) 41 | // }) 42 | }, 43 | render: () => {} 44 | } 45 | // #endif 46 | -------------------------------------------------------------------------------- /uni_modules/uni-popup/components/uni-popup/popup.js: -------------------------------------------------------------------------------- 1 | 2 | export default { 3 | data() { 4 | return { 5 | 6 | } 7 | }, 8 | created(){ 9 | this.popup = this.getParent() 10 | }, 11 | methods:{ 12 | /** 13 | * 获取父元素实例 14 | */ 15 | getParent(name = 'uniPopup') { 16 | let parent = this.$parent; 17 | let parentName = parent.$options.name; 18 | while (parentName !== name) { 19 | parent = parent.$parent; 20 | if (!parent) return false 21 | parentName = parent.$options.name; 22 | } 23 | return parent; 24 | }, 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /uni_modules/uni-popup/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "uni-popup", 3 | "displayName": "uni-popup 弹出层", 4 | "version": "1.8.3", 5 | "description": " Popup 组件,提供常用的弹层", 6 | "keywords": [ 7 | "uni-ui", 8 | "弹出层", 9 | "弹窗", 10 | "popup", 11 | "弹框" 12 | ], 13 | "repository": "https://github.com/dcloudio/uni-ui", 14 | "engines": { 15 | "HBuilderX": "" 16 | }, 17 | "directories": { 18 | "example": "../../temps/example_temps" 19 | }, 20 | "dcloudext": { 21 | "sale": { 22 | "regular": { 23 | "price": "0.00" 24 | }, 25 | "sourcecode": { 26 | "price": "0.00" 27 | } 28 | }, 29 | "contact": { 30 | "qq": "" 31 | }, 32 | "declaration": { 33 | "ads": "无", 34 | "data": "无", 35 | "permissions": "无" 36 | }, 37 | "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui", 38 | "type": "component-vue" 39 | }, 40 | "uni_modules": { 41 | "dependencies": [ 42 | "uni-scss", 43 | "uni-transition" 44 | ], 45 | "encrypt": [], 46 | "platforms": { 47 | "cloud": { 48 | "tcb": "y", 49 | "aliyun": "y" 50 | }, 51 | "client": { 52 | "App": { 53 | "app-vue": "y", 54 | "app-nvue": "y" 55 | }, 56 | "H5-mobile": { 57 | "Safari": "y", 58 | "Android Browser": "y", 59 | "微信浏览器(Android)": "y", 60 | "QQ浏览器(Android)": "y" 61 | }, 62 | "H5-pc": { 63 | "Chrome": "y", 64 | "IE": "y", 65 | "Edge": "y", 66 | "Firefox": "y", 67 | "Safari": "y" 68 | }, 69 | "小程序": { 70 | "微信": "y", 71 | "阿里": "y", 72 | "百度": "y", 73 | "字节跳动": "y", 74 | "QQ": "y" 75 | }, 76 | "快应用": { 77 | "华为": "u", 78 | "联盟": "u" 79 | }, 80 | "Vue": { 81 | "vue2": "y", 82 | "vue3": "y" 83 | } 84 | } 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /uni_modules/uni-popup/readme.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Popup 弹出层 4 | > **组件名:uni-popup** 5 | > 代码块: `uPopup` 6 | > 关联组件:`uni-transition` 7 | 8 | 9 | 弹出层组件,在应用中弹出一个消息提示窗口、提示框等 10 | 11 | ### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-popup) 12 | #### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /uni_modules/uni-scss/changelog.md: -------------------------------------------------------------------------------- 1 | ## 1.0.3(2022-01-21) 2 | - 优化 组件示例 3 | ## 1.0.2(2021-11-22) 4 | - 修复 / 符号在 vue 不同版本兼容问题引起的报错问题 5 | ## 1.0.1(2021-11-22) 6 | - 修复 vue3中scss语法兼容问题 7 | ## 1.0.0(2021-11-18) 8 | - init 9 | -------------------------------------------------------------------------------- /uni_modules/uni-scss/index.scss: -------------------------------------------------------------------------------- 1 | @import './styles/index.scss'; 2 | -------------------------------------------------------------------------------- /uni_modules/uni-scss/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "uni-scss", 3 | "displayName": "uni-scss 辅助样式", 4 | "version": "1.0.3", 5 | "description": "uni-sass是uni-ui提供的一套全局样式 ,通过一些简单的类名和sass变量,实现简单的页面布局操作,比如颜色、边距、圆角等。", 6 | "keywords": [ 7 | "uni-scss", 8 | "uni-ui", 9 | "辅助样式" 10 | ], 11 | "repository": "https://github.com/dcloudio/uni-ui", 12 | "engines": { 13 | "HBuilderX": "^3.1.0" 14 | }, 15 | "dcloudext": { 16 | "category": [ 17 | "JS SDK", 18 | "通用 SDK" 19 | ], 20 | "sale": { 21 | "regular": { 22 | "price": "0.00" 23 | }, 24 | "sourcecode": { 25 | "price": "0.00" 26 | } 27 | }, 28 | "contact": { 29 | "qq": "" 30 | }, 31 | "declaration": { 32 | "ads": "无", 33 | "data": "无", 34 | "permissions": "无" 35 | }, 36 | "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" 37 | }, 38 | "uni_modules": { 39 | "dependencies": [], 40 | "encrypt": [], 41 | "platforms": { 42 | "cloud": { 43 | "tcb": "y", 44 | "aliyun": "y" 45 | }, 46 | "client": { 47 | "App": { 48 | "app-vue": "y", 49 | "app-nvue": "u" 50 | }, 51 | "H5-mobile": { 52 | "Safari": "y", 53 | "Android Browser": "y", 54 | "微信浏览器(Android)": "y", 55 | "QQ浏览器(Android)": "y" 56 | }, 57 | "H5-pc": { 58 | "Chrome": "y", 59 | "IE": "y", 60 | "Edge": "y", 61 | "Firefox": "y", 62 | "Safari": "y" 63 | }, 64 | "小程序": { 65 | "微信": "y", 66 | "阿里": "y", 67 | "百度": "y", 68 | "字节跳动": "y", 69 | "QQ": "y" 70 | }, 71 | "快应用": { 72 | "华为": "n", 73 | "联盟": "n" 74 | }, 75 | "Vue": { 76 | "vue2": "y", 77 | "vue3": "y" 78 | } 79 | } 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /uni_modules/uni-scss/readme.md: -------------------------------------------------------------------------------- 1 | `uni-sass` 是 `uni-ui`提供的一套全局样式 ,通过一些简单的类名和`sass`变量,实现简单的页面布局操作,比如颜色、边距、圆角等。 2 | 3 | ### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-sass) 4 | #### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 -------------------------------------------------------------------------------- /uni_modules/uni-scss/styles/index.scss: -------------------------------------------------------------------------------- 1 | @import './setting/_variables.scss'; 2 | @import './setting/_border.scss'; 3 | @import './setting/_color.scss'; 4 | @import './setting/_space.scss'; 5 | @import './setting/_radius.scss'; 6 | @import './setting/_text.scss'; 7 | @import './setting/_styles.scss'; 8 | -------------------------------------------------------------------------------- /uni_modules/uni-scss/styles/setting/_border.scss: -------------------------------------------------------------------------------- 1 | .uni-border { 2 | border: 1px $uni-border-1 solid; 3 | } -------------------------------------------------------------------------------- /uni_modules/uni-scss/styles/setting/_color.scss: -------------------------------------------------------------------------------- 1 | 2 | // TODO 暂时不需要 class ,需要用户使用变量实现 ,如果使用类名其实并不推荐 3 | // @mixin get-styles($k,$c) { 4 | // @if $k == size or $k == weight{ 5 | // font-#{$k}:#{$c} 6 | // }@else{ 7 | // #{$k}:#{$c} 8 | // } 9 | // } 10 | $uni-ui-color:( 11 | // 主色 12 | primary: $uni-primary, 13 | primary-disable: $uni-primary-disable, 14 | primary-light: $uni-primary-light, 15 | // 辅助色 16 | success: $uni-success, 17 | success-disable: $uni-success-disable, 18 | success-light: $uni-success-light, 19 | warning: $uni-warning, 20 | warning-disable: $uni-warning-disable, 21 | warning-light: $uni-warning-light, 22 | error: $uni-error, 23 | error-disable: $uni-error-disable, 24 | error-light: $uni-error-light, 25 | info: $uni-info, 26 | info-disable: $uni-info-disable, 27 | info-light: $uni-info-light, 28 | // 中性色 29 | main-color: $uni-main-color, 30 | base-color: $uni-base-color, 31 | secondary-color: $uni-secondary-color, 32 | extra-color: $uni-extra-color, 33 | // 背景色 34 | bg-color: $uni-bg-color, 35 | // 边框颜色 36 | border-1: $uni-border-1, 37 | border-2: $uni-border-2, 38 | border-3: $uni-border-3, 39 | border-4: $uni-border-4, 40 | // 黑色 41 | black:$uni-black, 42 | // 白色 43 | white:$uni-white, 44 | // 透明 45 | transparent:$uni-transparent 46 | ) !default; 47 | @each $key, $child in $uni-ui-color { 48 | .uni-#{"" + $key} { 49 | color: $child; 50 | } 51 | .uni-#{"" + $key}-bg { 52 | background-color: $child; 53 | } 54 | } 55 | .uni-shadow-sm { 56 | box-shadow: $uni-shadow-sm; 57 | } 58 | .uni-shadow-base { 59 | box-shadow: $uni-shadow-base; 60 | } 61 | .uni-shadow-lg { 62 | box-shadow: $uni-shadow-lg; 63 | } 64 | .uni-mask { 65 | background-color:$uni-mask; 66 | } 67 | -------------------------------------------------------------------------------- /uni_modules/uni-scss/styles/setting/_radius.scss: -------------------------------------------------------------------------------- 1 | @mixin radius($r,$d:null ,$important: false){ 2 | $radius-value:map-get($uni-radius, $r) if($important, !important, null); 3 | // Key exists within the $uni-radius variable 4 | @if (map-has-key($uni-radius, $r) and $d){ 5 | @if $d == t { 6 | border-top-left-radius:$radius-value; 7 | border-top-right-radius:$radius-value; 8 | }@else if $d == r { 9 | border-top-right-radius:$radius-value; 10 | border-bottom-right-radius:$radius-value; 11 | }@else if $d == b { 12 | border-bottom-left-radius:$radius-value; 13 | border-bottom-right-radius:$radius-value; 14 | }@else if $d == l { 15 | border-top-left-radius:$radius-value; 16 | border-bottom-left-radius:$radius-value; 17 | }@else if $d == tl { 18 | border-top-left-radius:$radius-value; 19 | }@else if $d == tr { 20 | border-top-right-radius:$radius-value; 21 | }@else if $d == br { 22 | border-bottom-right-radius:$radius-value; 23 | }@else if $d == bl { 24 | border-bottom-left-radius:$radius-value; 25 | } 26 | }@else{ 27 | border-radius:$radius-value; 28 | } 29 | } 30 | 31 | @each $key, $child in $uni-radius { 32 | @if($key){ 33 | .uni-radius-#{"" + $key} { 34 | @include radius($key) 35 | } 36 | }@else{ 37 | .uni-radius { 38 | @include radius($key) 39 | } 40 | } 41 | } 42 | 43 | @each $direction in t, r, b, l,tl, tr, br, bl { 44 | @each $key, $child in $uni-radius { 45 | @if($key){ 46 | .uni-radius-#{"" + $direction}-#{"" + $key} { 47 | @include radius($key,$direction,false) 48 | } 49 | }@else{ 50 | .uni-radius-#{$direction} { 51 | @include radius($key,$direction,false) 52 | } 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /uni_modules/uni-scss/styles/setting/_space.scss: -------------------------------------------------------------------------------- 1 | 2 | @mixin fn($space,$direction,$size,$n) { 3 | @if $n { 4 | #{$space}-#{$direction}: #{$size*$uni-space-root}px 5 | } @else { 6 | #{$space}-#{$direction}: #{-$size*$uni-space-root}px 7 | } 8 | } 9 | @mixin get-styles($direction,$i,$space,$n){ 10 | @if $direction == t { 11 | @include fn($space, top,$i,$n); 12 | } 13 | @if $direction == r { 14 | @include fn($space, right,$i,$n); 15 | } 16 | @if $direction == b { 17 | @include fn($space, bottom,$i,$n); 18 | } 19 | @if $direction == l { 20 | @include fn($space, left,$i,$n); 21 | } 22 | @if $direction == x { 23 | @include fn($space, left,$i,$n); 24 | @include fn($space, right,$i,$n); 25 | } 26 | @if $direction == y { 27 | @include fn($space, top,$i,$n); 28 | @include fn($space, bottom,$i,$n); 29 | } 30 | @if $direction == a { 31 | @if $n { 32 | #{$space}:#{$i*$uni-space-root}px; 33 | } @else { 34 | #{$space}:#{-$i*$uni-space-root}px; 35 | } 36 | } 37 | } 38 | 39 | @each $orientation in m,p { 40 | $space: margin; 41 | @if $orientation == m { 42 | $space: margin; 43 | } @else { 44 | $space: padding; 45 | } 46 | @for $i from 0 through 16 { 47 | @each $direction in t, r, b, l, x, y, a { 48 | .uni-#{$orientation}#{$direction}-#{$i} { 49 | @include get-styles($direction,$i,$space,true); 50 | } 51 | .uni-#{$orientation}#{$direction}-n#{$i} { 52 | @include get-styles($direction,$i,$space,false); 53 | } 54 | } 55 | } 56 | } -------------------------------------------------------------------------------- /uni_modules/uni-scss/styles/setting/_text.scss: -------------------------------------------------------------------------------- 1 | @mixin get-styles($k,$c) { 2 | @if $k == size or $k == weight{ 3 | font-#{$k}:#{$c} 4 | }@else{ 5 | #{$k}:#{$c} 6 | } 7 | } 8 | 9 | @each $key, $child in $uni-headings { 10 | /* #ifndef APP-NVUE */ 11 | .uni-#{$key} { 12 | @each $k, $c in $child { 13 | @include get-styles($k,$c) 14 | } 15 | } 16 | /* #endif */ 17 | /* #ifdef APP-NVUE */ 18 | .container .uni-#{$key} { 19 | @each $k, $c in $child { 20 | @include get-styles($k,$c) 21 | } 22 | } 23 | /* #endif */ 24 | } 25 | -------------------------------------------------------------------------------- /uni_modules/uni-scss/styles/tools/functions.scss: -------------------------------------------------------------------------------- 1 | // 合并 map 2 | @function map-deep-merge($parent-map, $child-map){ 3 | $result: $parent-map; 4 | @each $key, $child in $child-map { 5 | $parent-has-key: map-has-key($result, $key); 6 | $parent-value: map-get($result, $key); 7 | $parent-type: type-of($parent-value); 8 | $child-type: type-of($child); 9 | $parent-is-map: $parent-type == map; 10 | $child-is-map: $child-type == map; 11 | 12 | @if (not $parent-has-key) or ($parent-type != $child-type) or (not ($parent-is-map and $child-is-map)){ 13 | $result: map-merge($result, ( $key: $child )); 14 | }@else { 15 | $result: map-merge($result, ( $key: map-deep-merge($parent-value, $child) )); 16 | } 17 | } 18 | @return $result; 19 | }; 20 | -------------------------------------------------------------------------------- /uni_modules/uni-scss/theme.scss: -------------------------------------------------------------------------------- 1 | // 间距基础倍数 2 | $uni-space-root: 2; 3 | // 边框半径默认值 4 | $uni-radius-root:5px; 5 | // 主色 6 | $uni-primary: #2979ff; 7 | // 辅助色 8 | $uni-success: #4cd964; 9 | // 警告色 10 | $uni-warning: #f0ad4e; 11 | // 错误色 12 | $uni-error: #dd524d; 13 | // 描述色 14 | $uni-info: #909399; 15 | // 中性色 16 | $uni-main-color: #303133; 17 | $uni-base-color: #606266; 18 | $uni-secondary-color: #909399; 19 | $uni-extra-color: #C0C4CC; 20 | // 背景色 21 | $uni-bg-color: #f5f5f5; 22 | // 边框颜色 23 | $uni-border-1: #DCDFE6; 24 | $uni-border-2: #E4E7ED; 25 | $uni-border-3: #EBEEF5; 26 | $uni-border-4: #F2F6FC; 27 | 28 | // 常规色 29 | $uni-black: #000000; 30 | $uni-white: #ffffff; 31 | $uni-transparent: rgba($color: #000000, $alpha: 0); 32 | -------------------------------------------------------------------------------- /uni_modules/uni-scss/variables.scss: -------------------------------------------------------------------------------- 1 | @import './styles/setting/_variables.scss'; 2 | // 间距基础倍数 3 | $uni-space-root: 2; 4 | // 边框半径默认值 5 | $uni-radius-root:5px; 6 | 7 | // 主色 8 | $uni-primary: #2979ff; 9 | $uni-primary-disable:mix(#fff,$uni-primary,50%); 10 | $uni-primary-light: mix(#fff,$uni-primary,80%); 11 | 12 | // 辅助色 13 | // 除了主色外的场景色,需要在不同的场景中使用(例如危险色表示危险的操作)。 14 | $uni-success: #18bc37; 15 | $uni-success-disable:mix(#fff,$uni-success,50%); 16 | $uni-success-light: mix(#fff,$uni-success,80%); 17 | 18 | $uni-warning: #f3a73f; 19 | $uni-warning-disable:mix(#fff,$uni-warning,50%); 20 | $uni-warning-light: mix(#fff,$uni-warning,80%); 21 | 22 | $uni-error: #e43d33; 23 | $uni-error-disable:mix(#fff,$uni-error,50%); 24 | $uni-error-light: mix(#fff,$uni-error,80%); 25 | 26 | $uni-info: #8f939c; 27 | $uni-info-disable:mix(#fff,$uni-info,50%); 28 | $uni-info-light: mix(#fff,$uni-info,80%); 29 | 30 | // 中性色 31 | // 中性色用于文本、背景和边框颜色。通过运用不同的中性色,来表现层次结构。 32 | $uni-main-color: #3a3a3a; // 主要文字 33 | $uni-base-color: #6a6a6a; // 常规文字 34 | $uni-secondary-color: #909399; // 次要文字 35 | $uni-extra-color: #c7c7c7; // 辅助说明 36 | 37 | // 边框颜色 38 | $uni-border-1: #F0F0F0; 39 | $uni-border-2: #EDEDED; 40 | $uni-border-3: #DCDCDC; 41 | $uni-border-4: #B9B9B9; 42 | 43 | // 常规色 44 | $uni-black: #000000; 45 | $uni-white: #ffffff; 46 | $uni-transparent: rgba($color: #000000, $alpha: 0); 47 | 48 | // 背景色 49 | $uni-bg-color: #f7f7f7; 50 | 51 | /* 水平间距 */ 52 | $uni-spacing-sm: 8px; 53 | $uni-spacing-base: 15px; 54 | $uni-spacing-lg: 30px; 55 | 56 | // 阴影 57 | $uni-shadow-sm:0 0 5px rgba($color: #d8d8d8, $alpha: 0.5); 58 | $uni-shadow-base:0 1px 8px 1px rgba($color: #a5a5a5, $alpha: 0.2); 59 | $uni-shadow-lg:0px 1px 10px 2px rgba($color: #a5a4a4, $alpha: 0.5); 60 | 61 | // 蒙版 62 | $uni-mask: rgba($color: #000000, $alpha: 0.4); 63 | -------------------------------------------------------------------------------- /uni_modules/uni-transition/changelog.md: -------------------------------------------------------------------------------- 1 | ## 1.3.2(2023-05-04) 2 | - 修复 NVUE 平台报错的问题 3 | ## 1.3.1(2021-11-23) 4 | - 修复 init 方法初始化问题 5 | ## 1.3.0(2021-11-19) 6 | - 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) 7 | - 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-transition](https://uniapp.dcloud.io/component/uniui/uni-transition) 8 | ## 1.2.1(2021-09-27) 9 | - 修复 init 方法不生效的 Bug 10 | ## 1.2.0(2021-07-30) 11 | - 组件兼容 vue3,如何创建 vue3 项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) 12 | ## 1.1.1(2021-05-12) 13 | - 新增 示例地址 14 | - 修复 示例项目缺少组件的 Bug 15 | ## 1.1.0(2021-04-22) 16 | - 新增 通过方法自定义动画 17 | - 新增 custom-class 非 NVUE 平台支持自定义 class 定制样式 18 | - 优化 动画触发逻辑,使动画更流畅 19 | - 优化 支持单独的动画类型 20 | - 优化 文档示例 21 | ## 1.0.2(2021-02-05) 22 | - 调整为 uni_modules 目录规范 23 | -------------------------------------------------------------------------------- /uni_modules/uni-transition/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "uni-transition", 3 | "displayName": "uni-transition 过渡动画", 4 | "version": "1.3.2", 5 | "description": "元素的简单过渡动画", 6 | "keywords": [ 7 | "uni-ui", 8 | "uniui", 9 | "动画", 10 | "过渡", 11 | "过渡动画" 12 | ], 13 | "repository": "https://github.com/dcloudio/uni-ui", 14 | "engines": { 15 | "HBuilderX": "" 16 | }, 17 | "directories": { 18 | "example": "../../temps/example_temps" 19 | }, 20 | "dcloudext": { 21 | "sale": { 22 | "regular": { 23 | "price": "0.00" 24 | }, 25 | "sourcecode": { 26 | "price": "0.00" 27 | } 28 | }, 29 | "contact": { 30 | "qq": "" 31 | }, 32 | "declaration": { 33 | "ads": "无", 34 | "data": "无", 35 | "permissions": "无" 36 | }, 37 | "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui", 38 | "type": "component-vue" 39 | }, 40 | "uni_modules": { 41 | "dependencies": ["uni-scss"], 42 | "encrypt": [], 43 | "platforms": { 44 | "cloud": { 45 | "tcb": "y", 46 | "aliyun": "y" 47 | }, 48 | "client": { 49 | "App": { 50 | "app-vue": "y", 51 | "app-nvue": "y" 52 | }, 53 | "H5-mobile": { 54 | "Safari": "y", 55 | "Android Browser": "y", 56 | "微信浏览器(Android)": "y", 57 | "QQ浏览器(Android)": "y" 58 | }, 59 | "H5-pc": { 60 | "Chrome": "y", 61 | "IE": "y", 62 | "Edge": "y", 63 | "Firefox": "y", 64 | "Safari": "y" 65 | }, 66 | "小程序": { 67 | "微信": "y", 68 | "阿里": "y", 69 | "百度": "y", 70 | "字节跳动": "y", 71 | "QQ": "y" 72 | }, 73 | "快应用": { 74 | "华为": "u", 75 | "联盟": "u" 76 | }, 77 | "Vue": { 78 | "vue2": "y", 79 | "vue3": "y" 80 | } 81 | } 82 | } 83 | } 84 | } -------------------------------------------------------------------------------- /uni_modules/uni-transition/readme.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Transition 过渡动画 4 | > **组件名:uni-transition** 5 | > 代码块: `uTransition` 6 | 7 | 8 | 元素过渡动画 9 | 10 | ### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-transition) 11 | #### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 -------------------------------------------------------------------------------- /vite.config.js: -------------------------------------------------------------------------------- 1 | import { 2 | defineConfig 3 | } from 'vite' 4 | import uni from '@dcloudio/vite-plugin-uni' 5 | 6 | export default defineConfig({ 7 | plugins: [ 8 | uni({ 9 | vueOptions: { 10 | template: { 11 | compilerOptions: { 12 | // 将所有UIKit-开头的标签作为自定义元素处理 13 | isCustomElement: tag => tag.startsWith("UIKit") 14 | } 15 | } 16 | } 17 | }) 18 | ] 19 | }) -------------------------------------------------------------------------------- /wfc.css: -------------------------------------------------------------------------------- 1 | .flex-row { 2 | display: flex; 3 | } 4 | 5 | .flex-column { 6 | display: flex; 7 | flex-direction: column; 8 | } 9 | 10 | .flex-1 { 11 | flex: 1; 12 | overflow: hidden; 13 | } 14 | 15 | .flex-justify-center { 16 | justify-content: center; 17 | } 18 | 19 | .flex-justify-start { 20 | justify-content: flex-start; 21 | } 22 | 23 | .flex-justify-end { 24 | justify-content: flex-end; 25 | } 26 | 27 | .flex-align-start { 28 | align-items: flex-start; 29 | } 30 | 31 | .flex-align-center { 32 | align-items: center; 33 | } 34 | 35 | .flex-align-end { 36 | align-items: flex-end; 37 | } 38 | 39 | .relative { 40 | position: relative; 41 | } 42 | 43 | .full-height { 44 | height: 100%; 45 | } 46 | 47 | .full-width { 48 | width: 100%; 49 | } 50 | -------------------------------------------------------------------------------- /wfc/av/engine/callEndReason.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | export default class CallEndReason { 6 | static REASON_Unknown = 0; 7 | static REASON_Busy = 1; 8 | static REASON_SignalError = 2; 9 | static REASON_Hangup = 3; 10 | static REASON_MediaError = 4; 11 | static REASON_RemoteHangup = 5; 12 | static REASON_OpenCameraFailure = 6; 13 | static REASON_Timeout = 7; 14 | static REASON_AcceptByOtherClient = 8; 15 | static REASON_AllLeft = 9; 16 | static RemoteBusy = 10; 17 | static RemoteTimeout = 11; 18 | static RemoteNetworkError = 12; 19 | static RoomDestroyed = 13; 20 | static RoomNotExist = 14; 21 | static RoomParticipantsFull = 15; 22 | 23 | static Interrupted = 16; 24 | static RemoteInterrupted = 17; 25 | } 26 | -------------------------------------------------------------------------------- /wfc/av/engine/callSession.js: -------------------------------------------------------------------------------- 1 | export default class CallSession { 2 | //通话ID 3 | callId; 4 | title; 5 | desc; 6 | //通话的发起者,如果发起者离开,会重新选举出最早加入者为发起者 7 | initiator; 8 | //邀请当前用户加入通话的用户 9 | inviter; 10 | //通话状态 11 | state; 12 | //开始时间 13 | startTime; 14 | //接通时间 15 | connectedTime; 16 | //结束时间 17 | endTime 18 | //会话 19 | conversation; 20 | //是否是音频 21 | audioOnly; 22 | //通话结束原因 23 | endReason; 24 | //是否是会议 25 | conference; 26 | //是否是观众,仅当会议有效 27 | audience; 28 | //是否是超级会议 29 | advanced; 30 | //是否是多人通话 31 | multiCall; 32 | // 是否关闭摄像头 33 | videoMuted; 34 | // 是否关闭麦克风 35 | audioMuted; 36 | 37 | //call状态 38 | static kWFAVEngineStateIdle = 0; 39 | static kWFAVEngineStateOutgoing = 1; 40 | static kWFAVEngineStateIncomming = 2; 41 | static kWFAVEngineStateConnecting = 3; 42 | static kWFAVEngineStateConnected = 4; 43 | 44 | //通话结束原因 45 | static kWFAVCallEndReasonUnknown = 0; 46 | static kWFAVCallEndReasonBusy = 1; 47 | static kWFAVCallEndReasonSignalError = 2; 48 | static kWFAVCallEndReasonHangup = 3; 49 | static kWFAVCallEndReasonMediaError = 4; 50 | static kWFAVCallEndReasonRemoteHangup = 5; 51 | static kWFAVCallEndReasonOpenCameraFailure = 6; 52 | static kWFAVCallEndReasonTimeout = 7; 53 | static kWFAVCallEndReasonAcceptByOtherClient = 8; 54 | static kWFAVCallEndReasonAllLeft = 9; 55 | static kWFAVCallEndReasonRemoteBusy = 10; 56 | static kWFAVCallEndReasonRemoteTimeout = 11; 57 | static kWFAVCallEndReasonRemoteNetworkError = 12; 58 | static kWFAVCallEndReasonRoomDestroyed = 13; 59 | static kWFAVCallEndReasonRoomNotExist = 14; 60 | static kWFAVCallEndReasonRoomParticipantsFull = 15; 61 | } 62 | -------------------------------------------------------------------------------- /wfc/av/engine/callState.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | export default class CallState { 6 | static STATUS_IDLE = 0; 7 | static STATUS_OUTGOING = 1; 8 | static STATUS_INCOMING = 2; 9 | static STATUS_CONNECTING = 3; 10 | static STATUS_CONNECTED = 4; 11 | } 12 | -------------------------------------------------------------------------------- /wfc/av/engine/participantProfile.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | export default class ParticipantProfile { 5 | userId; 6 | callExtra; 7 | state; 8 | joinTime = 0; 9 | acceptTime = 0; 10 | audioMuted = false; 11 | videoMuted = false; 12 | audience = false; 13 | screenSharing = false; 14 | } 15 | -------------------------------------------------------------------------------- /wfc/av/engine/videoType.js: -------------------------------------------------------------------------------- 1 | export default class VideoType{ 2 | // 不订阅视频流 3 | static NONE = 0; 4 | // 订阅大流 5 | static BIG_STREAM = 1; 6 | // 订阅小流 7 | static SMALL_STREAM = 2; 8 | } 9 | -------------------------------------------------------------------------------- /wfc/av/messages/callAnswerMessageContent.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | import MessageContent from '../../messages/messageContent'; 6 | import wfc from "../../client/wfc" 7 | import {_patchToJavaLong, _reverseToJsLongString, longValue, stringValue} from '../../util/longUtil' 8 | import MessageContentType from '../../messages/messageContentType'; 9 | 10 | export default class CallAnswerMessageContent extends MessageContent { 11 | callId; 12 | audioOnly; 13 | inviteMessageUid; 14 | 15 | constructor(mentionedType = 0, mentionedTargets = []) { 16 | super(MessageContentType.VOIP_CONTENT_TYPE_ACCEPT, mentionedType, mentionedTargets); 17 | } 18 | 19 | digest() { 20 | return ''; 21 | } 22 | 23 | encode() { 24 | let payload = super.encode(); 25 | payload.content = this.callId; 26 | 27 | var obj; 28 | if (this.audioOnly) { 29 | obj = '1'; 30 | } else { 31 | obj = '0'; 32 | } 33 | payload.binaryContent = wfc.utf8_to_b64(obj); 34 | let obj2 = { 35 | u: stringValue(this.inviteMessageUid), 36 | } 37 | let str = JSON.stringify(obj2); 38 | str = _patchToJavaLong(str, 'u'); 39 | payload.extra = str; 40 | return payload; 41 | } 42 | 43 | decode(payload) { 44 | super.decode(payload); 45 | this.callId = payload.content; 46 | let str = wfc.b64_to_utf8(payload.binaryContent); 47 | 48 | this.audioOnly = (str === '1'); 49 | str = payload.extra; 50 | if (str) { 51 | str = _reverseToJsLongString(str, 'u'); 52 | this.inviteMessageUid = longValue(JSON.parse(str).u); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /wfc/av/messages/callAnswerTMessageContent.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | import MessageContent from '../../messages/messageContent'; 6 | import MessageContentType from '../../messages/messageContentType'; 7 | import wfc from "../../client/wfc" 8 | 9 | export default class CallAnswerTMessageContent extends MessageContent { 10 | callId; 11 | audioOnly; 12 | 13 | constructor(mentionedType = 0, mentionedTargets = []) { 14 | super(MessageContentType.VOIP_CONTENT_TYPE_ACCEPT_T, mentionedType, mentionedTargets); 15 | } 16 | 17 | digest() { 18 | return ''; 19 | } 20 | 21 | encode() { 22 | let payload = super.encode(); 23 | payload.content = this.callId; 24 | 25 | var obj; 26 | if (this.audioOnly) { 27 | obj = '1'; 28 | } else { 29 | obj = '0'; 30 | } 31 | payload.binaryContent = wfc.utf8_to_b64(obj); 32 | return payload; 33 | }; 34 | 35 | decode(payload) { 36 | super.decode(payload); 37 | this.callId = payload.content; 38 | let str = wfc.b64_to_utf8(payload.binaryContent); 39 | 40 | this.audioOnly = (str === '1'); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /wfc/av/messages/callByeMessageContent.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | import MessageContent from '../../messages/messageContent'; 6 | import MessageContentType from '../../messages/messageContentType'; 7 | import wfc from "../../client/wfc" 8 | import {_patchToJavaLong, _reverseToJsLongString, longValue, stringValue} from "../../util/longUtil" 9 | 10 | export default class CallByeMessageContent extends MessageContent { 11 | callId; 12 | reason; 13 | inviteMsgUid; 14 | 15 | constructor(mentionedType = 0, mentionedTargets = []) { 16 | super(MessageContentType.VOIP_CONTENT_TYPE_END, mentionedType, mentionedTargets); 17 | } 18 | 19 | digest() { 20 | return ''; 21 | } 22 | 23 | encode() { 24 | let payload = super.encode(); 25 | payload.content = this.callId; 26 | let obj = { 27 | r: this.reason, 28 | u: this.inviteMsgUid ? stringValue(this.inviteMsgUid) : undefined, 29 | }; 30 | let str = JSON.stringify(obj) 31 | str = _patchToJavaLong(str, 'u'); 32 | payload.binaryContent = wfc.utf8_to_b64(str); 33 | payload.pushData = str; 34 | return payload; 35 | } 36 | 37 | decode(payload) { 38 | super.decode(payload); 39 | this.callId = payload.content; 40 | let str = wfc.b64_to_utf8(payload.binaryContent); 41 | str = _reverseToJsLongString(str, 'u'); 42 | let obj = JSON.parse(str); 43 | this.reason = obj.r; 44 | this.inviteMsgUid = obj.u ? longValue(obj.u) : undefined; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /wfc/av/messages/callModifyMessageContent.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | import MessageContent from '../../messages/messageContent'; 6 | import wfc from "../../client/wfc" 7 | import MessageContentType from '../../messages/messageContentType'; 8 | 9 | export default class CallModifyMessageContent extends MessageContent { 10 | callId; 11 | audioOnly; 12 | 13 | constructor(mentionedType = 0, mentionedTargets = []) { 14 | super(MessageContentType.VOIP_CONTENT_TYPE_MODIFY, mentionedType, mentionedTargets); 15 | } 16 | 17 | digest() { 18 | return ''; 19 | } 20 | 21 | encode() { 22 | let payload = super.encode(); 23 | payload.content = this.callId; 24 | 25 | var obj; 26 | if (this.audioOnly) { 27 | obj = '1'; 28 | } else { 29 | obj = '0'; 30 | } 31 | payload.binaryContent = wfc.utf8_to_b64(obj); 32 | return payload; 33 | }; 34 | 35 | decode(payload) { 36 | super.decode(payload); 37 | this.callId = payload.content; 38 | let str = wfc.b64_to_utf8(payload.binaryContent); 39 | 40 | this.audioOnly = (str === '1'); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /wfc/av/messages/callSignalMessageContent.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | import MessageContent from '../../messages/messageContent'; 6 | import MessageContentType from '../../messages/messageContentType'; 7 | import wfc from "../../client/wfc" 8 | 9 | export default class CallSignalMessageContent extends MessageContent { 10 | callId; 11 | payload; 12 | 13 | constructor(mentionedType = 0, mentionedTargets = []) { 14 | super(MessageContentType.VOIP_CONTENT_TYPE_SIGNAL, mentionedType, mentionedTargets); 15 | } 16 | 17 | digest() { 18 | return ''; 19 | } 20 | 21 | encode() { 22 | let payload = super.encode(); 23 | payload.content = this.callId; 24 | payload.binaryContent = wfc.utf8_to_b64(this.payload); 25 | return payload; 26 | }; 27 | 28 | decode(payload) { 29 | super.decode(payload); 30 | this.callId = payload.content; 31 | this.payload = wfc.b64_to_utf8(payload.binaryContent); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /wfc/av/messages/conferenceChangeModeContent.js: -------------------------------------------------------------------------------- 1 | import MessageContent from "../../messages/messageContent"; 2 | import MessageContentType from "../../messages/messageContentType"; 3 | import wfc from "../../client/wfc"; 4 | 5 | export default class ConferenceChangeModeContent extends MessageContent { 6 | callId; 7 | audience; 8 | 9 | constructor(callId, audience) { 10 | super(MessageContentType.CONFERENCE_CONTENT_TYPE_CHANGE_MODE); 11 | this.callId = callId; 12 | this.audience = audience; 13 | } 14 | 15 | encode() { 16 | let payload = super.encode(); 17 | payload.content = this.callId; 18 | let obj = {'a': this.audience}; 19 | payload.binaryContent = wfc.utf8_to_b64(JSON.stringify(obj)) 20 | return payload; 21 | } 22 | 23 | decode(payload) { 24 | super.decode(payload); 25 | this.callId = payload.content; 26 | if (payload.binaryContent) { 27 | let json = wfc.b64_to_utf8(payload.binaryContent); 28 | let obj = JSON.parse(json); 29 | this.audience = !!obj.a; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /wfc/av/messages/conferenceKickoffMemberMessageContent.js: -------------------------------------------------------------------------------- 1 | import MessageContent from "../../messages/messageContent"; 2 | import MessageContentType from "../../messages/messageContentType"; 3 | 4 | export default class ConferenceKickoffMemberMessageContent extends MessageContent { 5 | callId; 6 | 7 | constructor(callId) { 8 | super(MessageContentType.CONFERENCE_CONTENT_TYPE_KICKOFF_MEMBER) 9 | this.callId = callId; 10 | } 11 | 12 | encode() { 13 | let payload = super.encode(); 14 | payload.content = this.callId; 15 | return payload; 16 | } 17 | 18 | decode(payload) { 19 | super.decode(payload); 20 | this.callId = payload.content; 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /wfc/av/messages/joinCallRequestMessageContent.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | import MessageContent from '../../messages/messageContent'; 5 | import wfc from "../../client/wfc" 6 | import MessageContentType from '../../messages/messageContentType'; 7 | 8 | export default class JoinCallRequestMessageContent extends MessageContent { 9 | callId; 10 | clientId; 11 | 12 | constructor(callId, clientId) { 13 | super(MessageContentType.VOIP_Join_Call_Request); 14 | this.callId = callId; 15 | this.clientId = clientId; 16 | } 17 | 18 | digest() { 19 | return ''; 20 | } 21 | 22 | encode() { 23 | let payload = super.encode(); 24 | payload.content = this.callId; 25 | 26 | let obj = { 27 | clientId: this.clientId 28 | } 29 | payload.binaryContent = wfc.utf8_to_b64(JSON.stringify(obj)); 30 | return payload; 31 | } 32 | 33 | decode(payload) { 34 | super.decode(payload); 35 | this.callId = payload.content; 36 | let json = wfc.b64_to_utf8(payload.binaryContent); 37 | let obj = JSON.parse(json); 38 | this.clientId = obj.clientId; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /wfc/av/messages/multiCallOngoingMessageContent.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | import MessageContent from '../../messages/messageContent'; 5 | import wfc from "../../client/wfc" 6 | import MessageContentType from '../../messages/messageContentType'; 7 | 8 | export default class MultiCallOngoingMessageContent extends MessageContent { 9 | callId; 10 | initiator; 11 | audioOnly; 12 | targets; 13 | 14 | constructor(callId, initiator, audioOnly, targets) { 15 | super(MessageContentType.VOIP_Multi_Call_Ongoing); 16 | this.callId = callId; 17 | this.initiator = initiator; 18 | this.audioOnly = audioOnly; 19 | this.targets = targets; 20 | } 21 | 22 | digest(message) { 23 | let displayName = wfc.getGroupMemberDisplayName(message.conversation.target, this.initiator); 24 | return displayName + ' 发起的通话'; 25 | } 26 | 27 | encode() { 28 | let payload = super.encode(); 29 | payload.content = this.callId; 30 | 31 | let obj = { 32 | initiator: this.initiator, 33 | audioOnly: this.audioOnly ? 1 : 0, 34 | targets: this.targets 35 | } 36 | payload.binaryContent = wfc.utf8_to_b64(JSON.stringify(obj)); 37 | return payload; 38 | } 39 | 40 | decode(payload) { 41 | super.decode(payload); 42 | this.callId = payload.content; 43 | let json = wfc.b64_to_utf8(payload.binaryContent); 44 | let obj = JSON.parse(json); 45 | this.initiator = obj.initiator; 46 | this.audioOnly = obj.audioOnly === 1; 47 | this.targets = obj.targets; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /wfc/av/messages/muteVideoMessageContent.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | import NotificationMessageContent from "../../messages/notification/notificationMessageContent"; 6 | import MessageContentType from "../../messages/messageContentType"; 7 | import wfc from "../../client/wfc" 8 | 9 | class ParticipantStatus { 10 | userId; 11 | acceptTime; 12 | joinTime; 13 | videoMuted; 14 | } 15 | 16 | export default class MuteVideoMessageContent extends NotificationMessageContent { 17 | callId; 18 | videoMuted; 19 | existParticipants; 20 | 21 | constructor(mentionedType = 0, mentionedTargets = []) { 22 | super(MessageContentType.VOIP_CONTENT_TYPE_MUTE_VIDEO, mentionedType, mentionedTargets); 23 | } 24 | 25 | formatNotification(message) { 26 | // TODO 27 | return "mute video"; 28 | } 29 | 30 | encode() { 31 | let payload = super.encode(); 32 | payload.content = this.callId; 33 | 34 | let obj = { 35 | existParticipants: this.existParticipants, 36 | videoMuted: this.videoMuted, 37 | }; 38 | payload.binaryContent = wfc.utf8_to_b64(JSON.stringify(obj)); 39 | 40 | return payload; 41 | } 42 | 43 | decode(payload) { 44 | super.decode(payload); 45 | this.callId = payload.content; 46 | let json = wfc.b64_to_utf8(payload.binaryContent); 47 | let obj = JSON.parse(json); 48 | this.existParticipants = obj.existParticipants; 49 | this.videoMuted = obj.videoMuted; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /wfc/av/model/conferenceInfo.js: -------------------------------------------------------------------------------- 1 | export default class ConferenceInfo { 2 | conferenceId; 3 | conferenceTitle; 4 | password; 5 | pin; 6 | owner; 7 | managers = []; 8 | focus; 9 | // 秒 10 | startTime; 11 | endTime; 12 | audience; 13 | advance; 14 | //@SerializedName("allowSwitchMode") 15 | allowSwitchMode; // 其实更新allowTurnOnMic; 16 | noJoinBeforeStart = false; 17 | recording = false; 18 | 19 | 20 | isAllowTurnOnMic() { 21 | return this.allowSwitchMode; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /wfc/client/connectionStatus.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | export default class ConnectionStatus { 6 | static ConnectionStatusTimeInconsistent = -9; 7 | static ConnectionStatusNotLicensed = -8; 8 | static ConnectionStatusKickedOff = -7; 9 | static ConnectionStatusSecretKeyMismatch = -6; 10 | static ConnectionStatusTokenIncorrect = -5; 11 | static ConnectionStatusServerDown = -4; 12 | static ConnectionStatusRejected = -3; 13 | static ConnectionStatusLogout = -2; 14 | static ConnectionStatusUnconnected = -1; 15 | static ConnectionStatusConnecting = 0; 16 | static ConnectionStatusConnected = 1; 17 | static ConnectionStatusReceiveing = 2; 18 | 19 | static desc(status) { 20 | const desc = { 21 | '-9': '客户端和IM 服务端时间不同步,请进行时钟同步', 22 | '-8': 'IM 服务未授权或已过期,专业版IM-Server 是绑定域名或者 ip 的,只能通过所绑定的域名去连接', 23 | '-7': '被踢下线', 24 | '-6': '会话密钥错误,请参考 https://docs.wildfirechat.cn/faq/general.html 第12个问题排查', 25 | '-5': 'token错误', 26 | '-4': 'IM Server服务无法连通,请检查服务器是否宕机或者网络出现问题', 27 | '-3': '连接被服务器拒绝,一般是用户被封禁', 28 | '-2': '退出登录', 29 | '-1': '连接失败', 30 | '0': '连接中', 31 | '1': '连接成功,正常状态,所有业务可用', 32 | '2': '正在同步信息,登录以后要先同步消息,可能同步数据量比较大,这时可以选择等待连接状态变为1时来统一更新UI' 33 | }; 34 | return desc[status] 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /wfc/client/errorCode.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | export default class ErrorCode { 6 | //server error code 7 | static kEcServerSecrectKeyMismatch = 1; 8 | static kEcServerInvalidData = 2; 9 | static kEcServerServerError = 4; 10 | static kEcServerNotModified = 5; 11 | static kEcServerTokenIncorrect = 6; 12 | static kConnectionStatusKickedOff = 7; 13 | static kEcServerUserForbidden = 8; 14 | static kEcServerNotInGroup = 9; 15 | static kEcServerInvalidMessage = 10; 16 | static kEcServerGroupAlreadyExist = 11; 17 | static kEcServerPasswordIncorrect = 15; 18 | static kEcServerFriendAlreadyRequested = 16; 19 | static kEcServerFriendRequestOverFrequency = 17; 20 | static kEcServerFriendRquestBlocked = 18; 21 | static kEcServerFriendRequestOvertime = 19; 22 | static kEcServerNotInChatroom = 20; 23 | static kEcServerNotLicensed = 22; 24 | static kEcServerTimeInconsistent = 30; 25 | static kEcServerUserIsBlocked = 245; 26 | static kEcServerInBlacklist = 246; 27 | static kEcServerForbidden_send_msg = 247; 28 | static kEcServerNotRight = 248; 29 | static kEcServerTimeout = 249; 30 | static kEcServerOverFrequence = 250; 31 | static kEcServerInvalidParameter = 251; 32 | static kEcServerNotExist = 253; 33 | static kEcServerNotImplement = 254; 34 | 35 | } 36 | -------------------------------------------------------------------------------- /wfc/client/userSettingScope.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | export default class UserSettingScope { 6 | //不能直接使用,调用setConversation:silent:方法会使用到此值。 7 | static ConversationSilent = 1; 8 | static GlobalSilent = 2; 9 | //不能直接使用,调用setConversation:top:方法会使用到此值。 10 | static ConversationTop = 3; 11 | static HiddenNotificationDetail = 4; 12 | static GroupHideNickname = 5; 13 | static FavoriteGroup = 6; 14 | //不能直接使用,协议栈内会使用此值 15 | static Conversation_Sync = 7; 16 | //不能直接使用,协议栈内会使用此值 17 | static My_Channel = 8; 18 | //不能直接使用,协议栈内会使用此值 19 | static Listened_Channel = 9; 20 | static UserSettingPCOnline = 10; 21 | static UserSettingConversationReaded = 11; 22 | static WebOnline = 12; 23 | static DisableReceipt = 13; 24 | static FavoriteUser = 14; 25 | static MuteWhenPCOnline = 15; 26 | static LinesReaded = 16; 27 | static NoDisturbing = 17; 28 | static ConversationClearMessage = 18; 29 | static ConversationDraft = 19; 30 | static DisableSyncDraft = 20; 31 | static VoipSilent = 21; 32 | static PttReserved = 22; 33 | static CustomState = 23; 34 | static DisableSecretChat = 24; 35 | static PttSilent = 25; 36 | static GroupRemark = 26; 37 | 38 | // 不能直接使用,协议栈内部会使用此致 39 | static Privacy_Searchable = 27; 40 | 41 | // 不能直接使用,协议栈内部会使用此致 42 | static AddFriend_NoVerify = 28; 43 | // 用户自定义的scope需从1000开始,以防冲突 44 | static kUserSettingCustomBegin = 1000; 45 | } 46 | -------------------------------------------------------------------------------- /wfc/messages/ModifyChannelInfoType.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | export default class ModifyChannelInfoType { 6 | static Modify_Channel_Name = 0; 7 | static Modify_Channel_Portrait = 1; 8 | static Modify_Channel_Desc = 2; 9 | static Modify_Channel_Extra = 3; 10 | } 11 | -------------------------------------------------------------------------------- /wfc/messages/channelMenuEventMessageContent.js: -------------------------------------------------------------------------------- 1 | import MessageContent from "./messageContent"; 2 | import MessageContentType from "./messageContentType"; 3 | 4 | export default class ChannelMenuEventMessageContent extends MessageContent { 5 | menu 6 | 7 | constructor(menu) { 8 | super(MessageContentType.Channel_Menu_Event); 9 | this.menu = menu; 10 | } 11 | 12 | encode() { 13 | let payload = super.encode(); 14 | payload.content = JSON.stringify(this.menu); 15 | return payload; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /wfc/messages/deleteMessageContent.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | import MessageContent from './messageContent' 6 | import MessageContentType from './messageContentType'; 7 | import wfc from '../client/wfc' 8 | import Long from 'long' 9 | 10 | // 本消息由调用server api删除消息触发,请勿直接发送本消息 11 | export default class DeleteMessageContent extends MessageContent { 12 | operatorId = ''; 13 | messageUid = new Long(0); 14 | 15 | constructor(operatorId, messageUid) { 16 | super(MessageContentType.DeleteMessage_Notification); 17 | this.operatorId = operatorId; 18 | this.messageUid = messageUid; 19 | } 20 | 21 | formatNotification(message) { 22 | return "消息已删除"; 23 | } 24 | 25 | encode() { 26 | let payload = super.encode(); 27 | payload.content = this.operatorId; 28 | payload.binaryContent = wfc.utf8_to_b64(this.messageUid.toString()); 29 | return payload; 30 | } 31 | 32 | decode(payload) { 33 | super.decode(payload); 34 | this.operatorId = payload.content; 35 | this.messageUid = Long.fromString(wfc.b64_to_utf8(payload.binaryContent)); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /wfc/messages/enterChannelChatMessageContent.js: -------------------------------------------------------------------------------- 1 | import MessageContent from "./messageContent"; 2 | import MessageContentType from "./messageContentType"; 3 | 4 | export default class EnterChannelChatMessageContent extends MessageContent { 5 | constructor() { 6 | super(MessageContentType.Enter_Channel_Chat); 7 | } 8 | 9 | } 10 | -------------------------------------------------------------------------------- /wfc/messages/fileMessageContent.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | import MessageContentMediaType from "./messageContentMediaType"; 6 | import MediaMessageContent from "./mediaMessageContent"; 7 | import MessageContentType from "./messageContentType"; 8 | 9 | export default class FileMessageContent extends MediaMessageContent { 10 | name = ''; 11 | size = 0; 12 | 13 | constructor(fileOrLocalPath, remotePath, name, size) { 14 | super(MessageContentType.File, MessageContentMediaType.File, fileOrLocalPath, remotePath); 15 | if (fileOrLocalPath && fileOrLocalPath.name) { 16 | this.name = fileOrLocalPath.name; 17 | this.size = fileOrLocalPath.size; 18 | } else if (remotePath) { 19 | this.name = name ? name : remotePath.substring(remotePath.lastIndexOf('/') + 1) 20 | this.size = size ? size : 0; 21 | } 22 | } 23 | 24 | digest() { 25 | return '[文件]' + this.name; 26 | } 27 | 28 | encode() { 29 | let payload = super.encode(); 30 | payload.searchableContent = this.name; 31 | payload.content = this.size + ''; 32 | return payload; 33 | } 34 | 35 | decode(payload) { 36 | super.decode(payload); 37 | if (payload.searchableContent) { 38 | this.name = payload.searchableContent; 39 | this.size = Number(payload.content); 40 | } 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /wfc/messages/imageMessageContent.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | import MediaMessageContent from './mediaMessageContent'; 6 | import MessageContentMediaType from './messageContentMediaType'; 7 | import MessageContentType from './messageContentType'; 8 | 9 | export default class ImageMessageContent extends MediaMessageContent { 10 | // base64 encoded, 不包含头部:data:image/png;base64, 11 | thumbnail; 12 | imageWidth; 13 | imageHeight; 14 | 15 | 16 | constructor(fileOrLocalPath, remotePath, thumbnail) { 17 | super(MessageContentType.Image, MessageContentMediaType.Image, fileOrLocalPath, remotePath); 18 | this.thumbnail = thumbnail; 19 | } 20 | 21 | digest() { 22 | return '[图片]'; 23 | } 24 | 25 | encode() { 26 | let payload = super.encode(); 27 | payload.mediaType = MessageContentMediaType.Image; 28 | payload.binaryContent = this.thumbnail; 29 | if (this.imageWidth) { 30 | let obj = { 31 | w: this.imageWidth, 32 | h: this.imageHeight 33 | } 34 | payload.content = JSON.stringify(obj) 35 | } 36 | return payload; 37 | } 38 | 39 | decode(payload) { 40 | super.decode(payload); 41 | this.thumbnail = payload.binaryContent; 42 | if (payload.content) { 43 | let obj = JSON.parse(payload.content) 44 | this.imageWidth = obj['w']; 45 | this.imageHeight = obj['h']; 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /wfc/messages/leaveChannelChatMessageContent.js: -------------------------------------------------------------------------------- 1 | import MessageContent from "./messageContent"; 2 | import MessageContentType from "./messageContentType"; 3 | 4 | export default class LeaveChannelChatMessageContent extends MessageContent { 5 | constructor() { 6 | super(MessageContentType.Leave_Channel_Chat); 7 | } 8 | 9 | } 10 | -------------------------------------------------------------------------------- /wfc/messages/linkMessageContent.js: -------------------------------------------------------------------------------- 1 | import MessageContent from "./messageContent"; 2 | import MessageContentType from "./messageContentType"; 3 | import wfc from "../client/wfc"; 4 | 5 | export default class LinkMessageContent extends MessageContent { 6 | title; 7 | contentDigest; 8 | url; 9 | thumbnail; 10 | 11 | 12 | constructor() { 13 | super(MessageContentType.Link); 14 | } 15 | 16 | encode() { 17 | let payload = super.encode(); 18 | let obj = { 19 | d: this.contentDigest, 20 | u: this.url, 21 | t: this.thumbnail 22 | } 23 | 24 | payload.searchableContent = this.title; 25 | payload.binaryContent = wfc.utf8_to_b64(JSON.stringify(obj)); 26 | 27 | return payload; 28 | } 29 | 30 | decode(payload) { 31 | super.decode(payload); 32 | this.title = payload.searchableContent; 33 | let obj = JSON.parse(wfc.b64_to_utf8(payload.binaryContent)); 34 | this.contentDigest = obj.d; 35 | this.url = obj.u; 36 | this.thumbnail = obj.t; 37 | } 38 | digest(message) { 39 | let tmp = this.title ? this.title.trim() : this.contentDigest ? this.contentDigest.trim() : null; 40 | return tmp ? tmp : this.url; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /wfc/messages/locationMessageContent.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | import MessageContent from './messageContent' 6 | 7 | export default class LocationMessageContent extends MessageContent { 8 | title; 9 | // base64 encoded, 不包含头部:data:image/png;base64, 10 | thumbnail; 11 | lat; 12 | long; 13 | 14 | 15 | digest() { 16 | return '位置' 17 | } 18 | 19 | encode() { 20 | let payload = super.encode(); 21 | payload.searchableContent = this.title; 22 | payload.binaryContent = this.thumbnail; 23 | let location = { 24 | lat: this.lat, 25 | long: this.long 26 | }; 27 | payload.content = JSON.stringify(location); 28 | return payload; 29 | } 30 | 31 | decode(payload) { 32 | super.decode(payload); 33 | this.title = payload.searchableContent; 34 | this.thumbnail = payload.binaryContent; 35 | let location = JSON.parse(payload.content); 36 | this.lat = location.lat; 37 | this.long = location.long; 38 | } 39 | 40 | 41 | } 42 | -------------------------------------------------------------------------------- /wfc/messages/markUnreadMessageContent.js: -------------------------------------------------------------------------------- 1 | import MessageContent from "./messageContent"; 2 | import MessageContentType from "./messageContentType"; 3 | import {_patchToJavaLong, _reverseToJsLongString, longValue, stringValue} from "../util/longUtil"; 4 | import wfc from "../client/wfc"; 5 | 6 | export default class MarkUnreadMessageContent extends MessageContent { 7 | messageUid; 8 | timestamp; 9 | 10 | constructor(messageUid) { 11 | super(MessageContentType.Mark_Unread_Sync); 12 | this.messageUid = messageUid; 13 | } 14 | 15 | encode() { 16 | let payload = super.encode(); 17 | let obj = { 18 | u: stringValue(this.messageUid), 19 | t: stringValue(this.timestamp), 20 | } 21 | let str = JSON.stringify(obj) 22 | str = _patchToJavaLong(str, 'u'); 23 | str = _patchToJavaLong(str, 't'); 24 | payload.binaryContent = wfc.utf8_to_b64(str); 25 | 26 | return payload; 27 | } 28 | 29 | decode(payload) { 30 | super.decode(payload); 31 | 32 | let str = wfc.b64_to_utf8(payload.binaryContent); 33 | str = _reverseToJsLongString(str, 'u'); 34 | str = _reverseToJsLongString(str, 't'); 35 | let obj = JSON.parse(str); 36 | this.messageUid = obj.u ? longValue(obj.u) : undefined; 37 | this.timestamp = obj.t ? longValue(obj.t) : undefined; 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /wfc/messages/messageContent.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | import MessagePayload from "./messagePayload"; 6 | 7 | export default class MessageContent { 8 | type; 9 | //0 普通消息, 1 部分提醒, 2 提醒全部 10 | mentionedType = 0; 11 | //提醒对象,mentionedType 1时有效 12 | mentionedTargets = []; 13 | extra; 14 | pushContent; 15 | 16 | constructor(type, mentionedType = 0, mentionedTargets = []) { 17 | this.type = type; 18 | this.mentionedType = mentionedType; 19 | this.mentionedTargets = mentionedTargets; 20 | } 21 | 22 | digest(message) { 23 | return '...digest...'; 24 | } 25 | 26 | /** 27 | * return MessagePayload in json format 28 | */ 29 | encode() { 30 | let payload = new MessagePayload(); 31 | payload.type = this.type; 32 | payload.mentionedType = this.mentionedType; 33 | payload.mentionedTargets = this.mentionedTargets; 34 | payload.extra = this.extra; 35 | return payload; 36 | } 37 | 38 | /** 39 | * 40 | * @param {object} payload object json.parse from message#content 41 | */ 42 | decode(payload) { 43 | this.type = payload.type; 44 | this.mentionedType = payload.mentionedType; 45 | if (payload.hasOwnProperty('mentionedTarget')) { 46 | // web 47 | this.mentionedTargets = payload.mentionedTarget; 48 | } else { 49 | // pc 50 | this.mentionedTargets = payload.mentionedTargets; 51 | } 52 | this.extra = payload.extra; 53 | this.pushContent = payload.pushContent; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /wfc/messages/messageContentMediaType.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | export default class MessageContentMediaType { 6 | static General = 0; 7 | static Image = 1; 8 | static Voice = 2; 9 | static Video = 3; 10 | static File = 4; 11 | static Portrait = 5; 12 | static Favorite = 6; 13 | static Sticker = 7; 14 | static Moments = 8; 15 | } 16 | -------------------------------------------------------------------------------- /wfc/messages/messagePayload.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | /** 6 | * 7 | "content": { 8 | "type": 1, 9 | "searchableContent": "1234", 10 | "pushContent": "", 11 | "content": "", 12 | "binaryContent": "", 13 | "localContent": "", 14 | "mediaType": 0, 15 | "remoteMediaUrl": "", 16 | "localMediaPath": "", 17 | "mentionedType": 0, 18 | "mentionedTargets": [ ] 19 | }, 20 | */ 21 | export default class MessagePayload { 22 | type; 23 | searchableContent; 24 | pushContent; 25 | pushData; 26 | content; 27 | binaryContent; // base64 string, 图片时,不包含头部信息:data:image/png;base64, 28 | localContent; 29 | mediaType; 30 | remoteMediaUrl; 31 | localMediaPath; 32 | mentionedType = 0; 33 | mentionedTargets = []; 34 | extra; 35 | } 36 | -------------------------------------------------------------------------------- /wfc/messages/messageStatus.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | export default class MessageStatus { 6 | static All = -1; 7 | static Sending = 0; 8 | static Sent = 1; 9 | static SendFailure = 2; 10 | static Mentioned = 3; 11 | static AllMentioned = 4; 12 | static Unread = 5; 13 | static Readed = 6; 14 | static Played = 7; 15 | } 16 | -------------------------------------------------------------------------------- /wfc/messages/notification/addGroupMemberNotification.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | import wfc from '../../client/wfc' 6 | import MessageContentType from '../messageContentType'; 7 | 8 | import GroupNotificationContent from './groupNotification'; 9 | 10 | export default class AddGroupMemberNotification extends GroupNotificationContent { 11 | invitor = ''; 12 | invitees = []; 13 | 14 | constructor(invitor, invitees) { 15 | super(MessageContentType.AddGroupMember_Notification); 16 | this.invitor = invitor; 17 | this.invitees = invitees; 18 | } 19 | 20 | formatNotification() { 21 | let notifyStr; 22 | if (this.invitees.length === 1 && this.invitees[0] === this.invitor) { 23 | if (this.fromSelf) { 24 | return '您加入了群组'; 25 | } else { 26 | return wfc.getGroupMemberDisplayName(this.groupId, this.invitor) + ' 加入了群组'; 27 | } 28 | } 29 | 30 | if (this.fromSelf) { 31 | notifyStr = '您邀请:'; 32 | } else { 33 | notifyStr = wfc.getGroupMemberDisplayName(this.groupId, this.invitor) + '邀请:'; 34 | } 35 | 36 | let membersStr = ''; 37 | let userInfos = wfc.getUserInfos(this.invitees, this.groupId); 38 | userInfos.forEach(m => { 39 | membersStr += ' ' + m.displayName; 40 | }); 41 | 42 | return notifyStr + membersStr + '加入了群组'; 43 | } 44 | 45 | encode() { 46 | let payload = super.encode(); 47 | let obj = { 48 | g: this.groupId, 49 | o: this.invitor, 50 | ms: this.invitees, 51 | }; 52 | payload.binaryContent = wfc.utf8_to_b64(JSON.stringify(obj)); 53 | return payload; 54 | } 55 | 56 | decode(payload) { 57 | super.decode(payload); 58 | let json = wfc.b64_to_utf8(payload.binaryContent); 59 | let obj = JSON.parse(json); 60 | this.groupId = obj.g; 61 | this.invitor = obj.o; 62 | this.invitees = obj.ms; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /wfc/messages/notification/changeGroupNameNotification.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | import wfc from '../../client/wfc' 6 | import MessageContentType from "../messageContentType"; 7 | 8 | import GroupNotificationContent from "./groupNotification"; 9 | 10 | export default class ChangeGroupNameNotification extends GroupNotificationContent { 11 | operator = ''; 12 | name = ''; 13 | 14 | constructor(operator, name) { 15 | super(MessageContentType.ChangeGroupName_Notification); 16 | this.operator = operator; 17 | this.name = name; 18 | } 19 | 20 | formatNotification() { 21 | if (this.fromSelf) { 22 | return '您修改群名称为:' + this.name; 23 | } else { 24 | return wfc.getGroupMemberDisplayName(this.groupId, this.operator) + '修改群名称为:' + this.name; 25 | } 26 | } 27 | 28 | encode() { 29 | let payload = super.encode(); 30 | let obj = { 31 | g: this.groupId, 32 | n: this.name, 33 | o: this.operator, 34 | }; 35 | payload.binaryContent = wfc.utf8_to_b64(JSON.stringify(obj)); 36 | return payload; 37 | } 38 | 39 | decode(payload) { 40 | super.decode(payload); 41 | let json = wfc.b64_to_utf8(payload.binaryContent) 42 | let obj = JSON.parse(json); 43 | this.groupId = obj.g; 44 | this.operator = obj.o; 45 | this.name = obj.n; 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /wfc/messages/notification/changeGroupPortraitNotification.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | import wfc from '../../client/wfc' 6 | import MessageContentType from "../messageContentType"; 7 | 8 | import GroupNotificationContent from "./groupNotification"; 9 | 10 | export default class ChangeGroupPortraitNotification extends GroupNotificationContent { 11 | operator = ''; 12 | 13 | constructor(operator) { 14 | super(MessageContentType.ChangeGroupPortrait_Notification); 15 | this.operator = operator; 16 | } 17 | 18 | formatNotification() { 19 | if (this.fromSelf) { 20 | return '您修改群头像'; 21 | } else { 22 | return wfc.getGroupMemberDisplayName(this.groupId, this.operator) + '修改了群头像'; 23 | } 24 | } 25 | 26 | encode() { 27 | let payload = super.encode(); 28 | let obj = { 29 | g: this.groupId, 30 | n: this.name, 31 | }; 32 | payload.binaryContent = wfc.utf8_to_b64(JSON.stringify(obj)); 33 | return payload; 34 | } 35 | 36 | decode(payload) { 37 | super.decode(payload); 38 | let json = wfc.b64_to_utf8(payload.binaryContent) 39 | let obj = JSON.parse(json); 40 | this.groupId = obj.g; 41 | this.operator = obj.o; 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /wfc/messages/notification/chatRoomWelcomeNotificationContent.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | import NotificationMessageContent from "./notificationMessageContent"; 6 | 7 | export default class ChatRoomWelcomeNotificationContent extends NotificationMessageContent { 8 | welcome; 9 | 10 | 11 | formatNotification(message) { 12 | return this.welcome; 13 | } 14 | 15 | encode() { 16 | return super.encode(); 17 | } 18 | 19 | decode(payload) { 20 | super.decode(payload); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /wfc/messages/notification/createGroupNotification.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | import wfc from '../../client/wfc' 6 | import MessageContentType from '../messageContentType'; 7 | 8 | import GroupNotificationContent from './groupNotification'; 9 | 10 | export default class CreateGroupNotification extends GroupNotificationContent { 11 | creator = ''; 12 | groupName = ''; 13 | 14 | constructor(creator, groupName) { 15 | super(MessageContentType.CreateGroup_Notification); 16 | this.creator = creator; 17 | this.groupName = groupName; 18 | } 19 | 20 | formatNotification() { 21 | if (this.fromSelf) { 22 | return '您创建了群组 ' + this.groupName; 23 | } else { 24 | return wfc.getUserDisplayName(this.creator) + '创建了群组 ' + this.groupName; 25 | } 26 | } 27 | 28 | encode() { 29 | let payload = super.encode(); 30 | let obj = { 31 | g: this.groupId, 32 | n: this.groupName, 33 | o: this.creator, 34 | }; 35 | payload.binaryContent = wfc.utf8_to_b64(JSON.stringify(obj)); 36 | return payload; 37 | } 38 | 39 | decode(payload) { 40 | super.decode(payload); 41 | let json = wfc.b64_to_utf8(payload.binaryContent) 42 | let obj = JSON.parse(json); 43 | this.groupId = obj.g; 44 | this.creator = obj.o; 45 | this.groupName = obj.n; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /wfc/messages/notification/dismissGroupNotification.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | import wfc from '../../client/wfc' 6 | import MessageContentType from '../messageContentType'; 7 | 8 | import GroupNotificationContent from './groupNotification'; 9 | 10 | export default class DismissGroupNotification extends GroupNotificationContent { 11 | operator = ''; 12 | 13 | constructor(operator) { 14 | super(MessageContentType.DismissGroup_Notification); 15 | this.operator = operator; 16 | } 17 | 18 | formatNotification() { 19 | if (this.fromSelf) { 20 | return '您解散了群组'; 21 | } else { 22 | return wfc.getGroupMemberDisplayName(this.groupId, this.operator) + '解散了群组'; 23 | } 24 | } 25 | 26 | encode() { 27 | let payload = super.encode(); 28 | let obj = { 29 | g: this.groupId, 30 | o: this.operator, 31 | }; 32 | payload.binaryContent = wfc.utf8_to_b64(JSON.stringify(obj)); 33 | return payload; 34 | } 35 | 36 | decode(payload) { 37 | super.decode(payload); 38 | let json = wfc.b64_to_utf8(payload.binaryContent) 39 | let obj = JSON.parse(json); 40 | this.groupId = obj.g; 41 | this.operator = obj.o; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /wfc/messages/notification/friendAddedNotification.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | import NotificationMessageContent from "./notificationMessageContent"; 6 | import MessageContentType from "../messageContentType"; 7 | 8 | export default class FriendAddedNotification extends NotificationMessageContent { 9 | 10 | constructor() { 11 | super(MessageContentType.Friend_Added); 12 | } 13 | 14 | formatNotification() { 15 | return "你们已经是好友了,可以开始聊天了。"; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /wfc/messages/notification/friendGreetingNotification.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022 WildFireChat. All rights reserved. 3 | */ 4 | 5 | import NotificationMessageContent from "./notificationMessageContent"; 6 | import MessageContentType from "../messageContentType"; 7 | 8 | export default class FriendGreetingNotification extends NotificationMessageContent { 9 | constructor() { 10 | super(MessageContentType.Friend_Greeting); 11 | } 12 | 13 | formatNotification(message) { 14 | return "以上是打招呼的内容"; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /wfc/messages/notification/groupJoinTypeNotificationContent.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | import GroupNotificationContent from "./groupNotification"; 6 | import wfc from "../../client/wfc"; 7 | import MessageContentType from "../messageContentType"; 8 | 9 | export default class GroupJoinTypeNotificationContent extends GroupNotificationContent { 10 | operator; 11 | 12 | //在group type为Restricted时,0 开放加入权限(群成员可以拉人,用户也可以主动加入);1 只能群成员拉人入群;2 只能群管理拉人入群 13 | joinType; 14 | 15 | 16 | constructor(operator, joinType) { 17 | super(MessageContentType.ChangeJoinType_Notification); 18 | this.operator = operator; 19 | this.type = joinType; 20 | } 21 | 22 | formatNotification(message) { 23 | let notifyStr; 24 | if (this.fromSelf) { 25 | notifyStr = '您'; 26 | } else { 27 | notifyStr = wfc.getGroupMemberDisplayName(this.groupId, this.operator); 28 | } 29 | switch (this.joinType) { 30 | case 0: 31 | notifyStr += ' 开放了加入群组功能'; 32 | break; 33 | case 1: 34 | notifyStr += ' 仅允许群成员邀请加入群组'; 35 | break; 36 | case 2: 37 | notifyStr += " 关闭了加入群组功能"; 38 | break; 39 | default: 40 | break; 41 | } 42 | return notifyStr; 43 | } 44 | 45 | encode() { 46 | let payload = super.encode(); 47 | let obj = { 48 | g: this.groupId, 49 | o: this.operator, 50 | n: (this.joinType + '') 51 | }; 52 | payload.binaryContent = wfc.utf8_to_b64(JSON.stringify(obj)); 53 | return super.encode(); 54 | } 55 | 56 | decode(payload) { 57 | super.decode(payload); 58 | let obj = JSON.parse(wfc.b64_to_utf8(payload.binaryContent)); 59 | this.groupId = obj.g; 60 | this.operator = obj.o; 61 | this.joinType = parseInt(obj.n); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /wfc/messages/notification/groupMuteNotificationContent.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | import GroupNotificationContent from "./groupNotification"; 6 | import MessageContentType from "../messageContentType"; 7 | import wfc from "../../client/wfc"; 8 | 9 | export default class GroupMuteNotificationContent extends GroupNotificationContent { 10 | operator; 11 | 12 | //0 正常;1 全局禁言 13 | muteType; 14 | 15 | constructor(operator, muteType) { 16 | super(MessageContentType.MuteGroup_Notification); 17 | this.operator = operator; 18 | this.muteType = muteType; 19 | } 20 | 21 | formatNotification(message) { 22 | // return sb.toString(); 23 | let notifyStr = this.fromSelf ? '您' : wfc.getGroupMemberDisplayName(this.groupId, this.operator); 24 | notifyStr += this.muteType === 0 ? ' 关闭了全员禁言' : ' 开启了全员禁言'; 25 | 26 | return notifyStr; 27 | } 28 | 29 | encode() { 30 | let payload = super.encode(); 31 | let obj = { 32 | g: this.groupId, 33 | o: this.operator, 34 | n: this.muteType + '' 35 | }; 36 | payload.binaryContent = wfc.utf8_to_b64(JSON.stringify(obj)); 37 | return payload; 38 | } 39 | 40 | decode(payload) { 41 | super.decode(payload); 42 | let obj = JSON.parse(wfc.b64_to_utf8(payload.binaryContent)); 43 | this.groupId = obj.g; 44 | this.operator = obj.o; 45 | this.muteType = parseInt(obj.n); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /wfc/messages/notification/groupNotification.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | import NotificationMessageContent from "./notificationMessageContent"; 6 | 7 | export default class GroupNotificationContent extends NotificationMessageContent { 8 | groupId = ''; 9 | constructor(type) { 10 | super(type); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /wfc/messages/notification/groupPrivateChatNotificationContent.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | import GroupNotificationContent from "./groupNotification"; 6 | import MessageContentType from "../messageContentType"; 7 | import wfc from "../../client/wfc"; 8 | 9 | export default class GroupPrivateChatNotificationContent extends GroupNotificationContent { 10 | operator; 11 | 12 | //是否运行群中普通成员私聊。0 允许,1不允许 13 | privateChatType; 14 | 15 | constructor(operator, privateChatType) { 16 | super(MessageContentType.ChangePrivateChat_Notification); 17 | this.operator = operator; 18 | this.privateChatType = privateChatType; 19 | } 20 | 21 | formatNotification(message) { 22 | // return sb.toString(); 23 | let notifyStr = this.fromSelf ? '您' : wfc.getGroupMemberDisplayName(this.groupId, this.operator); 24 | notifyStr += this.privateChatType === 0 ? ' 开启了成员私聊' : ' 关闭了成员私聊'; 25 | 26 | return notifyStr; 27 | } 28 | 29 | encode() { 30 | let payload = super.encode(); 31 | let obj = { 32 | g: this.groupId, 33 | o: this.operator, 34 | n: this.privateChatType + '' 35 | }; 36 | payload.binaryContent = wfc.utf8_to_b64(JSON.stringify(obj)); 37 | return payload; 38 | } 39 | 40 | decode(payload) { 41 | super.decode(payload); 42 | let obj = JSON.parse(wfc.b64_to_utf8(payload.binaryContent)); 43 | this.groupId = obj.g; 44 | this.operator = obj.o; 45 | this.privateChatType = parseInt(obj.n); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /wfc/messages/notification/kickoffGroupMemberNotification.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | import wfc from '../../client/wfc' 6 | import MessageContentType from "../messageContentType"; 7 | 8 | import GroupNotificationContent from "./groupNotification"; 9 | 10 | export default class KickoffGroupMemberNotification extends GroupNotificationContent { 11 | operator = ''; 12 | kickedMembers = []; 13 | 14 | constructor(operator, kickedMembers) { 15 | super(MessageContentType.KickOffGroupMember_Notification); 16 | this.operator = operator; 17 | this.kickedMembers = kickedMembers; 18 | } 19 | 20 | formatNotification() { 21 | let notifyStr; 22 | if (this.fromSelf) { 23 | notifyStr = '您把 '; 24 | } else { 25 | notifyStr = wfc.getGroupMemberDisplayName(this.groupId, this.operator) + '把 '; 26 | } 27 | 28 | let kickedMembersStr = ''; 29 | let userInfos = wfc.getUserInfos(this.kickedMembers, this.groupId); 30 | userInfos.forEach(userInfo => { 31 | if (userInfo.uid === wfc.getUserId()) { 32 | kickedMembersStr += ' 您'; 33 | } else { 34 | kickedMembersStr += ' ' + userInfo.displayName; 35 | } 36 | }); 37 | 38 | return notifyStr + kickedMembersStr + ' 移除了群组'; 39 | } 40 | 41 | encode() { 42 | let payload = super.encode(); 43 | let obj = { 44 | g: this.groupId, 45 | ms: this.kickedMembers, 46 | o: this.operateUser, 47 | }; 48 | payload.binaryContent = wfc.utf8_to_b64(JSON.stringify(obj)); 49 | return payload; 50 | } 51 | 52 | decode(payload) { 53 | super.decode(payload); 54 | let json = wfc.b64_to_utf8(payload.binaryContent) 55 | let obj = JSON.parse(json); 56 | this.groupId = obj.g; 57 | this.operator = obj.o; 58 | this.kickedMembers = obj.ms; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /wfc/messages/notification/kickoffGroupMemberVisiableNotification.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | import wfc from '../../client/wfc' 6 | import MessageContentType from "../messageContentType"; 7 | 8 | import GroupNotificationContent from "./groupNotification"; 9 | 10 | export default class KickoffGroupMemberVisiableNotification extends GroupNotificationContent { 11 | operator = ''; 12 | kickedMembers = []; 13 | 14 | constructor(operator, kickedMembers) { 15 | super(MessageContentType.KickOffGroupMember_Visible_Notification); 16 | this.operator = operator; 17 | this.kickedMembers = kickedMembers; 18 | } 19 | 20 | formatNotification() { 21 | let notifyStr; 22 | if (this.fromSelf) { 23 | notifyStr = '您把 '; 24 | } else { 25 | notifyStr = wfc.getGroupMemberDisplayName(this.groupId, this.operator) + '把 '; 26 | } 27 | 28 | let kickedMembersStr = ''; 29 | let userInfos = wfc.getUserInfos(this.kickedMembers, this.groupId); 30 | userInfos.forEach(userInfo => { 31 | if (userInfo.uid === wfc.getUserId()) { 32 | kickedMembersStr += ' 您'; 33 | } else { 34 | kickedMembersStr += ' ' + userInfo.displayName; 35 | } 36 | }); 37 | 38 | return notifyStr + kickedMembersStr + ' 移除了群组'; 39 | } 40 | 41 | encode() { 42 | let payload = super.encode(); 43 | let obj = { 44 | g: this.groupId, 45 | ms: this.kickedMembers, 46 | o: this.operateUser, 47 | }; 48 | payload.binaryContent = wfc.utf8_to_b64(JSON.stringify(obj)); 49 | return payload; 50 | } 51 | 52 | decode(payload) { 53 | super.decode(payload); 54 | let json = wfc.b64_to_utf8(payload.binaryContent) 55 | let obj = JSON.parse(json); 56 | this.groupId = obj.g; 57 | this.operator = obj.o; 58 | this.kickedMembers = obj.ms; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /wfc/messages/notification/modifyGroupExtraNotification.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | import wfc from '../../client/wfc' 6 | import MessageContentType from '../messageContentType'; 7 | 8 | import GroupNotificationContent from './groupNotification'; 9 | 10 | export default class ModifyGroupExtraNotification extends GroupNotificationContent { 11 | operator = ''; 12 | groupExtra = ''; 13 | 14 | constructor(creator, groupExtra) { 15 | super(MessageContentType.ModifyGroupExtra_Notification); 16 | this.operator = creator; 17 | this.groupExtra = groupExtra; 18 | } 19 | 20 | formatNotification() { 21 | let notificationStr = ''; 22 | if (this.fromSelf) { 23 | notificationStr += '你'; 24 | } else { 25 | let userInfo = wfc.getUserInfo(this.operator, false, this.groupId) 26 | if (userInfo.friendAlias) { 27 | notificationStr += userInfo.friendAlias; 28 | } else if (userInfo.displayName) { 29 | notificationStr += userInfo.displayName; 30 | } else { 31 | notificationStr += this.operator; 32 | } 33 | } 34 | notificationStr += '修改'; 35 | notificationStr += '群附加信息为'; 36 | notificationStr += this.groupExtra; 37 | 38 | return notificationStr; 39 | } 40 | 41 | encode() { 42 | let payload = super.encode(); 43 | let obj = { 44 | g: this.groupId, 45 | n: this.groupExtra, 46 | o: this.operator, 47 | }; 48 | payload.binaryContent = wfc.utf8_to_b64(JSON.stringify(obj)); 49 | return payload; 50 | } 51 | 52 | decode(payload) { 53 | super.decode(payload); 54 | let json = wfc.b64_to_utf8(payload.binaryContent) 55 | let obj = JSON.parse(json); 56 | this.groupId = obj.g; 57 | this.operator = obj.o; 58 | this.groupExtra = obj.n; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /wfc/messages/notification/notificationMessageContent.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | import MessageContent from "../messageContent"; 6 | 7 | export default class NotificationMessageContent extends MessageContent { 8 | // message#protoMessageToMessage时设置 9 | fromSelf = false; 10 | 11 | constructor(type) { 12 | super(type); 13 | } 14 | 15 | digest(message) { 16 | var desc = ''; 17 | try { 18 | desc = this.formatNotification(message); 19 | } catch (error) { 20 | console.log('disgest', error); 21 | } 22 | return desc; 23 | } 24 | 25 | formatNotification(message) { 26 | return '..nofication..'; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /wfc/messages/notification/quitGroupNotification.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | import wfc from '../../client/wfc' 6 | import MessageContentType from '../messageContentType'; 7 | 8 | import GroupNotificationContent from './groupNotification'; 9 | 10 | export default class QuitGroupNotification extends GroupNotificationContent { 11 | operator = ''; 12 | 13 | constructor(operator) { 14 | super(MessageContentType.QuitGroup_Notification); 15 | this.operator = operator; 16 | } 17 | 18 | formatNotification() { 19 | if (this.fromSelf) { 20 | return '您退出了群组'; 21 | } else { 22 | return wfc.getGroupMemberDisplayName(this.groupId, this.operator) + '退出了群组'; 23 | } 24 | } 25 | 26 | encode() { 27 | let payload = super.encode(); 28 | let obj = { 29 | g: this.groupId, 30 | o: this.operator, 31 | }; 32 | payload.binaryContent = wfc.utf8_to_b64(JSON.stringify(obj)); 33 | return payload; 34 | } 35 | 36 | decode(payload) { 37 | super.decode(payload); 38 | let json = wfc.b64_to_utf8(payload.binaryContent) 39 | let obj = JSON.parse(json); 40 | this.groupId = obj.g; 41 | this.operator = obj.o; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /wfc/messages/notification/quitGroupVisiableNotification.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | import wfc from '../../client/wfc' 6 | import MessageContentType from '../messageContentType'; 7 | 8 | import GroupNotificationContent from './groupNotification'; 9 | 10 | export default class QuitVisiableGroupNotification extends GroupNotificationContent { 11 | operator = ''; 12 | 13 | constructor(operator) { 14 | super(MessageContentType.QuitGroup_Visible_Notification); 15 | this.operator = operator; 16 | } 17 | 18 | formatNotification() { 19 | if (this.fromSelf) { 20 | return '您退出了群组'; 21 | } else { 22 | return wfc.getGroupMemberDisplayName(this.groupId, this.operator) + '退出了群组'; 23 | } 24 | } 25 | 26 | encode() { 27 | let payload = super.encode(); 28 | let obj = { 29 | g: this.groupId, 30 | o: this.operator, 31 | }; 32 | payload.binaryContent = wfc.utf8_to_b64(JSON.stringify(obj)); 33 | return payload; 34 | } 35 | 36 | decode(payload) { 37 | super.decode(payload); 38 | let json = wfc.b64_to_utf8(payload.binaryContent) 39 | let obj = JSON.parse(json); 40 | this.groupId = obj.g; 41 | this.operator = obj.o; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /wfc/messages/notification/richNotificationMessageContent.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | import wfc from '../../client/wfc' 6 | import MessageContentType from '../messageContentType'; 7 | 8 | import NotificationMessageContent from "./notificationMessageContent"; 9 | 10 | export default class RichNotificationMessageContent extends NotificationMessageContent { 11 | 12 | // 富通知消息 13 | title; 14 | desc; 15 | remark; 16 | 17 | // @[@{@"key":@"登陆账户", @"value":@"野火IM", @"color":@"#173155"}, @{@"key":@"登陆地点", @"value":@"北京", @"color":@"#173155"}] 18 | datas; 19 | 20 | // 附加信息 21 | exName; 22 | exPortrait; 23 | exUrl; 24 | 25 | // 应用信息 26 | appId; 27 | 28 | constructor() { 29 | super(MessageContentType.Rich_Notification); 30 | } 31 | 32 | formatNotification() { 33 | return this.title; 34 | } 35 | 36 | encode() { 37 | let payload = super.encode(); 38 | payload.pushContent = this.title; 39 | payload.content = this.desc; 40 | 41 | let obj = { 42 | remark: this.remark, 43 | exName: this.exName, 44 | exPortrait: this.exPortrait, 45 | exUrl: this.exUrl, 46 | appId: this.appId, 47 | datas: this.datas, 48 | } 49 | payload.binaryContent = wfc.utf8_to_b64(JSON.stringify(obj)) 50 | 51 | return payload; 52 | } 53 | 54 | decode(payload) { 55 | super.decode(payload); 56 | this.title = payload.pushContent; 57 | this.desc = payload.content; 58 | let json = wfc.b64_to_utf8(payload.binaryContent) 59 | let obj = JSON.parse(json); 60 | this.remark = obj.remark; 61 | this.exName = obj.exName; 62 | this.exPortrait = obj.exPortrait; 63 | this.exUrl = obj.exUrl; 64 | this.appId = obj.appId; 65 | this.datas = obj.datas; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /wfc/messages/notification/startSecretChatNotification.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | import NotificationMessageContent from './notificationMessageContent' 6 | import MessageContentType from "../messageContentType"; 7 | import wfc from "../../client/wfc"; 8 | import SecretChatState from "../../model/secretChatState"; 9 | 10 | export default class StartSecretChatNotification extends NotificationMessageContent { 11 | 12 | constructor() { 13 | super(MessageContentType.StartSecretChat_Notification); 14 | } 15 | 16 | formatNotification(message) { 17 | let state = wfc.getSecretChatInfo(message.conversation.target).state; 18 | if (state === SecretChatState.Starting) { 19 | return "等待对方响应"; 20 | } else if (state === SecretChatState.Accepting) { 21 | return "密聊会话建立中"; 22 | } else if (state === SecretChatState.Established) { 23 | return "密聊会话已建立"; 24 | } else if (state === SecretChatState.Canceled) { 25 | return "密聊会话已取消"; 26 | } else { 27 | return "密聊会话不可用"; 28 | } 29 | } 30 | 31 | encode() { 32 | return super.encode(); 33 | } 34 | 35 | decode(payload) { 36 | super.decode(payload); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /wfc/messages/notification/templateNotification.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | import NotificationMessageContent from './notificationMessageContent' 6 | 7 | export default class TemplateNotification extends NotificationMessageContent { 8 | tip = ''; 9 | 10 | constructor(type) { 11 | super(type) 12 | this.tip = ''; 13 | } 14 | 15 | formatNotification() { 16 | return this.tip; 17 | } 18 | 19 | digest() { 20 | return this.tip; 21 | } 22 | 23 | encode() { 24 | let payload = super.encode(); 25 | payload.content = this.tip; 26 | return payload; 27 | }; 28 | 29 | decode(payload) { 30 | super.decode(payload); 31 | this.tip = payload.content; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /wfc/messages/notification/tipNotification.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | import NotificationMessageContent from './notificationMessageContent' 6 | import MessageContentType from '../messageContentType'; 7 | 8 | export default class TipNotificationMessageContent extends NotificationMessageContent { 9 | tip = ''; 10 | 11 | constructor(tip) { 12 | super(MessageContentType.Tip_Notification); 13 | this.tip = tip; 14 | } 15 | 16 | formatNotification() { 17 | return this.tip; 18 | } 19 | 20 | digest() { 21 | return this.tip; 22 | } 23 | 24 | encode() { 25 | let payload = super.encode(); 26 | payload.content = this.tip; 27 | return payload; 28 | }; 29 | 30 | decode(payload) { 31 | super.decode(payload); 32 | this.tip = payload.content; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /wfc/messages/notification/transferGroupOwnerNotification.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | import wfc from '../../client/wfc' 6 | import MessageContentType from '../messageContentType'; 7 | import GroupNotificationContent from './groupNotification'; 8 | 9 | export default class TransferGroupOwnerNotification extends GroupNotificationContent { 10 | operator = ''; 11 | newOwner = ''; 12 | 13 | constructor(operator, newOwner) { 14 | super(MessageContentType.TransferGroupOwner_Notification); 15 | this.operator = operator; 16 | this.newOwner = newOwner; 17 | } 18 | 19 | formatNotification() { 20 | if (this.fromSelf) { 21 | return '您把群转让给了 ' + wfc.getGroupMemberDisplayName(this.groupId, this.newOwner); 22 | } else { 23 | return wfc.getGroupMemberDisplayName(this.groupId, this.operator) + '把群转让给了 ' + wfc.getGroupMemberDisplayName(this.groupId, this.newOwner) 24 | } 25 | } 26 | 27 | encode() { 28 | let payload = super.encode(); 29 | let obj = { 30 | g: this.groupId, 31 | o: this.operator, 32 | m: this.newOwner, 33 | }; 34 | payload.binaryContent = wfc.utf8_to_b64(JSON.stringify(obj)); 35 | return payload; 36 | } 37 | 38 | decode(payload) { 39 | super.decode(payload); 40 | let json = wfc.b64_to_utf8(payload.binaryContent) 41 | let obj = JSON.parse(json); 42 | this.groupId = obj.g; 43 | this.operator = obj.o; 44 | this.newOwner = obj.m; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /wfc/messages/pcLoginRequestMessageContent.js: -------------------------------------------------------------------------------- 1 | import MessageContent from "./messageContent"; 2 | import MessageContentType from "./messageContentType"; 3 | import MessageContentMediaType from "./messageContentMediaType"; 4 | import wfc from "../client/wfc"; 5 | 6 | export default class PcLoginRequestMessageContent extends MessageContent{ 7 | platform; 8 | sessionId; 9 | 10 | 11 | constructor() { 12 | super(MessageContentType.PC_Login_Request); 13 | } 14 | 15 | digest() { 16 | return '[PC请求登录]'; 17 | } 18 | 19 | encode() { 20 | let payload = super.encode(); 21 | payload.mediaType = MessageContentMediaType.File; 22 | let obj = { 23 | p : this.platform, 24 | t: this.sessionId, 25 | }; 26 | payload.binaryContent = wfc.utf8_to_b64(JSON.stringify(obj)); 27 | return payload; 28 | } 29 | 30 | decode(payload) { 31 | super.decode(payload); 32 | let obj = JSON.parse(wfc.b64_to_utf8(payload.binaryContent)); 33 | this.platform = obj.p; 34 | this.sessionId = obj.t; 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /wfc/messages/persistFlag.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | 6 | export default class PersistFlag { 7 | static No_Persist = 0; 8 | static Persist = 1; 9 | static Persist_And_Count = 3; 10 | static Transparent = 4; 11 | } 12 | -------------------------------------------------------------------------------- /wfc/messages/ptextMessageContent.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | import MessageContentType from './messageContentType'; 6 | import TextMessageContent from './textMessageContent'; 7 | 8 | 9 | export default class PTextMessageContent extends TextMessageContent { 10 | 11 | constructor(content, mentionedType = 0, mentionedTargets = []) { 12 | super(content, mentionedType, mentionedTargets); 13 | this.type = MessageContentType.P_Text; 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /wfc/messages/soundMessageContent.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | import MediaMessageContent from './mediaMessageContent' 6 | import MessageContentMediaType from './messageContentMediaType'; 7 | import MessageContentType from './messageContentType'; 8 | 9 | export default class SoundMessageContent extends MediaMessageContent { 10 | duration; 11 | 12 | constructor(fileOrLocalPath, remotePath, duration) { 13 | super(MessageContentType.Voice, MessageContentMediaType.Voice, fileOrLocalPath, remotePath); 14 | this.duration = duration; 15 | } 16 | 17 | digest() { 18 | return '[语音]'; 19 | } 20 | 21 | encode() { 22 | let payload = super.encode(); 23 | payload.mediaType = MessageContentMediaType.Voice; 24 | let obj = { 25 | duration: this.duration, 26 | }; 27 | payload.content = JSON.stringify(obj); 28 | return payload; 29 | } 30 | 31 | decode(payload) { 32 | super.decode(payload); 33 | let obj = JSON.parse(payload.content); 34 | this.duration = obj.duration; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /wfc/messages/stickerMessageContent.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | import MessageContentMediaType from "./messageContentMediaType"; 6 | import MediaMessageContent from "./mediaMessageContent"; 7 | import MessageContentType from "./messageContentType"; 8 | 9 | import wfc from "../client/wfc" 10 | 11 | 12 | export default class StickerMessageContent extends MediaMessageContent { 13 | width = 200; 14 | height = 200; 15 | 16 | constructor(filerOrLocalPath, remotePath, width, height) { 17 | super(MessageContentType.Sticker, MessageContentMediaType.Sticker, filerOrLocalPath, remotePath); 18 | this.width = width; 19 | this.height = height; 20 | } 21 | 22 | digest() { 23 | return '[表情]'; 24 | } 25 | 26 | encode() { 27 | let payload = super.encode(); 28 | payload.mediaType = MessageContentMediaType.File; 29 | let obj = { 30 | x: this.width, 31 | y: this.height, 32 | }; 33 | payload.binaryContent = wfc.utf8_to_b64(JSON.stringify(obj)); 34 | return payload; 35 | } 36 | 37 | decode(payload) { 38 | super.decode(payload); 39 | let obj = JSON.parse(wfc.b64_to_utf8(payload.binaryContent)); 40 | this.width = obj.x; 41 | this.height = obj.y; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /wfc/messages/streamingTextGeneratedMessageContent.js: -------------------------------------------------------------------------------- 1 | import MessageContent from "./messageContent"; 2 | import MessageContentType from "./messageContentType"; 3 | 4 | export default class StreamingTextGeneratedMessageContent extends MessageContent { 5 | text = ''; 6 | streamId = ''; 7 | 8 | constructor() { 9 | super(MessageContentType.Streaming_Text_Generated); 10 | } 11 | 12 | digest(message) { 13 | return this.text; 14 | } 15 | 16 | encode() { 17 | let payload = super.encode(); 18 | payload.searchableContent = this.text; 19 | payload.content = this.streamId; 20 | return payload; 21 | } 22 | 23 | decode(payload) { 24 | super.decode(payload); 25 | this.text = payload.searchableContent; 26 | this.streamId = payload.content; 27 | } 28 | } -------------------------------------------------------------------------------- /wfc/messages/streamingTextGeneratingMessageContent.js: -------------------------------------------------------------------------------- 1 | import MessageContent from "./messageContent"; 2 | import MessageContentType from "./messageContentType"; 3 | 4 | export default class StreamingTextGeneratingMessageContent extends MessageContent { 5 | text = ''; 6 | streamId = ''; 7 | 8 | constructor() { 9 | super(MessageContentType.Streaming_Text_Generating); 10 | } 11 | 12 | digest(message) { 13 | return this.text; 14 | } 15 | 16 | encode() { 17 | let payload = super.encode(); 18 | payload.searchableContent = this.text; 19 | payload.content = this.streamId; 20 | return payload; 21 | } 22 | 23 | decode(payload) { 24 | super.decode(payload); 25 | this.text = payload.searchableContent; 26 | this.streamId = payload.content; 27 | } 28 | } -------------------------------------------------------------------------------- /wfc/messages/textMessageContent.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | import MessageContent from './messageContent' 6 | import MessageContentType from './messageContentType'; 7 | import wfc from '../client/wfc' 8 | import QuoteInfo from "../model/quoteInfo"; 9 | 10 | export default class TextMessageContent extends MessageContent { 11 | content; 12 | quoteInfo; 13 | 14 | constructor(content, mentionedType = 0, mentionedTargets = []) { 15 | super(MessageContentType.Text, mentionedType, mentionedTargets); 16 | this.content = content; 17 | } 18 | 19 | digest() { 20 | return this.content; 21 | } 22 | 23 | encode() { 24 | let payload = super.encode(); 25 | payload.searchableContent = this.content; 26 | if (this.quoteInfo) { 27 | let obj = { 28 | "quote": this.quoteInfo.encode() 29 | } 30 | // JSON.parse 和 JSON.stringify 不能处理java long 31 | let orgStr = JSON.stringify(obj); 32 | let str = orgStr.replace(/"u":"([0-9]+)"/, "\"u\":$1"); 33 | 34 | payload.binaryContent = wfc.utf8_to_b64(str); 35 | } 36 | return payload; 37 | } 38 | 39 | decode(payload) { 40 | super.decode(payload); 41 | this.content = payload.searchableContent; 42 | if (payload.binaryContent && payload.binaryContent.length > 0) { 43 | // JSON.parse 和 JSON.stringify 不能处理java long 44 | let quoteInfoStr = wfc.b64_to_utf8(payload.binaryContent) 45 | // FIXME node 环境,decodeURIComponent 方法,有时候会在最后添加上@字符,目前尚未找到原因,先规避 46 | quoteInfoStr = quoteInfoStr.substring(0, quoteInfoStr.lastIndexOf('}') + 1) 47 | quoteInfoStr = quoteInfoStr.replace(/"u":([0-9]+),/, '"u":"$1",') 48 | let obj = JSON.parse(quoteInfoStr).quote 49 | 50 | this.quoteInfo = new QuoteInfo(); 51 | this.quoteInfo.decode(obj); 52 | } 53 | } 54 | 55 | setQuoteInfo(quoteInfo) { 56 | this.quoteInfo = quoteInfo; 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /wfc/messages/typingMessageContent.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | import MessageContent from "./messageContent"; 6 | import MessageContentType from "./messageContentType"; 7 | 8 | export default class TypingMessageContent extends MessageContent { 9 | 10 | static TYPING_TEXT = 0; 11 | static TYPING_VOICE = 1; 12 | static TYPING_CAMERA = 2; 13 | static TYPING_LOCATION = 3; 14 | static TYPING_FILE = 4; 15 | 16 | typingType = TypingMessageContent.TYPING_TEXT; 17 | 18 | constructor(type) { 19 | super(MessageContentType.Typing); 20 | this.typingType = type; 21 | } 22 | 23 | digest() { 24 | return this.content; 25 | } 26 | 27 | encode() { 28 | let payload = super.encode(); 29 | payload.content = this.typingType + ''; 30 | return payload; 31 | } 32 | 33 | decode(payload) { 34 | super.decode(payload); 35 | this.typingType = parseInt(payload.content); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /wfc/messages/unknownMessageContent.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | import MessageContent from "./messageContent"; 6 | import MessageContentType from "./messageContentType"; 7 | 8 | export default class UnknownMessageContent extends MessageContent { 9 | originalPayload; 10 | 11 | constructor(originalPayload) { 12 | super(MessageContentType.Unknown); 13 | this.originalPayload = originalPayload; 14 | } 15 | 16 | encode() { 17 | return this.originalPayload; 18 | } 19 | 20 | decode(paylaod) { 21 | this.originalPayload = paylaod; 22 | } 23 | 24 | digest() { 25 | return '未知类型消息'; 26 | } 27 | } -------------------------------------------------------------------------------- /wfc/messages/unsupportMessageConten.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | import MessageContent from "./messageContent"; 6 | 7 | export default class UnsupportMessageContent extends MessageContent { 8 | 9 | digest() { 10 | return '尚不支持该类型消息, 请手机查看 : ' + this.type; 11 | } 12 | } -------------------------------------------------------------------------------- /wfc/messages/videoMessageContent.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | import MediaMessageContent from './mediaMessageContent' 6 | import MessageContentMediaType from './messageContentMediaType'; 7 | import MessageContentType from './messageContentType'; 8 | 9 | export default class VideoMessageContent extends MediaMessageContent { 10 | // base64 encoded 11 | thumbnail; 12 | duration; 13 | 14 | constructor(fileOrLocalPath, remotePath, thumbnail, duration = 0) { 15 | super(MessageContentType.Video, MessageContentMediaType.Video, fileOrLocalPath, remotePath); 16 | this.thumbnail = thumbnail; 17 | this.duration = duration; 18 | } 19 | 20 | digest() { 21 | return '[视频]'; 22 | } 23 | 24 | encode() { 25 | let payload = super.encode(); 26 | payload.binaryContent = this.thumbnail; 27 | let obj = { 28 | d: this.duration, 29 | duration: this.duration 30 | } 31 | payload.content = JSON.stringify(obj); 32 | payload.mediaType = MessageContentMediaType.Video; 33 | return payload; 34 | } 35 | 36 | decode(payload) { 37 | super.decode(payload); 38 | this.thumbnail = payload.binaryContent; 39 | if (payload.content) { 40 | let obj = JSON.parse(payload.content) 41 | this.duration = obj.d; 42 | if (this.duration === undefined) { 43 | this.duration = obj.duration; 44 | } 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /wfc/model/NullChannelInfo.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | import ChannelInfo from "./channelInfo"; 6 | 7 | export default class NullChannelInfo extends ChannelInfo { 8 | constructor(channelId) { 9 | super() 10 | this.channelId = channelId; 11 | this.name = `<${channelId}>` 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /wfc/model/channelInfo.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | export default class ChannelInfo { 6 | channelId; 7 | name; 8 | portrait; 9 | desc; 10 | owner; 11 | // 0, public; 1, private; 2, destoryed 12 | status; 13 | extra; 14 | updateDt; 15 | menus; 16 | //第0位表示是否允许查看用户所有信息,还是只允许看用户id,用户名称,用户昵称和用户头像 17 | static StatusMaskFullInfo = 0x01; 18 | //第1位表示是否允许查看非订阅用户信息 19 | static StatusMaskUnsubscribedUserAccess = 0x02; 20 | //第2位表示是否允许主动添加用户订阅关系 21 | static StatusMaskActiveSubscribe = 0x04; 22 | //第3位表示是否允许给非订阅用户发送消息 23 | static StatusMaskMessageUnsubscribed = 0x08; 24 | //第4位表示是否私有 25 | static StatusMaskPrivate = 0x10; 26 | 27 | //第6位表示是否删除 28 | static StatusMaskDeleted = 0x40; 29 | 30 | //第8位表示是否全局频道,全局平道发送消息时,会广播给系统所有人 31 | static StatusMaskGlobal = 0x80; 32 | } 33 | -------------------------------------------------------------------------------- /wfc/model/channelMenu.js: -------------------------------------------------------------------------------- 1 | export default class ChannelMenu { 2 | menuId; 3 | type; 4 | name; 5 | key; 6 | url; 7 | mediaId; 8 | articleId; 9 | appId; 10 | appPage; 11 | extra; 12 | subMenus; 13 | } 14 | -------------------------------------------------------------------------------- /wfc/model/chatRoomInfo.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | export default class ChatRoomInfo { 6 | chatRoomId; 7 | title; 8 | desc; 9 | portrait; 10 | extra; 11 | // 0, normal; 1, not start; 2, end 12 | state; 13 | memberCount; 14 | createDt; 15 | updateDt; 16 | } -------------------------------------------------------------------------------- /wfc/model/chatRoomMemberInfo.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | export default class ChatRoomMemberInfo { 6 | memberCount; 7 | members; 8 | } -------------------------------------------------------------------------------- /wfc/model/conversation.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | import ConversationType from "./conversationType"; 6 | 7 | /** 8 | * 9 | "conversation":{ 10 | "conversationType": 0, 11 | "target": "UZUWUWuu", 12 | "line": 0, 13 | } 14 | */ 15 | export default class Conversation { 16 | type = ConversationType.Single; 17 | conversationType = this.type; // 这行是为了做一个兼容处理 18 | target = ''; 19 | line = 0; 20 | 21 | constructor(type, target, line = 0) { 22 | this.type = type; 23 | this.conversationType = type; 24 | this.target = target; 25 | this.line = line; 26 | } 27 | 28 | equal(conversation) { 29 | if (!conversation) { 30 | return false; 31 | } 32 | return this.type === conversation.type 33 | && this.target === conversation.target 34 | && this.line === conversation.line; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /wfc/model/conversationSearchResult.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | import Conversation from "./conversation"; 6 | import Message from "../messages/message"; 7 | 8 | export default class ConversationSearchResult { 9 | conversation; 10 | //only matchCount == 1, load the message 11 | matchMessage; 12 | timestamp; 13 | matchCount; 14 | 15 | static fromProtoConversationSearchResult(obj) { 16 | let conversationSearchResult = new ConversationSearchResult(); 17 | if (obj.conversation) { 18 | conversationSearchResult.conversation = new Conversation(obj.conversation.conversationType !== undefined ? obj.conversation.conversationType : obj.conversation.type, obj.conversation.target, obj.conversation.line); 19 | } else { 20 | conversationSearchResult.conversation = new Conversation(obj.conversationType, obj.target, obj.line); 21 | } 22 | conversationSearchResult.matchCount = obj.marchedCount; 23 | if (obj.marchedCount === 1) { 24 | conversationSearchResult.matchMessage = Message.fromProtoMessage(obj.marchedMessage); 25 | } 26 | conversationSearchResult.timestamp = Number(obj.timestamp); 27 | 28 | return conversationSearchResult; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /wfc/model/conversationType.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | export default class ConversationType { 6 | static Single = 0; 7 | static Group = 1; 8 | static ChatRoom = 2; 9 | static Channel = 3; 10 | static SecretChat = 5; 11 | } 12 | -------------------------------------------------------------------------------- /wfc/model/fileRecord.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | export default class FileRecord { 6 | userId; 7 | conversation; 8 | messageUid; 9 | name; 10 | url; 11 | size; 12 | downloadCount; 13 | timestamp; 14 | } 15 | -------------------------------------------------------------------------------- /wfc/model/friend.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | export default class Friend { 6 | userId; 7 | alias; 8 | extra; 9 | timestamp; 10 | } 11 | -------------------------------------------------------------------------------- /wfc/model/friendRequest.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | export default class FriendRequest { 6 | direction; 7 | target; 8 | reason; 9 | extra; 10 | // RequestStatus_Sent = 0, 11 | // RequestStatus_Accepted = 1, 12 | // RequestStatus_Rejected = 3 13 | status; 14 | readStatus; 15 | timestamp; 16 | } 17 | -------------------------------------------------------------------------------- /wfc/model/groupInfo.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | import GroupType from "./groupType"; 6 | 7 | /* 8 | public String target; 9 | public String name; 10 | public String portrait; 11 | public String owner; 12 | public GroupType type; 13 | public int memberCount; 14 | public String extra; 15 | public long updateDt 16 | */ 17 | 18 | export default class GroupInfo { 19 | target = ''; 20 | name = ''; 21 | portrait = ''; 22 | owner = ''; 23 | type = GroupType.Normal; 24 | memberCount = 0; 25 | extra = ''; 26 | remark = ''; 27 | updateDt = 0; 28 | deleted = 0; 29 | memberDt = 0; 30 | 31 | //0 正常;1 全局禁言 32 | mute = 0; 33 | 34 | //在group type为Restricted时,0 开放加入权限(群成员可以拉人,用户也可以主动加入);1 只能群成员拉人入群;2 只能群管理拉人入群 35 | joinType = 0; 36 | 37 | //是否运行群中普通成员私聊。0 允许,1不允许 38 | privateChat = 0; 39 | 40 | //是否是超级群组 41 | superGroup = 0; 42 | 43 | //是否可以搜索到该群,功能暂未实现 44 | searchable 45 | 46 | //是否可以查看群历史消息, 0 不允许,1允许。仅专业版有效 47 | historyMessage; 48 | 49 | //群最大成员数。仅专业版有效 50 | maxMemberCount; 51 | } 52 | -------------------------------------------------------------------------------- /wfc/model/groupMember.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | import wfc from '../client/wfc' 6 | 7 | export default class GroupMember { 8 | groupId = ''; 9 | memberId = ''; 10 | alias = ''; 11 | extra = ''; 12 | type = 0; 13 | updateDt = 0; 14 | createDt = 0; 15 | 16 | getName() { 17 | let u = wfc.getUserInfo(this.memberId); 18 | return u.displayName; 19 | } 20 | 21 | getPortrait() { 22 | let u = wfc.getUserInfo(this.memberId); 23 | return u.portrait; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /wfc/model/groupMemberType.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | export default class GroupMemberType { 6 | static Normal = 0; 7 | static Manager = 1; 8 | static Owner = 2; 9 | static Muted = 3; 10 | static Removed = 4; 11 | static Allowed = 5; 12 | } 13 | -------------------------------------------------------------------------------- /wfc/model/groupSearchResult.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | import GroupInfo from "./groupInfo"; 6 | 7 | export default class GroupSearchResult { 8 | groupInfo; 9 | //0 march group name, 1 march group member name, 2 both 10 | matchType; 11 | matchMembers = []; 12 | 13 | static fromProtoGroupSearchResult(obj) { 14 | let groupSearchResult = new GroupSearchResult(); 15 | groupSearchResult.groupInfo = Object.assign(new GroupInfo(), obj.groupInfo) 16 | groupSearchResult.matchType = obj.marchedType; 17 | groupSearchResult.matchMembers = obj.marchedMemberNames; 18 | return groupSearchResult; 19 | 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /wfc/model/groupType.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | export default class GroupType { 6 | static Normal = 0; 7 | static Free = 1; 8 | static Restricted = 2; 9 | static Organization = 3; 10 | } 11 | -------------------------------------------------------------------------------- /wfc/model/internal/friendInfo.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | export default class FriendInfo { 6 | uid = ''; 7 | updateDt = 0; 8 | state = 0; // 0, 正常;1,无关系;2 黑名单 9 | alias = ''; 10 | blacked = 0; 11 | extra = ''; 12 | } 13 | -------------------------------------------------------------------------------- /wfc/model/mention.js: -------------------------------------------------------------------------------- 1 | export default class Mention { 2 | start; 3 | end; 4 | isMentionAll; 5 | uid; 6 | 7 | constructor(start, end, uid, isMentionAll) { 8 | this.start = start; 9 | this.end = end; 10 | this.uid = uid; 11 | this.isMentionAll = isMentionAll; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /wfc/model/modifyGroupInfoType.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | export default class ModifyGroupInfoType { 6 | static Modify_Group_Name = 0; 7 | static Modify_Group_Portrait = 1; 8 | static Modify_Group_Extra = 2; 9 | static Modify_Group_Mute = 3; 10 | static Modify_Group_JoinType = 4; 11 | static Modify_Group_PrivateChat = 5; 12 | static Modify_Group_Searchable = 6; 13 | } 14 | -------------------------------------------------------------------------------- /wfc/model/modifyMyInfoEntry.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | export default class ModifyMyInfoEntry { 6 | /** 7 | * 8 | * @type {number} 可选值,参考{@link ModifyMyInfoType } 9 | */ 10 | type = -1; 11 | value = ''; 12 | } 13 | -------------------------------------------------------------------------------- /wfc/model/modifyMyInfoType.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | export default class ModifyMyInfoType { 6 | static Modify_DisplayName = 0; 7 | static Modify_Portrait = 1; 8 | static Modify_Gender = 2; 9 | static Modify_Mobile = 3; 10 | static Modify_Email = 4; 11 | static Modify_Address = 5; 12 | static Modify_Company = 6; 13 | static Modify_Social = 7; 14 | static Modify_Extra = 8; 15 | 16 | } -------------------------------------------------------------------------------- /wfc/model/nullGroupInfo.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | import GroupInfo from "./groupInfo"; 6 | 7 | export default class NullGroupInfo extends GroupInfo { 8 | constructor(groupId) { 9 | super(); 10 | this.target = groupId; 11 | // this.name = '<' + groupId+ '>'; 12 | this.name = '群聊'; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /wfc/model/nullUserInfo.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | import UserInfo from "./userInfo"; 6 | 7 | export default class NullUserInfo extends UserInfo { 8 | constructor(userId) { 9 | super(); 10 | this.uid = userId; 11 | //this.name = '<' + userId + '>'; 12 | this.name = '用户'; 13 | this.displayName = this.name; 14 | this.portrait = ''; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /wfc/model/pcsession.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | export default class PCSession { 6 | token = ''; 7 | status = 0; 8 | expired = 0; 9 | device_name = ''; 10 | } -------------------------------------------------------------------------------- /wfc/model/quoteInfo.js: -------------------------------------------------------------------------------- 1 | import wfc from "../client/wfc"; 2 | import {stringValue} from "../util/longUtil"; 3 | import Long from "long"; 4 | 5 | export default class QuoteInfo { 6 | messageUid; 7 | userId; 8 | userDisplayName; 9 | messageDigest; 10 | 11 | static initWithMessage(message) { 12 | let info = new QuoteInfo(); 13 | if (message) { 14 | info.messageUid = message.messageUid; 15 | info.userId = message.from; 16 | let userInfo = wfc.getUserInfo(message.from, false); 17 | info.userDisplayName = userInfo.displayName; 18 | info.messageDigest = message.messageContent.digest(); 19 | if (info.messageDigest.length > 48) { 20 | info.messageDigest = info.messageDigest.substr(0, 48); 21 | } 22 | } 23 | return info; 24 | } 25 | 26 | encode() { 27 | let obj = { 28 | u: stringValue(this.messageUid), 29 | i: this.userId, 30 | n: this.userDisplayName, 31 | d: this.messageDigest, 32 | }; 33 | return obj; 34 | } 35 | 36 | decode(obj) { 37 | if (obj.messageUid) { 38 | this.messageUid = Long.fromValue(obj.messageUid); 39 | this.userId = obj.userId; 40 | this.userDisplayName = obj.userDisplayName; 41 | this.messageDigest = obj.messageDigest; 42 | 43 | } else { 44 | this.messageUid = Long.fromValue(obj.u || obj.messageUid); 45 | this.userId = obj.i; 46 | this.userDisplayName = obj.n; 47 | this.messageDigest = obj.d; 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /wfc/model/readEntry.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | export default class ReadEntry { 6 | userId; 7 | conversation; 8 | readTime; 9 | } 10 | -------------------------------------------------------------------------------- /wfc/model/searchType.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | export default class SearchType { 6 | //模糊搜索displayName,精确搜索name或电话号码 7 | static General = 0; 8 | 9 | //精确搜索name或电话号码 10 | static NameOrMobile = 1; 11 | 12 | //精确搜索name 13 | static Name = 2; 14 | 15 | //精确搜索电话号码 16 | static Mobile = 3; 17 | } 18 | -------------------------------------------------------------------------------- /wfc/model/secretChatInfo.js: -------------------------------------------------------------------------------- 1 | export default class SecretChatInfo { 2 | targetId; 3 | userId; 4 | state; 5 | burnTime; 6 | createTime; 7 | } 8 | -------------------------------------------------------------------------------- /wfc/model/secretChatState.js: -------------------------------------------------------------------------------- 1 | export default class SecretChatState { 2 | //密聊会话建立中 3 | static Starting = 0; 4 | 5 | //密聊会话接受中 6 | static Accepting = 1; 7 | 8 | //密聊会话已建立 9 | static Established = 2; 10 | 11 | //密聊会话已取消 12 | static Canceled = 3; 13 | 14 | } 15 | -------------------------------------------------------------------------------- /wfc/model/unreadCount.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | export default class UnreadCount { 6 | // 单聊未读数 7 | unread = 0; 8 | // 群聊@数 9 | unreadMention = 0; 10 | // 群聊@All数 11 | unreadMentionAll = 0; 12 | } -------------------------------------------------------------------------------- /wfc/model/userClientState.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | export default class UserClientState { 6 | /** 7 | Platform_UNSET = 0; 8 | Platform_iOS = 1; 9 | Platform_Android = 2; 10 | Platform_Windows = 3; 11 | Platform_OSX = 4; 12 | Platform_WEB = 5; 13 | Platform_WX = 6; 14 | Platform_LINUX = 7; 15 | Platform_iPad = 8; 16 | Platform_APad = 9; 17 | */ 18 | platform; 19 | 20 | //设备的在线状态,0是在线,1是有session但不在线,其它不在线。 21 | state; 22 | 23 | //最后可见 24 | lastSeen; 25 | 26 | } 27 | -------------------------------------------------------------------------------- /wfc/model/userCustomState.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | export default class UserCustomState { 6 | //0,未设置,1 忙碌,2 离开(主动设置),3 离开(长时间不操作),4 隐身,其它可以自主扩展。 7 | state; 8 | text; 9 | } 10 | -------------------------------------------------------------------------------- /wfc/model/userInfo.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | /* 6 | { 7 | "uid": "uiuJuJcc", 8 | "name": "13888888888", 9 | "displayName": "imndx", 10 | "gender": 0, 11 | "portrait": "https://avatars.io/gravatar/uiuJuJcc", 12 | "mobile": "13888888888", 13 | "email": "", 14 | "address": "", 15 | "company": "", 16 | "social": "", 17 | "extra": "", 18 | "type": -472579968, 19 | "updateDt": 1550652404513 20 | } 21 | 22 | */ 23 | export default class UserInfo { 24 | uid = ''; 25 | name = ''; 26 | displayName = ''; 27 | groupAlias = ''; 28 | friendAlias = ''; 29 | gender = 0; 30 | portrait = ''; 31 | mobile = ''; 32 | email = ''; 33 | address = ''; 34 | social = ''; 35 | extra = ''; 36 | type = 0; //0 normal; 1 robot; 2 thing; 37 | //0 normal; 1 deleted; 38 | deleted = 0; 39 | updateDt = 0; 40 | } 41 | -------------------------------------------------------------------------------- /wfc/model/userOnlineState.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | export default class UserOnlineState { 6 | userId; 7 | customState; 8 | clientStates; 9 | 10 | // 手机在线、web在线、pc在线 11 | desc() { 12 | if (this.customState.state > 0) { 13 | //0,未设置,1 忙碌,2 离开(主动设置),3 离开(长时间不操作),4 隐身,其它可以自主扩展。 14 | let cs = ['未设置', '忙碌', '离开(主动离开)', '离开(长时间未操作)', '隐身']; 15 | return this.customState.text + cs[this.customState.state]; 16 | } 17 | 18 | let onlineClientDesc = ''; 19 | let lastSeenDesc = ''; 20 | this.clientStates.forEach(s => { 21 | // 22 | // /** 23 | // Platform_UNSET = 0; 24 | // Platform_iOS = 1; 25 | // Platform_Android = 2; 26 | // Platform_Windows = 3; 27 | // Platform_OSX = 4; 28 | // Platform_WEB = 5; 29 | // Platform_WX = 6; 30 | // Platform_LINUX = 7; 31 | // Platform_iPad = 8; 32 | // Platform_APad = 9; 33 | // */ 34 | // platform; 35 | // 36 | // //设备的在线状态,0是在线,1是有session但不在线,其它不在线。 37 | // state; 38 | // 39 | // //最后可见 40 | // lastSeen; 41 | 42 | let ps = ['', 'iOS', 'Android', 'Windows', 'mac', 'Web', '小程序', 'Linux', 'iPad', 'Android-Pad']; 43 | if (s.state === 0) { 44 | onlineClientDesc += ps[s.platform] + ' ' 45 | } else if ([1, 2, 8, 9].indexOf(s.platform) >= 0) { 46 | // TODO 47 | lastSeenDesc += ps[s.platform] + ' '; 48 | } 49 | }); 50 | 51 | if (onlineClientDesc.trim()) { 52 | return onlineClientDesc + '在线'; 53 | } else if (lastSeenDesc.trim()) { 54 | return lastSeenDesc + '不久前在线'; 55 | } 56 | //return '不在线'; 57 | return ''; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /wfc/model/userSettingEntry.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | import UserSettingScope from "../client/userSettingScope"; 6 | 7 | export default class UserSettingEntry { 8 | scope = UserSettingScope.kUserSettingCustomBegin; 9 | key = ''; 10 | value = ''; 11 | updateDt = 0; 12 | } 13 | -------------------------------------------------------------------------------- /wfc/ptt/messages/pttSoundMessageContent.js: -------------------------------------------------------------------------------- 1 | import SoundMessageContent from "../../messages/soundMessageContent"; 2 | 3 | export default class PttSoundMessageContent extends SoundMessageContent { 4 | 5 | constructor(file, duration) { 6 | super(file, null, duration); 7 | this.type = 23; 8 | } 9 | 10 | digest(message) { 11 | return '[对讲语音]' 12 | } 13 | 14 | encode() { 15 | let payload = super.encode(); 16 | payload.searchableContent = '[对讲语音]'; 17 | return payload; 18 | } 19 | 20 | decode(payload) { 21 | super.decode(payload); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /wfc/ptt/pttEndReason.js: -------------------------------------------------------------------------------- 1 | export default class PttEndReason{ 2 | //用户主动释放 3 | static User_Release = 0; 4 | //讲话超时 5 | static Timeout = 1; 6 | //被抢占 7 | static Take_Over = 2; 8 | //网络错误 9 | static Network_Error = 3; 10 | //频道禁言,只有频道主能讲话 11 | static Channel_Muted = 4; 12 | //成员被禁言 13 | static Member_Muted = 5; 14 | //音频服务错误 15 | static Media_Error = 6; 16 | //不在频道内 17 | static Not_InChannel = 7; 18 | //用户被封禁 19 | static User_Disabled = 8; 20 | 21 | } 22 | -------------------------------------------------------------------------------- /wfc/ptt/pttErrorCode.js: -------------------------------------------------------------------------------- 1 | export default class PttErrorCode{ 2 | static UNKNOWN = -1; 3 | static OCCUPIED = -2; 4 | static MAX_SPEAKER = -3; 5 | static GROUP_MUTED = -4; 6 | static GROUP_MEMBER_MUTED = -5; 7 | static TALKING = -6; 8 | static NOT_IN_GROUP = -7; 9 | static PTT_DISABLED = -8; 10 | // 没有录音权限等,会触发 11 | static RECORDER_ERROR = -9; 12 | } 13 | -------------------------------------------------------------------------------- /wfc/ptt/pttEventType.js: -------------------------------------------------------------------------------- 1 | export default class PttEventType { 2 | //某人开始在频道中讲话 3 | // function (conversation, userId) {} 4 | static userStartTalking = 'userStartTalking' 5 | 6 | //某人结束在频道中讲话 7 | // function (conversation, userId) {} 8 | static userEndTalking = 'userEndTalking' 9 | 10 | //接收到用户自定义数据 11 | // function (conversation, userId, data) {} 12 | static receiveData = 'receiveData'; 13 | 14 | //用户说话音量大小回调 15 | // function (conversation, userId, averageAmplitude) {} 16 | static userAmplitudeUpdate = 'userAmplitudeUpdate'; 17 | 18 | } 19 | -------------------------------------------------------------------------------- /wfc/ptt/talkingCallback.js: -------------------------------------------------------------------------------- 1 | 2 | export default class TalkingCallback { 3 | 4 | // 对讲优先级,默认优先级都是0,数字越高,优先级越高 5 | talkingPriority(conversation) { 6 | console.log('talkingPriority', conversation) 7 | return 0; 8 | } 9 | 10 | //可以开始讲话了 11 | onStartTalking(conversation) { 12 | console.log('onStartTalking', conversation) 13 | } 14 | 15 | //reason包括超时,被禁言,被强制抢麦等 16 | onTalkingEnd(conversation, reason) { 17 | console.log('onTalkingEnd', conversation, reason) 18 | } 19 | 20 | //errorCode包括单工模式下没有抢到麦,全工模式下超过最大发言人数,被禁言。 21 | onRequestFail(conversation, errorCode) { 22 | console.log('onRequestFail', conversation, errorCode); 23 | } 24 | 25 | // 说话音量通知,每400秒通知一次 26 | // 暂不支持 27 | onAmplitudeUpdate(averageAmplitude) { 28 | console.log('onAmplitudeUpdate', averageAmplitude); 29 | } 30 | 31 | /** 32 | * 默认发送的是 PTTSoundMessageContent,正常不用修改 33 | * @param conversation 34 | * @param {File | string} fileOrLocalPath File类型,或者dataUri或者本地路径,本地路径是必须是绝对路径 35 | * @param {number} duration 36 | */ 37 | onCreateSoundMessageContent(conversation, fileOrLocalPath, duration) { 38 | // TODO 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /wfc/util/base64.min.js: -------------------------------------------------------------------------------- 1 | // 如果使用 vite时,提示:The requested module '/wfc/util/base64.min.js' does not provide an export named 'atob' 2 | // 请用本文件的内容,替换 base64.min.js 3 | 4 | const c = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; 5 | 6 | export function btoa(e) { 7 | for ( 8 | var t, r, o = String(e), n = 0, a = c, i = ""; 9 | o.charAt(0 | n) || ((a = "="), n % 1); 10 | i += a.charAt(63 & (t >> (8 - (n % 1) * 8))) 11 | ) { 12 | if (255 < (r = o.charCodeAt((n += 0.75)))) 13 | throw new Error( 14 | "'btoa' failed: The string to be encoded contains characters outside of the Latin1 range." 15 | ); 16 | t = (t << 8) | r; 17 | } 18 | return i; 19 | } 20 | 21 | export function atob(e) { 22 | var t = String(e).replace(/[=]+$/, ""); 23 | if (t.length % 4 == 1) 24 | throw new Error( 25 | "'atob' failed: The string to be decoded is not correctly encoded." 26 | ); 27 | for ( 28 | var r, o, n = 0, a = 0, i = ""; 29 | (o = t.charAt(a++)); 30 | ~o && ((r = n % 4 ? 64 * r + o : o), n++ % 4) 31 | ? (i += String.fromCharCode(255 & (r >> ((-2 * n) & 6)))) 32 | : 0 33 | ) 34 | o = c.indexOf(o); 35 | return i; 36 | } -------------------------------------------------------------------------------- /wfcScheme.js: -------------------------------------------------------------------------------- 1 | export default class WfcScheme { 2 | static QR_CODE_PREFIX_PC_SESSION = "wildfirechat://pcsession/"; 3 | static QR_CODE_PREFIX_USER = "wildfirechat://user/"; 4 | static QR_CODE_PREFIX_GROUP = "wildfirechat://group/"; 5 | static QR_CODE_PREFIX_CHANNEL = "wildfirechat://channel/"; 6 | static QR_CODE_PREFIX_CONFERENCE = "wildfirechat://conference/"; 7 | 8 | static buildConferenceLink(conferenceId, password) { 9 | let link = WfcScheme.QR_CODE_PREFIX_CONFERENCE + conferenceId; 10 | if (password) { 11 | link += '/?pwd=' + password 12 | } 13 | return link; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /wfc_custom_message/README.md: -------------------------------------------------------------------------------- 1 | ## 说明 2 | 3 | **自定义消息扩展野火IM 功能时,请勿直接修改`wfc`目录下的内容,修改之后,会为后续升级带来很大的麻烦** 4 | 5 | ## 自定义消息步骤 6 | 7 | 1. 定义消息类型,参考[customMessageContentType](./customMessageContentType.js),`1000`以下为内部保留,请使用`1000`以上的消息类型 8 | 2. 实现自定义消息,普通消息参考[testCustomMessageContent](./testCustomMessageContent.js),通知消息参考[testCustomNotificationMessageContent](./testCustomNotificationMessageContent.js) 9 | 3. 配置自定义消息,参考[customMessageConfig](./customMessageConfig.js) 10 | 4. 实现自定义消息对应的 UI,普通类型消息请参考[testCustomMessageContentView](../pages/conversation/message/content/TestCustomMessageContentView.vue); 11 | 普通通知类消息,默认会使用默认通知样式,具体参考[NotificationMessageContentView](../pages/conversation/message/NotificationMessageContentView.vue); 12 | 5. 配置自定义消息和自定义消息 UI 的对应关系,普通消息参考[MessageContentContainerView](../pages/conversation/message/MessageContentContainerView.vue); 13 | 需要自定义通知类消息 UI 时,请参考考[MessageItemView](../ui/main/conversation/MessageItemView.vue) 14 | -------------------------------------------------------------------------------- /wfc_custom_message/customMessageConfig.js: -------------------------------------------------------------------------------- 1 | import PersistFlag from "../wfc/messages/persistFlag"; 2 | import CustomMessageContentType from "./customMessageContentType"; 3 | import TestCustomMessageContent from "./testCustomMessageContent"; 4 | import TestCustomNotificationMessageContent from "./testCustomNotificationMessageContent"; 5 | import wfc from "../wfc/client/wfc"; 6 | 7 | export default class CustomMessageConfig { 8 | static CustomMessageContents = [ 9 | { 10 | name: 'testCustomMessage', // 消息名字 11 | flag: PersistFlag.Persist,// 消息的存储类型,根据消息是否需要存储选择 12 | type: CustomMessageContentType.MESSAGE_CONTENT_TYPE_CUSTOM_MESSAGE_TEST, // 消息类型 13 | contentClazz: TestCustomMessageContent, // 消息类型定义 14 | }, 15 | { 16 | name: 'testCustomNotificationMessage', 17 | flag: PersistFlag.Persist, 18 | type: CustomMessageContentType.MESSAGE_CONTENT_TYPE_CUSTOM_MESSAGE_TEST_NOTIFICATION, 19 | contentClazz: TestCustomNotificationMessageContent, 20 | }, 21 | // 在此配置更多自定义消息 22 | ]; 23 | 24 | // 请勿修改 25 | static registerCustomMessages() { 26 | CustomMessageConfig.CustomMessageContents.forEach(cmc => { 27 | wfc.registerMessageContent(cmc.name, cmc.flag, cmc.type, cmc.contentClazz) 28 | }) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /wfc_custom_message/customMessageContentType.js: -------------------------------------------------------------------------------- 1 | export default class CustomMessageContentType { 2 | // 1000 以下为内部消息保留,自定义消息需使用 1000 以上的数字 3 | static MESSAGE_CONTENT_TYPE_CUSTOM_MESSAGE_TEST = 1001; 4 | static MESSAGE_CONTENT_TYPE_CUSTOM_MESSAGE_TEST_NOTIFICATION = 1002; 5 | } 6 | -------------------------------------------------------------------------------- /wfc_custom_message/testCustomMessageContent.js: -------------------------------------------------------------------------------- 1 | import CustomMessageContentType from "./customMessageContentType"; 2 | 3 | 4 | import MessageContent from '../wfc/messages/messageContent' 5 | 6 | /** 7 | * 对应的 UI,请参考{@link TestCustomMessageContentView} 8 | */ 9 | export default class TestCustomMessageContent extends MessageContent { 10 | content; 11 | 12 | constructor(content) { 13 | super(CustomMessageContentType.MESSAGE_CONTENT_TYPE_CUSTOM_MESSAGE_TEST); 14 | this.content = content; 15 | } 16 | 17 | // 会话列表显示对应会话时,会显示会话最后一条消息的摘要信息 18 | digest() { 19 | return this.content; 20 | } 21 | 22 | // 发送消息时,会进行 encode 操作,实际发送的是 payload 23 | encode() { 24 | let payload = super.encode(); 25 | payload.searchableContent = this.content; 26 | return payload; 27 | } 28 | 29 | // 收到消息时,会执行 decode 操作,从 payload 解析到具体的消息内容,encode 和 decode 的操作要对应起来 30 | decode(payload) { 31 | super.decode(payload); 32 | this.content = payload.searchableContent; 33 | } 34 | } 35 | 36 | -------------------------------------------------------------------------------- /wfc_custom_message/testCustomNotificationMessageContent.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WildFireChat. All rights reserved. 3 | */ 4 | 5 | import CustomMessageContentType from "./customMessageContentType"; 6 | import NotificationMessageContent from "../wfc/messages/notification/notificationMessageContent"; 7 | 8 | /** 9 | * 对应的 UI 请参考{@link NotificationMessageContentView},或 {@link RichNotificationMessageContentView} 10 | */ 11 | export default class TestCustomNotificationMessageContent extends NotificationMessageContent { 12 | tip = ''; 13 | 14 | constructor(tip) { 15 | super(CustomMessageContentType.MESSAGE_CONTENT_TYPE_CUSTOM_MESSAGE_TEST_NOTIFICATION); 16 | this.tip = tip; 17 | } 18 | 19 | // 会话界面显示通知时,将显示本函数的返回值 20 | formatNotification() { 21 | return this.tip; 22 | } 23 | 24 | digest() { 25 | return this.tip; 26 | } 27 | 28 | encode() { 29 | let payload = super.encode(); 30 | payload.content = this.tip; 31 | return payload; 32 | }; 33 | 34 | decode(payload) { 35 | super.decode(payload); 36 | this.tip = payload.content; 37 | } 38 | } 39 | --------------------------------------------------------------------------------
{{ $t('group.name', [sharedContactState.currentGroup.name]) }}
删除消息
删除此条消息?
{{ message.messageContent.digest(message) }}
{{ $t('message.sender') }}
2021/2/3 11:44
{{ $t('message.content') }}
{{ $t('message.unsupport_message_desc') }}