This tutorial explains how to get your application to insert itself into the various default menus. Start by creating a standard module with the name Tutorial05. Before we provide any code that will let this application insert itself in system menus, we want to talk a bit about the design challenges of getting modules to interact.
It is common for applications to want to use components that have been created by other applications. RedSquare and the Arcade both let the Chat module render itself into their sidebars, for instance, while third party crypto modules can add themselves to the Saito Wallet. Similarly, if RedSquare is installed the in-game menu will let players tweet a screenshot of their game.
Programmers who are new to Saito often try to achieve this sort of cross-module interactivity by hardcoding connections between applications. This can be done by iterating through all of the modules that exist on the app.modules.mods object until you find the module you want and manually calling the functions in that module.
let chatmod = app.modules.returnModuleByName("Chat");
if (chatmod) {
// do something!
}
The problem with this approach is that it requires hardcoding a dependency between modules, so that if a user does not have both modules installed, or wants to upgrade either of their modules they now need to manage the dependencies between those modules.
We solve this with a design pattern called the respondTo() approach. In this approach, modules or UI components can ask Saito to provide them with a list of modules that respondTo() specific requests. The objects returned by those modules contain a specific mix of variables and functions that can be queried for data, or rendered directly to the screen.
Because the respondTo function returns an object or an array of objects, it provides an extremely flexible way to define behavior. It also accepts an arbitrary obj parameter that allow more flexibility in how your module responds to the request and data. UI Components will typically respondTo other components and expose their render() function. It can also be used to provide an API for your module that other modules can query.
To see how this works in practice, let's create a Tutorial05 application so that it responds to the standard menu components Saito makes available and allows users to interact or load it through standard navigation components.
This design pattern is used by the UI Components that display menus throughout the site. You can learn more about all of the triggers to which modules can respondTo(), but if you are getting started here are the three common, useful triggers to which modules can respond that will insert options into the Saito UI:
respondTo(type = '', obj) {
if (type === 'user-menu') {
return [{
text: `Tutorial05 User Menu`,
icon: 'fa-solid fa-5',
callback: function (app, publicKey) {
app.connection.emit('tutorial05-event', type);
}
}];
}
if (type === 'saito-header') {
return [
{
text: 'Tutorial05',
icon: 'fa-solid fa-5',
callback: function (app, id) {
app.connection.emit('tutorial05-event', type);
},
}
];
}
if (type == 'saito-floating-menu') {
return [
{
text: 'Tutorial05',
icon: 'fa-solid fa-5',
callback: function (app, id) {
app.connection.emit('tutorial05-event', type);
},
}
]
}
return null;
}
Add this function to your application and compile it, and you'll be able to see that your module is now part of the three major menus: the main-menu that appears when you click on the hamburger menu, the user menu that appears if you click on a user's publickey or username, and the floating menu that appears on mobile devices. You can see if by visiting RedSquare on your phone and clicking on the "add tweet" button that will appear on the bottom-right of your screen.
You'll notice that the example doesn't do anything yet, because we define these callbacks to emit a custom event tutorial05-event. The Saito API connection object allows us to emit and respond to any kind of event. This is another very useful way for you to integrate your module with UI components. You can instantiate UI components and set listeners for events, rerendering whenever the event is triggered.
To finish our example, we need to add some code to the constructor of Tutorial05, as follows:
app.connection.on('tutorial05-event', (click_source) => {
alert('User clicked on me -- ' + click_source);
});
Now, if you compile and run the tutorial, the alert will show up when you click the hooks in the Saito UI that our module creates.
In this module, we learned about
app.connection eventsIn the next tutorial we will learn more about some of Saito's standard UI components and how to extend them with CSS insertion.
tutorial05 code can be referenced here.