/lib/pages/search/search_view.dart
https://gitlab.com/DerMolly/fluffychat · Dart · 299 lines · 291 code · 6 blank · 2 comment · 13 complexity · 0f5187a60ed029a76749ce482ccc5031 MD5 · raw file
- import 'package:flutter/material.dart';
- import 'package:flutter_gen/gen_l10n/l10n.dart';
- import 'package:future_loading_dialog/future_loading_dialog.dart';
- import 'package:matrix/matrix.dart';
- import 'package:vrouter/vrouter.dart';
- import 'package:fluffychat/pages/chat_list/chat_list_item.dart';
- import 'package:fluffychat/widgets/avatar.dart';
- import 'package:fluffychat/widgets/contacts_list.dart';
- import 'package:fluffychat/widgets/default_app_bar_search_field.dart';
- import 'package:fluffychat/widgets/matrix.dart';
- import '../../utils/localized_exception_extension.dart';
- import '../../utils/platform_infos.dart';
- import 'search.dart';
- class SearchView extends StatelessWidget {
- final SearchController controller;
- const SearchView(this.controller, {Key? key}) : super(key: key);
- @override
- Widget build(BuildContext context) {
- final server = controller.genericSearchTerm?.isValidMatrixId ?? false
- ? controller.genericSearchTerm!.domain
- : controller.server;
- if (controller.lastServer != server) {
- controller.lastServer = server;
- controller.publicRoomsResponse = null;
- }
- controller.publicRoomsResponse ??= Matrix.of(context)
- .client
- .queryPublicRooms(
- server: server,
- filter: PublicRoomQueryFilter(
- genericSearchTerm: controller.genericSearchTerm,
- ),
- )
- .catchError((error) {
- if (!(controller.genericSearchTerm?.isValidMatrixId ?? false)) {
- throw error;
- }
- return QueryPublicRoomsResponse.fromJson({
- 'chunk': [],
- });
- }).then((QueryPublicRoomsResponse res) {
- final genericSearchTerm = controller.genericSearchTerm;
- if (genericSearchTerm != null &&
- !res.chunk.any((room) =>
- (room.aliases?.contains(controller.genericSearchTerm) ?? false) ||
- room.canonicalAlias == controller.genericSearchTerm)) {
- // we have to tack on the original alias
- res.chunk.add(
- PublicRoomsChunk(
- aliases: [genericSearchTerm],
- name: genericSearchTerm,
- numJoinedMembers: 0,
- roomId: '!unknown',
- worldReadable: true,
- guestCanJoin: true,
- ),
- );
- }
- return res;
- });
- final rooms = List<Room>.from(Matrix.of(context).client.rooms);
- rooms.removeWhere(
- (room) =>
- room.lastEvent == null ||
- !room.displayname
- .toLowerCase()
- .contains(controller.controller.text.toLowerCase()),
- );
- const tabCount = 3;
- return DefaultTabController(
- length: tabCount,
- initialIndex: controller.controller.text.startsWith('#') ? 0 : 1,
- child: Scaffold(
- appBar: AppBar(
- leading: const BackButton(),
- titleSpacing: 0,
- title: DefaultAppBarSearchField(
- autofocus: true,
- hintText: L10n.of(context)!.search,
- searchController: controller.controller,
- suffix: const Icon(Icons.search_outlined),
- onChanged: controller.search,
- ),
- bottom: TabBar(
- indicatorColor: Theme.of(context).colorScheme.secondary,
- labelColor: Theme.of(context).colorScheme.secondary,
- unselectedLabelColor: Theme.of(context).textTheme.bodyText1!.color,
- labelStyle: const TextStyle(fontSize: 16),
- labelPadding: const EdgeInsets.symmetric(
- horizontal: 8,
- vertical: 0,
- ),
- tabs: [
- Tab(child: Text(L10n.of(context)!.discover, maxLines: 1)),
- Tab(child: Text(L10n.of(context)!.chats, maxLines: 1)),
- Tab(child: Text(L10n.of(context)!.people, maxLines: 1)),
- ],
- ),
- ),
- body: TabBarView(
- children: [
- ListView(
- keyboardDismissBehavior: PlatformInfos.isIOS
- ? ScrollViewKeyboardDismissBehavior.onDrag
- : ScrollViewKeyboardDismissBehavior.manual,
- children: [
- const SizedBox(height: 12),
- ListTile(
- leading: CircleAvatar(
- foregroundColor: Theme.of(context).colorScheme.secondary,
- backgroundColor: Theme.of(context).secondaryHeaderColor,
- child: const Icon(Icons.edit_outlined),
- ),
- title: Text(L10n.of(context)!.changeTheServer),
- onTap: controller.setServer,
- ),
- FutureBuilder<QueryPublicRoomsResponse>(
- future: controller.publicRoomsResponse,
- builder: (BuildContext context,
- AsyncSnapshot<QueryPublicRoomsResponse> snapshot) {
- if (snapshot.hasError) {
- return Column(
- mainAxisSize: MainAxisSize.min,
- children: [
- const SizedBox(height: 32),
- const Icon(
- Icons.error_outlined,
- size: 80,
- color: Colors.grey,
- ),
- Center(
- child: Text(
- snapshot.error!.toLocalizedString(context),
- textAlign: TextAlign.center,
- style: const TextStyle(
- color: Colors.grey,
- fontSize: 16,
- ),
- ),
- ),
- ],
- );
- }
- if (snapshot.connectionState != ConnectionState.done) {
- return const Center(
- child: CircularProgressIndicator.adaptive(
- strokeWidth: 2));
- }
- final publicRoomsResponse = snapshot.data!;
- if (publicRoomsResponse.chunk.isEmpty) {
- return Column(
- mainAxisSize: MainAxisSize.min,
- children: [
- const SizedBox(height: 32),
- const Icon(
- Icons.search_outlined,
- size: 80,
- color: Colors.grey,
- ),
- Center(
- child: Text(
- L10n.of(context)!.noPublicRoomsFound,
- textAlign: TextAlign.center,
- style: const TextStyle(
- color: Colors.grey,
- fontSize: 16,
- ),
- ),
- ),
- ],
- );
- }
- return GridView.builder(
- shrinkWrap: true,
- padding: const EdgeInsets.all(12),
- physics: const NeverScrollableScrollPhysics(),
- gridDelegate:
- const SliverGridDelegateWithFixedCrossAxisCount(
- crossAxisCount: 2,
- childAspectRatio: 1,
- crossAxisSpacing: 16,
- mainAxisSpacing: 16,
- ),
- itemCount: publicRoomsResponse.chunk.length,
- itemBuilder: (BuildContext context, int i) => Material(
- elevation: 2,
- borderRadius: BorderRadius.circular(16),
- child: InkWell(
- onTap: () => controller.joinGroupAction(
- publicRoomsResponse.chunk[i],
- ),
- borderRadius: BorderRadius.circular(16),
- child: Padding(
- padding: const EdgeInsets.all(8.0),
- child: Column(
- mainAxisSize: MainAxisSize.min,
- children: [
- Avatar(
- mxContent:
- publicRoomsResponse.chunk[i].avatarUrl,
- name: publicRoomsResponse.chunk[i].name,
- ),
- Text(
- publicRoomsResponse.chunk[i].name!,
- style: const TextStyle(
- fontSize: 16,
- fontWeight: FontWeight.bold,
- ),
- maxLines: 1,
- textAlign: TextAlign.center,
- ),
- Text(
- L10n.of(context)!.countParticipants(
- publicRoomsResponse
- .chunk[i].numJoinedMembers),
- style: const TextStyle(fontSize: 10.5),
- maxLines: 1,
- textAlign: TextAlign.center,
- ),
- Text(
- publicRoomsResponse.chunk[i].topic ??
- L10n.of(context)!.noDescription,
- maxLines: 4,
- textAlign: TextAlign.center,
- ),
- ],
- ),
- ),
- ),
- ),
- );
- }),
- ],
- ),
- ListView.builder(
- keyboardDismissBehavior: PlatformInfos.isIOS
- ? ScrollViewKeyboardDismissBehavior.onDrag
- : ScrollViewKeyboardDismissBehavior.manual,
- itemCount: rooms.length,
- itemBuilder: (_, i) => ChatListItem(rooms[i]),
- ),
- controller.foundProfiles.isNotEmpty
- ? ListView.builder(
- keyboardDismissBehavior: PlatformInfos.isIOS
- ? ScrollViewKeyboardDismissBehavior.onDrag
- : ScrollViewKeyboardDismissBehavior.manual,
- itemCount: controller.foundProfiles.length,
- itemBuilder: (BuildContext context, int i) {
- final foundProfile = controller.foundProfiles[i];
- return ListTile(
- onTap: () async {
- final roomID = await showFutureLoadingDialog(
- context: context,
- future: () async {
- final client = Matrix.of(context).client;
- final roomId = await client
- .startDirectChat(foundProfile.userId);
- return roomId;
- },
- );
- if (roomID.error == null) {
- VRouter.of(context)
- .toSegments(['rooms', roomID.result!]);
- }
- },
- leading: Avatar(
- mxContent: foundProfile.avatarUrl,
- name: foundProfile.displayName ?? foundProfile.userId,
- //size: 24,
- ),
- title: Text(
- foundProfile.displayName ??
- foundProfile.userId.localpart!,
- style: const TextStyle(),
- maxLines: 1,
- ),
- subtitle: Text(
- foundProfile.userId,
- maxLines: 1,
- style: const TextStyle(
- fontSize: 12,
- ),
- ),
- );
- },
- )
- : ContactsList(searchController: controller.controller),
- ],
- ),
- ),
- );
- }
- }