feat: tela de apps com logos/menu de exclusao, correcao de tema nas mini apps e sidebar de navegacao
Some checks failed
Main Deploy Workflow / deploy_web (push) Has been cancelled
Main Deploy Workflow / deploy_playstore_internal (push) Has been cancelled
Close stale issues and PRs / stale (push) Has been cancelled

This commit is contained in:
2026-09-19 00:08:35 -03:00
parent 1f692b1e4e
commit 6c689d1f34
23 changed files with 1039 additions and 114 deletions

View File

@@ -21,6 +21,36 @@ The available apps page (`/rooms/apps`) lists the built-in apps (`tasks`,
`accountdata`) under *Installed* once you install them, plus every app you
import.
## Manifest (meta tags)
Before installing an app, TatuChat reads the `<meta>` tags of the document and
uses them as the app's manifest. **Every tag listed below must be present** in
the `<head>` of your document, even if the value is empty — except `id` and
`name`, which must also be non-empty. An app that is missing any of these tags
**cannot be installed**.
```html
<meta name="mini-app-id" content="myapp">
<meta name="mini-app-name" content="My App">
<meta name="mini-app-category" content="productivity">
<meta name="mini-app-description" content="What my app does">
<meta name="mini-app-logo" content=""> <!-- empty is allowed -->
<meta name="mini-app-in-chat" content="false"> <!-- true|false -->
```
`mini-app-in-chat` must be `true` or `false` (empty defaults to `false`).
Values are trimmed and read case-insensitively.
The `mini-app-id` is used **as the key in the account data store**: the app's
store is persisted under `im.tatuchat.miniapps.data.<id>` and its HTML source
under `im.tatuchat.miniapps.source.<id>`. It must be unique: ids of built-in
apps (`tasks`, `accountdata`) are reserved and an already installed id cannot
be reused. This id is also the `widgetId` your app must send in the bridge
protocol.
The remaining fields are stored as metadata (`category`, `description`, `logo`,
`inChat`) and shown in the *Apps* page.
## Talking to TatuChat
The host listens for `message` events. A channel app sends a request with
@@ -64,10 +94,11 @@ function bridgeRequest(action, data) {
window.addEventListener('message', function (event) {
const msg = event.data;
if (!msg || msg.api !== 'fromMiniApp' || !msg.requestId) return;
if (msg.response === undefined) return;
if (!_pending.has(msg.requestId)) return;
const pending = _pending.get(msg.requestId);
_pending.delete(msg.requestId);
const response = msg.response || {};
const response = msg.response;
if (response.error) pending.reject(new Error(response.error));
else pending.resolve(response.data);
});
@@ -121,18 +152,18 @@ only if `avatarDataUri` is absent.
### `io.tatuchat.theme.get`
Resolves with the color palette currently used by TatuChat, so your app can
match the ecosystem (light/dark aware). Colors are `#AARRGGBB` hex strings
suitable for CSS.
match the ecosystem (light/dark aware). Colors are `#RRGGBBAA` hex strings
(CSS 8-digit order: red, green, blue, alpha) suitable for CSS.
```js
const { palette } = await bridgeRequest('io.tatuchat.theme.get');
// => {
// brightness: 'light' | 'dark',
// primary: '#FF00D084',
// onPrimary: '#FF000000',
// primaryContainer: '#FF...',
// surface: '#FF...',
// surfaceContainerLowest/Low/Container/High/Highest: '#FF...',
// primary: '#00D084FF',
// onPrimary: '#000000FF',
// primaryContainer: '#00D08433',
// surface: '#FEF7FF00',
// surfaceContainerLowest/Low/Container/High/Highest: '#…',
// secondary..., tertiary..., error...,
// outline, outlineVariant, background, onBackground, onSurface, ...
// }