Skip to content

kapp.preferences (config streamer)

Les préférences sont la configuration de l'appli définie par le streamer dans son dashboard. Tu déclares leur structure dans preferences.config.js, et tu les lis à l'exécution via kapp.preferences (ou le global prefs).

Lire les préférences

  • kapp.preferences.get(path = null): Record<string, any> | undefined — lit une préférence par chemin ('global.theme.color'). Renvoie undefined si le chemin n'existe pas. Sans argument : renvoie tout l'arbre.
  • kapp.preferences.preferences — l'arbre complet (objet). Exposé aussi en global prefs.
js
const color = kapp.preferences.get('global.theme.color') ?? '#9146FF';
// équivalent pratique : const color = prefs.global?.theme?.color ?? '#9146FF';

Écrire les préférences (avancé)

  • await kapp.preferences.set(changes: { path: string, data: any }[]): Promise<{ changeset, errors }> — applique une liste de modifications, persistées côté serveur. Émet EVENTS.UPDATED après sync.
js
const { errors } = await kapp.preferences.set([{ path: 'global.counter', data: 0 }]);
if (errors.length) console.warn('prefs non appliquées', errors);

Déclarer la structure : preferences.config.js

Arbre de groupes et d'items typés, exporté en module.exports. Compilé en config/preferences.config.json par le HUB (transpile / watch). Réutilise des structures avec modules/Model.js.

js
const { Model } = require('./modules/Model');

module.exports = {
    type: 'group',
    appearance: { wrap: 'tabs' },
    groupItems: {
        global: {
            type: 'group',
            label: { en: 'Global', fr: 'Global' },
            groupItems: {
                color: {
                    type: 'string',
                    label: { en: 'Theme color', fr: 'Couleur du thème' },
                },
            },
        },
    },
};

Type spécial : runTarget (cible lançable)

Un item runTarget affiche au streamer un picker mixant les applis oneshot installées et les widgets de son channel. La valeur lue (get(path) / prefs) est directement une cible pour kapp.apps.run() : { type: 'app', slug } | { type: 'widget', id } | null (rien de choisi). set() accepte le même objet. wuOptions.targets: 'app' | 'widget' restreint le picker ; default interdit ; en collection → tableau de cibles. Détails et exemples : app-to-app.md.

Type spécial : mediaFile (média du streamer ou de la bibliothèque publique)

Un item mediaFile affiche au streamer un picker de média : ses propres fichiers ou un asset de la bibliothèque publique Kappapps (référencé directement, sans copie). wuOptions : allowedTypes: ['sound'|'video'|'image'], withPosition: bool.

La valeur lue (get(path) / prefs) est hydratée en { file, volume, position } — passe-la telle quelle à kapp.medias.playMedia(pref), quel que soit le média choisi (channel ou bibliothèque).

Default : uniquement un asset de la bibliothèque publique, référencé par son slug — jamais un média de channel (aucun sens cross-channel) :

js
alertSound: {
    type: 'mediaFile',
    label: { en: 'Alert sound', fr: 'Son d\'alerte' },
    wuOptions: { allowedTypes: ['sound'] },
    default: { library: 'kapp-ding', volume: 70 },
},

Le slug se trouve dans le catalogue (kapp.medias.library(), champ slug). Un slug inexistant = erreur CRIT à la validation de l'appli ; un asset dépublié = WARN (il reste jouable, mais il n'apparaît plus au catalogue).

Type spécial : status (statut de stream du channel)

Un item status affiche au streamer un sélecteur de ses statuts de stream configurés (les mêmes que k.statuses). La valeur lue (get(path) / prefs) est hydratée en { id, name, keyword } — même forme que StatusData de k.statuses — ou null si rien n'est sélectionné, ou si le statut choisi a été supprimé depuis. default/defaults interdits ; pas de wuOptions.

js
favoriteStatus: {
    type: 'status',
    label: { en: 'Favorite status', fr: 'Statut favori' },
},

Type spécial : announces (annonce multi-canal configurée par le streamer)

Un item announces affiche au streamer le formulaire d'annonce complet : messages, variations, et les tracks qu'il veut activer (chat, écran, voix, dashboard, Discord, services d'appli). wuOptions.tags déclare les tags #…# que ton appli fournira, pour qu'il sache quoi écrire.

Ne lis pas la valeur pour la rejouer toi-même — donne son chemin au service d'annonces :

js
// preferences.config.js
messages: {
    type: 'group',
    groupItems: {
        onWin: {
            type: 'announces',
            label: { en: 'On win', fr: 'À la victoire' },
            wuOptions: { tags: { user: 'Le gagnant', amount: 'Les points gagnés' } },
        },
    },
},
js
// script.js
await kapp.announces.play('messages.onWin', { user: user.getDisplayName(), amount: '250' });

Scope à déclarer dans infos.json : announces:play — et lui seul, quelles que soient les tracks que le streamer activera. La valeur hydratée porte une référence interne (_ref) et un discord.webhook réduit à un booléen : le webhook du streamer ne sort jamais du serveur.

appearance : options de présentation d'un item

Chaque item (groupe, collection ou champ) accepte un objet appearance qui pilote son rendu dans le dashboard streamer :

CléValeursEffet
wrap'tabs' | 'list' (défaut)Sur un group ou une collection : affiche les enfants en onglets plutôt qu'empilés.
tabsStyle'underline' | 'pills'Sur un group en wrap: 'tabs' : force le style des onglets. Par défaut le style est automatique (underline pour le groupe racine, pills pour les groupes imbriqués) — c'est la hiérarchie visuelle recommandée.
choicesStyle'cards' | 'select' (défaut)Sur un multipleChoice à choices statiques (objet) : affiche les options en cartes cochables au lieu d'un <select multiple>. Ignoré (WARN) si choices est un path dynamique.
colorDéprécié, ignoré : la colorisation par appli n'est plus rendue, tous les items utilisent l'accent neutre du design system. La clé reste tolérée dans les schémas existants ; ne plus la déclarer dans une nouvelle appli.
foldedtrue | falseL'item démarre replié (dépliable via sa poignée ou son titre).
hiddentrue | falseItem masqué dans le formulaire (la valeur reste lue/écrite normalement).
handletrue | falseAffiche la poignée de pli/tri à gauche de l'item.
lineBreaktrue | falseInsère un séparateur horizontal avant l'item ; lineBreakText: '...' y ajoute un texte.
formDéprécié, ignoré : le formulaire utilise un layout unique (label au-dessus du champ).
js
settings: {
    type: 'group',
    label: { en: 'Advanced', fr: 'Avancé' },
    appearance: { folded: true, handle: true },
    groupItems: { /* ... */ },
},

Pièges

  • prefs n'est pas réactif : après un set(), relis la valeur (ou écoute EVENTS.UPDATED).
  • N'édite pas config/preferences.config.json à la main : il est régénéré depuis le .js.
  • get(path) renvoie undefined pour un chemin inconnu → prévois des valeurs par défaut.