Agency Docs
QBESXStandalone

Agency-Watch Apps Personalizadas

Ahora con AgencyOS27: una actualización gratuita para quien ya tenga el reloj.

v27.0.0Gratis7 Páginas

⌚ Crea tu propia app para el Agency-Watch

El reloj está abierto. Un dueño de servidor puede añadir una app que se ve y se comporta como una integrada, con los mismos componentes, los mismos colores y las mismas traducciones.

Requisito: la edición Pro. Las apps propias solo existen si el Agency-Phone funciona en el servidor y el jugador lo tiene. Sin Pro se registran pero nunca se entregan: la interfaz nunca sabe de ellas, no aparecen en la App Store y el servidor rechaza cada acción que envían. Se comprueba en tres sitios distintos y no se puede desactivar.

ArchivoObligatorioQué hace
apps/<id>/app.luasíRegistra la app: nombre, icono, color, categoría.
apps/<id>/app.jssíLa pantalla: qué dibuja y cómo reacciona.
apps/<id>/app.cssnoTu propio estilo. Solo se carga con style = true.
apps/<id>/server.luanoLógica de servidor a la que tu app puede llamar.

La carpeta se llama exactamente igual que el id de la app. Así el reloj encuentra app.js y app.css sin escribir la ruta dos veces, y las rutas escritas dos veces acaban separándose tarde o temprano.

Todo lo que hay bajo apps/ está en escrow_ignore: sigue siendo legible y editable en tu disco, y una actualización del reloj nunca lo sobrescribe.

1 Registrar la app

apps/hello/app.lua

AgencyWatchApp({
    id       = 'hello',          -- lowercase, digits and _, must match the folder
    name     = 'Hello',
    icon     = 'raster',         -- one of the built-in icons, see below
    color    = '#5ac8fa',        -- #rrggbb
    category = 'tools',          -- tools | games | driving | style | connected
    style    = true,             -- also load app.css
    texts    = { en = 'Hello', de = 'Hallo' },   -- optional, name per language
})

Una app con un id mal formado, sin nombre, con una categoría desconocida o con un color que no sea #rrggbb se rechaza en la consola del servidor, claramente y con el motivo. No existe el registro a medias: ese tipo de error solo se vería cuando un jugador tocara la app.

Ejecuta refresh y restart Agency-Watch después de añadir archivos. Al arrancar, el reloj indica qué se ha registrado.

2 Dibujar la pantalla

apps/hello/app.js

AgencyWatch.app('hello', {

    render: function (w) {            // required, returns HTML
        var d = w.data();
        return w.card('Hello, ' + w.esc(d.name)) +
               w.section('Steps') +
               w.row({ icon: 'schritte', static: true,
                       top: String(d.steps || 0) }) +
               w.button('Roll a die', ' data-roll');
    },

    bind: function (w) {              // optional, runs right after
        w.click('[data-roll]', function () {
            w.toServer('roll', { sides: 6 }).then(function (a) {
                if (a.ok) w.notify('Hello', 'You rolled ' + a.data.value);
            });
        });
    },
});

render se ejecuta cada vez que se construye la pantalla, así que no guarda estado entre llamadas. Lo que tenga que sobrevivir a un redibujado va en una variable fuera del objeto de la app.

Ambas funciones se ejecutan dentro de una red de seguridad. Si tu código lanza un error, tu app muestra una línea de error y el reloj sigue funcionando; el error real va a la consola F8.

3 La caja de herramientas

w contiene todo lo que necesita una app en un reloj y nada más. Una interfaz que lo hace todo ya no se puede cambiar nunca, por eso esta es pequeña a propósito.

LlamadaQué te da
w.data()Una instantánea plana: time, hour, minute, date, weekday, name, job, health, armour, pulse, steps, distance, calories, speed, heading, weather, pro.
w.row({icon, top, bottom, end, attrs, static})Una fila de lista con el estilo propio del reloj.
w.section(text)Un título de sección.
w.card(html)Una superficie.
w.button(text, attrs)Un botón. attrs es una cadena de atributos en bruto, por ejemplo ' data-roll'.
w.toggle(on)Un interruptor de encendido/apagado.
w.center(html)Centrado, para un único valor grande.
w.icon(name)Uno de los iconos integrados.
w.esc(text)Escapa texto. Úsalo para todo lo que no sea tuyo.
w.text(key, fallback)Una traducción del reloj.
w.click(selector, fn)Añade un listener. Solo dentro de bind.
w.notify(title, text, icon, colour)Una notificación en el reloj.
w.refresh()Redibuja, sin la animación de entrada.
w.close()Vuelve atrás, como la flecha de la cabecera.
w.toServer(action, data)Pregunta al servidor. Devuelve una promesa.
w.id, w.versionEl id de tu app y la versión de AgencyOS.

La instantánea es una copia, no una referencia. El reloj también lleva contactos, mensajes y datos de tarjetas; nada de eso está ahí.

4 El lado del servidor

apps/hello/server.lua

AgencyWatchAction('hello', 'roll', function(src, data)
    local sides = tonumber(data and data.sides) or 6
    if sides < 2 then sides = 2 end
    if sides > 100 then sides = 100 end
    return { value = math.random(1, math.floor(sides)) }
end)

w.toServer siempre se resuelve, con { ok: true, data: … } o { ok: false, reason: '…' }, incluso si el servidor nunca respondió. Tu app nunca puede quedarse colgada esperando, y el motivo siempre está en el nivel superior, sea cual sea el lado que rechazó.

reasonSignificado
no_proSin edición Pro. Sin ella no existen las apps propias.
unknownNo hay ninguna app ni acción registrada con ese nombre.
too_fastLímite de frecuencia: como mucho diez peticiones cada cinco segundos por jugador.
errorTu handler lanzó un error. Los detalles están en la consola del servidor.
timeoutSin respuesta en doce segundos.
dataLa petición no era una tabla.

Lo que llega en data viene del cliente y es un deseo, no un hecho. Comprueba cada valor antes de usarlo. Todo lo que cuenta (dinero, objetos, resultados) va en el servidor y en ningún otro sitio.

5 Estilo

Los colores del reloj están disponibles como variables CSS y siguen lo que el usuario eligió en Studio. Con colores fijos tendrás una app que sigue azul en un reloj verde.

var(--text)   var(--text-2)   var(--leise)
var(--akzent) var(--gruen)    var(--rot)    var(--gelb)
var(--karte)  var(--karte-hoch)   var(--linie)
var(--grund)

Pon un prefijo a tus propias clases. La pantalla se comparte con todas las demás apps, y una clase llamada .large encontrará compañía.

6 Iconos integrados

Pasa cualquiera de estos a icon en app.lua o a w.icon():

akku auto blitz brief einkauf farben flugzeug gewitter glocke haken helligkeit herz hoch hupe karte karte-pin kein-signal kino kompass kreuz krone lampe laufen lautlos links loeschen minus mobil mond nebel neuladen pause personen pin plus qr raster rechts regen regler runter sanduhr schild schloss schloss-auf schnee schritte signal sonne sp-fall sp-flug sp-ring sp-turm sprechen stoppuhr telefon telefon-aus tempo ton uhr verboten wiedergabe wlan wolke zahnrad

Los nombres de los iconos se quedan como están a propósito. Son ids, no etiquetas: un jugador nunca los lee, y renombrar un id rompe todas las apps que ya lo usan.

📦 El reloj trae un ejemplo que funciona

apps/example/ dentro del resource es una app completa y ejecutable: componentes, una llamada al servidor, una notificación y su propio CSS. Copia la carpeta, cámbiale el nombre y tendrás un punto de partida que ya funciona.

Hay una versión corta de esta página al lado, en apps/README.md.

¿Sigues atascado después de esta página? Nuestro soporte se encarga.