대기실 번호판을 만든다. 큰 숫자 하나, 대기 인원 한 줄, 버튼 두 개.
이런 걸 만드는 데 보통 무엇이 필요한가. 프로젝트를 만들고, 위젯 트리를 짜고, 빌드하고, 패널에 설치한다. 번호 글씨를 키우려면 그 네 단계를 다시 돈다.
여기서는 화면이 서버에 있는 파일 하나다. 접속하면 그 파일이 온다.
화면
전부다.
{ "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.