Agency Docs
QBESXStandalone

Agency-Watch Apps Personalizados

Agora com o AgencyOS27: uma atualização grátis para quem já tem o relógio.

v27.0.0Grátis7 Páginas

⌚ Criar a tua própria app para o Agency-Watch

O relógio está aberto. Um dono de servidor pode adicionar uma app com o aspeto e o comportamento de uma integrada, usando os mesmos componentes, as mesmas cores e as mesmas traduções.

Requisito: a edição Pro. As apps próprias só existem quando o Agency-Phone corre no servidor e o jogador o tem. Sem Pro são registadas mas nunca entregues: a interface nunca sabe delas, não aparecem na App Store e o servidor recusa todas as ações que enviam. Isto é verificado em três sítios diferentes e não pode ser desligado.

FicheiroObrigatórioO que faz
apps/<id>/app.luasimRegista a app: nome, ícone, cor, categoria.
apps/<id>/app.jssimO ecrã: o que desenha e como reage.
apps/<id>/app.cssnãoO teu próprio estilo. Só é carregado com style = true.
apps/<id>/server.luanãoLógica de servidor que a tua app pode chamar.

A pasta tem exatamente o nome do id da app. É assim que o relógio encontra app.js e app.css sem o caminho ser escrito duas vezes, e caminhos escritos duas vezes acabam por divergir mais cedo ou mais tarde.

Tudo o que está em apps/ está em escrow_ignore: continua legível e editável no teu disco, e uma atualização do relógio nunca o substitui.

1 Registar a 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
})

Uma app com um id mal formado, sem nome, com uma categoria desconhecida ou uma cor que não seja #rrggbb é recusada na consola do servidor, claramente e com o motivo. Não existe registo a meio: esse tipo de erro só apareceria quando um jogador tocasse na app.

Corre refresh e restart Agency-Watch depois de adicionares ficheiros. Ao arrancar, o relógio indica o que foi registado.

2 Desenhar o ecrã

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 corre sempre que o ecrã é construído, por isso não guarda estado entre chamadas. O que tiver de sobreviver a um redesenho vai para uma variável fora do objeto da app.

As duas funções correm dentro de uma rede de segurança. Se o teu código lançar um erro, a tua app mostra uma linha de erro e o relógio continua a funcionar; o erro real vai para a consola F8.

3 A caixa de ferramentas

w tem tudo o que uma app num relógio precisa, e nada mais. Uma interface que faz tudo nunca mais pode ser alterada, por isso esta é pequena de propósito.

ChamadaO que te dá
w.data()Um instantâneo simples: 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})Uma linha de lista no estilo do relógio.
w.section(text)Um título de secção.
w.card(html)Uma superfície.
w.button(text, attrs)Um botão. attrs é uma string de atributos em bruto, por exemplo ' data-roll'.
w.toggle(on)Um interruptor ligar/desligar.
w.center(html)Centrado, para um único valor grande.
w.icon(name)Um dos ícones integrados.
w.esc(text)Escapa texto. Usa-o para tudo o que não seja teu.
w.text(key, fallback)Uma tradução do relógio.
w.click(selector, fn)Associa um listener. Só dentro de bind.
w.notify(title, text, icon, colour)Uma notificação no relógio.
w.refresh()Redesenha, sem a animação de entrada.
w.close()Volta atrás, como a seta do cabeçalho.
w.toServer(action, data)Pergunta ao servidor. Devolve uma promise.
w.id, w.versionO id da tua app e a versão do AgencyOS.

O instantâneo é uma cópia, não uma referência. O relógio também guarda contactos, mensagens e dados de cartões; nada disso está lá.

4 O lado do 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 resolve sempre, com { ok: true, data: … } ou { ok: false, reason: '…' }, mesmo quando o servidor nunca respondeu. A tua app nunca fica presa à espera, e o motivo está sempre no nível de topo, seja qual for o lado que recusou.

reasonSignificado
no_proSem edição Pro. Sem ela não existem apps próprias.
unknownNão existe essa app nem essa ação registada.
too_fastLimite de pedidos: no máximo dez pedidos por cada cinco segundos por jogador.
errorO teu handler lançou um erro. Os detalhes estão na consola do servidor.
timeoutSem resposta em doze segundos.
dataO pedido não era uma tabela.

O que chega em data vem do cliente e é um desejo, não um facto. Verifica cada valor antes de o usares. Tudo o que conta (dinheiro, itens, resultados) pertence ao servidor e a mais lado nenhum.

5 Estilo

As cores do relógio estão disponíveis como variáveis CSS e seguem o que o utilizador escolheu no Studio. Cores fixas dão uma app que continua azul num relógio 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)

Dá um prefixo às tuas próprias classes. O ecrã é partilhado com todas as outras apps, e uma classe chamada .large vai encontrar companhia.

6 Ícones integrados

Passa qualquer um destes a icon em app.lua ou 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

Os nomes dos ícones ficam como estão de propósito. São ids, não rótulos: um jogador nunca os lê, e mudar o nome de um id estraga todas as apps que já o usam.

📦 O relógio traz um exemplo que funciona

apps/example/ dentro do resource é uma app completa e executável: componentes, uma chamada ao servidor, uma notificação e CSS próprio. Copia a pasta, muda-lhe o nome e tens um ponto de partida que já funciona.

Há uma versão curta desta página ao lado, em apps/README.md.

Continuas sem avançar depois desta página? O nosso suporte assume daqui.