Note: This is a living and breathing document. It is still changing and being completed.
This document briefly outlines how to create, register and make use of plugins. Plugins are the best way to extend and customise the KiwiIRC mobile app, while keeping the core code intact. This makes it easier to update the core code with the latest features and bug fixed in your custom app.
There are two types of plugins:
-
Single-file
.js
: Easier to create. Your plugin has to live in a single javascript file. -
NPM dependency: The plugin is a npm package that can have multiple files. This way allows adding NativeScript plugins and other resources.
You can bundle a multiple file project in a single file with webpack and use that. See this example.
To add a single-file plugin to the App Project, follow the steps:
-
Copy the
.js
toapp/assets/plugins
folder (e.g.app/assets/plugins/my-plugin.js
); -
Add the plugin in
app/assets/config.json
, like so:
{
...
"plugins": [
{ "name": "my-plugin", "url": "./assets/plugins/my-plugin.js"}
],
...
}
These Kiwi mobile plugins are NativeScript plugins. This means that they must follow the NativeScript plugin requirements.
Use the kiwiirc-mobile-plugin-sample as a starting point.
-
Download the repo as a .zip file;
-
Change the name of the package in
src/package.json
(e.g.my-kiwi-plugin
); -
Add the plugin as a local dependency:
yarn add <path to plugin 'src' folder>/my-kiwi-plugin
See other options to install NativeScript plugins here.
require()
the plugin in the App Project's `app/plugins.js``:// require npm plugins: require('my-kiwi-plugin');
NPM plugins can include a platforms
directory. This directory holds resource files similar to the app/App_Resources
directory.
Check the sample plugin project to see the expected folder structure.
This directory is used for image resources (see how to use them here). These can be accessed for example with background: url('res://my_img')'
.
Inside the main .js
file (src/index.js
for npm plugins), you must register a plugin using the
kiwi.plugin()
call, such as:
kiwi.plugin('plugin_name', function(kiwi, log) {
// Plugin code here
});
Your plugin function will be called once mobile app has been loaded and ready to start. You can listen for events and use any of the below API in your plugin.
As a very simple example, this plugin will listen for any new networks being created and set the default server address to irc.freenode.net
:
kiwi.plugin('my_plugin', function(kiwi) {
kiwi.on('network.new', function(event) {
event.network.connection.server = 'irc.freenode.net';
event.network.connection.port = 6667;
});
});
The main API interface
kiwi
is a global object that
Property | Description |
---|---|
.version |
The app version (set in package.json ) |
.Vue |
A Vuejs global instance |
.i18n |
Access to the app's translation module (i18next) |
.JSON5 |
Expose JSON5 so that plugins can use the same config format |
.state |
The Kiwi internal application state. Described below |
.plugin(pluginName, fn) |
Create a new plugin |
.addUi(type, component, props) |
Add a UI component. Described bellow |
.addStartup(name, startupObject) |
Add a new startup screen. Described bellow |
.replaceModule(module, new_module) |
Replace a module or component. Described bellow |
.require(module) |
Get a Kiwi internal module instance |
.on(eventName, fn) |
Listen for an application event |
.once(eventName, fn) |
Listen for an application event one time only |
.off(eventName, fn) |
Stop listening for an application event |
.emit(eventName, arg1, arg2) |
Emit an event on the application ](#event-bus)event bus](#event-bus) |
You can add components to:
'input_top'
: above the input box with the full width of the screen.'input_tool'
: on the right hand side of the input box. Use it to add buttons to send files, for instance.browser
: the top left corner of theStateBrowser
(main window).
Example:
import HelloMessage from './components/HelloMessage';
// Add component above the input
kiwi.addUi(
'input_top', // or 'input_tool', 'browser'
HelloMessage, // component
{ state: kiwi.state } // props
);
Adds a startup method. Use it to implement custom login or registration methods.
kiwi.addStartup('MyStartup', startup);
kiwi.addStartup(name: string, startup: StartupInstance)
name
: name of the startup method. Set the name inapp/assets/config.json
:{ ... "startupScreen": "MyStartup", ...}
startup
: startup instance. An object with:constructor(state, log)
: constructor called with the app state and a logger.startup(vueInstance: VueComponent): Promise
: the startup method.vueInstance
: reference to the loading screen component. Use it to navigate to a login screen (e.g.vueInstance.$navigateTo()
orvueInstance.$showModal()
);- Returns:
Promise
that when resolved means that the login was successful (app continues to the main screen), when rejected shows the message in an error screen;
logout(): Promise
: function called before the app does the actual log out. Use it for extra clean up tasks in an external service, for instance.- Returns:
Promise
that when resolved means that the logout can continue, when rejected the logout process stops and the app navigates back to the previous state in the main screen.
- Returns:
Replaces a core module (.js
or .vue
file) with a custom implementation. Basically, swaps a file in the core code
(kiwirc-mobile
and kiwirc-mobile/kiwiirc
) with another one.
Example:
kiwi.replaceModule('mobile/components/UserSettings', require('./UserSettings').default);
kiwi.replaceModule(moduleName: string, newModule: Object)
moduleName
: path to the module to be replaced. If replacing a module inkiwiirc-mobile
, prefix the path withmobile/
.newModule
: new module replacing themoduleName
The Kiwi internal application state. The entire application uses this interface to modify state such as adding or removing networks, adding buffers / messages / users, getting the active network or buffer.
exportState(includeBuffers)
importState(stateStr)
resetState()
setting(name, val)
getSetting(name)
setSetting(name, newVal)
getActiveNetwork()
getNetwork(networkid)
getNetworkFromAddress(netAddr)
addNetwork(name, nick, serverInfo)
removeNetwork(networkid)
getActiveBuffer()
setActiveBuffer(networkid, bufferName)
openLastActiveBuffer()
updateBufferLastRead(networkid, bufferName)
getOrAddBufferByName(networkid, bufferName)
getBufferByName(networkid, bufferName)
addBuffer(networkid, bufferName)
removeBuffer(buffer)
addMessage(buffer, message)
getMessages(buffer)
getUser(networkid, nick, usersArr_)
usersTransaction(networkid, fn)
addUser(networkid, user, usersArr_)
removeUser(networkid, user)
addMultipleUsersToBuffer(buffer, newUsers)
addUserToBuffer(buffer, user, modes)
removeUserFromBuffer(buffer, nick)
getBuffersWithUser(networkid, nick)
changeUserNick(networkid, oldNick, newNick)
getStartups()
This is the main event bus for the application. Events are emitted by many places and some allow you to emit your own so that you can interact with Kiwi.
These events can be listened for via kiwi.on('event.name', function() {})
. For events marked that they can be fired from plugins, you can do so via kiwi.emit('event.name', arg1, arg2)
.
Name | Arguments | Can be fired from plugins | Description |
---|---|---|---|
app.suspended |
No | Called when the app goes to the background | |
app.resumed |
No | Called when the app returns from background | |
ui.active_buffer |
buffer | yes | Show a buffer page |
server.open |
network, openTab | yes | Show the settings for a given network |
input.raw |
rawText | yes | Simulate user input |
userbox.show |
user, props | yes | Open the user information panel for the given user |
irc.raw |
command, event, network | no | Raw IRC message from the IRC server |
irc.raw.[command] |
command, event, network | no | A raw IRC message from the IRC server |
irc.[command] |
event, network, ircEventObj | no | A parsed IRC event from the IRC library |
network.new |
eventObj | no | A new network has been added |
network.removed |
eventObj | no | A network has been deleted |
network.connecting |
eventObj | no | A network connection is about to start |
buffer.new |
eventObj | no | A new buffer has been added |
buffer.close |
eventObj | no | A buffer has been closed |
message.render |
eventObj | no | A message is about to be rendered |