From 01d797e53f9913d6559e50b8b03dafa4854d4ef2 Mon Sep 17 00:00:00 2001 From: ggurdin <46800240+ggurdin@users.noreply.github.com> Date: Tue, 3 Jun 2025 14:34:13 -0400 Subject: [PATCH] feat: find your people page --- assets/l10n/intl_en.arb | 3 +- lib/config/routes.dart | 74 ++-- lib/pages/chat_list/chat_list_view.dart | 3 + .../learning_progress_indicator_button.dart | 15 +- .../learning_progress_indicators.dart | 4 +- .../find_your_people/find_your_people.dart | 102 ++++++ .../find_your_people_constants.dart | 3 + .../find_your_people_side_view.dart | 48 +++ .../find_your_people_view.dart | 242 ++++++++++++++ .../find_your_people/public_space_tile.dart | 104 ++++++ lib/pangea/user/constants/age_limits.dart | 4 - .../models/user_profile_search_model.dart | 27 -- lib/pangea/user/pages/find_partner.dart | 179 ---------- lib/pangea/user/pages/find_partner_view.dart | 315 ------------------ lib/pangea/user/repo/user_repo.dart | 48 --- lib/pangea/user/widgets/list_placeholder.dart | 72 ---- .../writing_assistance_input_row.dart | 113 ------- lib/widgets/layouts/two_column_layout.dart | 11 +- lib/widgets/navigation_rail.dart | 72 ++-- 19 files changed, 600 insertions(+), 839 deletions(-) create mode 100644 lib/pangea/find_your_people/find_your_people.dart create mode 100644 lib/pangea/find_your_people/find_your_people_constants.dart create mode 100644 lib/pangea/find_your_people/find_your_people_side_view.dart create mode 100644 lib/pangea/find_your_people/find_your_people_view.dart create mode 100644 lib/pangea/find_your_people/public_space_tile.dart delete mode 100644 lib/pangea/user/constants/age_limits.dart delete mode 100644 lib/pangea/user/models/user_profile_search_model.dart delete mode 100644 lib/pangea/user/pages/find_partner.dart delete mode 100644 lib/pangea/user/pages/find_partner_view.dart delete mode 100644 lib/pangea/user/repo/user_repo.dart delete mode 100644 lib/pangea/user/widgets/list_placeholder.dart delete mode 100644 lib/pangea/writing_assistance/writing_assistance_input_row.dart diff --git a/assets/l10n/intl_en.arb b/assets/l10n/intl_en.arb index 7a55d66c9..899a6beb5 100644 --- a/assets/l10n/intl_en.arb +++ b/assets/l10n/intl_en.arb @@ -4975,5 +4975,6 @@ "canBeFoundViaInvitation": "\u2022 invitation", "canBeFoundViaCodeOrLink": "\u2022 code or link", "canBeFoundViaKnock": "\u2022 request to join and admin approval", - "anyoneCanJoin": "Anyone can join! However, admin can kick and ban whoever misbehaves. Those who are banned may not return!" + "anyoneCanJoin": "Anyone can join! However, admin can kick and ban whoever misbehaves. Those who are banned may not return!", + "createYourSpace": "Create your space" } diff --git a/lib/config/routes.dart b/lib/config/routes.dart index ec16f5c64..15937973e 100644 --- a/lib/config/routes.dart +++ b/lib/config/routes.dart @@ -32,6 +32,8 @@ import 'package:fluffychat/pages/settings_style/settings_style.dart'; import 'package:fluffychat/pangea/activity_generator/activity_generator.dart'; import 'package:fluffychat/pangea/activity_planner/activity_planner_page.dart'; import 'package:fluffychat/pangea/activity_suggestions/suggestions_page.dart'; +import 'package:fluffychat/pangea/find_your_people/find_your_people.dart'; +import 'package:fluffychat/pangea/find_your_people/find_your_people_side_view.dart'; import 'package:fluffychat/pangea/guard/p_vguard.dart'; import 'package:fluffychat/pangea/learning_settings/pages/settings_learning.dart'; import 'package:fluffychat/pangea/login/pages/login_or_signup_view.dart'; @@ -42,7 +44,6 @@ import 'package:fluffychat/pangea/spaces/constants/space_constants.dart'; import 'package:fluffychat/pangea/spaces/utils/join_with_alias.dart'; import 'package:fluffychat/pangea/spaces/utils/join_with_link.dart'; import 'package:fluffychat/pangea/subscription/pages/settings_subscription.dart'; -import 'package:fluffychat/pangea/user/pages/find_partner.dart'; import 'package:fluffychat/widgets/config_viewer.dart'; import 'package:fluffychat/widgets/layouts/empty_page.dart'; import 'package:fluffychat/widgets/layouts/two_column_layout.dart'; @@ -153,17 +154,11 @@ abstract class AppRoutes { ), GoRoute( path: '/join_with_alias', - pageBuilder: (context, state) => Matrix.of(context).client.isLogged() - ? chatListShellRouteBuilder( - context, - state, - JoinWithAlias(alias: state.uri.queryParameters['alias']), - ) - : defaultPageBuilder( - context, - state, - JoinWithAlias(alias: state.uri.queryParameters['alias']), - ), + pageBuilder: (context, state) => defaultPageBuilder( + context, + state, + JoinWithAlias(alias: state.uri.queryParameters['alias']), + ), ), GoRoute( path: '/user_age', @@ -195,8 +190,13 @@ abstract class AppRoutes { pageBuilder: (context, state, child) => noTransitionPageBuilder( context, state, + // #Pangea + // FluffyThemes.isColumnMode(context) && + // state.fullPath?.startsWith('/rooms/settings') == false FluffyThemes.isColumnMode(context) && - state.fullPath?.startsWith('/rooms/settings') == false + state.fullPath?.startsWith('/rooms/settings') == false && + state.fullPath?.startsWith('/rooms/communities') == false + // Pangea# ? TwoColumnLayout( mainView: ChatList( activeChat: state.pathParameters['roomid'], @@ -302,16 +302,30 @@ abstract class AppRoutes { redirect: loggedOutRedirect, ), // #Pangea - GoRoute( - path: 'partner', - pageBuilder: (context, state) => defaultPageBuilder( + ShellRoute( + pageBuilder: (context, state, child) => defaultPageBuilder( context, state, - const FindPartner(), + FluffyThemes.isColumnMode(context) + ? TwoColumnLayout( + mainView: const FindYourPeopleSideView(), + sideView: child, + dividerColor: Colors.transparent, + ) + : child, ), - redirect: loggedOutRedirect, + routes: [ + GoRoute( + path: 'communities', + redirect: loggedOutRedirect, + pageBuilder: (context, state) => defaultPageBuilder( + context, + state, + const FindYourPeople(), + ), + ), + ], ), - // #Pangea GoRoute( path: 'homepage', redirect: loggedOutRedirect, @@ -748,27 +762,5 @@ abstract class AppRoutes { redirect: loggedOutRedirect, ), ]; - - static Page chatListShellRouteBuilder( - context, - state, - child, - ) => - noTransitionPageBuilder( - context, - state, - FluffyThemes.isColumnMode(context) && - state.fullPath?.startsWith('/rooms/settings') == false - ? TwoColumnLayout( - mainView: ChatList( - activeChat: state.pathParameters['roomid'], - activeSpaceId: state.uri.queryParameters['spaceId'], - displayNavigationRail: - state.path?.startsWith('/rooms/settings') != true, - ), - sideView: child, - ) - : child, - ); // Pangea# } diff --git a/lib/pages/chat_list/chat_list_view.dart b/lib/pages/chat_list/chat_list_view.dart index f2ed0c1c1..72e22c76d 100644 --- a/lib/pages/chat_list/chat_list_view.dart +++ b/lib/pages/chat_list/chat_list_view.dart @@ -41,6 +41,9 @@ class ChatListView extends StatelessWidget { activeSpaceId: controller.activeSpaceId, onGoToChats: controller.clearActiveSpace, onGoToSpaceId: controller.setActiveSpace, + // #Pangea + clearActiveSpace: controller.clearActiveSpace, + // Pangea# ), Container( color: Theme.of(context).dividerColor, diff --git a/lib/pangea/analytics_summary/learning_progress_indicator_button.dart b/lib/pangea/analytics_summary/learning_progress_indicator_button.dart index 542293f1d..30ea42199 100644 --- a/lib/pangea/analytics_summary/learning_progress_indicator_button.dart +++ b/lib/pangea/analytics_summary/learning_progress_indicator_button.dart @@ -2,14 +2,18 @@ import 'package:flutter/material.dart'; import 'package:fluffychat/widgets/hover_builder.dart'; -class LearningProgressIndicatorButton extends StatelessWidget { +class HoverButton extends StatelessWidget { final VoidCallback? onPressed; final Widget child; + final BorderRadius? borderRadius; + final double hoverOpacity; - const LearningProgressIndicatorButton({ + const HoverButton({ super.key, required this.onPressed, required this.child, + this.borderRadius, + this.hoverOpacity = 0.2, }); @override @@ -23,9 +27,12 @@ class LearningProgressIndicatorButton extends StatelessWidget { child: Container( decoration: BoxDecoration( color: hovered - ? Theme.of(context).colorScheme.primary.withAlpha(50) + ? Theme.of(context) + .colorScheme + .primary + .withAlpha((hoverOpacity * 255).round()) : Colors.transparent, - borderRadius: BorderRadius.circular(36.0), + borderRadius: borderRadius ?? BorderRadius.circular(36.0), ), padding: const EdgeInsets.symmetric( vertical: 2.0, diff --git a/lib/pangea/analytics_summary/learning_progress_indicators.dart b/lib/pangea/analytics_summary/learning_progress_indicators.dart index c25d378fb..d7a6d1c98 100644 --- a/lib/pangea/analytics_summary/learning_progress_indicators.dart +++ b/lib/pangea/analytics_summary/learning_progress_indicators.dart @@ -105,7 +105,7 @@ class LearningProgressIndicatorsState spacing: 16.0, children: ConstructTypeEnum.values .map( - (c) => LearningProgressIndicatorButton( + (c) => HoverButton( onPressed: () { showDialog( context: context, @@ -124,7 +124,7 @@ class LearningProgressIndicatorsState .toList(), ), ), - LearningProgressIndicatorButton( + HoverButton( onPressed: () => showDialog( context: context, builder: (c) => const SettingsLearning(), diff --git a/lib/pangea/find_your_people/find_your_people.dart b/lib/pangea/find_your_people/find_your_people.dart new file mode 100644 index 000000000..24fe4d78a --- /dev/null +++ b/lib/pangea/find_your_people/find_your_people.dart @@ -0,0 +1,102 @@ +import 'dart:async'; + +import 'package:flutter/material.dart'; + +import 'package:matrix/matrix.dart'; + +import 'package:fluffychat/pangea/common/utils/error_handler.dart'; +import 'package:fluffychat/pangea/find_your_people/find_your_people_view.dart'; +import 'package:fluffychat/widgets/matrix.dart'; + +class FindYourPeople extends StatefulWidget { + const FindYourPeople({super.key}); + + @override + State createState() => FindYourPeopleState(); +} + +class FindYourPeopleState extends State { + final TextEditingController searchController = TextEditingController(); + + String? error; + bool loading = true; + + Timer? _coolDown; + + final List spaceItems = []; + + @override + void initState() { + super.initState(); + setSpaceItems(); + } + + @override + void dispose() { + searchController.dispose(); + _coolDown?.cancel(); + super.dispose(); + } + + void onSearchEnter(String text, {bool globalSearch = true}) { + if (text.isEmpty) { + setSpaceItems(); + return; + } + + _coolDown?.cancel(); + _coolDown = Timer(const Duration(milliseconds: 500), setSpaceItems); + } + + Future setSpaceItems() async { + setState(() { + loading = true; + error = null; + spaceItems.clear(); + }); + + try { + final resp = await Matrix.of(context).client.queryPublicRooms( + filter: PublicRoomQueryFilter( + roomTypes: ['m.space'], + genericSearchTerm: searchController.text, + ), + limit: 100, + ); + spaceItems.addAll(resp.chunk); + spaceItems.sort((a, b) { + int getPriority(item) { + final bool hasTopic = item.topic != null && item.topic!.isNotEmpty; + final bool hasAvatar = item.avatarUrl != null; + + if (hasTopic && hasAvatar) return 0; // Highest priority + if (hasAvatar) return 1; // Second priority + if (hasTopic) return 2; // Third priority + return 3; // Lowest priority + } + + return getPriority(a).compareTo(getPriority(b)); + }); + } catch (e, s) { + ErrorHandler.logError( + e: e, + s: s, + data: { + 'searchText': searchController.text, + }, + ); + error = e.toString(); + } finally { + if (mounted) { + setState(() { + loading = false; + }); + } + } + } + + @override + Widget build(BuildContext context) { + return FindYourPeopleView(controller: this); + } +} diff --git a/lib/pangea/find_your_people/find_your_people_constants.dart b/lib/pangea/find_your_people/find_your_people_constants.dart new file mode 100644 index 000000000..04cf879ff --- /dev/null +++ b/lib/pangea/find_your_people/find_your_people_constants.dart @@ -0,0 +1,3 @@ +class FindYourPeopleConstants { + static const String sideBearFileName = "Bear_Find_your_people.png"; +} diff --git a/lib/pangea/find_your_people/find_your_people_side_view.dart b/lib/pangea/find_your_people/find_your_people_side_view.dart new file mode 100644 index 000000000..0514455e7 --- /dev/null +++ b/lib/pangea/find_your_people/find_your_people_side_view.dart @@ -0,0 +1,48 @@ +import 'package:flutter/material.dart'; + +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:go_router/go_router.dart'; + +import 'package:fluffychat/config/app_config.dart'; +import 'package:fluffychat/config/themes.dart'; +import 'package:fluffychat/pangea/find_your_people/find_your_people_constants.dart'; +import 'package:fluffychat/widgets/navigation_rail.dart'; + +class FindYourPeopleSideView extends StatelessWidget { + const FindYourPeopleSideView({super.key}); + + @override + Widget build(BuildContext context) { + return Row( + children: [ + if (FluffyThemes.isColumnMode(context) || + AppConfig.displayNavigationRail) ...[ + SpacesNavigationRail( + activeSpaceId: null, + onGoToChats: () => context.go('/rooms'), + onGoToSpaceId: (spaceId) => context.go('/rooms?spaceId=$spaceId'), + ), + Container( + color: Colors.transparent, + width: 1, + ), + ], + Expanded( + child: Center( + child: SizedBox( + width: 250.0, + child: CachedNetworkImage( + imageUrl: + "${AppConfig.assetsBaseURL}/${FindYourPeopleConstants.sideBearFileName}", + errorWidget: (context, url, error) => const SizedBox(), + placeholder: (context, url) => const Center( + child: CircularProgressIndicator.adaptive(), + ), + ), + ), + ), + ), + ], + ); + } +} diff --git a/lib/pangea/find_your_people/find_your_people_view.dart b/lib/pangea/find_your_people/find_your_people_view.dart new file mode 100644 index 000000000..064f6089c --- /dev/null +++ b/lib/pangea/find_your_people/find_your_people_view.dart @@ -0,0 +1,242 @@ +import 'package:flutter/material.dart'; + +import 'package:flutter_gen/gen_l10n/l10n.dart'; +import 'package:go_router/go_router.dart'; + +import 'package:fluffychat/config/themes.dart'; +import 'package:fluffychat/pangea/find_your_people/find_your_people.dart'; +import 'package:fluffychat/pangea/find_your_people/public_space_tile.dart'; +import 'package:fluffychat/pangea/spaces/utils/space_code.dart'; + +class FindYourPeopleView extends StatelessWidget { + final FindYourPeopleState controller; + + const FindYourPeopleView({ + super.key, + required this.controller, + }); + + @override + Widget build(BuildContext context) { + final theme = Theme.of(context); + final isColumnMode = FluffyThemes.isColumnMode(context); + + return Scaffold( + appBar: isColumnMode + ? null + : AppBar( + leading: IconButton( + icon: Icon( + Icons.chevron_left, + color: theme.colorScheme.primary, + ), + onPressed: () => Navigator.of(context).pop(), + ), + title: Icon( + Icons.groups_outlined, + size: 20.0, + color: theme.colorScheme.primary, + ), + centerTitle: false, + leadingWidth: 48.0, + actions: [ + TextButton( + child: Row( + children: [ + Icon( + Icons.join_full, + color: theme.colorScheme.primary, + size: 20.0, + ), + const SizedBox(width: 8.0), + Text( + L10n.of(context).joinWithCode, + style: TextStyle( + color: theme.colorScheme.primary, + fontSize: 10.0, + ), + ), + ], + ), + onPressed: () => + SpaceCodeUtil.joinWithSpaceCodeDialog(context), + ), + ], + ), + floatingActionButton: isColumnMode + ? null + : FloatingActionButton.extended( + onPressed: () => context.push('/rooms/newspace'), + icon: const Icon(Icons.add_box_outlined), + label: Text( + L10n.of(context).space, + overflow: TextOverflow.fade, + ), + ), + body: Padding( + padding: isColumnMode + ? const EdgeInsets.symmetric( + horizontal: 24.0, + vertical: 20.0, + ) + : const EdgeInsets.all(12.0), + child: Column( + spacing: 16.0, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (isColumnMode) + Padding( + padding: const EdgeInsets.symmetric( + vertical: 16.0, + horizontal: 12.0, + ), + child: Text( + L10n.of(context).findYourPeople, + style: const TextStyle(fontSize: 32.0), + ), + ), + Expanded( + child: Column( + spacing: isColumnMode ? 32.0 : 16.0, + children: [ + Container( + height: 48.0, + padding: isColumnMode + ? const EdgeInsets.symmetric(horizontal: 12) + : null, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + spacing: 10, + children: [ + Expanded( + child: SizedBox( + height: 40.0, + child: TextField( + controller: controller.searchController, + onChanged: controller.onSearchEnter, + textInputAction: TextInputAction.search, + decoration: InputDecoration( + filled: !isColumnMode, + fillColor: isColumnMode + ? null + : theme.colorScheme.secondaryContainer, + border: OutlineInputBorder( + borderSide: isColumnMode + ? const BorderSide() + : BorderSide.none, + borderRadius: BorderRadius.circular(100), + ), + contentPadding: EdgeInsets.zero, + hintText: L10n.of(context).findYourPeople, + hintStyle: TextStyle( + color: theme.colorScheme.onPrimaryContainer, + fontWeight: FontWeight.normal, + fontSize: 16.0, + ), + floatingLabelBehavior: + FloatingLabelBehavior.never, + prefixIcon: IconButton( + onPressed: () {}, + icon: Icon( + Icons.search_outlined, + color: theme.colorScheme.onPrimaryContainer, + ), + ), + ), + ), + ), + ), + if (isColumnMode) + TextButton( + child: Row( + children: [ + Icon( + Icons.join_full, + color: theme.colorScheme.onPrimaryContainer, + size: 24.0, + ), + const SizedBox(width: 8.0), + Text( + L10n.of(context).joinWithCode, + style: TextStyle( + color: theme.colorScheme.onPrimaryContainer, + fontSize: 14.0, + ), + ), + ], + ), + onPressed: () => + SpaceCodeUtil.joinWithSpaceCodeDialog(context), + ), + if (isColumnMode) + TextButton( + child: Row( + children: [ + Icon( + Icons.add_box_outlined, + color: theme.colorScheme.onPrimaryContainer, + size: 24.0, + ), + const SizedBox(width: 8.0), + Text( + L10n.of(context).createYourSpace, + style: TextStyle( + color: theme.colorScheme.onPrimaryContainer, + fontSize: 14.0, + ), + ), + ], + ), + onPressed: () => context.push('/rooms/newspace'), + ), + ], + ), + ), + controller.error != null + ? Row( + spacing: 8.0, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + L10n.of(context).oopsSomethingWentWrong, + ), + IconButton( + onPressed: controller.setSpaceItems, + icon: const Icon(Icons.refresh), + ), + ], + ) + : controller.loading + ? const CircularProgressIndicator.adaptive() + : controller.spaceItems.isEmpty + ? Text( + L10n.of(context).nothingFound, + ) + : Expanded( + child: ListView.builder( + itemCount: controller.spaceItems.length, + itemBuilder: (context, index) { + final space = + controller.spaceItems[index]; + return Padding( + padding: isColumnMode + ? const EdgeInsets.only( + bottom: 32.0, + ) + : const EdgeInsets.only( + bottom: 16.0, + ), + child: PublicSpaceTile(space: space), + ); + }, + ), + ), + ], + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/pangea/find_your_people/public_space_tile.dart b/lib/pangea/find_your_people/public_space_tile.dart new file mode 100644 index 000000000..7a5c05f99 --- /dev/null +++ b/lib/pangea/find_your_people/public_space_tile.dart @@ -0,0 +1,104 @@ +import 'package:flutter/material.dart'; + +import 'package:flutter_gen/gen_l10n/l10n.dart'; +import 'package:matrix/matrix.dart'; + +import 'package:fluffychat/config/themes.dart'; +import 'package:fluffychat/pangea/analytics_summary/learning_progress_indicator_button.dart'; +import 'package:fluffychat/pangea/public_spaces/public_room_bottom_sheet.dart'; +import 'package:fluffychat/widgets/avatar.dart'; + +class PublicSpaceTile extends StatelessWidget { + final PublicRoomsChunk space; + const PublicSpaceTile({super.key, required this.space}); + + @override + Widget build(BuildContext context) { + final bool isColumnMode = FluffyThemes.isColumnMode(context); + + return HoverButton( + onPressed: () => PublicRoomBottomSheet.show( + context: context, + chunk: space, + ), + borderRadius: BorderRadius.circular(10.0), + hoverOpacity: 0.1, + child: Padding( + padding: isColumnMode + ? const EdgeInsets.all(12.0) + : const EdgeInsets.all(0.0), + child: Column( + spacing: 12, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox( + height: isColumnMode ? 80.0 : 58.0, + child: Row( + children: [ + Avatar( + mxContent: space.avatarUrl, + name: space.name, + size: isColumnMode ? 80.0 : 58.0, + borderRadius: BorderRadius.circular( + 10, + ), + ), + Flexible( + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + spacing: 8.0, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + space.name ?? '', + style: TextStyle( + fontSize: isColumnMode ? 20.0 : 14.0, + height: 1.2, + ), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + Row( + spacing: 10, + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Icon( + Icons.group, + size: isColumnMode ? 30.0 : 16.0, + ), + Text( + L10n.of(context).countParticipants( + space.numJoinedMembers, + ), + style: TextStyle( + fontSize: isColumnMode ? 20.0 : 12.0, + height: 1.2, + ), + ), + ], + ), + ], + ), + ), + ), + ], + ), + ), + if (isColumnMode && space.topic != null && space.topic!.isNotEmpty) + Text( + space.topic!, + style: const TextStyle( + fontSize: 20.0, + height: 1.2, + ), + maxLines: 2, + overflow: TextOverflow.ellipsis, + ), + ], + ), + ), + ); + } +} diff --git a/lib/pangea/user/constants/age_limits.dart b/lib/pangea/user/constants/age_limits.dart deleted file mode 100644 index 9a07840ef..000000000 --- a/lib/pangea/user/constants/age_limits.dart +++ /dev/null @@ -1,4 +0,0 @@ -class AgeLimits { - static const int toAccessFeatures = 18; - static const int toUseTheApp = 13; -} diff --git a/lib/pangea/user/models/user_profile_search_model.dart b/lib/pangea/user/models/user_profile_search_model.dart deleted file mode 100644 index 212e8e392..000000000 --- a/lib/pangea/user/models/user_profile_search_model.dart +++ /dev/null @@ -1,27 +0,0 @@ -import 'user_model.dart'; - -class UserProfileSearchResponse { - int count; - String? next; - String? previous; - List results; - - UserProfileSearchResponse({ - required this.count, - required this.next, - required this.previous, - required this.results, - }); - - factory UserProfileSearchResponse.fromJson(Map json) { - return UserProfileSearchResponse( - count: json["count"], - next: json["next"], - previous: json["previous"], - results: json["results"] - .map((p) => PangeaProfile.fromJson(p)) - .toList() - .cast(), - ); - } -} diff --git a/lib/pangea/user/pages/find_partner.dart b/lib/pangea/user/pages/find_partner.dart deleted file mode 100644 index 5b3b1d52c..000000000 --- a/lib/pangea/user/pages/find_partner.dart +++ /dev/null @@ -1,179 +0,0 @@ -import 'dart:async'; - -import 'package:flutter/material.dart'; - -import 'package:country_picker/country_picker.dart'; -import 'package:flutter_gen/gen_l10n/l10n.dart'; - -import 'package:fluffychat/pangea/common/utils/error_handler.dart'; -import 'package:fluffychat/pangea/learning_settings/models/language_model.dart'; -import 'package:fluffychat/pangea/user/models/user_model.dart'; -import '../../../widgets/matrix.dart'; -import '../../common/controllers/pangea_controller.dart'; -import '../models/user_profile_search_model.dart'; -import '../repo/user_repo.dart'; -import 'find_partner_view.dart'; - -class FindPartner extends StatefulWidget { - const FindPartner({super.key}); - - @override - State createState() => FindPartnerController(); -} - -class FindPartnerController extends State { - PangeaController pangeaController = MatrixState.pangeaController; - - bool initialLoad = true; - bool loading = false; - String currentSearchTerm = ""; - late LanguageModel targetLanguageSearch; - late LanguageModel sourceLanguageSearch; - String? countrySearch; - String? flagEmoji; - - //PTODO - implement pagination - String? nextUrl = ""; - int nextPage = 1; - - Timer? coolDown; - - final List _userProfilesCache = []; - - final scrollController = ScrollController(); - String? error; - - @override - void initState() { - targetLanguageSearch = pangeaController.languageController.userL1 ?? - pangeaController.pLanguageStore.targetOptions[1]; - sourceLanguageSearch = pangeaController.languageController.userL2 ?? - pangeaController.pLanguageStore.targetOptions[0]; - - scrollController.addListener(() { - if (scrollController.position.pixels == - scrollController.position.maxScrollExtent) { - searchUserProfiles(); - } - }); - - searchUserProfiles().then((_) => setState(() => initialLoad = false)); - - super.initState(); - } - - @override - void dispose() { - scrollController.dispose(); - super.dispose(); - } - - @override - Widget build(BuildContext context) { - if (error != null && error!.isNotEmpty) { - return Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text(L10n.of(context).oopsSomethingWentWrong), - Text(L10n.of(context).errorPleaseRefresh), - ], - ), - ); - } - return FindPartnerView(this); - } - - List get userProfiles => _userProfilesCache.where((p) { - return (p.targetLanguage != null && - targetLanguageSearch.langCode == p.targetLanguage) && - (p.sourceLanguage != null && - sourceLanguageSearch.langCode == p.sourceLanguage) && - (countrySearch == null || - (p.country != null && countrySearch == p.country)); - }).toList(); - - void searchUserProfilesWithCoolDown(String text) { - coolDown?.cancel(); - coolDown = Timer( - const Duration(milliseconds: 0), - () => searchUserProfiles(), - ); - } - - Future searchUserProfiles() async { - coolDown?.cancel(); - if (loading || nextUrl == null) return; - setState(() => loading = true); - - UserProfileSearchResponse response; - try { - final String accessToken = pangeaController.userController.accessToken; - response = await PUserRepo.searchUserProfiles( - accessToken: accessToken, - targetLanguage: targetLanguageSearch.langCode, - sourceLanguage: sourceLanguageSearch.langCode, - country: countrySearch, - limit: 15, - pageNumber: nextPage.toString(), - ); - } catch (err, s) { - error = err.toString(); - setState(() => loading = false); - ErrorHandler.logError( - e: err, - s: s, - data: { - "accessToken": pangeaController.userController.accessToken, - "targetLanguage": targetLanguageSearch.langCode, - "sourceLanguage": sourceLanguageSearch.langCode, - "country": countrySearch, - "pageNumber": nextPage.toString(), - }, - ); - return; - } - - nextUrl = response.next; - nextPage++; - - final String? currentUserId = pangeaController.matrixState.client.userID; - _userProfilesCache.addAll( - response.results.where( - (p) => - !_userProfilesCache.any( - (element) => p.pangeaUserId == element.pangeaUserId, - ) && - p.pangeaUserId != currentUserId, - ), - ); - - setState(() => loading = false); - } - - Future filterUserProfiles({ - LanguageModel? targetLanguage, - LanguageModel? sourceLanguage, - Country? country, - }) async { - if (country != null) { - if (country.name != "World Wide") { - countrySearch = country.displayNameNoCountryCode; - flagEmoji = country.flagEmoji; - } else { - countrySearch = null; - flagEmoji = null; - } - } - if (targetLanguage != null) { - targetLanguageSearch = targetLanguage; - } - if (sourceLanguage != null) { - sourceLanguageSearch = sourceLanguage; - } - nextPage = 1; - nextUrl = ""; - await searchUserProfiles(); - setState(() {}); - } -} diff --git a/lib/pangea/user/pages/find_partner_view.dart b/lib/pangea/user/pages/find_partner_view.dart deleted file mode 100644 index 5ba019bbe..000000000 --- a/lib/pangea/user/pages/find_partner_view.dart +++ /dev/null @@ -1,315 +0,0 @@ -import 'package:flutter/material.dart'; - -import 'package:country_picker/country_picker.dart'; -import 'package:flutter_gen/gen_l10n/l10n.dart'; -import 'package:go_router/go_router.dart'; -import 'package:matrix/matrix.dart' as matrix; - -import 'package:fluffychat/config/app_config.dart'; -import 'package:fluffychat/config/themes.dart'; -import 'package:fluffychat/pangea/common/widgets/pangea_logo_svg.dart'; -import 'package:fluffychat/pangea/learning_settings/utils/country_display.dart'; -import 'package:fluffychat/pangea/learning_settings/widgets/p_language_dropdown.dart'; -import 'package:fluffychat/pangea/user/models/user_model.dart'; -import 'package:fluffychat/pangea/user/widgets/list_placeholder.dart'; -import 'package:fluffychat/widgets/avatar.dart'; -import 'package:fluffychat/widgets/matrix.dart'; -import '../../../widgets/profile_bottom_sheet.dart'; -import 'find_partner.dart'; - -class FindPartnerView extends StatelessWidget { - final FindPartnerController controller; - const FindPartnerView(this.controller, {super.key}); - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - leading: IconButton( - icon: const Icon(Icons.close_outlined), - onPressed: () => context.pop(), - ), - centerTitle: true, - title: const PageTitleText(), - ), - body: Center( - child: Container( - constraints: const BoxConstraints( - maxWidth: FluffyThemes.columnWidth * 2, - minWidth: FluffyThemes.columnWidth * 2, - ), - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - LanguageSelectionRow( - controller: controller, - isSource: true, - ), - LanguageSelectionRow( - controller: controller, - isSource: false, - ), - Padding( - padding: const EdgeInsets.all(18), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - L10n.of(context).iWantALanguagePartnerFrom, - style: const TextStyle(fontSize: 16), - ), - Row( - children: [ - Text( - controller.countrySearch ?? - L10n.of(context).worldWide, - ), - Padding( - padding: const EdgeInsets.fromLTRB(15, 0, 15, 0), - child: controller.flagEmoji != null - ? RichText( - text: TextSpan( - text: controller.flagEmoji, - style: const TextStyle(fontSize: 30), - ), - ) - : const PangeaLogoSvg(width: 30), - ), - IconButton( - icon: const Icon(Icons.expand_more), - onPressed: () => showCountryPicker( - showWorldWide: true, - context: context, - showPhoneCode: false, - onSelect: (Country country) { - controller.filterUserProfiles( - country: country, - ); - }, - ), - ), - ], - ), - ], - ), - ), - controller.initialLoad - ? const ExpandedContainer(body: ListPlaceholder()) - : controller.userProfiles.isNotEmpty - ? ExpandedContainer( - body: ListView.builder( - controller: controller.scrollController, - itemCount: controller.userProfiles.length + 1, - itemBuilder: (context, i) => i != - controller.userProfiles.length - ? UserProfileEntry( - pangeaProfile: controller.userProfiles[i], - controller: controller, - ) - : controller.loading - ? const Center( - child: CircularProgressIndicator - .adaptive(), - ) - : const SizedBox.shrink(), - ), - ) - : ExpandedContainer( - body: Center( - child: Text(L10n.of(context).noResults), - ), - ), - ], - ), - ), - ), - ); - } -} - -class ExpandedContainer extends StatelessWidget { - const ExpandedContainer({ - super.key, - required this.body, - }); - - final Widget body; - - @override - Widget build(BuildContext context) { - return Expanded( - child: Container( - margin: const EdgeInsets.fromLTRB(0, 20, 0, 20), - child: body, - ), - ); - } -} - -class ProfileSearchTextField extends StatelessWidget { - const ProfileSearchTextField({ - super.key, - required this.controller, - }); - - final FindPartnerController controller; - - @override - Widget build(BuildContext context) { - return TextField( - autofocus: true, - decoration: InputDecoration( - hintText: L10n.of(context).searchBy, - suffixIconConstraints: const BoxConstraints( - maxWidth: 48, - maxHeight: 48, - minWidth: 48, - ), - suffixIcon: controller.initialLoad - ? const CircularProgressIndicator.adaptive() - : const Icon(Icons.search_outlined), - contentPadding: const EdgeInsets.symmetric(horizontal: 16), - ), - onChanged: controller.searchUserProfilesWithCoolDown, - ); - } -} - -class PageTitleText extends StatelessWidget { - const PageTitleText({ - super.key, - }); - - @override - Widget build(BuildContext context) { - return FittedBox( - child: Text( - L10n.of(context).iWantAConversationPartner, - style: TextStyle( - color: Theme.of(context).textTheme.bodyLarge!.color, - fontSize: 18, - fontWeight: FontWeight.w700, - ), - overflow: TextOverflow.clip, - textAlign: TextAlign.center, - ), - ); - } -} - -class LanguageSelectionRow extends StatelessWidget { - const LanguageSelectionRow({ - super.key, - required this.controller, - required this.isSource, - }); - - final FindPartnerController controller; - final bool isSource; - - @override - Widget build(BuildContext context) { - return Row( - children: [ - Flexible( - child: ListTile( - title: isSource - ? Text( - L10n.of(context).iWantALanguagePartnerWhoSpeaks, - style: const TextStyle(fontSize: 16), - ) - : Text( - L10n.of(context).iWantALanguagePartnerWhoIsLearning, - style: const TextStyle(fontSize: 16), - ), - ), - ), - Flexible( - child: PLanguageDropdown( - languages: isSource - ? controller.pangeaController.pLanguageStore.baseOptions - : controller.pangeaController.pLanguageStore.targetOptions, - onChange: (language) { - controller.filterUserProfiles( - sourceLanguage: isSource ? language : null, - targetLanguage: isSource ? null : language, - ); - }, - isL2List: !isSource, - initialLanguage: isSource - ? controller.sourceLanguageSearch - : controller.targetLanguageSearch, - decorationText: isSource - ? L10n.of(context).myBaseLanguage - : L10n.of(context).iWantToLearn, - ), - ), - ], - ); - } -} - -class UserProfileEntry extends StatelessWidget { - final PangeaProfile pangeaProfile; - final FindPartnerController controller; - - const UserProfileEntry({ - super.key, - required this.pangeaProfile, - required this.controller, - }); - - @override - Widget build(BuildContext context) { - return Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - FutureBuilder( - future: Matrix.of(context) - .client - .getProfileFromUserId(pangeaProfile.pangeaUserId), - builder: ((context, snapshot) { - final matrixProfile = snapshot.data; - return ListTile( - leading: Avatar( - name: matrixProfile == null || matrixProfile.avatarUrl == null - ? pangeaProfile.pangeaUserId - : null, - mxContent: matrixProfile?.avatarUrl, - ), - title: Row( - children: [ - Flexible( - child: Text( - //PTODO - get matrix u and show displayName - matrixProfile?.displayName ?? - pangeaProfile.pangeaUserId.replaceAll( - ":${AppConfig.defaultHomeserver.replaceAll("matrix.", "")}", - "", - ), - overflow: TextOverflow.ellipsis, - ), - ), - const SizedBox(width: 20), - RichText( - text: TextSpan( - text: CountryDisplayUtil.flagEmoji(pangeaProfile.country), - style: const TextStyle(fontSize: 15), - ), - ), - ], - ), - onTap: () => showModalBottomSheet( - context: context, - builder: (c) => ProfileBottomSheet( - userId: pangeaProfile.pangeaUserId, - outerContext: context, - ), - ), - ); - }), - ), - ], - ); - } -} diff --git a/lib/pangea/user/repo/user_repo.dart b/lib/pangea/user/repo/user_repo.dart deleted file mode 100644 index 9f6320f32..000000000 --- a/lib/pangea/user/repo/user_repo.dart +++ /dev/null @@ -1,48 +0,0 @@ -import 'dart:convert'; - -import 'package:http/http.dart'; - -import 'package:fluffychat/pangea/common/config/environment.dart'; -import 'package:fluffychat/pangea/common/constants/model_keys.dart'; -import '../../common/network/requests.dart'; -import '../../common/network/urls.dart'; -import '../models/user_profile_search_model.dart'; - -class PUserRepo { - static Future searchUserProfiles({ - // List? interests, - String? targetLanguage, - String? sourceLanguage, - String? country, - // String? speaks, - String? pageNumber, - required String accessToken, - required int limit, - }) async { - final Requests req = Requests( - accessToken: accessToken, - choreoApiKey: Environment.choreoApiKey, - ); - final Map body = {}; - // if (interests != null) body[ModelKey.userInterests] = interests.toString(); - if (targetLanguage != null) { - body[ModelKey.userTargetLanguage] = targetLanguage; - } - if (sourceLanguage != null) { - body[ModelKey.userSourceLanguage] = sourceLanguage; - } - if (country != null) body[ModelKey.userCountry] = country; - - final String searchUrl = - "${PApiUrls.searchUserProfiles}?limit=$limit${pageNumber != null ? '&page=$pageNumber' : ''}"; - - final Response res = await req.post( - url: searchUrl, - body: body, - ); - - //PTODO - implement paginiation - make another call with next url - - return UserProfileSearchResponse.fromJson(jsonDecode(res.body)); - } -} diff --git a/lib/pangea/user/widgets/list_placeholder.dart b/lib/pangea/user/widgets/list_placeholder.dart deleted file mode 100644 index 4b37c08d6..000000000 --- a/lib/pangea/user/widgets/list_placeholder.dart +++ /dev/null @@ -1,72 +0,0 @@ -import 'package:flutter/material.dart'; - -class ListPlaceholder extends StatelessWidget { - static const dummyChatCount = 5; - - const ListPlaceholder({super.key}); - - @override - Widget build(BuildContext context) { - final titleColor = - Theme.of(context).textTheme.bodyLarge!.color!.withAlpha(100); - final subtitleColor = - Theme.of(context).textTheme.bodyLarge!.color!.withAlpha(50); - - return ListView.builder( - itemCount: dummyChatCount, - itemBuilder: (context, i) => Opacity( - opacity: (dummyChatCount - i) / dummyChatCount, - child: Material( - child: ListTile( - leading: CircleAvatar( - backgroundColor: titleColor, - child: CircularProgressIndicator( - strokeWidth: 1, - color: Theme.of(context).textTheme.bodyLarge!.color, - ), - ), - title: Row( - children: [ - Expanded( - child: Container( - height: 14, - decoration: BoxDecoration( - color: titleColor, - borderRadius: BorderRadius.circular(3), - ), - ), - ), - const SizedBox(width: 36), - Container( - height: 14, - width: 14, - decoration: BoxDecoration( - color: subtitleColor, - borderRadius: BorderRadius.circular(14), - ), - ), - const SizedBox(width: 12), - Container( - height: 14, - width: 14, - decoration: BoxDecoration( - color: subtitleColor, - borderRadius: BorderRadius.circular(14), - ), - ), - ], - ), - subtitle: Container( - decoration: BoxDecoration( - color: subtitleColor, - borderRadius: BorderRadius.circular(3), - ), - height: 12, - margin: const EdgeInsets.only(right: 22), - ), - ), - ), - ), - ); - } -} diff --git a/lib/pangea/writing_assistance/writing_assistance_input_row.dart b/lib/pangea/writing_assistance/writing_assistance_input_row.dart deleted file mode 100644 index 462c8b5d3..000000000 --- a/lib/pangea/writing_assistance/writing_assistance_input_row.dart +++ /dev/null @@ -1,113 +0,0 @@ -// // presents choices from vocab_bank_repo -// // displays them as emoji choices -// // once selection, these words are inserted into the input bar - -// import 'dart:async'; - -// import 'package:fluffychat/config/themes.dart'; -// import 'package:fluffychat/pages/chat/chat.dart'; -// import 'package:fluffychat/pangea/choreographer/controllers/choreographer.dart'; -// import 'package:fluffychat/pangea/constructs/construct_identifier.dart'; -// import 'package:fluffychat/pangea/emojis/emoji_stack.dart'; -// import 'package:fluffychat/pangea/learning_settings/constants/language_constants.dart'; -// import 'package:fluffychat/pangea/toolbar/reading_assistance_input_row/message_emoji_choice_item.dart'; -// import 'package:fluffychat/pangea/word_bank/vocab_bank_repo.dart'; -// import 'package:fluffychat/pangea/word_bank/vocab_request.dart'; -// import 'package:fluffychat/pangea/word_bank/vocab_response.dart'; -// import 'package:fluffychat/widgets/matrix.dart'; -// import 'package:flutter/material.dart'; - -// class WritingAssistanceInputRow extends StatefulWidget { -// final ChatController controller; - -// const WritingAssistanceInputRow( -// this.controller, { -// super.key, -// }); - -// @override -// WritingAssistanceInputRowState createState() => -// WritingAssistanceInputRowState(); -// } - -// class WritingAssistanceInputRowState extends State { -// List suggestions = []; - -// StreamSubscription? _choreoSub; - -// Choreographer get choreographer => widget.controller.choreographer; - -// @override -// void initState() { -// // Rebuild the widget each time there's an update from choreo -// _choreoSub = choreographer.stateListener.stream.listen((_) { -// setSuggestions(); -// }); -// setSuggestions(); -// super.initState(); -// } - -// @override -// void dispose() { -// _choreoSub?.cancel(); -// super.dispose(); -// } - -// Future setSuggestions() async { -// final String currentText = choreographer.currentText; - -// final VocabRequest request = VocabRequest( -// langCode: MatrixState -// .pangeaController.languageController.userL2?.langCodeShort ?? -// LanguageKeys.defaultLanguage, -// level: MatrixState -// .pangeaController.userController.profile.userSettings.cefrLevel, -// prefix: currentText, -// ); - -// final VocabResponse response = await VocabRepo.get(request); - -// setState(() { -// suggestions = response.vocab; -// }); -// } - -// @override -// Widget build(BuildContext context) { -// return AnimatedContainer( -// duration: FluffyThemes.animationDuration, -// curve: FluffyThemes.animationCurve, -// child: SingleChildScrollView( -// scrollDirection: Axis.horizontal, -// child: Row( -// children: suggestions -// .map( -// (suggestion) => MessageEmojiChoiceItem( -// topContent: EmojiStack( -// emoji: suggestion.userSetEmoji, -// // suggestion.userSetEmoji ?? -// // MatrixState -// // .pangeaController.getAnalytics.constructListModel -// // .getConstructUses(suggestion) -// // ?.xpEmoji ?? -// // AnalyticsConstants.emojiForSeed, -// style: const TextStyle(fontSize: 24), -// ), -// content: suggestion.lemma, -// onTap: () { -// choreographer.onPredictorSelect(suggestion.lemma); -// // setState(() { -// // suggestions = []; -// // }); -// }, -// isSelected: false, -// textSize: 16, -// greenHighlight: false, -// ), -// ) -// .toList(), -// ), -// ), -// ); -// } -// } diff --git a/lib/widgets/layouts/two_column_layout.dart b/lib/widgets/layouts/two_column_layout.dart index 86a6f56c5..f440cfcfd 100644 --- a/lib/widgets/layouts/two_column_layout.dart +++ b/lib/widgets/layouts/two_column_layout.dart @@ -5,11 +5,17 @@ import 'package:fluffychat/config/themes.dart'; class TwoColumnLayout extends StatelessWidget { final Widget mainView; final Widget sideView; + // #Pangea + final Color? dividerColor; + // Pangea# const TwoColumnLayout({ super.key, required this.mainView, required this.sideView, + // #Pangea + this.dividerColor, + // Pangea# }); @override Widget build(BuildContext context) { @@ -27,7 +33,10 @@ class TwoColumnLayout extends StatelessWidget { ), Container( width: 1.0, - color: theme.dividerColor, + // #Pangea + // color: theme.dividerColor, + color: dividerColor ?? theme.dividerColor, + // Pangea# ), Expanded( child: ClipRRect( diff --git a/lib/widgets/navigation_rail.dart b/lib/widgets/navigation_rail.dart index 802fe5c8b..2599dcb15 100644 --- a/lib/widgets/navigation_rail.dart +++ b/lib/widgets/navigation_rail.dart @@ -7,7 +7,6 @@ import 'package:matrix/matrix.dart'; import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/config/themes.dart'; import 'package:fluffychat/pages/chat_list/navi_rail_item.dart'; -import 'package:fluffychat/pangea/spaces/utils/space_code.dart'; import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_locals.dart'; import 'package:fluffychat/utils/stream_extension.dart'; import 'package:fluffychat/widgets/avatar.dart'; @@ -17,11 +16,17 @@ class SpacesNavigationRail extends StatelessWidget { final String? activeSpaceId; final void Function() onGoToChats; final void Function(String) onGoToSpaceId; + // #Pangea + final void Function()? clearActiveSpace; + // Pangea# const SpacesNavigationRail({ required this.activeSpaceId, required this.onGoToChats, required this.onGoToSpaceId, + // #Pangea + this.clearActiveSpace, + // Pangea# super.key, }); @@ -35,12 +40,9 @@ class SpacesNavigationRail extends StatelessWidget { .path .startsWith('/rooms/settings'); // #Pangea - final isHomepage = GoRouter.of(context) - .routeInformationProvider - .value - .uri - .path - .contains('homepage'); + final path = GoRouter.of(context).routeInformationProvider.value.uri.path; + final isHomepage = path.contains('homepage'); + final isCommunities = path.contains('communities'); final isColumnMode = FluffyThemes.isColumnMode(context); // return StreamBuilder( return Material( @@ -78,18 +80,25 @@ class SpacesNavigationRail extends StatelessWidget { scrollDirection: Axis.vertical, // #Pangea // itemCount: rootSpaces.length + 2, - itemCount: rootSpaces.length + 4, + itemCount: rootSpaces.length + 3, // Pangea# itemBuilder: (context, i) { // #Pangea if (i == 0) { return NaviRailItem( isSelected: isColumnMode - ? activeSpaceId == null && !isSettings + ? activeSpaceId == null && + !isSettings && + !isCommunities : isHomepage, - onTap: () => isColumnMode - ? onGoToChats() - : context.go("/rooms/homepage"), + onTap: () { + if (isColumnMode) { + onGoToChats(); + } else { + clearActiveSpace?.call(); + context.go("/rooms/homepage"); + } + }, backgroundColor: Colors.transparent, icon: FutureBuilder( future: client.fetchOwnProfile(), @@ -122,7 +131,8 @@ class SpacesNavigationRail extends StatelessWidget { // isSelected: activeSpaceId == null && !isSettings, isSelected: activeSpaceId == null && !isSettings && - !isHomepage, + !isHomepage && + !isCommunities, // Pangea# onTap: onGoToChats, icon: const Padding( @@ -139,28 +149,26 @@ class SpacesNavigationRail extends StatelessWidget { } i--; if (i == rootSpaces.length) { - // #Pangea return NaviRailItem( - isSelected: false, - onTap: () => - SpaceCodeUtil.joinWithSpaceCodeDialog(context), + // #Pangea + // isSelected: false, + // onTap: () => context.go('/rooms/newspace'), + // icon: const Padding( + // padding: EdgeInsets.all(8.0), + // child: Icon(Icons.add), + // ), + // toolTip: L10n.of(context).createNewSpace, + isSelected: isCommunities, + onTap: () { + clearActiveSpace?.call(); + context.go('/rooms/communities'); + }, icon: const Padding( - padding: EdgeInsets.all(8.0), - child: Icon(Icons.join_right_outlined), + padding: EdgeInsets.all(10.0), + child: Icon(Icons.groups), ), - toolTip: L10n.of(context).joinByCode, - ); - } - if (i == rootSpaces.length + 1) { - // Pangea# - return NaviRailItem( - isSelected: false, - onTap: () => context.go('/rooms/newspace'), - icon: const Padding( - padding: EdgeInsets.all(8.0), - child: Icon(Icons.add), - ), - toolTip: L10n.of(context).createNewSpace, + toolTip: L10n.of(context).findYourPeople, + // Pangea# ); } final space = rootSpaces[i];