jld3103
2 years ago
4 changed files with 130 additions and 1 deletions
@ -0,0 +1,101 @@
|
||||
import 'package:flutter/material.dart'; |
||||
import 'package:neon/src/blocs/accounts.dart'; |
||||
import 'package:neon/src/models/account.dart'; |
||||
import 'package:neon/src/widgets/group_avatar.dart'; |
||||
import 'package:neon/src/widgets/user_avatar.dart'; |
||||
import 'package:nextcloud/core.dart' as core; |
||||
import 'package:provider/provider.dart'; |
||||
|
||||
class NeonAutocomplete extends StatelessWidget { |
||||
const NeonAutocomplete({ |
||||
required this.account, |
||||
required this.itemType, |
||||
required this.itemId, |
||||
required this.shareTypes, |
||||
required this.onSelected, |
||||
this.sorter, |
||||
this.limit = 10, |
||||
this.validator, |
||||
this.decoration, |
||||
this.onFieldSubmitted, |
||||
super.key, |
||||
}); |
||||
|
||||
final Account account; |
||||
|
||||
final String itemType; |
||||
final String itemId; |
||||
final List<int> shareTypes; |
||||
final void Function(core.AutocompleteResult entry) onSelected; |
||||
final String? sorter; |
||||
final int limit; |
||||
final FormFieldValidator<String>? validator; |
||||
final InputDecoration? decoration; |
||||
final ValueChanged<String>? onFieldSubmitted; |
||||
|
||||
@override |
||||
Widget build(final BuildContext context) => Autocomplete<core.AutocompleteResult>( |
||||
fieldViewBuilder: ( |
||||
final context, |
||||
final controller, |
||||
final focusNode, |
||||
final onFieldSubmitted, |
||||
) => |
||||
TextFormField( |
||||
controller: controller, |
||||
focusNode: focusNode, |
||||
validator: validator, |
||||
decoration: decoration, |
||||
onFieldSubmitted: (final value) { |
||||
onFieldSubmitted(); |
||||
this.onFieldSubmitted?.call(value); |
||||
}, |
||||
), |
||||
optionsBuilder: (final text) async { |
||||
final result = await account.client.core.autoComplete.$get( |
||||
search: text.text, |
||||
itemType: itemType, |
||||
itemId: itemId, |
||||
shareTypes: shareTypes, |
||||
); |
||||
return result.body.ocs.data; |
||||
}, |
||||
displayStringForOption: (final option) => option.id, |
||||
optionsViewBuilder: (final context, final onSelected, final options) => Align( |
||||
alignment: Alignment.topLeft, |
||||
child: Material( |
||||
elevation: 4, |
||||
child: ConstrainedBox( |
||||
constraints: const BoxConstraints(maxHeight: 200), |
||||
child: ListView.builder( |
||||
padding: EdgeInsets.zero, |
||||
shrinkWrap: true, |
||||
itemCount: options.length, |
||||
itemBuilder: (final context, final index) { |
||||
final option = options.elementAt(index); |
||||
Widget? icon; |
||||
switch (option.source) { |
||||
case 'users': |
||||
icon = NeonUserAvatar( |
||||
username: option.id, |
||||
account: Provider.of<AccountsBloc>(context, listen: false).activeAccount.value!, |
||||
); |
||||
case 'groups': |
||||
icon = const NeonGroupAvatar(); |
||||
} |
||||
return ListTile( |
||||
title: Text(option.label), |
||||
subtitle: Text(option.id), |
||||
leading: icon, |
||||
onTap: () { |
||||
onSelected(option); |
||||
}, |
||||
); |
||||
}, |
||||
), |
||||
), |
||||
), |
||||
), |
||||
onSelected: onSelected, |
||||
); |
||||
} |
@ -0,0 +1,26 @@
|
||||
import 'package:flutter/material.dart'; |
||||
import 'package:neon/src/theme/sizes.dart'; |
||||
|
||||
class NeonGroupAvatar extends StatelessWidget { |
||||
const NeonGroupAvatar({ |
||||
this.icon = Icons.group, |
||||
this.backgroundColor, |
||||
this.foregroundColor, |
||||
super.key, |
||||
}); |
||||
|
||||
final IconData icon; |
||||
final Color? backgroundColor; |
||||
final Color? foregroundColor; |
||||
|
||||
@override |
||||
Widget build(final BuildContext context) => CircleAvatar( |
||||
radius: smallIconSize, |
||||
backgroundColor: backgroundColor, |
||||
child: Icon( |
||||
icon, |
||||
color: foregroundColor, |
||||
size: smallIconSize, |
||||
), |
||||
); |
||||
} |
Loading…
Reference in new issue