待合室の番号板を作る。大きな数字ひとつ、待ち人数の一行、ボタン二つ。
これを作るのに普通は何が要るか。プロジェクトを作り、ウィジェットツリーを組み、ビルドし、パネルにインストールする。数字を大きくしたければ、その四段をもう一周する。
ここでは 画面がサーバーにあるファイル一枚だ。 接続すればそのファイルが来る。
画面
これで全部だ。
{ "type": "page", "title": "Front Desk",
"content": { "type": "center",
"child": { "type": "linear", "direction": "vertical", "spacing": 16, "alignment": "center", "children": [
{ "type": "text", "text": "NOW SERVING", "style": { "fontSize": 18, "letterSpacing": 4, "color": "#6b7280" } },
{ "type": "text", "text": "{{now}}", "style": { "fontSize": 96, "fontWeight": "bold", "color": "#111827" } },
{ "type": "text", "text": "{{waiting}} waiting · issued {{issued}}", "style": { "fontSize": 20, "color": "#6b7280" } },
{ "type": "linear", "direction": "horizontal", "spacing": 12, "children": [
{ "type": "button", "label": "Call next", "onTap": { "type": "tool", "tool": "queue.next" } },
{ "type": "button", "label": "Take a ticket", "onTap": { "type": "tool", "tool": "queue.take" } } ] } ] } } }
題は十行と付けたが、実際には 九行、848 バイトで終わった。
{{now}} のところに番号が入る。ボタンの onTap は道具の名を呼ぶ — この記事ではまだ押しても何も起きない。それは次の記事だ。
その九行はサーバーにある
サーバー側のコードはこれだけだ。
server.addResource(
uri: 'ui://app',
name: 'Front Desk screen',
description: 'The screen definition, served as a file',
mimeType: 'application/json',
handler: (uri, params) async => ReadResourceResult(contents: [
ResourceContentInfo(
uri: 'ui://app',
mimeType: 'application/json',
text: File(_screenPath).readAsStringSync(),
)
]),
);
毎回ファイルを読み直している。 起動時に一度読んでメモリに持てば速いが、そうすると画面を直すたびにサーバーを再起動しなければならず、その瞬間このサンプルの主張 — ファイルを直せば別のアプリになる — が嘘になる。
/// Read fresh on every request, deliberately. A screen cached at boot is a
/// screen you have to restart the server to change, and then the thing this
/// sample claims — edit the file, get a new app — stops being true.