mirror of
https://github.com/block/buzz.git
synced 2026-11-10 11:21:05 +00:00
Refine prototype agent list and creation form styling
Signed-off-by: Tom Brow <tomb@block.xyz>
This commit is contained in:
@@ -482,14 +482,6 @@ class ChannelsPage extends HookConsumerWidget {
|
||||
onPressed: openCommunitySwitcher,
|
||||
),
|
||||
nativeActions: [
|
||||
if (onSearch != null)
|
||||
IosNavigationAction(
|
||||
label: 'Search',
|
||||
symbol: 'magnifyingglass',
|
||||
sharesBackground: true,
|
||||
icon: BuzzIcons.search300,
|
||||
onPressed: onSearch,
|
||||
),
|
||||
if (onAgents != null)
|
||||
IosNavigationAction(
|
||||
label: 'Agents',
|
||||
@@ -498,6 +490,14 @@ class ChannelsPage extends HookConsumerWidget {
|
||||
icon: BuzzIcons.bot,
|
||||
onPressed: onAgents,
|
||||
),
|
||||
if (onSearch != null)
|
||||
IosNavigationAction(
|
||||
label: 'Search',
|
||||
symbol: 'magnifyingglass',
|
||||
sharesBackground: true,
|
||||
icon: BuzzIcons.search300,
|
||||
onPressed: onSearch,
|
||||
),
|
||||
if (onInbox != null)
|
||||
IosNavigationAction(
|
||||
label: 'Inbox',
|
||||
|
||||
@@ -24,18 +24,18 @@ class _ChannelHeaderActions extends StatelessWidget {
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
if (onSearch != null)
|
||||
IconButton(
|
||||
tooltip: 'Search',
|
||||
icon: const Icon(BuzzIcons.search300),
|
||||
onPressed: onSearch,
|
||||
),
|
||||
if (onAgents != null)
|
||||
IconButton(
|
||||
tooltip: 'Agents',
|
||||
icon: const Icon(BuzzIcons.bot),
|
||||
onPressed: onAgents,
|
||||
),
|
||||
if (onSearch != null)
|
||||
IconButton(
|
||||
tooltip: 'Search',
|
||||
icon: const Icon(BuzzIcons.search300),
|
||||
onPressed: onSearch,
|
||||
),
|
||||
if (onInbox != null)
|
||||
Semantics(
|
||||
label: hasUnreadInbox ? 'Inbox, unread' : 'Inbox',
|
||||
|
||||
@@ -5,7 +5,6 @@ import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
|
||||
import '../features/profile/user_profile_sheet.dart';
|
||||
import '../features/profile/presence_cache_provider.dart';
|
||||
import '../shared/community/community_provider.dart';
|
||||
import '../shared/crypto/nip_oa.dart';
|
||||
import '../shared/identity_names/identity_names_provider.dart';
|
||||
@@ -88,7 +87,6 @@ class PrototypeAgentsSheet extends HookConsumerWidget {
|
||||
);
|
||||
keys.sort((a, b) => names.labelFor(a).compareTo(names.labelFor(b)));
|
||||
final profiles = ref.watch(userCacheProvider);
|
||||
final presence = ref.watch(presentedPresenceProvider);
|
||||
final failed = directory.hasError || registered.hasError;
|
||||
final loading =
|
||||
controller.busy ||
|
||||
@@ -109,7 +107,8 @@ class PrototypeAgentsSheet extends HookConsumerWidget {
|
||||
icon: const Icon(Icons.close),
|
||||
onPressed: () => Navigator.pop(context),
|
||||
),
|
||||
trailing: TextButton(
|
||||
trailing: IconButton(
|
||||
tooltip: 'Add agent',
|
||||
onPressed: community == null || controller.busy
|
||||
? null
|
||||
: () => showBuzzModalBottomSheet<bool>(
|
||||
@@ -122,7 +121,7 @@ class PrototypeAgentsSheet extends HookConsumerWidget {
|
||||
onCreated: () => ref.invalidate(agentDirectoryProvider),
|
||||
),
|
||||
),
|
||||
child: const Text('Add agent'),
|
||||
icon: const Icon(Icons.add),
|
||||
),
|
||||
child: RefreshIndicator(
|
||||
onRefresh: refresh,
|
||||
@@ -161,6 +160,7 @@ class PrototypeAgentsSheet extends HookConsumerWidget {
|
||||
key: ValueKey(key),
|
||||
contentPadding: const EdgeInsets.symmetric(
|
||||
horizontal: Grid.xxs,
|
||||
vertical: Grid.xxs,
|
||||
),
|
||||
leading: AvatarImage(
|
||||
imageUrl: profiles[key]?.avatarUrl,
|
||||
@@ -172,19 +172,6 @@ class PrototypeAgentsSheet extends HookConsumerWidget {
|
||||
),
|
||||
),
|
||||
title: Text(names.labelFor(key)),
|
||||
subtitle: presence[key] == 'online'
|
||||
? Row(
|
||||
children: [
|
||||
Icon(
|
||||
Icons.circle,
|
||||
size: Grid.xxs,
|
||||
color: context.appColors.success,
|
||||
),
|
||||
const SizedBox(width: Grid.half),
|
||||
const Text('Online'),
|
||||
],
|
||||
)
|
||||
: null,
|
||||
onTap: () => Navigator.pop(context, key),
|
||||
),
|
||||
],
|
||||
|
||||
@@ -36,6 +36,38 @@ class CreatePrototypeAgentSheet extends HookConsumerWidget {
|
||||
final active = ref.watch(activeCommunityProvider).asData?.value;
|
||||
final sameCommunity = active?.id == community.id;
|
||||
final pending = controller.pending != null;
|
||||
final canCreate =
|
||||
!controller.busy && sameCommunity && name.text.trim().isNotEmpty;
|
||||
final actionStyle = IconButton.styleFrom(
|
||||
minimumSize: const Size.square(44),
|
||||
backgroundColor: context.colors.surfaceContainerHighest,
|
||||
side: BorderSide(color: context.colors.outlineVariant),
|
||||
shape: const CircleBorder(),
|
||||
);
|
||||
InputDecoration fieldDecoration(String label, {String? hint}) =>
|
||||
InputDecoration(
|
||||
labelText: label,
|
||||
floatingLabelBehavior: FloatingLabelBehavior.always,
|
||||
hintText: hint,
|
||||
filled: true,
|
||||
fillColor: context.colors.surfaceContainerHighest,
|
||||
contentPadding: const EdgeInsets.symmetric(
|
||||
horizontal: Grid.xs,
|
||||
vertical: Grid.xs,
|
||||
),
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(Radii.container),
|
||||
borderSide: BorderSide.none,
|
||||
),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(Radii.container),
|
||||
borderSide: BorderSide.none,
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(Radii.container),
|
||||
borderSide: BorderSide.none,
|
||||
),
|
||||
);
|
||||
|
||||
Future<void> create() async {
|
||||
error.value = null;
|
||||
@@ -91,16 +123,28 @@ class CreatePrototypeAgentSheet extends HookConsumerWidget {
|
||||
),
|
||||
child: BuzzTitledSheetLayout(
|
||||
title: 'Create agent',
|
||||
leading: TextButton(
|
||||
leading: IconButton(
|
||||
tooltip: 'Cancel',
|
||||
style: actionStyle,
|
||||
onPressed: controller.busy ? null : () => Navigator.pop(context),
|
||||
child: const Text('Cancel'),
|
||||
icon: const Icon(Icons.close),
|
||||
),
|
||||
trailing: TextButton(
|
||||
onPressed:
|
||||
controller.busy || !sameCommunity || name.text.trim().isEmpty
|
||||
? null
|
||||
: create,
|
||||
child: Text(pending ? 'Resume' : 'Create'),
|
||||
trailing: IconButton(
|
||||
tooltip: pending ? 'Resume' : 'Create',
|
||||
style: actionStyle.copyWith(
|
||||
backgroundColor: WidgetStatePropertyAll(
|
||||
canCreate
|
||||
? context.colors.primary
|
||||
: context.colors.surfaceContainerHighest,
|
||||
),
|
||||
foregroundColor: WidgetStatePropertyAll(
|
||||
canCreate
|
||||
? context.colors.onPrimary
|
||||
: context.colors.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
onPressed: canCreate ? create : null,
|
||||
icon: const Icon(Icons.check),
|
||||
),
|
||||
child: SingleChildScrollView(
|
||||
padding: const EdgeInsets.all(Grid.gutter),
|
||||
@@ -112,28 +156,21 @@ class CreatePrototypeAgentSheet extends HookConsumerWidget {
|
||||
autofocus: true,
|
||||
enabled: !controller.busy && !pending,
|
||||
textCapitalization: TextCapitalization.words,
|
||||
decoration: const InputDecoration(
|
||||
labelText: 'Display name',
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
decoration: fieldDecoration('Name'),
|
||||
),
|
||||
const SizedBox(height: Grid.sm),
|
||||
TextField(
|
||||
controller: instructions,
|
||||
enabled: !controller.busy && !pending,
|
||||
minLines: 4,
|
||||
maxLines: 7,
|
||||
decoration: const InputDecoration(
|
||||
labelText: 'Instructions (optional)',
|
||||
hintText: 'Describe what this agent should do.',
|
||||
border: OutlineInputBorder(),
|
||||
maxLines: 6,
|
||||
textCapitalization: TextCapitalization.sentences,
|
||||
textInputAction: TextInputAction.newline,
|
||||
decoration: fieldDecoration(
|
||||
'Instructions (optional)',
|
||||
hint: 'Describe what this agent should do.',
|
||||
),
|
||||
),
|
||||
const SizedBox(height: Grid.xs),
|
||||
Text(
|
||||
'Runs remotely and responds to you in ${community.name}.',
|
||||
style: context.textTheme.bodySmall,
|
||||
),
|
||||
if (controller.busy) ...[
|
||||
const SizedBox(height: Grid.xs),
|
||||
const LinearProgressIndicator(),
|
||||
|
||||
@@ -164,7 +164,7 @@ void main() {
|
||||
'Reply concisely.',
|
||||
);
|
||||
await tester.pump();
|
||||
await tester.tap(find.text('Create'));
|
||||
await tester.tap(find.byTooltip('Create'));
|
||||
await tester.pumpAndSettle();
|
||||
expect(controller.submittedName, 'Scout');
|
||||
expect(controller.submittedInstructions, 'Reply concisely.');
|
||||
|
||||
Reference in New Issue
Block a user