add search & block
This commit is contained in:
parent
03b6c1b129
commit
0adc26a5fb
|
@ -1,5 +1,7 @@
|
||||||
PODS:
|
PODS:
|
||||||
- Flutter (1.0.0)
|
- Flutter (1.0.0)
|
||||||
|
- flutter_keyboard_visibility (0.0.1):
|
||||||
|
- Flutter
|
||||||
- image_picker (0.0.1):
|
- image_picker (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- package_info_plus (0.4.5):
|
- package_info_plus (0.4.5):
|
||||||
|
@ -15,6 +17,7 @@ PODS:
|
||||||
|
|
||||||
DEPENDENCIES:
|
DEPENDENCIES:
|
||||||
- Flutter (from `Flutter`)
|
- Flutter (from `Flutter`)
|
||||||
|
- flutter_keyboard_visibility (from `.symlinks/plugins/flutter_keyboard_visibility/ios`)
|
||||||
- image_picker (from `.symlinks/plugins/image_picker/ios`)
|
- image_picker (from `.symlinks/plugins/image_picker/ios`)
|
||||||
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
|
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
|
||||||
- path_provider (from `.symlinks/plugins/path_provider/ios`)
|
- path_provider (from `.symlinks/plugins/path_provider/ios`)
|
||||||
|
@ -25,6 +28,8 @@ DEPENDENCIES:
|
||||||
EXTERNAL SOURCES:
|
EXTERNAL SOURCES:
|
||||||
Flutter:
|
Flutter:
|
||||||
:path: Flutter
|
:path: Flutter
|
||||||
|
flutter_keyboard_visibility:
|
||||||
|
:path: ".symlinks/plugins/flutter_keyboard_visibility/ios"
|
||||||
image_picker:
|
image_picker:
|
||||||
:path: ".symlinks/plugins/image_picker/ios"
|
:path: ".symlinks/plugins/image_picker/ios"
|
||||||
package_info_plus:
|
package_info_plus:
|
||||||
|
@ -40,12 +45,13 @@ EXTERNAL SOURCES:
|
||||||
|
|
||||||
SPEC CHECKSUMS:
|
SPEC CHECKSUMS:
|
||||||
Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a
|
Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a
|
||||||
image_picker: e06f7a68f000bd36f552c1847e33cda96ed31f1f
|
flutter_keyboard_visibility: 0339d06371254c3eb25eeb90ba8d17dca8f9c069
|
||||||
|
image_picker: 9aa50e1d8cdacdbed739e925b7eea16d014367e6
|
||||||
package_info_plus: 6c92f08e1f853dc01228d6f553146438dafcd14e
|
package_info_plus: 6c92f08e1f853dc01228d6f553146438dafcd14e
|
||||||
path_provider: abfe2b5c733d04e238b0d8691db0cfd63a27a93c
|
path_provider: d1e9807085df1f9cc9318206cd649dc0b76be3de
|
||||||
share_plus: 056a1e8ac890df3e33cb503afffaf1e9b4fbae68
|
share_plus: 056a1e8ac890df3e33cb503afffaf1e9b4fbae68
|
||||||
shared_preferences: af6bfa751691cdc24be3045c43ec037377ada40d
|
shared_preferences: 5033afbb22d372e15aff8ff766df9021b845f273
|
||||||
url_launcher: 6fef411d543ceb26efce54b05a0a40bfd74cbbef
|
url_launcher: b6e016d912f04be9f5bf6e8e82dc599b7ba59649
|
||||||
|
|
||||||
PODFILE CHECKSUM: aafe91acc616949ddb318b77800a7f51bffa2a4c
|
PODFILE CHECKSUM: aafe91acc616949ddb318b77800a7f51bffa2a4c
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,134 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_typeahead/flutter_typeahead.dart';
|
||||||
|
import 'package:lemmy_api_client/v3.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
import '../../../util/extensions/api.dart';
|
||||||
|
import '../../../widgets/avatar.dart';
|
||||||
|
import 'blocks_store.dart';
|
||||||
|
|
||||||
|
class BlockPersonDialog extends StatelessWidget {
|
||||||
|
const BlockPersonDialog();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return AlertDialog(
|
||||||
|
title: Row(
|
||||||
|
children: const [
|
||||||
|
Expanded(child: Text('Block User')),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
content: TypeAheadField<PersonViewSafe>(
|
||||||
|
suggestionsCallback: (pattern) async {
|
||||||
|
if (pattern.trim().isEmpty) return const Iterable.empty();
|
||||||
|
return LemmyApiV3(context.read<BlocksStore>().instanceHost)
|
||||||
|
.run(Search(
|
||||||
|
q: pattern,
|
||||||
|
auth: context.read<BlocksStore>().token.raw,
|
||||||
|
type: SearchType.users,
|
||||||
|
limit: 10,
|
||||||
|
))
|
||||||
|
.then((value) => value.users);
|
||||||
|
},
|
||||||
|
itemBuilder: (context, user) {
|
||||||
|
return ListTile(
|
||||||
|
leading: Avatar(
|
||||||
|
url: user.person.avatar,
|
||||||
|
radius: 20,
|
||||||
|
),
|
||||||
|
title: Text(user.person.originPreferredName),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
onSuggestionSelected: (suggestion) =>
|
||||||
|
Navigator.of(context).pop(suggestion),
|
||||||
|
loadingBuilder: (context) => Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: const [
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.all(16),
|
||||||
|
child: CircularProgressIndicator.adaptive(),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
keepSuggestionsOnLoading: false,
|
||||||
|
noItemsFoundBuilder: (context) => const SizedBox(),
|
||||||
|
hideOnEmpty: true,
|
||||||
|
textFieldConfiguration: const TextFieldConfiguration(autofocus: true),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Future<PersonViewSafe?> show(BuildContext context) async {
|
||||||
|
final store = context.read<BlocksStore>();
|
||||||
|
return showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => Provider.value(
|
||||||
|
value: store,
|
||||||
|
child: const BlockPersonDialog(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class BlockCommunityDialog extends StatelessWidget {
|
||||||
|
const BlockCommunityDialog();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return AlertDialog(
|
||||||
|
title: Row(
|
||||||
|
children: const [
|
||||||
|
Expanded(child: Text('Block Community')),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
content: TypeAheadField<CommunityView>(
|
||||||
|
suggestionsCallback: (pattern) async {
|
||||||
|
if (pattern.trim().isEmpty) return const Iterable.empty();
|
||||||
|
return LemmyApiV3(context.read<BlocksStore>().instanceHost)
|
||||||
|
.run(Search(
|
||||||
|
q: pattern,
|
||||||
|
auth: context.read<BlocksStore>().token.raw,
|
||||||
|
type: SearchType.communities,
|
||||||
|
limit: 10,
|
||||||
|
))
|
||||||
|
.then((value) => value.communities);
|
||||||
|
},
|
||||||
|
itemBuilder: (context, community) {
|
||||||
|
return ListTile(
|
||||||
|
leading: Avatar(
|
||||||
|
url: community.community.icon,
|
||||||
|
radius: 20,
|
||||||
|
),
|
||||||
|
title: Text(community.community.originPreferredName),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
onSuggestionSelected: (suggestion) =>
|
||||||
|
Navigator.of(context).pop(suggestion),
|
||||||
|
loadingBuilder: (context) => Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: const [
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.all(16),
|
||||||
|
child: CircularProgressIndicator.adaptive(),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
keepSuggestionsOnLoading: false,
|
||||||
|
noItemsFoundBuilder: (context) => const SizedBox(),
|
||||||
|
hideOnEmpty: true,
|
||||||
|
textFieldConfiguration: const TextFieldConfiguration(autofocus: true),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Future<CommunityView?> show(BuildContext context) async {
|
||||||
|
final store = context.read<BlocksStore>();
|
||||||
|
return showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => Provider.value(
|
||||||
|
value: store,
|
||||||
|
child: const BlockCommunityDialog(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,11 +1,14 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
|
import 'package:nested/nested.dart';
|
||||||
|
|
||||||
|
import '../../../hooks/logged_in_action.dart';
|
||||||
import '../../../hooks/stores.dart';
|
import '../../../hooks/stores.dart';
|
||||||
import '../../../l10n/l10n_from_string.dart';
|
import '../../../l10n/l10n_from_string.dart';
|
||||||
import '../../../stores/accounts_store.dart';
|
import '../../../stores/accounts_store.dart';
|
||||||
import '../../../util/async_store_listener.dart';
|
import '../../../util/async_store_listener.dart';
|
||||||
import '../../../util/observer_consumers.dart';
|
import '../../../util/observer_consumers.dart';
|
||||||
|
import 'block_dialog.dart';
|
||||||
import 'block_tile.dart';
|
import 'block_tile.dart';
|
||||||
import 'blocks_store.dart';
|
import 'blocks_store.dart';
|
||||||
|
|
||||||
|
@ -70,13 +73,26 @@ class _UserBlocksWrapper extends StatelessWidget {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _UserBlocks extends StatelessWidget {
|
class _UserBlocks extends HookWidget {
|
||||||
const _UserBlocks();
|
const _UserBlocks();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return AsyncStoreListener(
|
final loggedInAction =
|
||||||
asyncStore: context.read<BlocksStore>().blocksState,
|
useLoggedInAction(context.read<BlocksStore>().instanceHost);
|
||||||
|
|
||||||
|
return Nested(
|
||||||
|
children: [
|
||||||
|
AsyncStoreListener(
|
||||||
|
asyncStore: context.read<BlocksStore>().blocksState,
|
||||||
|
),
|
||||||
|
AsyncStoreListener(
|
||||||
|
asyncStore: context.read<BlocksStore>().communityBlockingState,
|
||||||
|
),
|
||||||
|
AsyncStoreListener(
|
||||||
|
asyncStore: context.read<BlocksStore>().userBlockingState,
|
||||||
|
),
|
||||||
|
],
|
||||||
child: ObserverBuilder<BlocksStore>(
|
child: ObserverBuilder<BlocksStore>(
|
||||||
builder: (context, store) {
|
builder: (context, store) {
|
||||||
return RefreshIndicator(
|
return RefreshIndicator(
|
||||||
|
@ -114,14 +130,27 @@ class _UserBlocks extends StatelessWidget {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
// TODO: add user search & block
|
// TODO: add user search & block
|
||||||
// ListTile(
|
ListTile(
|
||||||
// leading: const Padding(
|
leading: Padding(
|
||||||
// padding: EdgeInsets.only(left: 16, right: 10),
|
padding: const EdgeInsets.only(left: 16, right: 10),
|
||||||
// child: Icon(Icons.add),
|
child: store.userBlockingState.isLoading
|
||||||
// ),
|
? const CircularProgressIndicator.adaptive()
|
||||||
// onTap: () {},
|
: const Icon(Icons.add),
|
||||||
// title: const Text('Block User'),
|
),
|
||||||
// ),
|
onTap: store.userBlockingState.isLoading
|
||||||
|
? null
|
||||||
|
: loggedInAction(
|
||||||
|
(token) async {
|
||||||
|
final person =
|
||||||
|
await BlockPersonDialog.show(context);
|
||||||
|
|
||||||
|
if (person != null) {
|
||||||
|
await store.blockUser(token, person.person.id);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
title: const Text('Block User'),
|
||||||
|
),
|
||||||
const Divider(),
|
const Divider(),
|
||||||
for (final community in store.blockedCommunities!)
|
for (final community in store.blockedCommunities!)
|
||||||
Provider(
|
Provider(
|
||||||
|
@ -136,14 +165,30 @@ class _UserBlocks extends StatelessWidget {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
// TODO: add community search & block
|
// TODO: add community search & block
|
||||||
// const ListTile(
|
ListTile(
|
||||||
// leading: Padding(
|
leading: Padding(
|
||||||
// padding: EdgeInsets.only(left: 16, right: 10),
|
padding: const EdgeInsets.only(left: 16, right: 10),
|
||||||
// child: Icon(Icons.add),
|
child: store.communityBlockingState.isLoading
|
||||||
// ),
|
? const CircularProgressIndicator.adaptive()
|
||||||
// onTap: () {},
|
: const Icon(Icons.add),
|
||||||
// title: Text('Block Community'),
|
),
|
||||||
// ),
|
onTap: store.communityBlockingState.isLoading
|
||||||
|
? null
|
||||||
|
: loggedInAction(
|
||||||
|
(token) async {
|
||||||
|
final community =
|
||||||
|
await BlockCommunityDialog.show(context);
|
||||||
|
|
||||||
|
if (community != null) {
|
||||||
|
await store.blockCommunity(
|
||||||
|
token,
|
||||||
|
community.community.id,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
title: const Text('Block Community'),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
|
@ -16,13 +16,16 @@ abstract class _BlocksStore with Store {
|
||||||
_BlocksStore({required this.instanceHost, required this.token});
|
_BlocksStore({required this.instanceHost, required this.token});
|
||||||
|
|
||||||
@observable
|
@observable
|
||||||
List<UserBlockStore>? _blockedUsers;
|
ObservableList<UserBlockStore>? _blockedUsers;
|
||||||
|
|
||||||
@observable
|
@observable
|
||||||
List<CommunityBlockStore>? _blockedCommunities;
|
ObservableList<CommunityBlockStore>? _blockedCommunities;
|
||||||
|
|
||||||
final blocksState = AsyncStore<FullSiteView>();
|
final blocksState = AsyncStore<FullSiteView>();
|
||||||
|
|
||||||
|
final userBlockingState = AsyncStore<BlockedPerson>();
|
||||||
|
final communityBlockingState = AsyncStore<BlockedCommunity>();
|
||||||
|
|
||||||
@computed
|
@computed
|
||||||
Iterable<UserBlockStore>? get blockedUsers =>
|
Iterable<UserBlockStore>? get blockedUsers =>
|
||||||
_blockedUsers?.where((u) => u.blocked);
|
_blockedUsers?.where((u) => u.blocked);
|
||||||
|
@ -34,6 +37,60 @@ abstract class _BlocksStore with Store {
|
||||||
@computed
|
@computed
|
||||||
bool get isUsable => blockedUsers != null && blockedCommunities != null;
|
bool get isUsable => blockedUsers != null && blockedCommunities != null;
|
||||||
|
|
||||||
|
@action
|
||||||
|
Future<void> blockUser(Jwt token, int id) async {
|
||||||
|
if (_blockedUsers == null) {
|
||||||
|
throw StateError("_blockedUsers can't be null at this moment");
|
||||||
|
}
|
||||||
|
final res = await userBlockingState.runLemmy(
|
||||||
|
instanceHost,
|
||||||
|
BlockPerson(
|
||||||
|
personId: id,
|
||||||
|
block: true,
|
||||||
|
auth: token.raw,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (res != null &&
|
||||||
|
_blockedUsers!.indexWhere((element) => element.person.id == id) == -1) {
|
||||||
|
_blockedUsers!.add(
|
||||||
|
UserBlockStore(
|
||||||
|
instanceHost: instanceHost,
|
||||||
|
person: res.personView.person,
|
||||||
|
token: token,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
Future<void> blockCommunity(Jwt token, int id) async {
|
||||||
|
if (_blockedCommunities == null) {
|
||||||
|
throw StateError("_blockedCommunities can't be null at this moment");
|
||||||
|
}
|
||||||
|
final res = await communityBlockingState.runLemmy(
|
||||||
|
instanceHost,
|
||||||
|
BlockCommunity(
|
||||||
|
communityId: id,
|
||||||
|
block: true,
|
||||||
|
auth: token.raw,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (res != null &&
|
||||||
|
_blockedCommunities!
|
||||||
|
.indexWhere((element) => element.community.id == id) ==
|
||||||
|
-1) {
|
||||||
|
_blockedCommunities!.add(
|
||||||
|
CommunityBlockStore(
|
||||||
|
instanceHost: instanceHost,
|
||||||
|
community: res.communityView.community,
|
||||||
|
token: token,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@action
|
@action
|
||||||
Future<void> refresh() async {
|
Future<void> refresh() async {
|
||||||
final result =
|
final result =
|
||||||
|
@ -43,11 +100,13 @@ abstract class _BlocksStore with Store {
|
||||||
_blockedUsers = result.myUser!.personBlocks
|
_blockedUsers = result.myUser!.personBlocks
|
||||||
.map((e) => UserBlockStore(
|
.map((e) => UserBlockStore(
|
||||||
instanceHost: instanceHost, token: token, person: e.target))
|
instanceHost: instanceHost, token: token, person: e.target))
|
||||||
.toList();
|
.toList()
|
||||||
|
.asObservable();
|
||||||
_blockedCommunities = result.myUser!.communityBlocks
|
_blockedCommunities = result.myUser!.communityBlocks
|
||||||
.map((e) => CommunityBlockStore(
|
.map((e) => CommunityBlockStore(
|
||||||
instanceHost: instanceHost, token: token, community: e.community))
|
instanceHost: instanceHost, token: token, community: e.community))
|
||||||
.toList();
|
.toList()
|
||||||
|
.asObservable();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,13 +35,13 @@ mixin _$BlocksStore on _BlocksStore, Store {
|
||||||
final _$_blockedUsersAtom = Atom(name: '_BlocksStore._blockedUsers');
|
final _$_blockedUsersAtom = Atom(name: '_BlocksStore._blockedUsers');
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<UserBlockStore>? get _blockedUsers {
|
ObservableList<UserBlockStore>? get _blockedUsers {
|
||||||
_$_blockedUsersAtom.reportRead();
|
_$_blockedUsersAtom.reportRead();
|
||||||
return super._blockedUsers;
|
return super._blockedUsers;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
set _blockedUsers(List<UserBlockStore>? value) {
|
set _blockedUsers(ObservableList<UserBlockStore>? value) {
|
||||||
_$_blockedUsersAtom.reportWrite(value, super._blockedUsers, () {
|
_$_blockedUsersAtom.reportWrite(value, super._blockedUsers, () {
|
||||||
super._blockedUsers = value;
|
super._blockedUsers = value;
|
||||||
});
|
});
|
||||||
|
@ -51,18 +51,34 @@ mixin _$BlocksStore on _BlocksStore, Store {
|
||||||
Atom(name: '_BlocksStore._blockedCommunities');
|
Atom(name: '_BlocksStore._blockedCommunities');
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<CommunityBlockStore>? get _blockedCommunities {
|
ObservableList<CommunityBlockStore>? get _blockedCommunities {
|
||||||
_$_blockedCommunitiesAtom.reportRead();
|
_$_blockedCommunitiesAtom.reportRead();
|
||||||
return super._blockedCommunities;
|
return super._blockedCommunities;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
set _blockedCommunities(List<CommunityBlockStore>? value) {
|
set _blockedCommunities(ObservableList<CommunityBlockStore>? value) {
|
||||||
_$_blockedCommunitiesAtom.reportWrite(value, super._blockedCommunities, () {
|
_$_blockedCommunitiesAtom.reportWrite(value, super._blockedCommunities, () {
|
||||||
super._blockedCommunities = value;
|
super._blockedCommunities = value;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final _$blockUserAsyncAction = AsyncAction('_BlocksStore.blockUser');
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> blockUser(Jwt token, int id) {
|
||||||
|
return _$blockUserAsyncAction.run(() => super.blockUser(token, id));
|
||||||
|
}
|
||||||
|
|
||||||
|
final _$blockCommunityAsyncAction =
|
||||||
|
AsyncAction('_BlocksStore.blockCommunity');
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> blockCommunity(Jwt token, int id) {
|
||||||
|
return _$blockCommunityAsyncAction
|
||||||
|
.run(() => super.blockCommunity(token, id));
|
||||||
|
}
|
||||||
|
|
||||||
final _$refreshAsyncAction = AsyncAction('_BlocksStore.refresh');
|
final _$refreshAsyncAction = AsyncAction('_BlocksStore.refresh');
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
28
pubspec.lock
28
pubspec.lock
|
@ -237,6 +237,27 @@ packages:
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.18.0"
|
version: "0.18.0"
|
||||||
|
flutter_keyboard_visibility:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: flutter_keyboard_visibility
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "5.1.0"
|
||||||
|
flutter_keyboard_visibility_platform_interface:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: flutter_keyboard_visibility_platform_interface
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.0"
|
||||||
|
flutter_keyboard_visibility_web:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: flutter_keyboard_visibility_web
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.0"
|
||||||
flutter_launcher_icons:
|
flutter_launcher_icons:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
|
@ -282,6 +303,13 @@ packages:
|
||||||
description: flutter
|
description: flutter
|
||||||
source: sdk
|
source: sdk
|
||||||
version: "0.0.0"
|
version: "0.0.0"
|
||||||
|
flutter_typeahead:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: flutter_typeahead
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "3.2.1"
|
||||||
flutter_web_plugins:
|
flutter_web_plugins:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description: flutter
|
description: flutter
|
||||||
|
|
|
@ -62,6 +62,7 @@ dependencies:
|
||||||
# The following adds the Cupertino Icons font to your application.
|
# The following adds the Cupertino Icons font to your application.
|
||||||
# Use with the CupertinoIcons class for iOS style icons.
|
# Use with the CupertinoIcons class for iOS style icons.
|
||||||
cupertino_icons: ^1.0.2
|
cupertino_icons: ^1.0.2
|
||||||
|
flutter_typeahead: ^3.2.1
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
|
Loading…
Reference in New Issue