mirror of
https://github.com/block/buzz.git
synced 2026-11-02 15:31:27 +00:00
Present agent creation above retained Agents list
Signed-off-by: Tom Brow <tomb@block.xyz>
This commit is contained in:
@@ -164,11 +164,13 @@ class PrototypeAgentsSheet extends HookConsumerWidget {
|
||||
);
|
||||
keys.sort((a, b) => names.labelFor(a).compareTo(names.labelFor(b)));
|
||||
final profiles = ref.watch(userCacheProvider);
|
||||
final creating = useState(false);
|
||||
final failed = directory.hasError || registered.hasError;
|
||||
final loading =
|
||||
controller.busy ||
|
||||
directory.isLoading ||
|
||||
registered.connectionState != ConnectionState.done;
|
||||
!creating.value &&
|
||||
(controller.busy ||
|
||||
directory.isLoading ||
|
||||
registered.connectionState != ConnectionState.done);
|
||||
|
||||
Future<void> refresh() async {
|
||||
await controller.run(controller.refresh);
|
||||
@@ -186,18 +188,26 @@ class PrototypeAgentsSheet extends HookConsumerWidget {
|
||||
),
|
||||
trailing: IconButton(
|
||||
tooltip: 'Add agent',
|
||||
onPressed: community == null || controller.busy
|
||||
onPressed: community == null || controller.busy || creating.value
|
||||
? null
|
||||
: () => showBuzzModalBottomSheet<bool>(
|
||||
context: context,
|
||||
isScrollControlled: true,
|
||||
showCloseButton: false,
|
||||
builder: (_) => CreatePrototypeAgentSheet(
|
||||
controller: controller,
|
||||
community: community,
|
||||
onCreated: () => ref.invalidate(agentDirectoryProvider),
|
||||
),
|
||||
),
|
||||
: () async {
|
||||
creating.value = true;
|
||||
try {
|
||||
await showBuzzModalBottomSheet<bool>(
|
||||
context: context,
|
||||
useRootNavigator: true,
|
||||
isScrollControlled: true,
|
||||
showCloseButton: false,
|
||||
builder: (_) => CreatePrototypeAgentSheet(
|
||||
controller: controller,
|
||||
community: community,
|
||||
onCreated: () => ref.invalidate(agentDirectoryProvider),
|
||||
),
|
||||
);
|
||||
} finally {
|
||||
if (context.mounted) creating.value = false;
|
||||
}
|
||||
},
|
||||
icon: const Icon(Icons.add),
|
||||
),
|
||||
child: Material(
|
||||
@@ -212,7 +222,9 @@ class PrototypeAgentsSheet extends HookConsumerWidget {
|
||||
if (controller.account.account == null)
|
||||
ListTile(
|
||||
title: const Text('Sign in to create an agent'),
|
||||
subtitle: controller.busy ? Text(controller.status) : null,
|
||||
subtitle: controller.busy && !creating.value
|
||||
? Text(controller.status)
|
||||
: null,
|
||||
trailing: TextButton(
|
||||
onPressed: controller.busy ? null : controller.signIn,
|
||||
child: const Text('Sign in'),
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:buzz/prototype/agents_sheet.dart';
|
||||
import 'package:buzz/features/profile/user_profile_sheet.dart';
|
||||
import 'package:buzz/shared/mentions/agent_identity_provider.dart';
|
||||
@@ -35,6 +37,7 @@ class _Controller extends RemoteAgentController {
|
||||
String? submittedName;
|
||||
String? submittedInstructions;
|
||||
bool succeed = true;
|
||||
Completer<void>? creationGate;
|
||||
@override
|
||||
Future<void> ensureBinding() async {
|
||||
owner = 'owner';
|
||||
@@ -49,6 +52,12 @@ class _Controller extends RemoteAgentController {
|
||||
Future<bool> create(String name, {String instructions = ''}) async {
|
||||
submittedName = name;
|
||||
submittedInstructions = instructions;
|
||||
if (creationGate case final gate?) {
|
||||
return run(() async {
|
||||
await gate.future;
|
||||
if (!succeed) throw StateError('Creation failed. Retry.');
|
||||
});
|
||||
}
|
||||
status = 'Creation failed. Retry.';
|
||||
return succeed;
|
||||
}
|
||||
@@ -181,6 +190,111 @@ void main() {
|
||||
expect(find.byType(BottomSheet), findsNothing);
|
||||
});
|
||||
|
||||
for (final succeeds in [true, false]) {
|
||||
testWidgets(
|
||||
'creation overlays retained list; only top modal progresses: $succeeds',
|
||||
(tester) async {
|
||||
final account = BuilderlabAccountClient();
|
||||
final gate = Completer<void>();
|
||||
final controller = _Controller(account)
|
||||
..succeed = succeeds
|
||||
..creationGate = gate;
|
||||
addTearDown(() {
|
||||
controller.dispose();
|
||||
controller.relayAuth.dispose();
|
||||
account.dispose();
|
||||
});
|
||||
final existing = 'a' * 64;
|
||||
final added = 'b' * 64;
|
||||
final community = Community.create(
|
||||
name: 'Test',
|
||||
relayUrl: 'wss://test.example',
|
||||
pubkey: 'owner',
|
||||
);
|
||||
var completed = false;
|
||||
await tester.pumpWidget(
|
||||
ProviderScope(
|
||||
overrides: [
|
||||
activeCommunityProvider.overrideWith((ref) async => community),
|
||||
agentDirectoryProvider.overrideWith(
|
||||
(ref) async => [
|
||||
AgentDirectoryEntry(pubkey: existing),
|
||||
if (completed && succeeds) AgentDirectoryEntry(pubkey: added),
|
||||
],
|
||||
),
|
||||
],
|
||||
child: MaterialApp(
|
||||
theme: AppTheme.light(),
|
||||
home: Builder(
|
||||
builder: (context) => Scaffold(
|
||||
body: TextButton(
|
||||
onPressed: () => showPrototypeAgents(context, controller),
|
||||
child: const Text('Open Agents'),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.text('Open Agents'));
|
||||
await tester.pumpAndSettle();
|
||||
final list = tester.element(find.byType(PrototypeAgentsSheet));
|
||||
await tester.tap(find.byTooltip('Add agent'));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.byType(BottomSheet), findsNWidgets(2));
|
||||
expect(list.mounted, isTrue);
|
||||
final createContext = tester.element(
|
||||
find.byType(CreatePrototypeAgentSheet),
|
||||
);
|
||||
expect(
|
||||
Navigator.of(createContext),
|
||||
Navigator.of(createContext, rootNavigator: true),
|
||||
);
|
||||
expect(Navigator.of(list), isNot(Navigator.of(createContext)));
|
||||
await tester.enterText(find.widgetWithText(TextField, 'Name'), 'Scout');
|
||||
await tester.pump();
|
||||
await tester.tap(find.byTooltip('Create'));
|
||||
await tester.pump();
|
||||
await tester.pump(const Duration(milliseconds: 100));
|
||||
expect(controller.busy, isTrue);
|
||||
expect(find.byType(LinearProgressIndicator), findsOneWidget);
|
||||
expect(
|
||||
find.descendant(
|
||||
of: find.byType(PrototypeAgentsSheet),
|
||||
matching: find.byType(LinearProgressIndicator),
|
||||
),
|
||||
findsNothing,
|
||||
);
|
||||
expect(find.byKey(ValueKey(existing)), findsOneWidget);
|
||||
expect(
|
||||
tester
|
||||
.widget<IconButton>(find.widgetWithIcon(IconButton, Icons.check))
|
||||
.onPressed,
|
||||
isNull,
|
||||
);
|
||||
completed = true;
|
||||
gate.complete();
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.byType(BottomSheet), findsNWidgets(succeeds ? 1 : 2));
|
||||
expect(tester.element(find.byType(PrototypeAgentsSheet)), same(list));
|
||||
if (succeeds) {
|
||||
expect(find.byKey(ValueKey(added)), findsOneWidget);
|
||||
} else {
|
||||
expect(find.text('Creation failed. Retry.'), findsOneWidget);
|
||||
expect(
|
||||
tester
|
||||
.widget<IconButton>(
|
||||
find.widgetWithIcon(IconButton, Icons.check),
|
||||
)
|
||||
.onPressed,
|
||||
isNotNull,
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
for (final succeed in [true, false]) {
|
||||
testWidgets(
|
||||
'Create returns to list only after confirmed success: $succeed',
|
||||
|
||||
Reference in New Issue
Block a user