Agency Docs
QBESXStandalone

Agency-Watch Własne Aplikacje

Teraz z AgencyOS27: bezpłatna aktualizacja dla każdego, kto już posiada zegarek.

v27.0.1Za darmo7 Strony

⌚ Zbuduj własną aplikację dla Agency-Watch

Zegarek jest otwarty. Właściciel serwera może dodać aplikację, która wygląda i działa jak wbudowana, używając tych samych elementów składowych, kolorów oraz tłumaczeń.

Wymóg: edycja Pro. Własne aplikacje działają tylko wtedy, gdy Agency-Phone jest uruchomiony na serwerze, a gracz go posiada. Bez wersji Pro są one rejestrowane, ale nigdy niedostarczane: interfejs nigdy się o nich nie dowie, nie pojawią się w App Store, a serwer odrzuci każde wysłane przez nie działanie. Jest to sprawdzane w trzech niezależnych miejscach i nie można tego wyłączyć.

PlikWymaganeCo robi
apps/<id>/app.luatakRejestruje aplikację: nazwa, ikona, kolor, kategoria.
apps/<id>/app.jstakEkran: co rysuje i jak reaguje.
apps/<id>/app.cssnieTwoje własne style. Ładowane tylko wtedy, gdy style = true.
apps/<id>/server.luanieLogika serwera, którą twoja aplikacja może wywołać.

Folder ma dokładnie taką samą nazwę jak id aplikacji. W ten sposób zegarek znajduje app.js i app.css bez dwukrotnego wpisywania ścieżki, bo podwójnie zapisane ścieżki prędzej czy później zaczną się rozjeżdżać.

Wszystko pod apps/ to escrow_ignored: pozostaje czytelny i edytowalny na dysku, a aktualizacja watch nigdy go nie nadpisze.

1 Zarejestruj aplikację

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
})

Aplikacja z nieprawidłowym id, brakiem nazwy, nieznaną kategorią lub kolorem, który nie jest #rrggbb zostaje odrzucony, głośno i z podaniem powodu, w konsoli serwera. Połowiczna rejestracja nie istnieje: tego typu błąd pojawia się dopiero wtedy, gdy gracz w to kliknie.

Uruchom refresh i restart Agency-Watch po dodaniu plików. Przy starcie watch zgłasza zarejestrowane elementy.

2 Rysuj ekran

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 uruchamia się za każdym razem, gdy ekran jest budowany, więc nie zachowuje stanu między wywołaniami. Wszystko, co musi przetrwać ponowne renderowanie, trafia do zmiennej poza obiektem aplikacji.

Obie funkcje działają w bezpiecznym środowisku. Jeśli twój kod wywoła wyjątek, aplikacja wyświetli linię błędu, a zegarek będzie działał dalej; właściwy błąd trafia do konsoli F8.

3 Skrzynka z narzędziami

w zawiera wszystko, czego potrzebuje aplikacja na zegarku, i nic ponadto. Interfejs, który potrafi wszystko, nigdy nie może zostać zmieniony, dlatego ten jest celowo niewielki.

ZadzwońCo zyskujesz
w.data()Płaska migawka: 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})Wiersz listy w stylu zegarka.
w.section(text)Nagłówek sekcji.
w.card(html)Powierzchnia.
w.button(text, attrs)Przycisk. attrs to surowy ciąg atrybutów, np. ' data-roll'.
w.toggle(on)Przełącznik wł./wył.
w.center(html)Wyśrodkowany, dla pojedynczej dużej wartości.
w.icon(name)Jedna z wbudowanych ikon.
w.esc(text)Escapowanie tekstu. Użyj do wszystko który nie należy do ciebie.
w.text(key, fallback)Tłumaczenie z zegarka.
w.click(selector, fn)Podepnij listener. Tylko wewnątrz bind.
w.notify(title, text, icon, colour)Powiadomienie na zegarku.
w.refresh()Odrysuj ponownie, bez animacji wejścia.
w.close()Wróć, tak jak strzałka w nagłówku.
w.toServer(action, data)Zapytaj serwer. Zwraca promise.
w.id, w.versionTwoje app id i wersja AgencyOS.

Snapshot to kopia, a nie uchwyt. Zegarek zawiera także kontakty, wiadomości i dane kart; niczego z tego tam nie ma.

4 Strona serwera

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 zawsze zwraca wynik, z { ok: true, data: … } lub { ok: false, reason: '…' }, nawet jeśli serwer nigdy nie odpowiedział. Twoja aplikacja nigdy nie zawiesi się w oczekiwaniu, a powód zawsze znajduje się na najwyższym poziomie, bez względu na to, która strona odmówiła.

reasonZnaczenie
no_proBrak edycji Pro. Własne aplikacje bez niej nie istnieją.
unknownBrak zarejestrowanej aplikacji lub akcji.
too_fastRate limit: maksymalnie dziesięć żądań na pięć sekund na gracza.
errorTwój handler zgłosił błąd. Szczegóły znajdują się w konsoli serwera.
timeoutBrak odpowiedzi w ciągu dwunastu sekund.
dataŻądanie nie było tabelą.

Cokolwiek trafi do data pochodzi od klienta i jest życzenie, nie fakt. Sprawdzaj każdą wartość przed jej użyciem. Wszystko, co ma znaczenie (pieniądze, przedmioty, rezultaty), należy do serwera i nigdzie indziej.

5 Stylowanie

Kolory zegarka są dostępne jako zmienne CSS i dopasowują się do wyboru użytkownika w Studio. Sztywno zakodowane kolory sprawiają, że aplikacja pozostaje niebieska na zielonym zegarku.

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

Dodawaj prefiksy do własnych klas. Ekran jest współdzielony z każdą inną aplikacją, a klasa o nazwie .large znajdą przyjaciół.

6 Wbudowane ikony

Przekaż dowolne z nich do icon w app.lua lub do 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

Nazwy ikon celowo pozostają bez zmian. Są to identyfikatory, a nie etykiety: gracz nigdy ich nie czyta, a zmiana nazwy id psuje każdą aplikację, która już z niego korzysta.

📦 Działający przykład jest dostarczany z zegarkiem

apps/example/ wewnątrz zasobu znajduje się kompletna, gotowa do uruchomienia aplikacja: komponenty, wywołanie serwera, powiadomienie i własny CSS. Skopiuj folder, zmień jego nazwę i masz już działający punkt wyjścia.

Skrócona wersja tej strony znajduje się w apps/README.md obok.

Nadal nie idzie po tej stronie? Nasze wsparcie przejmuje sprawę.