codecamp

插件扩展

插件扩展通常不包含具体的界面,但可以在界面初始化及关键事件触发时得到通知并执行代码。例如可以通过监听用户发送消息,并在消息发送之前修改消息的内容。

每一个插件扩展需要提供一个入口模块文件,在 package.json  文件中通过 main  属性指定。如果不指定此文件则默认使用扩展包目录的 index.js  文件作为主入口模块文件。扩展主入口模块文件为一个 JavaScript 模块,当喧喧加载完毕时会逐个加载各个扩展的主入口模块。在扩展主入口模块中可以访问全局扩展对象 global.Xext 。扩展主入口模块应该返回一个对象,该对象可以包含如下生命周期函数:

扩展主入口模块

函数说明参数
onAttach(ext)当扩展被加载后调用,此时可以对扩展进行初始化
  • ext  为当前被载入的扩展对象

onReady(ext)当界面加载完毕时调用,此时扩展可以处理与界面相关操作。
  • ext  为当前被载入的扩展对象

onDetach(ext)当扩展被卸载时调用,此时应该将扩展使用的资源进行释放,例如销毁定时器等
  • ext  为当前被载入的扩展对象

onUserLogin(user, error)当用户登录完成时调用;
  • user  为登录的用户对象

  • error  当登录失败时返回的错误信息

onUserLoginout(user)当当前登录的退出登录时调用
  • user  为退出登录的用户对象

onUserStatusChange(status, oldStatus, user)当用户状态发生变化时调用
  • status  为用户新的状态代码

  • oldStatus  为用户之前的状态代码

  • user  为当前状态发生变化的用户对象

用户状态代码含义:

  • unverified - 0 : 未登录

  • disconnect - 1 : 登录过,但掉线了

  • logined - 2 : 登录成功

  • online - 3 : 在线

  • busy - 4 : 忙碌

  • away - 5 : 离开

onSendChatMessages(messages, chat, user)当用户发送聊天消息时调用
  • messages  为用户要发送出去的消息对象数组

  • chat  为用户发送消息的会话对象

  • user  为当前发送消息的用户的对象

onReceiveChatMessages(messages, user)当用户接收到聊天消息时调用
  • messages  为用户接收到的消息对象数组

  • user  为当前接收消息的用户的对象

onRenderChatMessageContent(content)当在界面上需要转化 markdown 格式的消息文本为 html 时会调用此回调方法
  • messages  为用户接收到的消息对象数组

  • user  为当前接收消息的用户的对象

MainView当作为内嵌应用时的 React 实现的界面主组件

MainView  应该返回一个 React 组件类或组件函数。

replaceViews用于配置替换系统内置界面组件

replaceViews  为一个对象,对象的键名为要替换的组件路径,键值为要用来替换的 React 组件类或组件函数。

commands扩展支持的命令

commands  为一个对象,对象的键名为响应的命令名称,键值为命令回调函数或者命令定义对象。

contextMenuCreators为消息增加操作菜单

contextMenuCreators  为一个菜单生成对象数组,对象数组为每个菜单生成对象。菜单生成对象包括 match  属性用于定义匹配的菜单类型,creator 属性用于生成菜单项目的函数。

urlInspectors网址解释器,可以将消息中的网址渲染成卡片形式

urlInspectors  为一个对象数组,每个对象包含有 test  属性为正则表达式用于匹配要解释的 url 地址,inspector  为回调函数(function(url: string) )用于生成 URL 对应的卡片参数。

下面为一个简单等插件扩展主入口模块示例:

// 从全局扩展对象中引入模块 
const {   
    app,   
    components,   
    utils 
} = global.Xext; 
// 用于存储计时器标志 
let timerTask = null; 
module.exports = {     
    onAttach: (ext) => {         
        // 扩展加载完毕了, 此时设置一个计时器,在加载完成 10 秒中之后在界面上显示一个消息         
        timerTask = setTimeout(() => {             
            alert('扩展加载完成已经 10 秒钟了,刚刚加载等扩展名称是:' + ext.displayName);         
        });     
     },     
     
     onDetach: (ext) => {         
         // 扩展将被卸载,此时应该清理计时器         
         clearTimeout(timerTask);         
         timerTask = null;     
     },     
     onUserLogin: (user, error) => {         
         // 当用户登录时在此处可以进行相关操作,下面以显示当前登录等结果和用户名为例         
         if (user && !error) { // 表示登录成功             
             components.Modal.alert('用户登录成功了,用户名称是:' + user.displayName);         
         } else {             
             components.Modal.alert('用户登录失败了。');         
         }     
     }, 
}

应用的插件机制

当一个扩展类型为 app (应用)时,同样可以在 package.json  文件中使用 main  属性指定一个主入口模块文件,从而使得一个应用扩展具备插件扩展的机制。同理,也可以将此方式理解为一个包含应用界面的插件。

replaceViews :界面替换机制

在主入口模块中可以使用 replaceViews  字段指定一个对象来替换喧喧默认的界面组件,这些组件在  /app/views 目录下。replaceViews  对象的键名为要替换的组件路径,键值为要用来替换的 React 组件类或组件函数。通过界面替换机制,可以使用插件的形式来定制喧喧的界面,例如将官方的登录界面替换为自己的实现。

下面的例子将展示使用自定义的 React 组件来替换官方的用户头像组件。这样可以将官方的圆形用户头像替换为方形的头像。更加详细的代码参考官方例子  replace-user-avatar-example

// 主入口文件 index.js 
const UserAvatar = require('./user-avatar'); 
module.exports = {     
    replaceViews: {         
        'common/user-avatar': UserAvatar,     
    } 
};
// user-avatar.js 文件 
// 从全局扩展对象中引入模块 
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;


管理应用扩展
主题扩展
温馨提示
下载编程狮App,免费阅读超1000+编程语言教程
取消
确定
目录

关闭

MIP.setData({ 'pageTheme' : getCookie('pageTheme') || {'day':true, 'night':false}, 'pageFontSize' : getCookie('pageFontSize') || 20 }); MIP.watch('pageTheme', function(newValue){ setCookie('pageTheme', JSON.stringify(newValue)) }); MIP.watch('pageFontSize', function(newValue){ setCookie('pageFontSize', newValue) }); function setCookie(name, value){ var days = 1; var exp = new Date(); exp.setTime(exp.getTime() + days*24*60*60*1000); document.cookie = name + '=' + value + ';expires=' + exp.toUTCString(); } function getCookie(name){ var reg = new RegExp('(^| )' + name + '=([^;]*)(;|$)'); return document.cookie.match(reg) ? JSON.parse(document.cookie.match(reg)[2]) : null; }