226 lines
7.5 KiB
Markdown
226 lines
7.5 KiB
Markdown
# Jibo Dynamic Menu System
|
|
|
|
This module provides a dynamic menu system that automatically scans the Skills directory for `menuEntry.json` files and adds them to Jibo's menu screen.
|
|
|
|
## How It Works
|
|
|
|
When Jibo boots up, the `main-menu-patch.js` module:
|
|
1. Patches `jibo.loader.load()` to intercept menu loading
|
|
2. Scans the `/opt/jibo/Jibo/Skills` directory for folders containing `menuEntry.json`
|
|
3. Injects the found skills/submenus into the main menu
|
|
4. Patches the main-menu skill's `redirectToSkill` to handle custom skill launches
|
|
|
|
## Quick Start
|
|
|
|
### Adding a Simple Skill Button to the Menu (you really should follow PROVIDERS.md at this point)
|
|
|
|
1. Create a folder in the `Skills` directory (e.g., `MySkill/`)
|
|
2. Add a `menuEntry.json` file inside:
|
|
|
|
```json
|
|
{
|
|
"type": "skill",
|
|
"title": "My Skill",
|
|
"icon": "resources/icons/settings.png",
|
|
"color": "blue",
|
|
"skillId": "MySkill",
|
|
"description": "Short description of my skill",
|
|
"order": 50
|
|
}
|
|
```
|
|
|
|
3. Your skill will automatically appear in Jibo's main menu!
|
|
|
|
**Note:** For the button to actually launch a skill, that skill must be a proper Jibo skill package registered in `@be/be/package.json`. If the skill isn't found, Jibo will show a fallback message.
|
|
|
|
### Creating a Submenu (Category/Folder)
|
|
|
|
1. Create a folder in the `Skills` directory (e.g., `Games/`)
|
|
2. Add a `menuEntry.json` marking it as a submenu:
|
|
|
|
```json
|
|
{
|
|
"type": "submenu",
|
|
"title": "Games",
|
|
"submenuTitle": "Choose a Game",
|
|
"icon": "resources/icons/fun-stuff.png",
|
|
"color": "purple",
|
|
"description": "Fun games to play with Jibo",
|
|
"order": 10
|
|
}
|
|
```
|
|
|
|
3. Inside that folder, create subfolders for each skill, each with their own `menuEntry.json`
|
|
4. A button will appear in the main menu that opens a submenu with those skills!
|
|
|
|
## Directory Structure Example (OLD)
|
|
|
|
```
|
|
/opt/jibo/Jibo/Skills/
|
|
├── @be/ # Core brain (ignored by scanner)
|
|
├── MySimpleSkill/
|
|
│ └── menuEntry.json # type: "skill" - appears as button in main menu
|
|
├── MyGames/
|
|
│ ├── menuEntry.json # type: "submenu" - opens submenu when pressed
|
|
│ ├── GameOne/
|
|
│ │ └── menuEntry.json # type: "skill" - appears in MyGames submenu
|
|
│ └── GameTwo/
|
|
│ └── menuEntry.json # type: "skill" - appears in MyGames submenu
|
|
```
|
|
|
|
## menuEntry.json Schema
|
|
|
|
| Field | Type | Required | Description |
|
|
|-------|------|----------|-------------|
|
|
| `type` | `"skill"` \| `"submenu"` | **Yes** | `"skill"` for buttons, `"submenu"` for folders |
|
|
| `title` | string | **Yes** | Button label shown on Jibo's screen |
|
|
| `icon` | string | **Yes** | Icon path (see Icon Paths below) |
|
|
| `color` | string | No | Button color theme (see below). Default: `"default"` |
|
|
| `skillId` | string | **Yes** (for skills) | The skill ID to launch |
|
|
| `submenuTitle` | string | No | Title shown when submenu is opened |
|
|
| `description` | string | No | Tooltip/accessibility text |
|
|
| `order` | number | No | Sort order (lower = first). Default: `100` |
|
|
| `hidden` | boolean | No | Set to `true` to hide from menu |
|
|
|
|
### Available Colors
|
|
|
|
- `default` - Standard gray
|
|
- `blue` - Blue theme
|
|
- `green` - Green theme
|
|
- `red` - Red theme
|
|
- `purple` - Purple theme
|
|
- `orange` - Orange theme
|
|
- `teal` - Teal/cyan theme
|
|
- `pink` - Pink theme
|
|
- `yellow` - Yellow theme
|
|
- `cyan` - Cyan theme
|
|
|
|
### Icon Paths
|
|
|
|
Icons are resolved relative to the `@be/main-menu` package. Available built-in icons:
|
|
|
|
| Icon Path | Description |
|
|
|-----------|-------------|
|
|
| `resources/icons/settings.png` | Settings gear |
|
|
| `resources/icons/fun-stuff.png` | Star/fun icon (good for submenus) |
|
|
| `resources/icons/clock.png` | Clock |
|
|
| `resources/icons/heart.png` | Heart |
|
|
| `resources/icons/surprise.png` | Gift/surprise |
|
|
| `resources/icons/dance.png` | Dancing figure |
|
|
| `resources/icons/joke.png` | Comedy mask |
|
|
| `resources/icons/tips.png` | Lightbulb |
|
|
| `resources/icons/gallery.png` | Photo gallery |
|
|
| `resources/icons/radio.png` | Music notes |
|
|
| `resources/icons/create.png` | Camera |
|
|
| `resources/icons/photobooth.png` | Photo booth |
|
|
| `resources/icons/exercise.png` | Exercise/yoga |
|
|
| `resources/icons/weather.png` | Weather cloud |
|
|
| `resources/icons/calendar.png` | Calendar |
|
|
| `resources/icons/circuit-saver.png` | Circuit saver |
|
|
| `resources/icons/dice.png` | Dice |
|
|
| `resources/icons/coin.png` | Coin |
|
|
| `resources/icons/emoji.png` | Emoji face |
|
|
| `resources/icons/word-of-the-day.png` | Word icon |
|
|
| `resources/icons/news.png` | News icon |
|
|
| `resources/icons/twerk.png` | Twerk icon |
|
|
| `resources/icons/scanner.png` | Scanner icon |
|
|
|
|
## Example: Complete Skill Setup
|
|
|
|
### Simple Skill (testSkillA/menuEntry.json)
|
|
```json
|
|
{
|
|
"type": "skill",
|
|
"title": "Test Skill A",
|
|
"icon": "resources/icons/settings.png",
|
|
"color": "blue",
|
|
"skillId": "testSkillA",
|
|
"description": "A test skill",
|
|
"order": 10
|
|
}
|
|
```
|
|
|
|
### Submenu (TestSubMenuA/menuEntry.json)
|
|
```json
|
|
{
|
|
"type": "submenu",
|
|
"title": "Test Submenu",
|
|
"submenuTitle": "Test Skills",
|
|
"icon": "resources/icons/fun-stuff.png",
|
|
"color": "purple",
|
|
"description": "A submenu with test skills",
|
|
"order": 20
|
|
}
|
|
```
|
|
|
|
### Skill inside Submenu (TestSubMenuA/testSkillB/menuEntry.json)
|
|
```json
|
|
{
|
|
"type": "skill",
|
|
"title": "Test Skill B",
|
|
"icon": "resources/icons/surprise.png",
|
|
"color": "green",
|
|
"skillId": "testSkillB",
|
|
"description": "A skill inside a submenu",
|
|
"order": 1
|
|
}
|
|
```
|
|
|
|
## Technical Details
|
|
|
|
### How the Patch Works
|
|
|
|
1. **postinit.js** calls `mainMenuPatch.applyPatch(be)` and `mainMenuPatch.patchLoader(jibo)`
|
|
2. When the main-menu skill tries to load `main-menu-verbal.json`, the patch intercepts it
|
|
3. The patch scans the Skills directory for `menuEntry.json` files
|
|
4. It converts them to the proper button format and injects them into the menu config
|
|
5. When a dynamic skill button is pressed, the patched `redirectToSkill` handles the launch
|
|
6. For submenus, a new menu view is displayed with the submenu's children
|
|
|
|
### Files
|
|
|
|
- `main-menu-patch.js` - Core patch that hooks into the system
|
|
- `skills-scanner.js` - Alternative scanning implementation (not currently used)
|
|
- `menu-manager.js` - Alternative menu display implementation (not currently used)
|
|
|
|
### Debugging
|
|
|
|
Check the browser console for log messages starting with `main-menu-patch:`. These show:
|
|
- When the patch is initialized
|
|
- When menu loads are intercepted
|
|
- How many dynamic skills are injected
|
|
- When skills/submenus are selected
|
|
|
|
## Limitations
|
|
|
|
- Nested submenus (submenus within submenus) are not supported
|
|
- Custom skills must be registered in `@be/be/package.json` to actually launch
|
|
- Icon files must exist in the `@be/main-menu/resources/icons/` directory
|
|
|
|
## Troubleshooting
|
|
|
|
### Skill button not appearing in menu?
|
|
|
|
1. Check that `menuEntry.json` exists and is valid JSON
|
|
2. Verify `hidden` is not set to `true`
|
|
3. Make sure `type` is set to `"skill"` or `"submenu"`
|
|
4. Check the browser console for `main-menu-patch:` log messages
|
|
|
|
### Submenu appears empty?
|
|
|
|
1. Make sure child skill folders have `menuEntry.json` files
|
|
2. Verify child skills have `type: "skill"` (nested submenus not supported)
|
|
3. Check that child folders are direct children of the submenu folder
|
|
|
|
### Skill button doesn't launch anything?
|
|
|
|
1. The skill needs to be a proper Jibo skill package
|
|
2. The skill must be registered in `@be/be/package.json` under `jibo.skills`
|
|
3. If unregistered, Jibo will show a fallback message
|
|
|
|
### Icon not loading?
|
|
|
|
1. Verify the icon path is correct (e.g., `resources/icons/settings.png`)
|
|
2. Only built-in icons from `@be/main-menu/resources/icons/` are supported
|
|
3. Check the list of available icons above
|