Files
Zos/Skills/@be/be/menu/README.md

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