-
Notifications
You must be signed in to change notification settings - Fork 171
Expand file tree
/
Copy pathmessage.dart
More file actions
91 lines (78 loc) · 2.78 KB
/
Copy pathmessage.dart
File metadata and controls
91 lines (78 loc) · 2.78 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
// Copyright 2025 The Flutter Authors.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:a2ui_core/a2ui_core.dart' as core;
import 'package:flutter/material.dart';
import 'package:flutter_markdown_plus/flutter_markdown_plus.dart';
import 'package:genui/genui.dart';
/// Renders surfaces through the experimental node layer (`NodeSurface`)
/// instead of `Surface`. Enable with `--dart-define=nodes=true`.
const bool _useNodeLayer = bool.fromEnvironment('nodes');
class Message {
Message({this.text, this.surfaceId, this.isUser = false})
: assert((surfaceId == null) != (text == null));
String? text;
final String? surfaceId;
final bool isUser;
}
class MessageView extends StatelessWidget {
const MessageView(this.message, this.host, {super.key});
final Message message;
/// The surface host used to render generative UI surfaces. Required only
/// when [Message.surfaceId] is non-null.
final SurfaceHost? host;
@override
Widget build(BuildContext context) {
final String? surfaceId = message.surfaceId;
if (surfaceId == null) {
if (message.isUser) {
return Text(message.text ?? '');
} else {
return MarkdownBody(data: message.text ?? '');
}
}
assert(
host != null,
'A SurfaceHost is required to render surface $surfaceId',
);
final SurfaceHost surfaceHost = host!;
if (_useNodeLayer && surfaceHost is SurfaceController) {
return _NodeLayerMessageSurface(
controller: surfaceHost,
surfaceId: surfaceId,
);
}
return Surface(surfaceContext: surfaceHost.contextFor(surfaceId));
}
}
/// Renders a surface through [NodeSurface] once its core model exists,
/// watching the definition snapshot only to learn about creation.
class _NodeLayerMessageSurface extends StatelessWidget {
const _NodeLayerMessageSurface({
required this.controller,
required this.surfaceId,
});
final SurfaceController controller;
final String surfaceId;
@override
Widget build(BuildContext context) {
final SurfaceContext surfaceContext = controller.contextFor(surfaceId);
return ValueListenableBuilder<SurfaceDefinition?>(
valueListenable: surfaceContext.definition,
builder: (context, definition, _) {
final core.SurfaceModel<core.ComponentApi>? surface = controller
.liveSurfaceFor(surfaceId);
final Catalog? catalog = surfaceContext.catalog;
if (definition == null || surface == null || catalog == null) {
return const SizedBox.shrink();
}
return NodeSurface(
surface: surface,
catalog: catalog,
onEvent: surfaceContext.handleUiEvent,
reportError: surfaceContext.reportError,
);
},
);
}
}