插件擴(kuò)展通常不包含具體的界面,但可以在界面初始化及關(guān)鍵事件觸發(fā)時得到通知并執(zhí)行代碼。例如可以通過監(jiān)聽用戶發(fā)送消息,并在消息發(fā)送之前修改消息的內(nèi)容。
每一個插件擴(kuò)展需要提供一個入口模塊文件,在 package.json 文件中通過 main 屬性指定。如果不指定此文件則默認(rèn)使用擴(kuò)展包目錄的 index.js 文件作為主入口模塊文件。擴(kuò)展主入口模塊文件為一個 JavaScript 模塊,當(dāng)喧喧加載完畢時會逐個加載各個擴(kuò)展的主入口模塊。在擴(kuò)展主入口模塊中可以訪問全局?jǐn)U展對象 global.Xext 。擴(kuò)展主入口模塊應(yīng)該返回一個對象,該對象可以包含如下生命周期函數(shù):
函數(shù) | 說明 | 參數(shù) |
onAttach(ext) | 當(dāng)擴(kuò)展被加載后調(diào)用,此時可以對擴(kuò)展進(jìn)行初始化 |
|
onReady(ext) | 當(dāng)界面加載完畢時調(diào)用,此時擴(kuò)展可以處理與界面相關(guān)操作。 |
|
onDetach(ext) | 當(dāng)擴(kuò)展被卸載時調(diào)用,此時應(yīng)該將擴(kuò)展使用的資源進(jìn)行釋放,例如銷毀定時器等 |
|
onUserLogin(user, error) | 當(dāng)用戶登錄完成時調(diào)用; |
|
onUserLoginout(user) | 當(dāng)當(dāng)前登錄的退出登錄時調(diào)用 |
|
onUserStatusChange(status, oldStatus, user) | 當(dāng)用戶狀態(tài)發(fā)生變化時調(diào)用 |
用戶狀態(tài)代碼含義:
|
onSendChatMessages(messages, chat, user) | 當(dāng)用戶發(fā)送聊天消息時調(diào)用 |
|
onReceiveChatMessages(messages, user) | 當(dāng)用戶接收到聊天消息時調(diào)用 |
|
onRenderChatMessageContent(content) | 當(dāng)在界面上需要轉(zhuǎn)化 markdown 格式的消息文本為 html 時會調(diào)用此回調(diào)方法 |
|
MainView | 當(dāng)作為內(nèi)嵌應(yīng)用時的 React 實現(xiàn)的界面主組件 |
|
replaceViews | 用于配置替換系統(tǒng)內(nèi)置界面組件 |
|
commands | 擴(kuò)展支持的命令 |
|
contextMenuCreators | 為消息增加操作菜單 |
|
urlInspectors | 網(wǎng)址解釋器,可以將消息中的網(wǎng)址渲染成卡片形式 |
|
下面為一個簡單等插件擴(kuò)展主入口模塊示例:
// 從全局?jǐn)U展對象中引入模塊 const { app, components, utils } = global.Xext; // 用于存儲計時器標(biāo)志 let timerTask = null; module.exports = { onAttach: (ext) => { // 擴(kuò)展加載完畢了, 此時設(shè)置一個計時器,在加載完成 10 秒中之后在界面上顯示一個消息 timerTask = setTimeout(() => { alert('擴(kuò)展加載完成已經(jīng) 10 秒鐘了,剛剛加載等擴(kuò)展名稱是:' + ext.displayName); }); }, onDetach: (ext) => { // 擴(kuò)展將被卸載,此時應(yīng)該清理計時器 clearTimeout(timerTask); timerTask = null; }, onUserLogin: (user, error) => { // 當(dāng)用戶登錄時在此處可以進(jìn)行相關(guān)操作,下面以顯示當(dāng)前登錄等結(jié)果和用戶名為例 if (user && !error) { // 表示登錄成功 components.Modal.alert('用戶登錄成功了,用戶名稱是:' + user.displayName); } else { components.Modal.alert('用戶登錄失敗了。'); } }, }
當(dāng)一個擴(kuò)展類型為 app (應(yīng)用)時,同樣可以在 package.json 文件中使用 main 屬性指定一個主入口模塊文件,從而使得一個應(yīng)用擴(kuò)展具備插件擴(kuò)展的機(jī)制。同理,也可以將此方式理解為一個包含應(yīng)用界面的插件。
在主入口模塊中可以使用 replaceViews 字段指定一個對象來替換喧喧默認(rèn)的界面組件,這些組件在 /app/views 目錄下。replaceViews 對象的鍵名為要替換的組件路徑,鍵值為要用來替換的 React 組件類或組件函數(shù)。通過界面替換機(jī)制,可以使用插件的形式來定制喧喧的界面,例如將官方的登錄界面替換為自己的實現(xiàn)。
下面的例子將展示使用自定義的 React 組件來替換官方的用戶頭像組件。這樣可以將官方的圓形用戶頭像替換為方形的頭像。更加詳細(xì)的代碼參考官方例子 replace-user-avatar-example。
// 主入口文件 index.js const UserAvatar = require('./user-avatar'); module.exports = { replaceViews: { 'common/user-avatar': UserAvatar, } };
// user-avatar.js 文件 // 從全局?jǐn)U展對象中引入模塊 const { views, components, utils, nodeModules, } = global.Xext; const {React} = nodeModules; const {PropTypes, Component} = React; const {StatusDot} = views.common; const {Avatar, Emojione} = components; const {HtmlHelper} = utils; let todayTime = new Date(); todayTime.setHours(0, 0, 0, 0); todayTime = todayTime.getTime(); class UserAvatar extends Component { render() { const user = this.props.user; const className = this.props.className; const showStatusDot = this.props.showStatusDot; // 使用 react 形式返回新的用戶頭像 } } UserAvatar.propTypes = { user: PropTypes.object, className: PropTypes.string, showStatusDot: PropTypes.bool, }; UserAvatar.defaultProps = { className: null, showStatusDot: null, user: null, }; module.exports = UserAvatar;
更多建議: